@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 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"}