@clampd/mcp-proxy 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +32 -0
- package/README.md +103 -0
- package/dist/dashboard.d.ts +64 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +516 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/fleet.d.ts +52 -0
- package/dist/fleet.d.ts.map +1 -0
- package/dist/fleet.js +274 -0
- package/dist/fleet.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +173 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptor.d.ts +92 -0
- package/dist/interceptor.d.ts.map +1 -0
- package/dist/interceptor.js +274 -0
- package/dist/interceptor.js.map +1 -0
- package/dist/logger.d.ts +6 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +15 -0
- package/dist/logger.js.map +1 -0
- package/dist/mock-server.d.ts +14 -0
- package/dist/mock-server.d.ts.map +1 -0
- package/dist/mock-server.js +128 -0
- package/dist/mock-server.js.map +1 -0
- package/dist/proxy.d.ts +59 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +578 -0
- package/dist/proxy.js.map +1 -0
- package/fleet.example.json +38 -0
- package/package.json +44 -0
- package/src/dashboard.ts +602 -0
- package/src/fleet.ts +329 -0
- package/src/index.ts +187 -0
- package/src/interceptor.ts +427 -0
- package/src/logger.ts +17 -0
- package/src/mock-server.ts +240 -0
- package/src/proxy.ts +752 -0
- package/tsconfig.json +20 -0
package/Dockerfile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
FROM node:22-alpine AS builder
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
COPY package.json package-lock.json* ./
|
|
6
|
+
RUN npm ci --ignore-scripts
|
|
7
|
+
|
|
8
|
+
COPY tsconfig.json ./
|
|
9
|
+
COPY src/ ./src/
|
|
10
|
+
RUN npm run build
|
|
11
|
+
|
|
12
|
+
# ── Runtime ────────────────────────────────────────────────────────────
|
|
13
|
+
FROM node:22-alpine
|
|
14
|
+
|
|
15
|
+
RUN addgroup -g 1001 clampd && adduser -D -u 1001 -G clampd clampd
|
|
16
|
+
|
|
17
|
+
WORKDIR /app
|
|
18
|
+
|
|
19
|
+
COPY --from=builder /app/package.json /app/package-lock.json* ./
|
|
20
|
+
RUN npm ci --omit=dev --ignore-scripts
|
|
21
|
+
|
|
22
|
+
COPY --from=builder /app/dist/ ./dist/
|
|
23
|
+
|
|
24
|
+
# Copy fleet config if present (for fleet mode)
|
|
25
|
+
COPY fleet*.json ./
|
|
26
|
+
|
|
27
|
+
USER clampd
|
|
28
|
+
EXPOSE 3003
|
|
29
|
+
|
|
30
|
+
# Single mode: reads config from env vars
|
|
31
|
+
# Fleet mode: set CMD to ["node", "dist/index.js", "--fleet-config", "fleet.json"]
|
|
32
|
+
CMD ["node", "dist/index.js"]
|
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# @clampd/mcp-proxy
|
|
2
|
+
|
|
3
|
+
Standalone MCP proxy that wraps **any** MCP server with Clampd's 9-stage security pipeline. Connect Claude Desktop, Cursor, or any MCP client to this proxy instead of directly to an MCP server. Every tool call is classified through ag-gateway — dangerous calls are blocked before they reach the tool.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install
|
|
9
|
+
cd sdk/typescript/mcp-proxy && npm install
|
|
10
|
+
|
|
11
|
+
# Run (wraps the filesystem MCP server)
|
|
12
|
+
npx tsx src/index.ts \
|
|
13
|
+
--upstream "npx -y @modelcontextprotocol/server-filesystem /tmp" \
|
|
14
|
+
--gateway http://localhost:8080 \
|
|
15
|
+
--agent-id b0000001-0000-0000-0000-000000000001 \
|
|
16
|
+
--api-key ag_test_acme_demo_2026
|
|
17
|
+
|
|
18
|
+
# Open the dashboard
|
|
19
|
+
open http://localhost:3003
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Claude Desktop Configuration
|
|
23
|
+
|
|
24
|
+
Add to your Claude Desktop `mcpServers` config:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"filesystem": {
|
|
30
|
+
"url": "http://localhost:3003/sse"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Environment Variables
|
|
37
|
+
|
|
38
|
+
| Variable | Description | Default |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `JWT_SECRET` | JWT signing secret for agent auth | (none) |
|
|
41
|
+
|
|
42
|
+
## CLI Options
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
--upstream, -u Command to spawn the upstream MCP server (required)
|
|
46
|
+
--agent-id, -a Clampd agent UUID (required)
|
|
47
|
+
--gateway, -g Clampd gateway URL (default: http://localhost:8080)
|
|
48
|
+
--api-key, -k Clampd API key (default: clmpd_demo_key)
|
|
49
|
+
--port, -p Port to listen on (default: 3003)
|
|
50
|
+
--secret, -s JWT signing secret
|
|
51
|
+
--dry-run Classify but never forward to upstream
|
|
52
|
+
--verbose, -v Enable debug logging
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Architecture
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Claude Desktop / Cursor / Any MCP Client
|
|
59
|
+
|
|
|
60
|
+
| MCP protocol (SSE transport)
|
|
61
|
+
v
|
|
62
|
+
Clampd MCP Proxy (:3003)
|
|
63
|
+
|
|
|
64
|
+
+---> GET /sse -- MCP SSE endpoint (client connects here)
|
|
65
|
+
+---> GET / -- Live dashboard (blocked/allowed in real-time)
|
|
66
|
+
+---> GET /health -- Health check JSON
|
|
67
|
+
+---> GET /events -- Dashboard SSE stream (live updates)
|
|
68
|
+
|
|
|
69
|
+
| For each tool call:
|
|
70
|
+
| 1. Extract tool_name + params from MCP call_tool request
|
|
71
|
+
| 2. POST to ag-gateway /v1/proxy { tool, params, target_url }
|
|
72
|
+
| 3. If gateway says BLOCK -> return MCP error to client
|
|
73
|
+
| 4. If gateway says ALLOW -> forward to upstream MCP server
|
|
74
|
+
|
|
|
75
|
+
v
|
|
76
|
+
Upstream MCP Server (filesystem, database, github, shell, etc.)
|
|
77
|
+
(spawned as child process, communicates via stdio)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Deployment
|
|
81
|
+
|
|
82
|
+
### Docker
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
docker build -t clampd-mcp-proxy .
|
|
86
|
+
docker run -p 3003:3003 clampd-mcp-proxy \
|
|
87
|
+
--upstream "npx -y @modelcontextprotocol/server-filesystem /tmp" \
|
|
88
|
+
--gateway http://host.docker.internal:8080 \
|
|
89
|
+
--agent-id b0000001-0000-0000-0000-000000000001
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### npm global install
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm install -g @clampd/mcp-proxy
|
|
96
|
+
clampd-mcp-proxy --upstream "..." --agent-id "..."
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### npx (no install)
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx @clampd/mcp-proxy --upstream "..." --agent-id "..."
|
|
103
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live dashboard — serves an HTML page at GET / with a real-time event log
|
|
3
|
+
* of all tool calls flowing through the proxy.
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Enriched event data (classification, session flags, intent labels, encodings)
|
|
7
|
+
* - Expandable detail rows with full gateway response data
|
|
8
|
+
* - Real-time risk trend SVG sparkline chart
|
|
9
|
+
* - Session summary panel with aggregated stats
|
|
10
|
+
* - Export (Copy Report / Download JSON)
|
|
11
|
+
* - Attack Demo panel with pre-built payloads
|
|
12
|
+
* - Status filter tabs (All / Allowed / Blocked / Flagged / Errors)
|
|
13
|
+
*/
|
|
14
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
15
|
+
import type { ProxyOptions } from "./proxy.js";
|
|
16
|
+
export interface ProxyEvent {
|
|
17
|
+
timestamp: string;
|
|
18
|
+
tool: string;
|
|
19
|
+
params: string;
|
|
20
|
+
status: "allowed" | "blocked" | "flagged" | "error";
|
|
21
|
+
risk_score: number;
|
|
22
|
+
latency_ms: number;
|
|
23
|
+
reason?: string;
|
|
24
|
+
matched_rules?: string[];
|
|
25
|
+
classification?: string;
|
|
26
|
+
session_flags?: string[];
|
|
27
|
+
intent_labels?: string[];
|
|
28
|
+
encodings_detected?: string[];
|
|
29
|
+
scope_granted?: string;
|
|
30
|
+
action?: string;
|
|
31
|
+
reasoning?: string;
|
|
32
|
+
degraded_stages?: string[];
|
|
33
|
+
scan_details?: {
|
|
34
|
+
pii_found?: Array<{
|
|
35
|
+
pii_type: string;
|
|
36
|
+
count: number;
|
|
37
|
+
}>;
|
|
38
|
+
secrets_found?: Array<{
|
|
39
|
+
secret_type: string;
|
|
40
|
+
count: number;
|
|
41
|
+
}>;
|
|
42
|
+
input_risk?: number;
|
|
43
|
+
output_risk?: number;
|
|
44
|
+
};
|
|
45
|
+
descriptor_hash?: string;
|
|
46
|
+
scope_token?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface SessionStats {
|
|
49
|
+
toolCallCount: number;
|
|
50
|
+
uniqueTools: string[];
|
|
51
|
+
blockedCount: number;
|
|
52
|
+
flaggedCount: number;
|
|
53
|
+
totalRisk: number;
|
|
54
|
+
firstCallAt: string;
|
|
55
|
+
lastCallAt: string;
|
|
56
|
+
rulesTriggered: Record<string, number>;
|
|
57
|
+
piiDetected: boolean;
|
|
58
|
+
secretsDetected: boolean;
|
|
59
|
+
}
|
|
60
|
+
export declare function serveDashboard(_req: IncomingMessage, res: ServerResponse, events: ProxyEvent[], opts: ProxyOptions & {
|
|
61
|
+
demoPanel?: boolean;
|
|
62
|
+
sessionStats?: SessionStats;
|
|
63
|
+
}): void;
|
|
64
|
+
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE;QACb,SAAS,CAAC,EAAE,KAAK,CAAC;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACvD,aAAa,CAAC,EAAE,KAAK,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAmhBD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,UAAU,EAAE,EACpB,IAAI,EAAE,YAAY,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAA;CAAE,GACxE,IAAI,CAON"}
|