@luutuankiet/mcp-proxy-shim 1.0.7 → 1.1.0-dev.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 +125 -24
- package/dist/core.d.ts +40 -0
- package/dist/core.js +496 -0
- package/dist/core.js.map +1 -0
- package/dist/http-server.d.ts +32 -0
- package/dist/http-server.js +238 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +10 -18
- package/dist/index.js +42 -573
- package/dist/index.js.map +1 -1
- package/dist/stdio.d.ts +6 -0
- package/dist/stdio.js +18 -0
- package/dist/stdio.js.map +1 -0
- package/package.json +8 -11
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Proxy Shim — HTTP Streamable Server Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Runs the schema-transforming MCP proxy as an HTTP Streamable server.
|
|
6
|
+
* Remote agents connect via HTTP POST/GET/DELETE to /mcp.
|
|
7
|
+
*
|
|
8
|
+
* Architecture:
|
|
9
|
+
* Remote Agent ──HTTP──▶ this server (:3000/mcp) ──HTTP──▶ mcpproxy-go (upstream)
|
|
10
|
+
*
|
|
11
|
+
* Each downstream client session gets its own MCP Server + Transport pair,
|
|
12
|
+
* but they all share a SINGLE upstream mcpproxy-go connection (module-level
|
|
13
|
+
* state in core.ts). This is efficient: one upstream session, many downstream.
|
|
14
|
+
*
|
|
15
|
+
* Environment variables:
|
|
16
|
+
* MCP_URL (required) Upstream mcpproxy-go StreamableHTTP endpoint
|
|
17
|
+
* MCP_PORT (optional) Port to listen on (default: 3000)
|
|
18
|
+
* MCP_HOST (optional) Host to bind to (default: 0.0.0.0)
|
|
19
|
+
* MCP_APIKEY (optional) API key for downstream clients. When set, requests
|
|
20
|
+
* must include ?apikey=KEY in the URL. Unset = open.
|
|
21
|
+
* https_proxy (optional) HTTPS proxy for upstream connection
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* MCP_URL="https://mcpproxy.kenluu.org/mcp/?apikey=KEY" npx @luutuankiet/mcp-proxy-shim-http
|
|
25
|
+
*
|
|
26
|
+
* Then point your MCP client at:
|
|
27
|
+
* http://localhost:3000/mcp
|
|
28
|
+
*
|
|
29
|
+
* For production, put a reverse proxy (Caddy/nginx) in front for TLS:
|
|
30
|
+
* https://shim.yourdomain.com/mcp ──▶ http://localhost:3000/mcp
|
|
31
|
+
*/
|
|
32
|
+
import { randomUUID } from "node:crypto";
|
|
33
|
+
import http from "node:http";
|
|
34
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
35
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
36
|
+
import { createShimServer, log, maskUrl, UPSTREAM_URL } from "./core.js";
|
|
37
|
+
const PORT = parseInt(process.env.MCP_PORT || "3000", 10);
|
|
38
|
+
const HOST = process.env.MCP_HOST || "0.0.0.0";
|
|
39
|
+
const APIKEY = process.env.MCP_APIKEY || null;
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Session management
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Each downstream client gets its own MCP Server + Transport pair.
|
|
44
|
+
// All of them share the SAME upstream mcpproxy-go session (module-level in core.ts).
|
|
45
|
+
const transports = new Map();
|
|
46
|
+
/**
|
|
47
|
+
* Create a new downstream session: fresh Server + Transport pair.
|
|
48
|
+
* The upstream connection is shared via core.ts module state.
|
|
49
|
+
*/
|
|
50
|
+
async function createSessionTransport() {
|
|
51
|
+
const transport = new StreamableHTTPServerTransport({
|
|
52
|
+
sessionIdGenerator: () => randomUUID(),
|
|
53
|
+
onsessioninitialized: (sessionId) => {
|
|
54
|
+
log(`HTTP session initialized: ${sessionId.slice(0, 12)}...`);
|
|
55
|
+
transports.set(sessionId, transport);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
transport.onclose = () => {
|
|
59
|
+
const sid = transport.sessionId;
|
|
60
|
+
if (sid && transports.has(sid)) {
|
|
61
|
+
log(`HTTP session closed: ${sid.slice(0, 12)}...`);
|
|
62
|
+
transports.delete(sid);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
// Each session gets its own shim server with lazy upstream init.
|
|
66
|
+
// core.ts ensures the upstream session is shared (module-level singleton).
|
|
67
|
+
const server = await createShimServer({ lazyInit: true });
|
|
68
|
+
await server.connect(transport);
|
|
69
|
+
return transport;
|
|
70
|
+
}
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// HTTP request handler
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
function parseBody(req) {
|
|
75
|
+
return new Promise((resolve) => {
|
|
76
|
+
const chunks = [];
|
|
77
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
78
|
+
req.on("end", () => {
|
|
79
|
+
try {
|
|
80
|
+
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
81
|
+
resolve(raw ? JSON.parse(raw) : null);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
resolve(null);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
req.on("error", () => resolve(null));
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async function handleMcpRequest(req, res) {
|
|
91
|
+
// CORS headers for browser-based clients
|
|
92
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
93
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
94
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Mcp-Session-Id, Last-Event-ID");
|
|
95
|
+
res.setHeader("Access-Control-Expose-Headers", "Mcp-Session-Id");
|
|
96
|
+
if (req.method === "OPTIONS") {
|
|
97
|
+
res.writeHead(204);
|
|
98
|
+
res.end();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
102
|
+
try {
|
|
103
|
+
if (req.method === "POST") {
|
|
104
|
+
const body = await parseBody(req);
|
|
105
|
+
if (sessionId && transports.has(sessionId)) {
|
|
106
|
+
// Existing session
|
|
107
|
+
const transport = transports.get(sessionId);
|
|
108
|
+
await transport.handleRequest(req, res, body);
|
|
109
|
+
}
|
|
110
|
+
else if (!sessionId && isInitializeRequest(body)) {
|
|
111
|
+
// New client — create session
|
|
112
|
+
const transport = await createSessionTransport();
|
|
113
|
+
await transport.handleRequest(req, res, body);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
117
|
+
res.end(JSON.stringify({
|
|
118
|
+
jsonrpc: "2.0",
|
|
119
|
+
error: { code: -32000, message: "Bad Request: No valid session ID provided" },
|
|
120
|
+
id: null,
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else if (req.method === "GET") {
|
|
125
|
+
// SSE stream reconnection
|
|
126
|
+
if (!sessionId || !transports.has(sessionId)) {
|
|
127
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
128
|
+
res.end("Invalid or missing session ID");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const lastEventId = req.headers["last-event-id"];
|
|
132
|
+
if (lastEventId) {
|
|
133
|
+
log(`Client reconnecting with Last-Event-ID: ${lastEventId}`);
|
|
134
|
+
}
|
|
135
|
+
const transport = transports.get(sessionId);
|
|
136
|
+
await transport.handleRequest(req, res);
|
|
137
|
+
}
|
|
138
|
+
else if (req.method === "DELETE") {
|
|
139
|
+
// Session termination
|
|
140
|
+
if (!sessionId || !transports.has(sessionId)) {
|
|
141
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
142
|
+
res.end("Invalid or missing session ID");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
log(`Session termination request: ${sessionId.slice(0, 12)}...`);
|
|
146
|
+
const transport = transports.get(sessionId);
|
|
147
|
+
await transport.handleRequest(req, res);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
res.writeHead(405, { "Content-Type": "text/plain" });
|
|
151
|
+
res.end("Method Not Allowed");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
log("HTTP handler error:", error.message);
|
|
156
|
+
if (!res.headersSent) {
|
|
157
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
158
|
+
res.end(JSON.stringify({
|
|
159
|
+
jsonrpc: "2.0",
|
|
160
|
+
error: { code: -32603, message: "Internal server error" },
|
|
161
|
+
id: null,
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// Server startup
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
async function main() {
|
|
170
|
+
log(`Starting HTTP Streamable server on ${HOST}:${PORT}`);
|
|
171
|
+
log(`Upstream: ${maskUrl(UPSTREAM_URL)}`);
|
|
172
|
+
log(`Auth: ${APIKEY ? "apikey required (?apikey=...)" : "OPEN (no MCP_APIKEY set)"}`);
|
|
173
|
+
const httpServer = http.createServer((req, res) => {
|
|
174
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
175
|
+
if (url.pathname === "/mcp" || url.pathname === "/mcp/") {
|
|
176
|
+
// Apikey gate — reject early if MCP_APIKEY is set and key doesn't match
|
|
177
|
+
if (APIKEY && url.searchParams.get("apikey") !== APIKEY) {
|
|
178
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
179
|
+
res.end(JSON.stringify({
|
|
180
|
+
jsonrpc: "2.0",
|
|
181
|
+
error: { code: -32001, message: "Unauthorized: invalid or missing apikey" },
|
|
182
|
+
id: null,
|
|
183
|
+
}));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
handleMcpRequest(req, res).catch((err) => {
|
|
187
|
+
log("Unhandled error in MCP handler:", err.message);
|
|
188
|
+
if (!res.headersSent) {
|
|
189
|
+
res.writeHead(500);
|
|
190
|
+
res.end("Internal Server Error");
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
else if (url.pathname === "/health" || url.pathname === "/healthz") {
|
|
195
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
196
|
+
res.end(JSON.stringify({
|
|
197
|
+
status: "ok",
|
|
198
|
+
sessions: transports.size,
|
|
199
|
+
uptime: process.uptime(),
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
204
|
+
res.end("Not Found — MCP endpoint is at /mcp");
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
httpServer.listen(PORT, HOST, () => {
|
|
208
|
+
log(`HTTP Streamable server listening on http://${HOST}:${PORT}/mcp`);
|
|
209
|
+
log(`Health check: http://${HOST}:${PORT}/health`);
|
|
210
|
+
log("Waiting for MCP client connections...");
|
|
211
|
+
});
|
|
212
|
+
// Graceful shutdown
|
|
213
|
+
const shutdown = async () => {
|
|
214
|
+
log("Shutting down HTTP server...");
|
|
215
|
+
for (const [sid, transport] of transports) {
|
|
216
|
+
try {
|
|
217
|
+
log(`Closing session ${sid.slice(0, 12)}...`);
|
|
218
|
+
await transport.close();
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
log(`Error closing session ${sid.slice(0, 12)}:`, err.message);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
transports.clear();
|
|
225
|
+
httpServer.close(() => {
|
|
226
|
+
log("HTTP server stopped");
|
|
227
|
+
process.exit(0);
|
|
228
|
+
});
|
|
229
|
+
setTimeout(() => process.exit(1), 5000).unref();
|
|
230
|
+
};
|
|
231
|
+
process.on("SIGINT", shutdown);
|
|
232
|
+
process.on("SIGTERM", shutdown);
|
|
233
|
+
}
|
|
234
|
+
main().catch((err) => {
|
|
235
|
+
log("Fatal:", err);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
});
|
|
238
|
+
//# sourceMappingURL=http-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,28 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* MCP
|
|
3
|
+
* MCP Proxy Shim — Unified Entry Point
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* What it does:
|
|
9
|
-
* - Passes through ALL upstream tools unchanged (retrieve_tools, upstream_servers, etc.)
|
|
10
|
-
* - Transforms call_tool_read / call_tool_write / call_tool_destructive schemas:
|
|
11
|
-
* upstream args_json:string → downstream args:object
|
|
12
|
-
* - On tool call: serializes args back to args_json before forwarding upstream
|
|
13
|
-
*
|
|
14
|
-
* Why not use SDK StreamableHTTPClientTransport:
|
|
15
|
-
* - Bug #396: 2nd callTool times out (broken session multiplexing)
|
|
16
|
-
* - We use plain fetch for upstream — reliable, simple, zero SDK client bugs
|
|
17
|
-
*
|
|
18
|
-
* Why low-level Server class (not McpServer):
|
|
19
|
-
* - Bug #893: McpServer.registerTool() breaks dynamic registration post-connect
|
|
20
|
-
* - Low-level Server.setRequestHandler() works correctly
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* (default) stdio transport — for local MCP clients (Claude Code, Cursor, etc.)
|
|
7
|
+
* serve HTTP Streamable transport — for remote agents over HTTP
|
|
21
8
|
*
|
|
22
9
|
* Usage:
|
|
10
|
+
* # Stdio mode (default)
|
|
23
11
|
* MCP_URL="https://proxy.example.com/mcp/?apikey=KEY" npx @luutuankiet/mcp-proxy-shim
|
|
24
12
|
*
|
|
25
|
-
*
|
|
13
|
+
* # HTTP server mode
|
|
14
|
+
* MCP_URL="https://proxy.example.com/mcp/?apikey=KEY" npx @luutuankiet/mcp-proxy-shim serve
|
|
15
|
+
* MCP_URL="..." MCP_PORT=8080 npx @luutuankiet/mcp-proxy-shim serve
|
|
16
|
+
*
|
|
17
|
+
* .mcp.json entry (stdio):
|
|
26
18
|
* { "mcpServers": { "proxy": { "type": "stdio", "command": "npx", "args": ["-y", "@luutuankiet/mcp-proxy-shim"], "env": { "MCP_URL": "..." } } } }
|
|
27
19
|
*/
|
|
28
20
|
export {};
|