@luutuankiet/mcp-proxy-shim 1.1.4 → 1.2.1
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/README.md +107 -100
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -2
- package/dist/index.js.map +1 -1
- package/dist/passthru.d.ts +43 -0
- package/dist/passthru.js +633 -0
- package/dist/passthru.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @luutuankiet/mcp-proxy-shim
|
|
2
2
|
|
|
3
|
-
**MCP shim for [mcpproxy-go](https://github.com/smart-mcp-proxy/mcpproxy-go)** — eliminates `args_json` string escaping overhead for LLM clients. Supports **stdio
|
|
3
|
+
**MCP shim for [mcpproxy-go](https://github.com/smart-mcp-proxy/mcpproxy-go)** — eliminates `args_json` string escaping overhead for LLM clients. Supports **stdio**, **HTTP Streamable**, **daemon**, and **passthru** modes.
|
|
4
4
|
|
|
5
5
|
## The Problem
|
|
6
6
|
|
|
@@ -197,137 +197,144 @@ Each downstream client gets its own MCP session, but all sessions **share a sing
|
|
|
197
197
|
| `/mcp` | DELETE | `?apikey=` | Session termination |
|
|
198
198
|
| `/health` | GET | None | Health check (session count, uptime) |
|
|
199
199
|
|
|
200
|
-
### Option C: Daemon Mode (
|
|
200
|
+
### Option C: Daemon Mode (REST + MCP gateway for cloud agents)
|
|
201
201
|
|
|
202
|
-
Run a
|
|
202
|
+
Run as a REST gateway that connects to a **single mcpproxy-go upstream** and exposes both REST endpoints (for curl-based subagents) and a Streamable HTTP `/mcp` endpoint (for MCP clients).
|
|
203
203
|
|
|
204
|
-
**Use case:** Cloud agents (claude.ai/code, Codespaces, etc.) that can't spawn MCP servers on the fly
|
|
204
|
+
**Use case:** Cloud agents (claude.ai/code, Codespaces, etc.) that can't spawn MCP servers on the fly, but can `curl`.
|
|
205
205
|
|
|
206
206
|
```
|
|
207
|
-
Cloud Agent ──
|
|
208
|
-
|
|
209
|
-
└── HTTP ──▶ remote API (with auth headers)
|
|
207
|
+
Cloud Agent ──curl──> daemon (:3456) ──HTTP──> mcpproxy-go (upstream)
|
|
208
|
+
<── clean JSON <──────────<── MCP response
|
|
210
209
|
```
|
|
211
210
|
|
|
212
|
-
#### Inline config
|
|
213
|
-
|
|
214
211
|
```bash
|
|
215
|
-
|
|
216
|
-
"github": {
|
|
217
|
-
"type": "stdio",
|
|
218
|
-
"command": "npx",
|
|
219
|
-
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
220
|
-
"env": { "GITHUB_TOKEN": "ghp_..." }
|
|
221
|
-
},
|
|
222
|
-
"my-api": {
|
|
223
|
-
"type": "streamableHttp",
|
|
224
|
-
"url": "https://api.example.com/mcp",
|
|
225
|
-
"headers": { "Authorization": "Bearer xxx", "X-Org-Id": "org_123" }
|
|
226
|
-
}
|
|
227
|
-
}' npx @luutuankiet/mcp-proxy-shim daemon
|
|
212
|
+
MCP_URL="https://your-proxy/mcp/?apikey=KEY" npx @luutuankiet/mcp-proxy-shim daemon
|
|
228
213
|
```
|
|
229
214
|
|
|
230
|
-
####
|
|
215
|
+
#### Daemon REST endpoints
|
|
231
216
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
217
|
+
| Endpoint | Method | Description |
|
|
218
|
+
|----------|--------|-------------|
|
|
219
|
+
| `/health` | GET | Health check + session info |
|
|
220
|
+
| `/retrieve_tools` | POST | BM25 tool search `{ query }` |
|
|
221
|
+
| `/describe_tools` | POST | Batch-hydrate full schemas `{ names: [...] }` |
|
|
222
|
+
| `/call` | POST | Execute tool `{ method, name, args }` |
|
|
223
|
+
| `/exec` | POST | Run code on upstream `{ code }` |
|
|
224
|
+
| `/reinit` | POST | Force new upstream session |
|
|
225
|
+
| `/mcp` | POST/GET/DELETE | Streamable HTTP MCP (backward compat) |
|
|
226
|
+
|
|
227
|
+
#### Daemon environment variables
|
|
228
|
+
|
|
229
|
+
| Variable | Default | Description |
|
|
230
|
+
|----------|---------|-------------|
|
|
231
|
+
| `MCP_URL` | **(required)** | mcpproxy-go StreamableHTTP endpoint |
|
|
232
|
+
| `MCP_PORT` | `3456` | Port to listen on |
|
|
233
|
+
| `MCP_HOST` | `0.0.0.0` | Host to bind to |
|
|
234
|
+
| `MCP_APIKEY` | — (open) | Require `?apikey=KEY` on requests |
|
|
235
235
|
|
|
236
|
-
|
|
237
|
-
- Flat: `{ "server-name": { "type": "stdio", ... } }`
|
|
238
|
-
- Wrapped: `{ "servers": { "server-name": { ... } } }`
|
|
239
|
-
- `.mcp.json` format: `{ "mcpServers": { "server-name": { ... } } }`
|
|
236
|
+
### Option D: Passthru Mode (generic MCP→REST bridge)
|
|
240
237
|
|
|
241
|
-
|
|
238
|
+
Connect to **any MCP server** (not just mcpproxy-go) and expose its tools as clean REST endpoints. Designed for MCP server development and testing — lets LLM agents consume any MCP server via simple `curl`.
|
|
242
239
|
|
|
243
|
-
|
|
240
|
+
**Use case:** You're building an MCP server and want Claude (or any LLM agent) to test it mid-session without restarting.
|
|
244
241
|
|
|
245
242
|
```
|
|
246
|
-
|
|
247
|
-
|
|
243
|
+
Agent ──curl──> passthru (:3456) ──stdio/HTTP──> your MCP server
|
|
244
|
+
<── clean JSON <── MCP response (unwrapped)
|
|
248
245
|
```
|
|
249
246
|
|
|
250
|
-
|
|
247
|
+
#### Stdio (spawn and manage the server process)
|
|
251
248
|
|
|
252
|
-
```
|
|
253
|
-
|
|
249
|
+
```bash
|
|
250
|
+
npx @luutuankiet/mcp-proxy-shim passthru -- npx tsx src/index.ts
|
|
251
|
+
|
|
252
|
+
# With extra env vars
|
|
253
|
+
npx @luutuankiet/mcp-proxy-shim passthru --env API_KEY=xxx -- python server.py
|
|
254
|
+
|
|
255
|
+
# With working directory
|
|
256
|
+
npx @luutuankiet/mcp-proxy-shim passthru --cwd ./my-server -- npm start
|
|
254
257
|
```
|
|
255
258
|
|
|
256
|
-
|
|
259
|
+
#### HTTP Streamable (connect to running server)
|
|
257
260
|
|
|
258
|
-
```
|
|
259
|
-
|
|
261
|
+
```bash
|
|
262
|
+
npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/mcp
|
|
263
|
+
|
|
264
|
+
# With auth headers
|
|
265
|
+
npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/mcp --header "Authorization: Bearer xxx"
|
|
260
266
|
```
|
|
261
267
|
|
|
262
|
-
|
|
268
|
+
#### SSE (legacy transport)
|
|
263
269
|
|
|
264
|
-
|
|
270
|
+
```bash
|
|
271
|
+
npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/sse --transport sse
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### Config file
|
|
265
275
|
|
|
266
|
-
|
|
276
|
+
```bash
|
|
277
|
+
npx @luutuankiet/mcp-proxy-shim passthru --config server.json
|
|
278
|
+
```
|
|
267
279
|
|
|
280
|
+
Config file formats:
|
|
268
281
|
```json
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
282
|
+
// Stdio
|
|
283
|
+
{"type": "stdio", "command": "npx", "args": ["tsx", "src/index.ts"], "env": {"API_KEY": "xxx"}}
|
|
284
|
+
|
|
285
|
+
// HTTP Streamable
|
|
286
|
+
{"type": "streamableHttp", "url": "http://localhost:3000/mcp", "headers": {"Authorization": "Bearer xxx"}}
|
|
287
|
+
|
|
288
|
+
// SSE
|
|
289
|
+
{"type": "sse", "url": "http://localhost:3000/sse", "headers": {}}
|
|
276
290
|
```
|
|
277
291
|
|
|
278
|
-
|
|
292
|
+
#### Passthru REST endpoints
|
|
293
|
+
|
|
294
|
+
| Endpoint | Method | Description | Example |
|
|
295
|
+
|----------|--------|-------------|----------|
|
|
296
|
+
| `/health` | GET | Server status + transport info | `curl localhost:3456/health` |
|
|
297
|
+
| `/tools` | GET | Dehydrated tool list (name, description snippet, param summary) | `curl localhost:3456/tools` |
|
|
298
|
+
| `/tools?q=keyword` | GET | Search tools by name/description | `curl "localhost:3456/tools?q=read"` |
|
|
299
|
+
| `/tools/:name` | GET | Full tool schema with `inputSchema` | `curl localhost:3456/tools/read_files` |
|
|
300
|
+
| `/call/:name` | POST | Invoke a tool with native JSON args | `curl -X POST localhost:3456/call/read_files -d '{"args": {"files": [...]}}'` |
|
|
301
|
+
| `/restart` | POST | Restart upstream MCP connection | `curl -X POST localhost:3456/restart` |
|
|
302
|
+
|
|
303
|
+
#### Dehydrated tool listing
|
|
304
|
+
|
|
305
|
+
The `/tools` endpoint returns token-efficient tool summaries:
|
|
279
306
|
|
|
280
307
|
```json
|
|
281
308
|
{
|
|
282
|
-
"
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
309
|
+
"tools": [
|
|
310
|
+
{
|
|
311
|
+
"name": "read_files",
|
|
312
|
+
"description": "Read the contents of multiple files simultaneously...",
|
|
313
|
+
"params": "files: object[]* | compact: boolean"
|
|
314
|
+
}
|
|
315
|
+
],
|
|
316
|
+
"count": 10,
|
|
317
|
+
"hint": "GET /tools/{name} for full inputSchema"
|
|
288
318
|
}
|
|
289
319
|
```
|
|
290
320
|
|
|
291
|
-
|
|
321
|
+
Params use `name: type` format with `*` for required fields. Use `/tools/:name` to get the full `inputSchema` when needed.
|
|
292
322
|
|
|
293
|
-
####
|
|
323
|
+
#### Token economics: passthru vs mcpproxy-go path
|
|
324
|
+
|
|
325
|
+
| Metric | Via mcpproxy-go daemon | Via passthru | Savings |
|
|
326
|
+
|--------|----------------------|--------------|--------|
|
|
327
|
+
| Round-trips to test one tool | 3 (retrieve + describe + call) | 1-2 (optional list + call) | **50-66%** |
|
|
328
|
+
| Request tokens per call | ~300 | ~50 | **83%** |
|
|
329
|
+
| Tool name length | `server_at_slash_path__tool_name` | `tool_name` (native) | **~85% shorter** |
|
|
330
|
+
| Response unwrapping | Automatic | Automatic | Same |
|
|
331
|
+
|
|
332
|
+
#### Passthru environment variables
|
|
294
333
|
|
|
295
334
|
| Variable | Default | Description |
|
|
296
335
|
|----------|---------|-------------|
|
|
297
|
-
| `MCP_SERVERS` | — | JSON string with server configs (inline) |
|
|
298
|
-
| `MCP_CONFIG` | — | Path to JSON config file (alternative to MCP_SERVERS) |
|
|
299
336
|
| `MCP_PORT` | `3456` | Port to listen on |
|
|
300
337
|
| `MCP_HOST` | `0.0.0.0` | Host to bind to |
|
|
301
|
-
| `MCP_APIKEY` | — (open) | Require `?apikey=KEY` on `/mcp` requests |
|
|
302
|
-
| `https_proxy` | — | HTTPS proxy for HTTP upstream connections |
|
|
303
|
-
|
|
304
|
-
#### Daemon endpoints
|
|
305
|
-
|
|
306
|
-
| Endpoint | Method | Description |
|
|
307
|
-
|----------|--------|-------------|
|
|
308
|
-
| `/mcp` | POST | MCP JSON-RPC (initialize, tools/list, tools/call) |
|
|
309
|
-
| `/mcp` | GET | SSE stream reconnection |
|
|
310
|
-
| `/mcp` | DELETE | Session termination |
|
|
311
|
-
| `/health` | GET | Per-server status, tool counts, uptime |
|
|
312
|
-
|
|
313
|
-
#### Production deployment
|
|
314
|
-
|
|
315
|
-
```yaml
|
|
316
|
-
# docker-compose.yml
|
|
317
|
-
services:
|
|
318
|
-
mcp-daemon:
|
|
319
|
-
image: node:22-slim
|
|
320
|
-
command: npx -y @luutuankiet/mcp-proxy-shim daemon
|
|
321
|
-
environment:
|
|
322
|
-
- MCP_CONFIG=/config/servers.json
|
|
323
|
-
- MCP_APIKEY=your-secret
|
|
324
|
-
ports:
|
|
325
|
-
- "3456:3456"
|
|
326
|
-
volumes:
|
|
327
|
-
- ./mcp-servers.json:/config/servers.json:ro
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
---
|
|
331
338
|
|
|
332
339
|
## Why Not `/mcp/all`?
|
|
333
340
|
|
|
@@ -385,15 +392,15 @@ We tested this live: added a YNAB financial tool mid-session → 43 new tools ap
|
|
|
385
392
|
|
|
386
393
|
### Transport Modes
|
|
387
394
|
|
|
388
|
-
| Feature | Stdio | HTTP Streamable (`serve`) | Daemon (`daemon`) |
|
|
389
|
-
|
|
390
|
-
| Use case | Local MCP client (Claude Code, Cursor) | Remote agents, single upstream | Cloud agents,
|
|
391
|
-
| Connection | stdin/stdout | HTTP on `/mcp` | HTTP
|
|
392
|
-
|
|
|
393
|
-
| Schema transforms | `args_json` → `args` | `args_json` → `args` | None (
|
|
394
|
-
| Auth | N/A (local process) | Optional `?apikey=` | Optional `?apikey=` |
|
|
395
|
-
| Multi-client | Single | Multiple sessions | Multiple sessions |
|
|
396
|
-
|
|
|
395
|
+
| Feature | Stdio | HTTP Streamable (`serve`) | Daemon (`daemon`) | Passthru (`passthru`) |
|
|
396
|
+
|---------|-------|--------------------------|-------------------|----------------------|
|
|
397
|
+
| Use case | Local MCP client (Claude Code, Cursor) | Remote agents, single upstream | Cloud agents, curl-based subagents | MCP server dev/testing |
|
|
398
|
+
| Connection | stdin/stdout | HTTP on `/mcp` | HTTP REST + `/mcp` | HTTP REST only |
|
|
399
|
+
| Upstream | Single (mcpproxy-go) | Single (mcpproxy-go) | Single (mcpproxy-go) | Any MCP server (stdio/HTTP/SSE) |
|
|
400
|
+
| Schema transforms | `args_json` → `args` | `args_json` → `args` | `args_json` → `args` | None (native schemas) |
|
|
401
|
+
| Auth | N/A (local process) | Optional `?apikey=` | Optional `?apikey=` | None (dev tool) |
|
|
402
|
+
| Multi-client | Single | Multiple sessions | Multiple sessions | Single |
|
|
403
|
+
| Response unwrapping | N/A | N/A | `deepUnwrapResult` | `deepUnwrapResult` |
|
|
397
404
|
|
|
398
405
|
### Session Management
|
|
399
406
|
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* (default) stdio transport — for local MCP clients (Claude Code, Cursor, etc.)
|
|
7
7
|
* serve HTTP Streamable transport — for remote agents over HTTP
|
|
8
8
|
* daemon REST + MCP gateway — single upstream via mcpproxy-go, exposes REST + /mcp
|
|
9
|
+
* passthru Generic MCP→REST bridge — connect to any MCP server for dev/testing
|
|
9
10
|
*
|
|
10
11
|
* Usage:
|
|
11
12
|
* # Stdio mode (default) — single upstream via mcpproxy-go
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* (default) stdio transport — for local MCP clients (Claude Code, Cursor, etc.)
|
|
7
7
|
* serve HTTP Streamable transport — for remote agents over HTTP
|
|
8
8
|
* daemon REST + MCP gateway — single upstream via mcpproxy-go, exposes REST + /mcp
|
|
9
|
+
* passthru Generic MCP→REST bridge — connect to any MCP server for dev/testing
|
|
9
10
|
*
|
|
10
11
|
* Usage:
|
|
11
12
|
* # Stdio mode (default) — single upstream via mcpproxy-go
|
|
@@ -53,6 +54,24 @@ if (subcommand === "--help" || subcommand === "-h") {
|
|
|
53
54
|
console.log(" POST /exec { code }");
|
|
54
55
|
console.log(" POST /reinit Force new upstream session");
|
|
55
56
|
console.log(" POST /mcp Streamable HTTP (backward compat)");
|
|
57
|
+
console.log("");
|
|
58
|
+
console.log("Passthru mode (generic MCP→REST bridge):");
|
|
59
|
+
console.log(" passthru -- <command> [args] Spawn a stdio MCP server");
|
|
60
|
+
console.log(" passthru --url <URL> Connect to HTTP Streamable server");
|
|
61
|
+
console.log(" passthru --url <URL> --transport sse Connect to SSE server");
|
|
62
|
+
console.log(" passthru --config <file> Load server config from JSON");
|
|
63
|
+
console.log("");
|
|
64
|
+
console.log("Passthru options:");
|
|
65
|
+
console.log(" --env KEY=VAL Extra env vars for stdio (repeatable)");
|
|
66
|
+
console.log(" --header K: V Extra headers for HTTP/SSE (repeatable)");
|
|
67
|
+
console.log(" --cwd <dir> Working directory for stdio server");
|
|
68
|
+
console.log("");
|
|
69
|
+
console.log("Passthru REST endpoints:");
|
|
70
|
+
console.log(" GET /health Server status + transport info");
|
|
71
|
+
console.log(" GET /tools Dehydrated tool list (?q=keyword to search)");
|
|
72
|
+
console.log(" GET /tools/:name Full tool schema with inputSchema");
|
|
73
|
+
console.log(" POST /call/:name Invoke tool. Body: {args: {...}}");
|
|
74
|
+
console.log(" POST /restart Restart upstream connection");
|
|
56
75
|
process.exit(0);
|
|
57
76
|
}
|
|
58
77
|
if (subcommand === "serve") {
|
|
@@ -63,12 +82,17 @@ else if (subcommand === "daemon") {
|
|
|
63
82
|
// Dynamic import — loads daemon mode (no core.ts dependency)
|
|
64
83
|
import("./daemon.js");
|
|
65
84
|
}
|
|
85
|
+
else if (subcommand === "passthru") {
|
|
86
|
+
// Dynamic import — generic MCP→REST bridge (no core.ts dependency)
|
|
87
|
+
import("./passthru.js");
|
|
88
|
+
}
|
|
66
89
|
else if (subcommand) {
|
|
67
90
|
console.error(`Unknown subcommand: "${subcommand}"`);
|
|
68
|
-
console.error("Usage: mcp-proxy-shim [serve|daemon]");
|
|
91
|
+
console.error("Usage: mcp-proxy-shim [serve|daemon|passthru]");
|
|
69
92
|
console.error(" (no args) stdio transport (default)");
|
|
70
93
|
console.error(" serve HTTP Streamable server");
|
|
71
|
-
console.error(" daemon
|
|
94
|
+
console.error(" daemon REST + MCP gateway (mcpproxy-go)");
|
|
95
|
+
console.error(" passthru Generic MCP→REST bridge");
|
|
72
96
|
process.exit(1);
|
|
73
97
|
}
|
|
74
98
|
else {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Proxy Shim — Passthru Mode
|
|
4
|
+
*
|
|
5
|
+
* Connects to any single MCP server (stdio, HTTP Streamable, SSE) and exposes
|
|
6
|
+
* its tools as clean REST endpoints. Designed for MCP server development
|
|
7
|
+
* and testing — lets LLM agents consume any MCP server via simple curl.
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* Agent ──curl──▶ passthru (:3456) ──MCP──▶ any MCP server
|
|
11
|
+
* ◀─ clean JSON ◀──────────◀─ MCP response
|
|
12
|
+
*
|
|
13
|
+
* REST endpoints:
|
|
14
|
+
* GET /health Server status + transport info + tool count
|
|
15
|
+
* GET /tools Dehydrated tool list (name, description snippet, param summary)
|
|
16
|
+
* GET /tools/:name Full tool schema with complete inputSchema
|
|
17
|
+
* POST /call/:name Invoke a tool with native JSON args → unwrapped result
|
|
18
|
+
* POST /restart Kill + respawn upstream, re-list tools
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* # Stdio — passthru spawns and manages the server process
|
|
22
|
+
* npx @luutuankiet/mcp-proxy-shim passthru -- npx tsx src/index.ts
|
|
23
|
+
*
|
|
24
|
+
* # Stdio with extra env vars
|
|
25
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --env API_KEY=xxx -- python server.py
|
|
26
|
+
*
|
|
27
|
+
* # HTTP Streamable — connect to running server
|
|
28
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/mcp
|
|
29
|
+
*
|
|
30
|
+
* # HTTP with auth headers
|
|
31
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/mcp --header "Authorization: Bearer xxx"
|
|
32
|
+
*
|
|
33
|
+
* # SSE (legacy transport)
|
|
34
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/sse --transport sse
|
|
35
|
+
*
|
|
36
|
+
* # From config file
|
|
37
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --config server.json
|
|
38
|
+
*
|
|
39
|
+
* Environment variables:
|
|
40
|
+
* MCP_PORT Port for REST server (default: 3456)
|
|
41
|
+
* MCP_HOST Host to bind to (default: 0.0.0.0)
|
|
42
|
+
*/
|
|
43
|
+
export declare function main(): Promise<void>;
|
package/dist/passthru.js
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Proxy Shim — Passthru Mode
|
|
4
|
+
*
|
|
5
|
+
* Connects to any single MCP server (stdio, HTTP Streamable, SSE) and exposes
|
|
6
|
+
* its tools as clean REST endpoints. Designed for MCP server development
|
|
7
|
+
* and testing — lets LLM agents consume any MCP server via simple curl.
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* Agent ──curl──▶ passthru (:3456) ──MCP──▶ any MCP server
|
|
11
|
+
* ◀─ clean JSON ◀──────────◀─ MCP response
|
|
12
|
+
*
|
|
13
|
+
* REST endpoints:
|
|
14
|
+
* GET /health Server status + transport info + tool count
|
|
15
|
+
* GET /tools Dehydrated tool list (name, description snippet, param summary)
|
|
16
|
+
* GET /tools/:name Full tool schema with complete inputSchema
|
|
17
|
+
* POST /call/:name Invoke a tool with native JSON args → unwrapped result
|
|
18
|
+
* POST /restart Kill + respawn upstream, re-list tools
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* # Stdio — passthru spawns and manages the server process
|
|
22
|
+
* npx @luutuankiet/mcp-proxy-shim passthru -- npx tsx src/index.ts
|
|
23
|
+
*
|
|
24
|
+
* # Stdio with extra env vars
|
|
25
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --env API_KEY=xxx -- python server.py
|
|
26
|
+
*
|
|
27
|
+
* # HTTP Streamable — connect to running server
|
|
28
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/mcp
|
|
29
|
+
*
|
|
30
|
+
* # HTTP with auth headers
|
|
31
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/mcp --header "Authorization: Bearer xxx"
|
|
32
|
+
*
|
|
33
|
+
* # SSE (legacy transport)
|
|
34
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --url http://localhost:3000/sse --transport sse
|
|
35
|
+
*
|
|
36
|
+
* # From config file
|
|
37
|
+
* npx @luutuankiet/mcp-proxy-shim passthru --config server.json
|
|
38
|
+
*
|
|
39
|
+
* Environment variables:
|
|
40
|
+
* MCP_PORT Port for REST server (default: 3456)
|
|
41
|
+
* MCP_HOST Host to bind to (default: 0.0.0.0)
|
|
42
|
+
*/
|
|
43
|
+
import http from "node:http";
|
|
44
|
+
import { readFileSync } from "node:fs";
|
|
45
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
46
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
47
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
48
|
+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
49
|
+
// ── Raw fetch for HTTP tool calls (workaround for SDK #396) ────────
|
|
50
|
+
// The SDK's StreamableHTTPClientTransport has broken session multiplexing
|
|
51
|
+
// that causes 2nd+ callTool to hang. For HTTP/SSE upstreams, we use the
|
|
52
|
+
// SDK only for initialize + tools/list, then raw fetch for tools/call.
|
|
53
|
+
// Stdio transport is unaffected — uses SDK client directly.
|
|
54
|
+
import { createRequire } from "node:module";
|
|
55
|
+
const _require = createRequire(import.meta.url);
|
|
56
|
+
const { ProxyAgent } = _require("undici");
|
|
57
|
+
const PROXY_URL = process.env.https_proxy || process.env.HTTPS_PROXY || "";
|
|
58
|
+
const proxyDispatcher = PROXY_URL ? new ProxyAgent(PROXY_URL) : undefined;
|
|
59
|
+
let httpSessionId = null;
|
|
60
|
+
let httpReqId = 0;
|
|
61
|
+
async function rawMcpRequest(url, method, params, headers) {
|
|
62
|
+
const body = {
|
|
63
|
+
jsonrpc: "2.0",
|
|
64
|
+
method,
|
|
65
|
+
params,
|
|
66
|
+
id: ++httpReqId,
|
|
67
|
+
};
|
|
68
|
+
const reqHeaders = {
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
Accept: "application/json, text/event-stream",
|
|
71
|
+
...(headers || {}),
|
|
72
|
+
};
|
|
73
|
+
if (httpSessionId) {
|
|
74
|
+
reqHeaders["Mcp-Session-Id"] = httpSessionId;
|
|
75
|
+
}
|
|
76
|
+
const fetchOpts = {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: reqHeaders,
|
|
79
|
+
body: JSON.stringify(body),
|
|
80
|
+
signal: AbortSignal.timeout(120_000),
|
|
81
|
+
};
|
|
82
|
+
if (proxyDispatcher) {
|
|
83
|
+
fetchOpts.dispatcher = proxyDispatcher;
|
|
84
|
+
}
|
|
85
|
+
const resp = await fetch(url, fetchOpts);
|
|
86
|
+
const sid = resp.headers.get("mcp-session-id");
|
|
87
|
+
if (sid)
|
|
88
|
+
httpSessionId = sid;
|
|
89
|
+
if (!resp.ok) {
|
|
90
|
+
const text = await resp.text();
|
|
91
|
+
throw new Error(`HTTP ${resp.status}: ${text.slice(0, 500)}`);
|
|
92
|
+
}
|
|
93
|
+
const contentType = resp.headers.get("content-type") || "";
|
|
94
|
+
if (contentType.includes("text/event-stream")) {
|
|
95
|
+
// Stream-parse SSE events — the stream may never close (SDK #396),
|
|
96
|
+
// so we read events incrementally and resolve on first JSON-RPC response.
|
|
97
|
+
const reader = resp.body.getReader();
|
|
98
|
+
const decoder = new TextDecoder();
|
|
99
|
+
let buffer = "";
|
|
100
|
+
try {
|
|
101
|
+
while (true) {
|
|
102
|
+
const { value, done } = await reader.read();
|
|
103
|
+
if (done)
|
|
104
|
+
break;
|
|
105
|
+
buffer += decoder.decode(value, { stream: true });
|
|
106
|
+
// Process complete SSE events (terminated by double newline)
|
|
107
|
+
const events = buffer.split("\n\n");
|
|
108
|
+
buffer = events.pop() || ""; // Keep incomplete event in buffer
|
|
109
|
+
for (const event of events) {
|
|
110
|
+
for (const line of event.split("\n")) {
|
|
111
|
+
if (line.startsWith("data: ")) {
|
|
112
|
+
const data = line.slice(6);
|
|
113
|
+
try {
|
|
114
|
+
const parsed = JSON.parse(data);
|
|
115
|
+
// Got a JSON-RPC response — cancel stream and return
|
|
116
|
+
reader.cancel().catch(() => { });
|
|
117
|
+
return parsed;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Not JSON, continue
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
reader.cancel().catch(() => { });
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
throw new Error("SSE stream ended without JSON-RPC response");
|
|
132
|
+
}
|
|
133
|
+
return (await resp.json());
|
|
134
|
+
}
|
|
135
|
+
// ── Logging ────────────────────────────────────────────────────────
|
|
136
|
+
function log(...args) {
|
|
137
|
+
console.error("[passthru]", ...args);
|
|
138
|
+
}
|
|
139
|
+
// ── Response unwrapping (salvaged from core.ts) ────────────────────
|
|
140
|
+
// Duplicated here intentionally to avoid importing core.ts which
|
|
141
|
+
// requires MCP_URL at module load time. Zero regression risk.
|
|
142
|
+
function isMcpContentWrapper(obj) {
|
|
143
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj))
|
|
144
|
+
return false;
|
|
145
|
+
const o = obj;
|
|
146
|
+
if (!Array.isArray(o.content) || o.content.length === 0)
|
|
147
|
+
return false;
|
|
148
|
+
const first = o.content[0];
|
|
149
|
+
return first?.type === "text" && typeof first?.text === "string";
|
|
150
|
+
}
|
|
151
|
+
function deepParseText(text, maxDepth = 5) {
|
|
152
|
+
let value = text;
|
|
153
|
+
let depth = 0;
|
|
154
|
+
while (typeof value === "string" && depth < maxDepth) {
|
|
155
|
+
try {
|
|
156
|
+
const parsed = JSON.parse(value);
|
|
157
|
+
if (isMcpContentWrapper(parsed)) {
|
|
158
|
+
if (parsed.content.length === 1) {
|
|
159
|
+
value = parsed.content[0].text;
|
|
160
|
+
depth++;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
return parsed.content.map((c) => c.type === "text" ? deepParseText(c.text, maxDepth - depth - 1) : c);
|
|
164
|
+
}
|
|
165
|
+
return parsed;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
function deepUnwrapResult(result) {
|
|
174
|
+
if (!isMcpContentWrapper(result))
|
|
175
|
+
return result;
|
|
176
|
+
if (result.content.length === 1) {
|
|
177
|
+
return deepParseText(result.content[0].text);
|
|
178
|
+
}
|
|
179
|
+
return result.content.map((c) => c.type === "text" ? deepParseText(c.text) : c);
|
|
180
|
+
}
|
|
181
|
+
// ── CLI Parsing ────────────────────────────────────────────────────
|
|
182
|
+
function parseArgs() {
|
|
183
|
+
const args = process.argv.slice(3); // skip node, script, "passthru"
|
|
184
|
+
// Check for --config file
|
|
185
|
+
const configIdx = args.indexOf("--config");
|
|
186
|
+
if (configIdx !== -1 && args[configIdx + 1]) {
|
|
187
|
+
const configPath = args[configIdx + 1];
|
|
188
|
+
try {
|
|
189
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
190
|
+
return JSON.parse(raw);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
log("Failed to read config:", err.message);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Check for --url (HTTP/SSE mode)
|
|
198
|
+
const urlIdx = args.indexOf("--url");
|
|
199
|
+
if (urlIdx !== -1 && args[urlIdx + 1]) {
|
|
200
|
+
const url = args[urlIdx + 1];
|
|
201
|
+
// Parse --transport (default: streamableHttp)
|
|
202
|
+
const transportIdx = args.indexOf("--transport");
|
|
203
|
+
const transport = transportIdx !== -1 && args[transportIdx + 1] === "sse"
|
|
204
|
+
? "sse"
|
|
205
|
+
: "streamableHttp";
|
|
206
|
+
// Parse --header flags (repeatable)
|
|
207
|
+
const headers = {};
|
|
208
|
+
for (let i = 0; i < args.length; i++) {
|
|
209
|
+
if (args[i] === "--header" && args[i + 1]) {
|
|
210
|
+
const colonIdx = args[i + 1].indexOf(":");
|
|
211
|
+
if (colonIdx > 0) {
|
|
212
|
+
const key = args[i + 1].slice(0, colonIdx).trim();
|
|
213
|
+
const val = args[i + 1].slice(colonIdx + 1).trim();
|
|
214
|
+
headers[key] = val;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
type: transport,
|
|
220
|
+
url,
|
|
221
|
+
...(Object.keys(headers).length > 0 ? { headers } : {}),
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
// Check for -- (stdio mode: everything after -- is the command)
|
|
225
|
+
const dashDashIdx = args.indexOf("--");
|
|
226
|
+
if (dashDashIdx !== -1) {
|
|
227
|
+
const cmdArgs = args.slice(dashDashIdx + 1);
|
|
228
|
+
if (cmdArgs.length === 0) {
|
|
229
|
+
log("Error: no command specified after --");
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
// Parse --env flags (before the --)
|
|
233
|
+
const env = {};
|
|
234
|
+
for (let i = 0; i < dashDashIdx; i++) {
|
|
235
|
+
if (args[i] === "--env" && args[i + 1]) {
|
|
236
|
+
const eqIdx = args[i + 1].indexOf("=");
|
|
237
|
+
if (eqIdx > 0) {
|
|
238
|
+
env[args[i + 1].slice(0, eqIdx)] = args[i + 1].slice(eqIdx + 1);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Parse --cwd
|
|
243
|
+
const cwdIdx = args.indexOf("--cwd");
|
|
244
|
+
const cwd = cwdIdx !== -1 && cwdIdx < dashDashIdx ? args[cwdIdx + 1] : undefined;
|
|
245
|
+
return {
|
|
246
|
+
type: "stdio",
|
|
247
|
+
command: cmdArgs[0],
|
|
248
|
+
args: cmdArgs.slice(1),
|
|
249
|
+
...(Object.keys(env).length > 0 ? { env } : {}),
|
|
250
|
+
...(cwd ? { cwd } : {}),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
log("Error: specify either --url <URL>, --config <file>, or -- <command>");
|
|
254
|
+
log("");
|
|
255
|
+
log("Examples:");
|
|
256
|
+
log(" passthru -- npx tsx src/index.ts");
|
|
257
|
+
log(" passthru --url http://localhost:3000/mcp");
|
|
258
|
+
log(" passthru --config server.json");
|
|
259
|
+
process.exit(1);
|
|
260
|
+
}
|
|
261
|
+
function createTransport(config) {
|
|
262
|
+
if (config.type === "stdio") {
|
|
263
|
+
log(`Stdio: ${config.command} ${(config.args || []).join(" ")}`);
|
|
264
|
+
return new StdioClientTransport({
|
|
265
|
+
command: config.command,
|
|
266
|
+
args: config.args || [],
|
|
267
|
+
env: { ...process.env, ...(config.env || {}) },
|
|
268
|
+
stderr: "pipe",
|
|
269
|
+
...(config.cwd ? { cwd: config.cwd } : {}),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
if (config.type === "sse") {
|
|
273
|
+
log(`SSE: ${config.url}`);
|
|
274
|
+
return new SSEClientTransport(new URL(config.url), config.headers
|
|
275
|
+
? { requestInit: { headers: config.headers } }
|
|
276
|
+
: undefined);
|
|
277
|
+
}
|
|
278
|
+
// Default: streamableHttp
|
|
279
|
+
log(`HTTP Streamable: ${config.url}`);
|
|
280
|
+
return new StreamableHTTPClientTransport(new URL(config.url), config.headers
|
|
281
|
+
? { requestInit: { headers: config.headers } }
|
|
282
|
+
: undefined);
|
|
283
|
+
}
|
|
284
|
+
// ── MCP Client Management ──────────────────────────────────────────
|
|
285
|
+
let client = null;
|
|
286
|
+
let transport = null;
|
|
287
|
+
let toolIndex = new Map();
|
|
288
|
+
let serverConfig;
|
|
289
|
+
let connectTime = 0;
|
|
290
|
+
let useRawFetch = false;
|
|
291
|
+
let httpUrl = null;
|
|
292
|
+
let httpHeaders = {};
|
|
293
|
+
async function connectServer(config) {
|
|
294
|
+
transport = createTransport(config);
|
|
295
|
+
// Pipe stderr for stdio servers (helpful for debugging)
|
|
296
|
+
if (transport instanceof StdioClientTransport && transport.stderr) {
|
|
297
|
+
transport.stderr.on("data", (chunk) => {
|
|
298
|
+
process.stderr.write(`[upstream] ${chunk}`);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
client = new Client({ name: "mcp-passthru", version: "1.0.0" }, { capabilities: {} });
|
|
302
|
+
// For HTTP/SSE transports, track URL for raw fetch workaround (SDK #396)
|
|
303
|
+
if (config.type !== "stdio") {
|
|
304
|
+
useRawFetch = true;
|
|
305
|
+
httpUrl = config.url;
|
|
306
|
+
httpHeaders = config.headers || {};
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
useRawFetch = false;
|
|
310
|
+
httpUrl = null;
|
|
311
|
+
httpHeaders = {};
|
|
312
|
+
}
|
|
313
|
+
log("Connecting to upstream MCP server...");
|
|
314
|
+
await client.connect(transport);
|
|
315
|
+
connectTime = Date.now();
|
|
316
|
+
// Capture session ID from transport for raw fetch
|
|
317
|
+
if (useRawFetch && transport instanceof StreamableHTTPClientTransport) {
|
|
318
|
+
httpSessionId = transport.sessionId || null;
|
|
319
|
+
}
|
|
320
|
+
log("Connected. Listing tools...");
|
|
321
|
+
await refreshTools();
|
|
322
|
+
}
|
|
323
|
+
async function refreshTools() {
|
|
324
|
+
if (!client)
|
|
325
|
+
throw new Error("Not connected");
|
|
326
|
+
const { tools } = await client.listTools();
|
|
327
|
+
toolIndex = new Map();
|
|
328
|
+
for (const tool of tools) {
|
|
329
|
+
toolIndex.set(tool.name, tool);
|
|
330
|
+
}
|
|
331
|
+
log(`Indexed ${toolIndex.size} tools`);
|
|
332
|
+
}
|
|
333
|
+
async function disconnectServer() {
|
|
334
|
+
if (client) {
|
|
335
|
+
try {
|
|
336
|
+
await client.close();
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
log("Close error:", err.message);
|
|
340
|
+
}
|
|
341
|
+
client = null;
|
|
342
|
+
}
|
|
343
|
+
if (transport) {
|
|
344
|
+
try {
|
|
345
|
+
await transport.close();
|
|
346
|
+
}
|
|
347
|
+
catch (err) {
|
|
348
|
+
log("Transport close error:", err.message);
|
|
349
|
+
}
|
|
350
|
+
transport = null;
|
|
351
|
+
}
|
|
352
|
+
toolIndex.clear();
|
|
353
|
+
}
|
|
354
|
+
// ── Tool Dehydration ───────────────────────────────────────────────
|
|
355
|
+
function dehydrateTool(tool) {
|
|
356
|
+
const desc = tool.description || "";
|
|
357
|
+
const truncDesc = desc.length > 120 ? desc.slice(0, 120) + "..." : desc;
|
|
358
|
+
// Build compact param summary: "name: type*" where * = required
|
|
359
|
+
let params = "";
|
|
360
|
+
if (tool.inputSchema?.properties) {
|
|
361
|
+
const required = new Set(tool.inputSchema.required || []);
|
|
362
|
+
const parts = [];
|
|
363
|
+
for (const [name, schema] of Object.entries(tool.inputSchema.properties)) {
|
|
364
|
+
const s = schema;
|
|
365
|
+
let typeStr = s.type || "any";
|
|
366
|
+
if (typeStr === "array" && s.items) {
|
|
367
|
+
const itemType = s.items.type || "any";
|
|
368
|
+
typeStr = `${itemType}[]`;
|
|
369
|
+
}
|
|
370
|
+
parts.push(`${name}: ${typeStr}${required.has(name) ? "*" : ""}`);
|
|
371
|
+
}
|
|
372
|
+
params = parts.join(" | ");
|
|
373
|
+
}
|
|
374
|
+
return { name: tool.name, description: truncDesc, params };
|
|
375
|
+
}
|
|
376
|
+
function searchTools(query) {
|
|
377
|
+
const tools = Array.from(toolIndex.values());
|
|
378
|
+
if (!query)
|
|
379
|
+
return tools.map(dehydrateTool);
|
|
380
|
+
const q = query.toLowerCase();
|
|
381
|
+
return tools
|
|
382
|
+
.filter((t) => {
|
|
383
|
+
const nameMatch = t.name.toLowerCase().includes(q);
|
|
384
|
+
const descMatch = (t.description || "").toLowerCase().includes(q);
|
|
385
|
+
return nameMatch || descMatch;
|
|
386
|
+
})
|
|
387
|
+
.map(dehydrateTool);
|
|
388
|
+
}
|
|
389
|
+
// ── HTTP Helpers ───────────────────────────────────────────────────
|
|
390
|
+
function parseBody(req) {
|
|
391
|
+
return new Promise((resolve) => {
|
|
392
|
+
const chunks = [];
|
|
393
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
394
|
+
req.on("end", () => {
|
|
395
|
+
try {
|
|
396
|
+
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
397
|
+
resolve(raw ? JSON.parse(raw) : {});
|
|
398
|
+
}
|
|
399
|
+
catch {
|
|
400
|
+
resolve({});
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
req.on("error", () => resolve({}));
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
function jsonResponse(res, status, body, req) {
|
|
407
|
+
// Format control via query param: ?pretty (default) or ?compact
|
|
408
|
+
// Agents that want minimal tokens use ?compact, humans get pretty by default
|
|
409
|
+
let indent = 2;
|
|
410
|
+
if (req) {
|
|
411
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
412
|
+
if (url.searchParams.has("compact"))
|
|
413
|
+
indent = undefined;
|
|
414
|
+
if (url.searchParams.get("pretty") === "false")
|
|
415
|
+
indent = undefined;
|
|
416
|
+
}
|
|
417
|
+
res.writeHead(status, {
|
|
418
|
+
"Content-Type": "application/json",
|
|
419
|
+
"Access-Control-Allow-Origin": "*",
|
|
420
|
+
});
|
|
421
|
+
res.end(JSON.stringify(body, null, indent));
|
|
422
|
+
}
|
|
423
|
+
function extractToolName(pathname, prefix) {
|
|
424
|
+
return decodeURIComponent(pathname.slice(prefix.length));
|
|
425
|
+
}
|
|
426
|
+
// ── Route Handlers ─────────────────────────────────────────────────
|
|
427
|
+
const startTime = Date.now();
|
|
428
|
+
let callCount = 0;
|
|
429
|
+
async function handleHealth(req, res) {
|
|
430
|
+
const transportType = serverConfig.type;
|
|
431
|
+
let target = serverConfig.type === "stdio"
|
|
432
|
+
? `${serverConfig.command} ${(serverConfig.args || []).join(" ")}`
|
|
433
|
+
: serverConfig.url;
|
|
434
|
+
// Mask credentials in URL (e.g., ?apikey=xxx → ?apikey=***)
|
|
435
|
+
target = target.replace(/apikey=[^&\s]+/gi, "apikey=***")
|
|
436
|
+
.replace(/token=[^&\s]+/gi, "token=***")
|
|
437
|
+
.replace(/\/\/([^:]+):[^@]+@/g, "//$1:***@");
|
|
438
|
+
jsonResponse(res, 200, {
|
|
439
|
+
ok: !!client,
|
|
440
|
+
transport: transportType,
|
|
441
|
+
target,
|
|
442
|
+
tools_count: toolIndex.size,
|
|
443
|
+
uptime: Math.round((Date.now() - startTime) / 1000),
|
|
444
|
+
connected_for: client ? Math.round((Date.now() - connectTime) / 1000) : null,
|
|
445
|
+
callCount,
|
|
446
|
+
}, req);
|
|
447
|
+
}
|
|
448
|
+
async function handleListTools(req, res) {
|
|
449
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
450
|
+
const query = url.searchParams.get("q") || undefined;
|
|
451
|
+
const tools = searchTools(query);
|
|
452
|
+
jsonResponse(res, 200, {
|
|
453
|
+
tools,
|
|
454
|
+
count: tools.length,
|
|
455
|
+
total: toolIndex.size,
|
|
456
|
+
...(query ? { query } : {}),
|
|
457
|
+
hint: "GET /tools/{name} for full inputSchema",
|
|
458
|
+
}, req);
|
|
459
|
+
}
|
|
460
|
+
async function handleGetTool(_req, res, toolName) {
|
|
461
|
+
const tool = toolIndex.get(toolName);
|
|
462
|
+
if (!tool) {
|
|
463
|
+
return jsonResponse(res, 404, {
|
|
464
|
+
error: `Tool not found: ${toolName}`,
|
|
465
|
+
available: Array.from(toolIndex.keys()),
|
|
466
|
+
}, _req);
|
|
467
|
+
}
|
|
468
|
+
jsonResponse(res, 200, tool, _req);
|
|
469
|
+
}
|
|
470
|
+
async function handleCallTool(req, res, toolName) {
|
|
471
|
+
if (!client) {
|
|
472
|
+
return jsonResponse(res, 503, { error: "Not connected to upstream server" });
|
|
473
|
+
}
|
|
474
|
+
const tool = toolIndex.get(toolName);
|
|
475
|
+
if (!tool) {
|
|
476
|
+
return jsonResponse(res, 404, {
|
|
477
|
+
error: `Tool not found: ${toolName}`,
|
|
478
|
+
available: Array.from(toolIndex.keys()),
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
const body = await parseBody(req);
|
|
482
|
+
const args = (body.args || body);
|
|
483
|
+
// If body has a top-level "args" key, use that; otherwise treat entire body as args
|
|
484
|
+
const toolArgs = body.args ? body.args : args;
|
|
485
|
+
try {
|
|
486
|
+
callCount++;
|
|
487
|
+
let result;
|
|
488
|
+
if (useRawFetch && httpUrl) {
|
|
489
|
+
// Raw fetch workaround for SDK #396 (StreamableHTTPClientTransport
|
|
490
|
+
// hangs on 2nd+ callTool due to broken session multiplexing)
|
|
491
|
+
const resp = await rawMcpRequest(httpUrl, "tools/call", {
|
|
492
|
+
name: toolName,
|
|
493
|
+
arguments: toolArgs,
|
|
494
|
+
}, httpHeaders);
|
|
495
|
+
if (!resp) {
|
|
496
|
+
return jsonResponse(res, 502, { error: "No response from upstream" });
|
|
497
|
+
}
|
|
498
|
+
if (resp.error) {
|
|
499
|
+
return jsonResponse(res, 502, {
|
|
500
|
+
error: "upstream error",
|
|
501
|
+
detail: resp.error,
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
result = resp.result ?? resp;
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
// Stdio transport — SDK client works fine
|
|
508
|
+
result = await client.callTool({
|
|
509
|
+
name: toolName,
|
|
510
|
+
arguments: toolArgs,
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
const unwrapped = deepUnwrapResult(result);
|
|
514
|
+
// Check if the upstream reported an error
|
|
515
|
+
const isError = result?.isError === true;
|
|
516
|
+
jsonResponse(res, isError ? 422 : 200, unwrapped, req);
|
|
517
|
+
}
|
|
518
|
+
catch (err) {
|
|
519
|
+
jsonResponse(res, 500, {
|
|
520
|
+
error: "Tool call failed",
|
|
521
|
+
detail: err.message,
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
async function handleRestart(_req, res) {
|
|
526
|
+
try {
|
|
527
|
+
log("Restarting upstream connection...");
|
|
528
|
+
await disconnectServer();
|
|
529
|
+
await connectServer(serverConfig);
|
|
530
|
+
jsonResponse(res, 200, {
|
|
531
|
+
ok: true,
|
|
532
|
+
tools_count: toolIndex.size,
|
|
533
|
+
tools: Array.from(toolIndex.keys()),
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
catch (err) {
|
|
537
|
+
jsonResponse(res, 500, {
|
|
538
|
+
ok: false,
|
|
539
|
+
error: err.message,
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
// ── Main ───────────────────────────────────────────────────────────
|
|
544
|
+
const PORT = parseInt(process.env.MCP_PORT || "3456", 10);
|
|
545
|
+
const HOST = process.env.MCP_HOST || "0.0.0.0";
|
|
546
|
+
export async function main() {
|
|
547
|
+
serverConfig = parseArgs();
|
|
548
|
+
log("Starting passthru mode...");
|
|
549
|
+
log(`Transport: ${serverConfig.type}`);
|
|
550
|
+
try {
|
|
551
|
+
await connectServer(serverConfig);
|
|
552
|
+
}
|
|
553
|
+
catch (err) {
|
|
554
|
+
log("Failed to connect:", err.message);
|
|
555
|
+
log("Server will start anyway — use POST /restart to retry");
|
|
556
|
+
}
|
|
557
|
+
const httpServer = http.createServer((req, res) => {
|
|
558
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
559
|
+
const pathname = url.pathname;
|
|
560
|
+
// CORS preflight
|
|
561
|
+
if (req.method === "OPTIONS") {
|
|
562
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
563
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
564
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
565
|
+
res.writeHead(204);
|
|
566
|
+
res.end();
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
const handler = async () => {
|
|
570
|
+
// GET /health
|
|
571
|
+
if ((pathname === "/health" || pathname === "/healthz") && req.method === "GET") {
|
|
572
|
+
return handleHealth(req, res);
|
|
573
|
+
}
|
|
574
|
+
// GET /tools
|
|
575
|
+
if (pathname === "/tools" && req.method === "GET") {
|
|
576
|
+
return handleListTools(req, res);
|
|
577
|
+
}
|
|
578
|
+
// GET /tools/:name
|
|
579
|
+
if (pathname.startsWith("/tools/") && req.method === "GET") {
|
|
580
|
+
const toolName = extractToolName(pathname, "/tools/");
|
|
581
|
+
return handleGetTool(req, res, toolName);
|
|
582
|
+
}
|
|
583
|
+
// POST /call/:name
|
|
584
|
+
if (pathname.startsWith("/call/") && req.method === "POST") {
|
|
585
|
+
const toolName = extractToolName(pathname, "/call/");
|
|
586
|
+
return handleCallTool(req, res, toolName);
|
|
587
|
+
}
|
|
588
|
+
// POST /restart
|
|
589
|
+
if (pathname === "/restart" && req.method === "POST") {
|
|
590
|
+
return handleRestart(req, res);
|
|
591
|
+
}
|
|
592
|
+
jsonResponse(res, 404, {
|
|
593
|
+
error: "Not Found",
|
|
594
|
+
endpoints: {
|
|
595
|
+
"GET /health": "Server status",
|
|
596
|
+
"GET /tools": "List tools (dehydrated). ?q=keyword to search",
|
|
597
|
+
"GET /tools/:name": "Full tool schema",
|
|
598
|
+
"POST /call/:name": "Invoke tool. Body: {args: {...}}",
|
|
599
|
+
"POST /restart": "Restart upstream connection",
|
|
600
|
+
},
|
|
601
|
+
});
|
|
602
|
+
};
|
|
603
|
+
handler().catch((err) => {
|
|
604
|
+
log("Unhandled error:", err.message);
|
|
605
|
+
if (!res.headersSent) {
|
|
606
|
+
jsonResponse(res, 500, { error: "Internal Server Error" });
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
httpServer.listen(PORT, HOST, () => {
|
|
611
|
+
log(`Passthru listening on http://${HOST}:${PORT}`);
|
|
612
|
+
log("Endpoints: /health, /tools, /tools/:name, /call/:name, /restart");
|
|
613
|
+
if (toolIndex.size > 0) {
|
|
614
|
+
log(`Tools available: ${Array.from(toolIndex.keys()).join(", ")}`);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
const shutdown = async () => {
|
|
618
|
+
log("Shutting down...");
|
|
619
|
+
await disconnectServer();
|
|
620
|
+
httpServer.close(() => {
|
|
621
|
+
log("Stopped");
|
|
622
|
+
process.exit(0);
|
|
623
|
+
});
|
|
624
|
+
setTimeout(() => process.exit(1), 5000).unref();
|
|
625
|
+
};
|
|
626
|
+
process.on("SIGINT", shutdown);
|
|
627
|
+
process.on("SIGTERM", shutdown);
|
|
628
|
+
}
|
|
629
|
+
main().catch((err) => {
|
|
630
|
+
log("Fatal:", err);
|
|
631
|
+
process.exit(1);
|
|
632
|
+
});
|
|
633
|
+
//# sourceMappingURL=passthru.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passthru.js","sourceRoot":"","sources":["../src/passthru.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luutuankiet/mcp-proxy-shim",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "MCP proxy shim for mcpproxy-go — transforms call_tool_* args_json:string to native args:object. Supports stdio and HTTP Streamable transports.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|