feat: add API key authentication system and update documentation
API Key System: - Add TpmjsApiKey, ApiUsageRecord, ApiUsageSummary models to schema - Create API key utilities (generate, hash, mask with tpmjs_sk_ prefix) - Implement dual auth middleware (session + API key) - Add rate limiting with Vercel KV - Create CRUD endpoints for API key management - Add usage tracking and analytics endpoint - Build API key management UI in dashboard - Build usage dashboard with charts Route Protection: - Require auth for MCP endpoints (mcp:execute scope) - Require auth for agent chat (agent:chat scope) - Require auth for bridge connections (bridge:connect scope) Documentation Updates: - Update all curl/fetch examples with Authorization header - Document API key format, scopes, and rate limits - Update PRD-MCP-BRIDGE.md, MCP-AGGREGATOR-DESIGN.md - Update API docs page with auth requirements - Update HOW_TO_PUBLISH_A_TOOL.md
This commit is contained in:
parent
b663ca3e05
commit
a3f1f3935e
20 changed files with 2813 additions and 90 deletions
|
|
@ -401,9 +401,9 @@ class TPMJSBridge {
|
|||
})));
|
||||
}
|
||||
|
||||
// 3. Connect to TPMJS WebSocket
|
||||
// 3. Connect to TPMJS WebSocket (requires API key with bridge:connect scope)
|
||||
this.ws = new WebSocket(
|
||||
`${this.config.tpmjsUrl}/api/bridge?token=${this.config.apiKey}`
|
||||
`${this.config.tpmjsUrl}/api/bridge?token=${this.config.apiKey}` // apiKey format: tpmjs_sk_...
|
||||
);
|
||||
|
||||
this.ws.on('open', () => {
|
||||
|
|
@ -443,6 +443,7 @@ class TPMJSBridge {
|
|||
}
|
||||
|
||||
// CLI entry point
|
||||
// API key is loaded from ~/.tpmjs/credentials.json (format: tpmjs_sk_...)
|
||||
const config = loadConfig(); // from ~/.tpmjs/bridge.json
|
||||
const bridge = new TPMJSBridge(config);
|
||||
bridge.start();
|
||||
|
|
@ -452,9 +453,12 @@ bridge.start();
|
|||
|
||||
Server-side handler for bridge connections.
|
||||
|
||||
**Authentication:** Requires TPMJS API key (format: `tpmjs_sk_...`) with `bridge:connect` scope.
|
||||
|
||||
```typescript
|
||||
// apps/web/src/app/api/bridge/route.ts
|
||||
import { prisma } from '@tpmjs/db';
|
||||
import { authenticateRequest, hasScope } from '~/lib/api-keys/middleware';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
|
|
@ -463,9 +467,9 @@ export async function GET(request: Request) {
|
|||
const { searchParams } = new URL(request.url);
|
||||
const token = searchParams.get('token');
|
||||
|
||||
// Validate API key
|
||||
const user = await validateApiKey(token);
|
||||
if (!user) {
|
||||
// Validate API key (must have bridge:connect scope)
|
||||
const authResult = await authenticateRequest();
|
||||
if (!authResult.authenticated || !hasScope(authResult, 'bridge:connect')) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
||||
|
|
@ -715,11 +719,19 @@ interface ToolExecutionError {
|
|||
|
||||
### Security Considerations
|
||||
|
||||
1. **API Key Authentication**: Bridge connections require valid API key
|
||||
2. **User Isolation**: Each user's bridge is isolated
|
||||
3. **Tool Whitelisting**: Users explicitly add tools to collections
|
||||
4. **Encrypted Credentials**: Remote MCP server credentials encrypted at rest
|
||||
5. **WebSocket Security**: WSS (TLS) required for bridge connections
|
||||
1. **API Key Authentication**: All API endpoints require a valid TPMJS API key (`tpmjs_sk_...` prefix)
|
||||
2. **Scope-Based Access**: API keys have specific scopes (e.g., `bridge:connect`, `mcp:execute`, `agent:chat`)
|
||||
3. **User Isolation**: Each user's bridge is isolated
|
||||
4. **Tool Whitelisting**: Users explicitly add tools to collections
|
||||
5. **Encrypted Credentials**: Remote MCP server credentials encrypted at rest
|
||||
6. **WebSocket Security**: WSS (TLS) required for bridge connections
|
||||
|
||||
**Required API Key Scopes:**
|
||||
- `bridge:connect` - For bridge WebSocket connections
|
||||
- `mcp:execute` - For MCP tool execution
|
||||
- `collection:read` - For accessing collection data
|
||||
|
||||
Generate API keys from Settings > TPMJS API Keys in the dashboard.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -819,12 +831,17 @@ After setup, user only needs ONE MCP server in their config:
|
|||
"mcpServers": {
|
||||
"tpmjs": {
|
||||
"type": "url",
|
||||
"url": "https://tpmjs.com/api/mcp/username/all-my-tools/http"
|
||||
"url": "https://tpmjs.com/api/mcp/username/all-my-tools/http",
|
||||
"headers": {
|
||||
"Authorization": "Bearer tpmjs_sk_your_api_key_here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Generate your API key from Settings > TPMJS API Keys. The key requires `mcp:execute` scope.
|
||||
|
||||
This single endpoint provides access to:
|
||||
- All npm tools in the collection
|
||||
- All remote MCP tools configured
|
||||
|
|
|
|||
|
|
@ -648,7 +648,7 @@ npx @tpmjs/bridge <command>
|
|||
**~/.tpmjs/credentials.json**
|
||||
```json
|
||||
{
|
||||
"apiKey": "tpmjs_xxxxxxxxxxxxxxxxxxxx",
|
||||
"apiKey": "tpmjs_sk_xxxxxxxxxxxxxxxxxxxx",
|
||||
"userId": "user_abc123",
|
||||
"email": "user@example.com",
|
||||
"expiresAt": "2026-01-12T00:00:00Z"
|
||||
|
|
@ -703,9 +703,11 @@ await manager.disconnect('chrome');
|
|||
#### Connection
|
||||
|
||||
```
|
||||
wss://tpmjs.com/api/bridge?token=tpmjs_xxxx
|
||||
wss://tpmjs.com/api/bridge?token=tpmjs_sk_your_api_key_here
|
||||
```
|
||||
|
||||
**Note:** All TPMJS API endpoints require authentication. Generate an API key from your dashboard at Settings > TPMJS API Keys. API keys use the `tpmjs_sk_` prefix.
|
||||
|
||||
#### Messages: Bridge → TPMJS
|
||||
|
||||
**Register Tools**
|
||||
|
|
@ -907,16 +909,28 @@ ALTER TABLE "CollectionBridgeTool" ADD CONSTRAINT "CollectionBridgeTool_collecti
|
|||
**Endpoint**: `GET /api/bridge`
|
||||
|
||||
**Query Parameters**:
|
||||
- `token` (required): User's API key
|
||||
- `token` (required): User's TPMJS API key (format: `tpmjs_sk_...`)
|
||||
|
||||
**Upgrade**: WebSocket
|
||||
|
||||
**Authentication**: Validates API key, returns 401 if invalid
|
||||
**Authentication**: Validates API key with `bridge:connect` scope, returns 401 if invalid
|
||||
|
||||
**Example**:
|
||||
```bash
|
||||
# Connect via WebSocket with API key
|
||||
wscat -c 'wss://tpmjs.com/api/bridge?token=tpmjs_sk_your_api_key_here'
|
||||
```
|
||||
|
||||
### Bridge Status API
|
||||
|
||||
**Endpoint**: `GET /api/user/bridge`
|
||||
|
||||
**Authentication**: Requires API key with `bridge:connect` scope
|
||||
```bash
|
||||
curl https://tpmjs.com/api/user/bridge \
|
||||
-H 'Authorization: Bearer tpmjs_sk_your_api_key_here'
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
|
|
@ -945,13 +959,18 @@ ALTER TABLE "CollectionBridgeTool" ADD CONSTRAINT "CollectionBridgeTool_collecti
|
|||
|
||||
### Collection Bridge Tools API
|
||||
|
||||
All collection endpoints require API key with `collection:read` scope.
|
||||
|
||||
**Add Tool**: `POST /api/collections/{id}/bridge-tools`
|
||||
|
||||
```json
|
||||
{
|
||||
"serverId": "chrome-devtools",
|
||||
"toolName": "screenshot"
|
||||
}
|
||||
```bash
|
||||
curl -X POST 'https://tpmjs.com/api/collections/{id}/bridge-tools' \
|
||||
-H 'Authorization: Bearer tpmjs_sk_your_api_key_here' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"serverId": "chrome-devtools",
|
||||
"toolName": "screenshot"
|
||||
}'
|
||||
```
|
||||
|
||||
**Remove Tool**: `DELETE /api/collections/{id}/bridge-tools/{toolId}`
|
||||
|
|
|
|||
|
|
@ -159,8 +159,9 @@ This happened with the `startTime is not defined` bug. Our executor code had a b
|
|||
### Investigating a Specific Tool
|
||||
|
||||
```bash
|
||||
# Check current health status
|
||||
curl -s 'https://tpmjs.com/api/tools?limit=50' | \
|
||||
# Check current health status (requires API key)
|
||||
curl -s 'https://tpmjs.com/api/tools?limit=50' \
|
||||
-H 'Authorization: Bearer tpmjs_sk_your_api_key_here' | \
|
||||
jq '.data[] | select(.package.npmPackageName == "PACKAGE_NAME") | {
|
||||
packageName: .package.npmPackageName,
|
||||
exportName: .exportName,
|
||||
|
|
@ -179,10 +180,11 @@ cat package/dist/index.js
|
|||
|
||||
### Manually Updating Health Status
|
||||
|
||||
For testing or correction:
|
||||
For testing or correction (requires API key with appropriate scope):
|
||||
|
||||
```bash
|
||||
curl -X POST 'https://tpmjs.com/api/tools/report-health' \
|
||||
-H 'Authorization: Bearer tpmjs_sk_your_api_key_here' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"packageName": "@scope/package",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue