mcp-proxy 5.5.4 → 5.5.6
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/dist/bin/mcp-proxy.d.ts +1 -0
- package/dist/bin/mcp-proxy.js +5173 -358
- package/dist/bin/mcp-proxy.js.map +1 -1
- package/dist/index.d.ts +100 -74
- package/dist/index.js +1843 -112
- package/dist/index.js.map +1 -1
- package/dist/stdio-CQWnvum1.js +21424 -0
- package/dist/stdio-CQWnvum1.js.map +1 -0
- package/jsr.json +1 -1
- package/package.json +11 -13
- package/src/InMemoryEventStore.test.ts +160 -0
- package/src/InMemoryEventStore.ts +1 -1
- package/dist/chunk-JCZNH6HS.js +0 -535
- package/dist/chunk-JCZNH6HS.js.map +0 -1
package/dist/chunk-JCZNH6HS.js
DELETED
|
@@ -1,535 +0,0 @@
|
|
|
1
|
-
// src/InMemoryEventStore.ts
|
|
2
|
-
var InMemoryEventStore = class {
|
|
3
|
-
events = /* @__PURE__ */ new Map();
|
|
4
|
-
/**
|
|
5
|
-
* Replays events that occurred after a specific event ID
|
|
6
|
-
* Implements EventStore.replayEventsAfter
|
|
7
|
-
*/
|
|
8
|
-
async replayEventsAfter(lastEventId, {
|
|
9
|
-
send
|
|
10
|
-
}) {
|
|
11
|
-
if (!lastEventId || !this.events.has(lastEventId)) {
|
|
12
|
-
return "";
|
|
13
|
-
}
|
|
14
|
-
const streamId = this.getStreamIdFromEventId(lastEventId);
|
|
15
|
-
if (!streamId) {
|
|
16
|
-
return "";
|
|
17
|
-
}
|
|
18
|
-
let foundLastEvent = false;
|
|
19
|
-
const sortedEvents = [...this.events.entries()].sort(
|
|
20
|
-
(a, b) => a[0].localeCompare(b[0])
|
|
21
|
-
);
|
|
22
|
-
for (const [
|
|
23
|
-
eventId,
|
|
24
|
-
{ message, streamId: eventStreamId }
|
|
25
|
-
] of sortedEvents) {
|
|
26
|
-
if (eventStreamId !== streamId) {
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
if (eventId === lastEventId) {
|
|
30
|
-
foundLastEvent = true;
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
if (foundLastEvent) {
|
|
34
|
-
await send(eventId, message);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return streamId;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Stores an event with a generated event ID
|
|
41
|
-
* Implements EventStore.storeEvent
|
|
42
|
-
*/
|
|
43
|
-
async storeEvent(streamId, message) {
|
|
44
|
-
const eventId = this.generateEventId(streamId);
|
|
45
|
-
this.events.set(eventId, { message, streamId });
|
|
46
|
-
return eventId;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Generates a unique event ID for a given stream ID
|
|
50
|
-
*/
|
|
51
|
-
generateEventId(streamId) {
|
|
52
|
-
return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Extracts the stream ID from an event ID
|
|
56
|
-
*/
|
|
57
|
-
getStreamIdFromEventId(eventId) {
|
|
58
|
-
const parts = eventId.split("_");
|
|
59
|
-
return parts.length > 0 ? parts[0] : "";
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// src/proxyServer.ts
|
|
64
|
-
import {
|
|
65
|
-
CallToolRequestSchema,
|
|
66
|
-
CompleteRequestSchema,
|
|
67
|
-
GetPromptRequestSchema,
|
|
68
|
-
ListPromptsRequestSchema,
|
|
69
|
-
ListResourcesRequestSchema,
|
|
70
|
-
ListResourceTemplatesRequestSchema,
|
|
71
|
-
ListToolsRequestSchema,
|
|
72
|
-
LoggingMessageNotificationSchema,
|
|
73
|
-
ReadResourceRequestSchema,
|
|
74
|
-
ResourceUpdatedNotificationSchema,
|
|
75
|
-
SubscribeRequestSchema,
|
|
76
|
-
UnsubscribeRequestSchema
|
|
77
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
78
|
-
var proxyServer = async ({
|
|
79
|
-
client,
|
|
80
|
-
server,
|
|
81
|
-
serverCapabilities
|
|
82
|
-
}) => {
|
|
83
|
-
if (serverCapabilities?.logging) {
|
|
84
|
-
server.setNotificationHandler(
|
|
85
|
-
LoggingMessageNotificationSchema,
|
|
86
|
-
async (args) => {
|
|
87
|
-
return client.notification(args);
|
|
88
|
-
}
|
|
89
|
-
);
|
|
90
|
-
client.setNotificationHandler(
|
|
91
|
-
LoggingMessageNotificationSchema,
|
|
92
|
-
async (args) => {
|
|
93
|
-
return server.notification(args);
|
|
94
|
-
}
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
if (serverCapabilities?.prompts) {
|
|
98
|
-
server.setRequestHandler(GetPromptRequestSchema, async (args) => {
|
|
99
|
-
return client.getPrompt(args.params);
|
|
100
|
-
});
|
|
101
|
-
server.setRequestHandler(ListPromptsRequestSchema, async (args) => {
|
|
102
|
-
return client.listPrompts(args.params);
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
if (serverCapabilities?.resources) {
|
|
106
|
-
server.setRequestHandler(ListResourcesRequestSchema, async (args) => {
|
|
107
|
-
return client.listResources(args.params);
|
|
108
|
-
});
|
|
109
|
-
server.setRequestHandler(
|
|
110
|
-
ListResourceTemplatesRequestSchema,
|
|
111
|
-
async (args) => {
|
|
112
|
-
return client.listResourceTemplates(args.params);
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (args) => {
|
|
116
|
-
return client.readResource(args.params);
|
|
117
|
-
});
|
|
118
|
-
if (serverCapabilities?.resources.subscribe) {
|
|
119
|
-
server.setNotificationHandler(
|
|
120
|
-
ResourceUpdatedNotificationSchema,
|
|
121
|
-
async (args) => {
|
|
122
|
-
return client.notification(args);
|
|
123
|
-
}
|
|
124
|
-
);
|
|
125
|
-
server.setRequestHandler(SubscribeRequestSchema, async (args) => {
|
|
126
|
-
return client.subscribeResource(args.params);
|
|
127
|
-
});
|
|
128
|
-
server.setRequestHandler(UnsubscribeRequestSchema, async (args) => {
|
|
129
|
-
return client.unsubscribeResource(args.params);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (serverCapabilities?.tools) {
|
|
134
|
-
server.setRequestHandler(CallToolRequestSchema, async (args) => {
|
|
135
|
-
return client.callTool(args.params);
|
|
136
|
-
});
|
|
137
|
-
server.setRequestHandler(ListToolsRequestSchema, async (args) => {
|
|
138
|
-
return client.listTools(args.params);
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
server.setRequestHandler(CompleteRequestSchema, async (args) => {
|
|
142
|
-
return client.complete(args.params);
|
|
143
|
-
});
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
// src/startHTTPServer.ts
|
|
147
|
-
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
148
|
-
import {
|
|
149
|
-
StreamableHTTPServerTransport
|
|
150
|
-
} from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
151
|
-
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
152
|
-
import http from "http";
|
|
153
|
-
import { randomUUID } from "crypto";
|
|
154
|
-
var getBody = (request) => {
|
|
155
|
-
return new Promise((resolve) => {
|
|
156
|
-
const bodyParts = [];
|
|
157
|
-
let body;
|
|
158
|
-
request.on("data", (chunk) => {
|
|
159
|
-
bodyParts.push(chunk);
|
|
160
|
-
}).on("end", () => {
|
|
161
|
-
body = Buffer.concat(bodyParts).toString();
|
|
162
|
-
try {
|
|
163
|
-
resolve(JSON.parse(body));
|
|
164
|
-
} catch (error) {
|
|
165
|
-
console.error("[mcp-proxy] error parsing body", error);
|
|
166
|
-
resolve(null);
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
};
|
|
171
|
-
var createJsonRpcErrorResponse = (code, message) => {
|
|
172
|
-
return JSON.stringify({
|
|
173
|
-
error: { code, message },
|
|
174
|
-
id: null,
|
|
175
|
-
jsonrpc: "2.0"
|
|
176
|
-
});
|
|
177
|
-
};
|
|
178
|
-
var handleResponseError = (error, res) => {
|
|
179
|
-
if (error instanceof Response) {
|
|
180
|
-
const fixedHeaders = {};
|
|
181
|
-
error.headers.forEach((value, key) => {
|
|
182
|
-
if (fixedHeaders[key]) {
|
|
183
|
-
if (Array.isArray(fixedHeaders[key])) {
|
|
184
|
-
fixedHeaders[key].push(value);
|
|
185
|
-
} else {
|
|
186
|
-
fixedHeaders[key] = [fixedHeaders[key], value];
|
|
187
|
-
}
|
|
188
|
-
} else {
|
|
189
|
-
fixedHeaders[key] = value;
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
res.writeHead(error.status, error.statusText, fixedHeaders).end(error.statusText);
|
|
193
|
-
return true;
|
|
194
|
-
}
|
|
195
|
-
return false;
|
|
196
|
-
};
|
|
197
|
-
var cleanupServer = async (server, onClose) => {
|
|
198
|
-
if (onClose) {
|
|
199
|
-
await onClose(server);
|
|
200
|
-
}
|
|
201
|
-
try {
|
|
202
|
-
await server.close();
|
|
203
|
-
} catch (error) {
|
|
204
|
-
console.error("[mcp-proxy] error closing server", error);
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
var handleStreamRequest = async ({
|
|
208
|
-
activeTransports,
|
|
209
|
-
createServer,
|
|
210
|
-
enableJsonResponse,
|
|
211
|
-
endpoint,
|
|
212
|
-
eventStore,
|
|
213
|
-
onClose,
|
|
214
|
-
onConnect,
|
|
215
|
-
req,
|
|
216
|
-
res,
|
|
217
|
-
stateless
|
|
218
|
-
}) => {
|
|
219
|
-
if (req.method === "POST" && new URL(req.url, "http://localhost").pathname === endpoint) {
|
|
220
|
-
try {
|
|
221
|
-
const sessionId = Array.isArray(req.headers["mcp-session-id"]) ? req.headers["mcp-session-id"][0] : req.headers["mcp-session-id"];
|
|
222
|
-
let transport;
|
|
223
|
-
let server;
|
|
224
|
-
const body = await getBody(req);
|
|
225
|
-
if (sessionId) {
|
|
226
|
-
const activeTransport = activeTransports[sessionId];
|
|
227
|
-
if (!activeTransport) {
|
|
228
|
-
res.setHeader("Content-Type", "application/json");
|
|
229
|
-
res.writeHead(404).end(createJsonRpcErrorResponse(-32001, "Session not found"));
|
|
230
|
-
return true;
|
|
231
|
-
}
|
|
232
|
-
transport = activeTransport.transport;
|
|
233
|
-
server = activeTransport.server;
|
|
234
|
-
} else if (!sessionId && isInitializeRequest(body)) {
|
|
235
|
-
transport = new StreamableHTTPServerTransport({
|
|
236
|
-
enableJsonResponse,
|
|
237
|
-
eventStore: eventStore || new InMemoryEventStore(),
|
|
238
|
-
onsessioninitialized: (_sessionId) => {
|
|
239
|
-
if (!stateless && _sessionId) {
|
|
240
|
-
activeTransports[_sessionId] = {
|
|
241
|
-
server,
|
|
242
|
-
transport
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
},
|
|
246
|
-
sessionIdGenerator: stateless ? void 0 : randomUUID
|
|
247
|
-
});
|
|
248
|
-
let isCleaningUp = false;
|
|
249
|
-
transport.onclose = async () => {
|
|
250
|
-
const sid = transport.sessionId;
|
|
251
|
-
if (isCleaningUp) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
isCleaningUp = true;
|
|
255
|
-
if (!stateless && sid && activeTransports[sid]) {
|
|
256
|
-
await cleanupServer(server, onClose);
|
|
257
|
-
delete activeTransports[sid];
|
|
258
|
-
} else if (stateless) {
|
|
259
|
-
await cleanupServer(server, onClose);
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
try {
|
|
263
|
-
server = await createServer(req);
|
|
264
|
-
} catch (error) {
|
|
265
|
-
if (handleResponseError(error, res)) {
|
|
266
|
-
return true;
|
|
267
|
-
}
|
|
268
|
-
res.writeHead(500).end("Error creating server");
|
|
269
|
-
return true;
|
|
270
|
-
}
|
|
271
|
-
server.connect(transport);
|
|
272
|
-
if (onConnect) {
|
|
273
|
-
await onConnect(server);
|
|
274
|
-
}
|
|
275
|
-
await transport.handleRequest(req, res, body);
|
|
276
|
-
return true;
|
|
277
|
-
} else if (stateless && !sessionId && !isInitializeRequest(body)) {
|
|
278
|
-
transport = new StreamableHTTPServerTransport({
|
|
279
|
-
enableJsonResponse,
|
|
280
|
-
eventStore: eventStore || new InMemoryEventStore(),
|
|
281
|
-
onsessioninitialized: () => {
|
|
282
|
-
},
|
|
283
|
-
sessionIdGenerator: void 0
|
|
284
|
-
});
|
|
285
|
-
try {
|
|
286
|
-
server = await createServer(req);
|
|
287
|
-
} catch (error) {
|
|
288
|
-
if (handleResponseError(error, res)) {
|
|
289
|
-
return true;
|
|
290
|
-
}
|
|
291
|
-
res.writeHead(500).end("Error creating server");
|
|
292
|
-
return true;
|
|
293
|
-
}
|
|
294
|
-
server.connect(transport);
|
|
295
|
-
if (onConnect) {
|
|
296
|
-
await onConnect(server);
|
|
297
|
-
}
|
|
298
|
-
await transport.handleRequest(req, res, body);
|
|
299
|
-
return true;
|
|
300
|
-
} else {
|
|
301
|
-
res.setHeader("Content-Type", "application/json");
|
|
302
|
-
res.writeHead(400).end(
|
|
303
|
-
createJsonRpcErrorResponse(
|
|
304
|
-
-32e3,
|
|
305
|
-
"Bad Request: No valid session ID provided"
|
|
306
|
-
)
|
|
307
|
-
);
|
|
308
|
-
return true;
|
|
309
|
-
}
|
|
310
|
-
await transport.handleRequest(req, res, body);
|
|
311
|
-
return true;
|
|
312
|
-
} catch (error) {
|
|
313
|
-
console.error("[mcp-proxy] error handling request", error);
|
|
314
|
-
res.setHeader("Content-Type", "application/json");
|
|
315
|
-
res.writeHead(500).end(createJsonRpcErrorResponse(-32603, "Internal Server Error"));
|
|
316
|
-
}
|
|
317
|
-
return true;
|
|
318
|
-
}
|
|
319
|
-
if (req.method === "GET" && new URL(req.url, "http://localhost").pathname === endpoint) {
|
|
320
|
-
const sessionId = req.headers["mcp-session-id"];
|
|
321
|
-
const activeTransport = sessionId ? activeTransports[sessionId] : void 0;
|
|
322
|
-
if (!sessionId) {
|
|
323
|
-
res.writeHead(400).end("No sessionId");
|
|
324
|
-
return true;
|
|
325
|
-
}
|
|
326
|
-
if (!activeTransport) {
|
|
327
|
-
res.writeHead(400).end("No active transport");
|
|
328
|
-
return true;
|
|
329
|
-
}
|
|
330
|
-
const lastEventId = req.headers["last-event-id"];
|
|
331
|
-
if (lastEventId) {
|
|
332
|
-
console.log(
|
|
333
|
-
`[mcp-proxy] client reconnecting with Last-Event-ID ${lastEventId} for session ID ${sessionId}`
|
|
334
|
-
);
|
|
335
|
-
} else {
|
|
336
|
-
console.log(
|
|
337
|
-
`[mcp-proxy] establishing new SSE stream for session ID ${sessionId}`
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
await activeTransport.transport.handleRequest(req, res);
|
|
341
|
-
return true;
|
|
342
|
-
}
|
|
343
|
-
if (req.method === "DELETE" && new URL(req.url, "http://localhost").pathname === endpoint) {
|
|
344
|
-
console.log("[mcp-proxy] received delete request");
|
|
345
|
-
const sessionId = req.headers["mcp-session-id"];
|
|
346
|
-
if (!sessionId) {
|
|
347
|
-
res.writeHead(400).end("Invalid or missing sessionId");
|
|
348
|
-
return true;
|
|
349
|
-
}
|
|
350
|
-
console.log("[mcp-proxy] received delete request for session", sessionId);
|
|
351
|
-
const activeTransport = activeTransports[sessionId];
|
|
352
|
-
if (!activeTransport) {
|
|
353
|
-
res.writeHead(400).end("No active transport");
|
|
354
|
-
return true;
|
|
355
|
-
}
|
|
356
|
-
try {
|
|
357
|
-
await activeTransport.transport.handleRequest(req, res);
|
|
358
|
-
await cleanupServer(activeTransport.server, onClose);
|
|
359
|
-
} catch (error) {
|
|
360
|
-
console.error("[mcp-proxy] error handling delete request", error);
|
|
361
|
-
res.writeHead(500).end("Error handling delete request");
|
|
362
|
-
}
|
|
363
|
-
return true;
|
|
364
|
-
}
|
|
365
|
-
return false;
|
|
366
|
-
};
|
|
367
|
-
var handleSSERequest = async ({
|
|
368
|
-
activeTransports,
|
|
369
|
-
createServer,
|
|
370
|
-
endpoint,
|
|
371
|
-
onClose,
|
|
372
|
-
onConnect,
|
|
373
|
-
req,
|
|
374
|
-
res
|
|
375
|
-
}) => {
|
|
376
|
-
if (req.method === "GET" && new URL(req.url, "http://localhost").pathname === endpoint) {
|
|
377
|
-
const transport = new SSEServerTransport("/messages", res);
|
|
378
|
-
let server;
|
|
379
|
-
try {
|
|
380
|
-
server = await createServer(req);
|
|
381
|
-
} catch (error) {
|
|
382
|
-
if (handleResponseError(error, res)) {
|
|
383
|
-
return true;
|
|
384
|
-
}
|
|
385
|
-
res.writeHead(500).end("Error creating server");
|
|
386
|
-
return true;
|
|
387
|
-
}
|
|
388
|
-
activeTransports[transport.sessionId] = transport;
|
|
389
|
-
let closed = false;
|
|
390
|
-
let isCleaningUp = false;
|
|
391
|
-
res.on("close", async () => {
|
|
392
|
-
closed = true;
|
|
393
|
-
if (isCleaningUp) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
isCleaningUp = true;
|
|
397
|
-
await cleanupServer(server, onClose);
|
|
398
|
-
delete activeTransports[transport.sessionId];
|
|
399
|
-
});
|
|
400
|
-
try {
|
|
401
|
-
await server.connect(transport);
|
|
402
|
-
await transport.send({
|
|
403
|
-
jsonrpc: "2.0",
|
|
404
|
-
method: "sse/connection",
|
|
405
|
-
params: { message: "SSE Connection established" }
|
|
406
|
-
});
|
|
407
|
-
if (onConnect) {
|
|
408
|
-
await onConnect(server);
|
|
409
|
-
}
|
|
410
|
-
} catch (error) {
|
|
411
|
-
if (!closed) {
|
|
412
|
-
console.error("[mcp-proxy] error connecting to server", error);
|
|
413
|
-
res.writeHead(500).end("Error connecting to server");
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
return true;
|
|
417
|
-
}
|
|
418
|
-
if (req.method === "POST" && req.url?.startsWith("/messages")) {
|
|
419
|
-
const sessionId = new URL(req.url, "https://example.com").searchParams.get(
|
|
420
|
-
"sessionId"
|
|
421
|
-
);
|
|
422
|
-
if (!sessionId) {
|
|
423
|
-
res.writeHead(400).end("No sessionId");
|
|
424
|
-
return true;
|
|
425
|
-
}
|
|
426
|
-
const activeTransport = activeTransports[sessionId];
|
|
427
|
-
if (!activeTransport) {
|
|
428
|
-
res.writeHead(400).end("No active transport");
|
|
429
|
-
return true;
|
|
430
|
-
}
|
|
431
|
-
await activeTransport.handlePostMessage(req, res);
|
|
432
|
-
return true;
|
|
433
|
-
}
|
|
434
|
-
return false;
|
|
435
|
-
};
|
|
436
|
-
var startHTTPServer = async ({
|
|
437
|
-
createServer,
|
|
438
|
-
enableJsonResponse,
|
|
439
|
-
eventStore,
|
|
440
|
-
host = "::",
|
|
441
|
-
onClose,
|
|
442
|
-
onConnect,
|
|
443
|
-
onUnhandledRequest,
|
|
444
|
-
port,
|
|
445
|
-
sseEndpoint = "/sse",
|
|
446
|
-
stateless,
|
|
447
|
-
streamEndpoint = "/mcp"
|
|
448
|
-
}) => {
|
|
449
|
-
const activeSSETransports = {};
|
|
450
|
-
const activeStreamTransports = {};
|
|
451
|
-
const httpServer = http.createServer(async (req, res) => {
|
|
452
|
-
if (req.headers.origin) {
|
|
453
|
-
try {
|
|
454
|
-
const origin = new URL(req.headers.origin);
|
|
455
|
-
res.setHeader("Access-Control-Allow-Origin", origin.origin);
|
|
456
|
-
res.setHeader("Access-Control-Allow-Credentials", "true");
|
|
457
|
-
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
458
|
-
res.setHeader("Access-Control-Allow-Headers", "*");
|
|
459
|
-
res.setHeader("Access-Control-Expose-Headers", "mcp-session-id");
|
|
460
|
-
} catch (error) {
|
|
461
|
-
console.error("[mcp-proxy] error parsing origin", error);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
if (req.method === "OPTIONS") {
|
|
465
|
-
res.writeHead(204);
|
|
466
|
-
res.end();
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
if (req.method === "GET" && req.url === `/ping`) {
|
|
470
|
-
res.writeHead(200).end("pong");
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
if (sseEndpoint && await handleSSERequest({
|
|
474
|
-
activeTransports: activeSSETransports,
|
|
475
|
-
createServer,
|
|
476
|
-
endpoint: sseEndpoint,
|
|
477
|
-
onClose,
|
|
478
|
-
onConnect,
|
|
479
|
-
req,
|
|
480
|
-
res
|
|
481
|
-
})) {
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
if (streamEndpoint && await handleStreamRequest({
|
|
485
|
-
activeTransports: activeStreamTransports,
|
|
486
|
-
createServer,
|
|
487
|
-
enableJsonResponse,
|
|
488
|
-
endpoint: streamEndpoint,
|
|
489
|
-
eventStore,
|
|
490
|
-
onClose,
|
|
491
|
-
onConnect,
|
|
492
|
-
req,
|
|
493
|
-
res,
|
|
494
|
-
stateless
|
|
495
|
-
})) {
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
if (onUnhandledRequest) {
|
|
499
|
-
await onUnhandledRequest(req, res);
|
|
500
|
-
} else {
|
|
501
|
-
res.writeHead(404).end();
|
|
502
|
-
}
|
|
503
|
-
});
|
|
504
|
-
await new Promise((resolve) => {
|
|
505
|
-
httpServer.listen(port, host, () => {
|
|
506
|
-
resolve(void 0);
|
|
507
|
-
});
|
|
508
|
-
});
|
|
509
|
-
return {
|
|
510
|
-
close: async () => {
|
|
511
|
-
for (const transport of Object.values(activeSSETransports)) {
|
|
512
|
-
await transport.close();
|
|
513
|
-
}
|
|
514
|
-
for (const transport of Object.values(activeStreamTransports)) {
|
|
515
|
-
await transport.transport.close();
|
|
516
|
-
}
|
|
517
|
-
return new Promise((resolve, reject) => {
|
|
518
|
-
httpServer.close((error) => {
|
|
519
|
-
if (error) {
|
|
520
|
-
reject(error);
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
resolve();
|
|
524
|
-
});
|
|
525
|
-
});
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
export {
|
|
531
|
-
InMemoryEventStore,
|
|
532
|
-
proxyServer,
|
|
533
|
-
startHTTPServer
|
|
534
|
-
};
|
|
535
|
-
//# sourceMappingURL=chunk-JCZNH6HS.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/InMemoryEventStore.ts","../src/proxyServer.ts","../src/startHTTPServer.ts"],"sourcesContent":["/**\n * This is a copy of the InMemoryEventStore from the typescript-sdk\n * https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/inMemoryEventStore.ts\n */\n\nimport type { EventStore } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\n\n/**\n * Simple in-memory implementation of the EventStore interface for resumability\n * This is primarily intended for examples and testing, not for production use\n * where a persistent storage solution would be more appropriate.\n */\nexport class InMemoryEventStore implements EventStore {\n private events: Map<string, { message: JSONRPCMessage; streamId: string }> =\n new Map();\n\n /**\n * Replays events that occurred after a specific event ID\n * Implements EventStore.replayEventsAfter\n */\n async replayEventsAfter(\n lastEventId: string,\n {\n send,\n }: { send: (eventId: string, message: JSONRPCMessage) => Promise<void> },\n ): Promise<string> {\n if (!lastEventId || !this.events.has(lastEventId)) {\n return \"\";\n }\n\n // Extract the stream ID from the event ID\n const streamId = this.getStreamIdFromEventId(lastEventId);\n\n if (!streamId) {\n return \"\";\n }\n\n let foundLastEvent = false;\n\n // Sort events by eventId for chronological ordering\n const sortedEvents = [...this.events.entries()].sort((a, b) =>\n a[0].localeCompare(b[0]),\n );\n\n for (const [\n eventId,\n { message, streamId: eventStreamId },\n ] of sortedEvents) {\n // Only include events from the same stream\n if (eventStreamId !== streamId) {\n continue;\n }\n\n // Start sending events after we find the lastEventId\n if (eventId === lastEventId) {\n foundLastEvent = true;\n continue;\n }\n\n if (foundLastEvent) {\n await send(eventId, message);\n }\n }\n\n return streamId;\n }\n\n /**\n * Stores an event with a generated event ID\n * Implements EventStore.storeEvent\n */\n async storeEvent(streamId: string, message: JSONRPCMessage): Promise<string> {\n const eventId = this.generateEventId(streamId);\n\n this.events.set(eventId, { message, streamId });\n\n return eventId;\n }\n\n /**\n * Generates a unique event ID for a given stream ID\n */\n private generateEventId(streamId: string): string {\n return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;\n }\n\n /**\n * Extracts the stream ID from an event ID\n */\n private getStreamIdFromEventId(eventId: string): string {\n const parts = eventId.split(\"_\");\n\n return parts.length > 0 ? parts[0] : \"\";\n }\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n CallToolRequestSchema,\n CompleteRequestSchema,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n LoggingMessageNotificationSchema,\n ReadResourceRequestSchema,\n ResourceUpdatedNotificationSchema,\n ServerCapabilities,\n SubscribeRequestSchema,\n UnsubscribeRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport const proxyServer = async ({\n client,\n server,\n serverCapabilities,\n}: {\n client: Client;\n server: Server;\n serverCapabilities: ServerCapabilities;\n}): Promise<void> => {\n if (serverCapabilities?.logging) {\n server.setNotificationHandler(\n LoggingMessageNotificationSchema,\n async (args) => {\n return client.notification(args);\n },\n );\n client.setNotificationHandler(\n LoggingMessageNotificationSchema,\n async (args) => {\n return server.notification(args);\n },\n );\n }\n\n if (serverCapabilities?.prompts) {\n server.setRequestHandler(GetPromptRequestSchema, async (args) => {\n return client.getPrompt(args.params);\n });\n\n server.setRequestHandler(ListPromptsRequestSchema, async (args) => {\n return client.listPrompts(args.params);\n });\n }\n\n if (serverCapabilities?.resources) {\n server.setRequestHandler(ListResourcesRequestSchema, async (args) => {\n return client.listResources(args.params);\n });\n\n server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async (args) => {\n return client.listResourceTemplates(args.params);\n },\n );\n\n server.setRequestHandler(ReadResourceRequestSchema, async (args) => {\n return client.readResource(args.params);\n });\n\n if (serverCapabilities?.resources.subscribe) {\n server.setNotificationHandler(\n ResourceUpdatedNotificationSchema,\n async (args) => {\n return client.notification(args);\n },\n );\n\n server.setRequestHandler(SubscribeRequestSchema, async (args) => {\n return client.subscribeResource(args.params);\n });\n\n server.setRequestHandler(UnsubscribeRequestSchema, async (args) => {\n return client.unsubscribeResource(args.params);\n });\n }\n }\n\n if (serverCapabilities?.tools) {\n server.setRequestHandler(CallToolRequestSchema, async (args) => {\n return client.callTool(args.params);\n });\n\n server.setRequestHandler(ListToolsRequestSchema, async (args) => {\n return client.listTools(args.params);\n });\n }\n\n server.setRequestHandler(CompleteRequestSchema, async (args) => {\n return client.complete(args.params);\n });\n};\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport {\n EventStore,\n StreamableHTTPServerTransport,\n} from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { isInitializeRequest } from \"@modelcontextprotocol/sdk/types.js\";\nimport http from \"http\";\nimport { randomUUID } from \"node:crypto\";\n\nimport { InMemoryEventStore } from \"./InMemoryEventStore.js\";\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype ServerLike = {\n close: Server[\"close\"];\n connect: Server[\"connect\"];\n};\n\nconst getBody = (request: http.IncomingMessage) => {\n return new Promise((resolve) => {\n const bodyParts: Buffer[] = [];\n let body: string;\n request\n .on(\"data\", (chunk) => {\n bodyParts.push(chunk);\n })\n .on(\"end\", () => {\n body = Buffer.concat(bodyParts).toString();\n try {\n resolve(JSON.parse(body));\n } catch (error) {\n console.error(\"[mcp-proxy] error parsing body\", error);\n resolve(null);\n }\n });\n });\n};\n\n// Helper function to create JSON RPC error responses\nconst createJsonRpcErrorResponse = (code: number, message: string) => {\n return JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n });\n};\n\n// Helper function to handle Response errors and send appropriate HTTP response\nconst handleResponseError = (\n error: unknown,\n res: http.ServerResponse,\n): boolean => {\n if (error instanceof Response) {\n const fixedHeaders: http.OutgoingHttpHeaders = {};\n error.headers.forEach((value, key) => {\n if (fixedHeaders[key]) {\n if (Array.isArray(fixedHeaders[key])) {\n (fixedHeaders[key] as string[]).push(value);\n } else {\n fixedHeaders[key] = [fixedHeaders[key] as string, value];\n }\n } else {\n fixedHeaders[key] = value;\n }\n });\n res\n .writeHead(error.status, error.statusText, fixedHeaders)\n .end(error.statusText);\n return true;\n }\n return false;\n};\n\n// Helper function to clean up server resources\nconst cleanupServer = async <T extends ServerLike>(\n server: T,\n onClose?: (server: T) => Promise<void>,\n) => {\n if (onClose) {\n await onClose(server);\n }\n\n try {\n await server.close();\n } catch (error) {\n console.error(\"[mcp-proxy] error closing server\", error);\n }\n};\n\nconst handleStreamRequest = async <T extends ServerLike>({\n activeTransports,\n createServer,\n enableJsonResponse,\n endpoint,\n eventStore,\n onClose,\n onConnect,\n req,\n res,\n stateless,\n}: {\n activeTransports: Record<\n string,\n { server: T; transport: StreamableHTTPServerTransport }\n >;\n createServer: (request: http.IncomingMessage) => Promise<T>;\n enableJsonResponse?: boolean;\n endpoint: string;\n eventStore?: EventStore;\n onClose?: (server: T) => Promise<void>;\n onConnect?: (server: T) => Promise<void>;\n req: http.IncomingMessage;\n res: http.ServerResponse;\n stateless?: boolean;\n}) => {\n if (\n req.method === \"POST\" &&\n new URL(req.url!, \"http://localhost\").pathname === endpoint\n ) {\n try {\n const sessionId = Array.isArray(req.headers[\"mcp-session-id\"])\n ? req.headers[\"mcp-session-id\"][0]\n : req.headers[\"mcp-session-id\"];\n\n let transport: StreamableHTTPServerTransport;\n\n let server: T;\n\n const body = await getBody(req);\n\n if (sessionId) {\n const activeTransport = activeTransports[sessionId];\n if (!activeTransport) {\n res.setHeader(\"Content-Type\", \"application/json\");\n res\n .writeHead(404)\n .end(createJsonRpcErrorResponse(-32001, \"Session not found\"));\n\n return true;\n }\n\n transport = activeTransport.transport;\n server = activeTransport.server;\n } else if (!sessionId && isInitializeRequest(body)) {\n // Create a new transport for the session\n transport = new StreamableHTTPServerTransport({\n enableJsonResponse,\n eventStore: eventStore || new InMemoryEventStore(),\n onsessioninitialized: (_sessionId) => {\n // add only when the id Session id is generated (skip in stateless mode)\n if (!stateless && _sessionId) {\n activeTransports[_sessionId] = {\n server,\n transport,\n };\n }\n },\n sessionIdGenerator: stateless ? undefined : randomUUID,\n });\n\n // Handle the server close event\n let isCleaningUp = false;\n\n transport.onclose = async () => {\n const sid = transport.sessionId;\n\n if (isCleaningUp) {\n return;\n }\n\n isCleaningUp = true;\n\n if (!stateless && sid && activeTransports[sid]) {\n await cleanupServer(server, onClose);\n delete activeTransports[sid];\n } else if (stateless) {\n // In stateless mode, always call onClose when transport closes\n await cleanupServer(server, onClose);\n }\n };\n\n try {\n server = await createServer(req);\n } catch (error) {\n if (handleResponseError(error, res)) {\n return true;\n }\n\n res.writeHead(500).end(\"Error creating server\");\n\n return true;\n }\n\n server.connect(transport);\n\n if (onConnect) {\n await onConnect(server);\n }\n\n await transport.handleRequest(req, res, body);\n\n return true;\n } else if (stateless && !sessionId && !isInitializeRequest(body)) {\n // In stateless mode, handle non-initialize requests by creating a new transport\n transport = new StreamableHTTPServerTransport({\n enableJsonResponse,\n eventStore: eventStore || new InMemoryEventStore(),\n onsessioninitialized: () => {\n // No session tracking in stateless mode\n },\n sessionIdGenerator: undefined,\n });\n\n try {\n server = await createServer(req);\n } catch (error) {\n if (handleResponseError(error, res)) {\n return true;\n }\n\n res.writeHead(500).end(\"Error creating server\");\n\n return true;\n }\n\n server.connect(transport);\n\n if (onConnect) {\n await onConnect(server);\n }\n\n await transport.handleRequest(req, res, body);\n\n return true;\n } else {\n // Error if the server is not created but the request is not an initialize request\n res.setHeader(\"Content-Type\", \"application/json\");\n\n res\n .writeHead(400)\n .end(\n createJsonRpcErrorResponse(\n -32000,\n \"Bad Request: No valid session ID provided\",\n ),\n );\n\n return true;\n }\n\n // Handle the request if the server is already created\n await transport.handleRequest(req, res, body);\n\n return true;\n } catch (error) {\n console.error(\"[mcp-proxy] error handling request\", error);\n\n res.setHeader(\"Content-Type\", \"application/json\");\n\n res\n .writeHead(500)\n .end(createJsonRpcErrorResponse(-32603, \"Internal Server Error\"));\n }\n return true;\n }\n\n if (\n req.method === \"GET\" &&\n new URL(req.url!, \"http://localhost\").pathname === endpoint\n ) {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n const activeTransport:\n | {\n server: T;\n transport: StreamableHTTPServerTransport;\n }\n | undefined = sessionId ? activeTransports[sessionId] : undefined;\n\n if (!sessionId) {\n res.writeHead(400).end(\"No sessionId\");\n\n return true;\n }\n\n if (!activeTransport) {\n res.writeHead(400).end(\"No active transport\");\n\n return true;\n }\n\n const lastEventId = req.headers[\"last-event-id\"] as string | undefined;\n\n if (lastEventId) {\n console.log(\n `[mcp-proxy] client reconnecting with Last-Event-ID ${lastEventId} for session ID ${sessionId}`,\n );\n } else {\n console.log(\n `[mcp-proxy] establishing new SSE stream for session ID ${sessionId}`,\n );\n }\n\n await activeTransport.transport.handleRequest(req, res);\n\n return true;\n }\n\n if (\n req.method === \"DELETE\" &&\n new URL(req.url!, \"http://localhost\").pathname === endpoint\n ) {\n console.log(\"[mcp-proxy] received delete request\");\n\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n\n if (!sessionId) {\n res.writeHead(400).end(\"Invalid or missing sessionId\");\n\n return true;\n }\n\n console.log(\"[mcp-proxy] received delete request for session\", sessionId);\n\n const activeTransport = activeTransports[sessionId];\n\n if (!activeTransport) {\n res.writeHead(400).end(\"No active transport\");\n return true;\n }\n\n try {\n await activeTransport.transport.handleRequest(req, res);\n\n await cleanupServer(activeTransport.server, onClose);\n } catch (error) {\n console.error(\"[mcp-proxy] error handling delete request\", error);\n\n res.writeHead(500).end(\"Error handling delete request\");\n }\n\n return true;\n }\n\n return false;\n};\n\nconst handleSSERequest = async <T extends ServerLike>({\n activeTransports,\n createServer,\n endpoint,\n onClose,\n onConnect,\n req,\n res,\n}: {\n activeTransports: Record<string, SSEServerTransport>;\n createServer: (request: http.IncomingMessage) => Promise<T>;\n endpoint: string;\n onClose?: (server: T) => Promise<void>;\n onConnect?: (server: T) => Promise<void>;\n req: http.IncomingMessage;\n res: http.ServerResponse;\n}) => {\n if (\n req.method === \"GET\" &&\n new URL(req.url!, \"http://localhost\").pathname === endpoint\n ) {\n const transport = new SSEServerTransport(\"/messages\", res);\n\n let server: T;\n\n try {\n server = await createServer(req);\n } catch (error) {\n if (handleResponseError(error, res)) {\n return true;\n }\n\n res.writeHead(500).end(\"Error creating server\");\n\n return true;\n }\n\n activeTransports[transport.sessionId] = transport;\n\n let closed = false;\n let isCleaningUp = false;\n\n res.on(\"close\", async () => {\n closed = true;\n\n // Prevent recursive cleanup\n if (isCleaningUp) {\n return;\n }\n\n isCleaningUp = true;\n await cleanupServer(server, onClose);\n\n delete activeTransports[transport.sessionId];\n });\n\n try {\n await server.connect(transport);\n\n await transport.send({\n jsonrpc: \"2.0\",\n method: \"sse/connection\",\n params: { message: \"SSE Connection established\" },\n });\n\n if (onConnect) {\n await onConnect(server);\n }\n } catch (error) {\n if (!closed) {\n console.error(\"[mcp-proxy] error connecting to server\", error);\n\n res.writeHead(500).end(\"Error connecting to server\");\n }\n }\n\n return true;\n }\n\n if (req.method === \"POST\" && req.url?.startsWith(\"/messages\")) {\n const sessionId = new URL(req.url, \"https://example.com\").searchParams.get(\n \"sessionId\",\n );\n\n if (!sessionId) {\n res.writeHead(400).end(\"No sessionId\");\n\n return true;\n }\n\n const activeTransport: SSEServerTransport | undefined =\n activeTransports[sessionId];\n\n if (!activeTransport) {\n res.writeHead(400).end(\"No active transport\");\n\n return true;\n }\n\n await activeTransport.handlePostMessage(req, res);\n\n return true;\n }\n\n return false;\n};\n\nexport const startHTTPServer = async <T extends ServerLike>({\n createServer,\n enableJsonResponse,\n eventStore,\n host = \"::\",\n onClose,\n onConnect,\n onUnhandledRequest,\n port,\n sseEndpoint = \"/sse\",\n stateless,\n streamEndpoint = \"/mcp\",\n}: {\n createServer: (request: http.IncomingMessage) => Promise<T>;\n enableJsonResponse?: boolean;\n eventStore?: EventStore;\n host?: string;\n onClose?: (server: T) => Promise<void>;\n onConnect?: (server: T) => Promise<void>;\n onUnhandledRequest?: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ) => Promise<void>;\n port: number;\n sseEndpoint?: null | string;\n stateless?: boolean;\n streamEndpoint?: null | string;\n}): Promise<SSEServer> => {\n const activeSSETransports: Record<string, SSEServerTransport> = {};\n\n const activeStreamTransports: Record<\n string,\n {\n server: T;\n transport: StreamableHTTPServerTransport;\n }\n > = {};\n\n /**\n * @author https://dev.classmethod.jp/articles/mcp-sse/\n */\n const httpServer = http.createServer(async (req, res) => {\n if (req.headers.origin) {\n try {\n const origin = new URL(req.headers.origin);\n\n res.setHeader(\"Access-Control-Allow-Origin\", origin.origin);\n res.setHeader(\"Access-Control-Allow-Credentials\", \"true\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n res.setHeader(\"Access-Control-Expose-Headers\", \"mcp-session-id\");\n } catch (error) {\n console.error(\"[mcp-proxy] error parsing origin\", error);\n }\n }\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (req.method === \"GET\" && req.url === `/ping`) {\n res.writeHead(200).end(\"pong\");\n return;\n }\n\n if (\n sseEndpoint &&\n (await handleSSERequest({\n activeTransports: activeSSETransports,\n createServer,\n endpoint: sseEndpoint,\n onClose,\n onConnect,\n req,\n res,\n }))\n ) {\n return;\n }\n\n if (\n streamEndpoint &&\n (await handleStreamRequest({\n activeTransports: activeStreamTransports,\n createServer,\n enableJsonResponse,\n endpoint: streamEndpoint,\n eventStore,\n onClose,\n onConnect,\n req,\n res,\n stateless,\n }))\n ) {\n return;\n }\n\n if (onUnhandledRequest) {\n await onUnhandledRequest(req, res);\n } else {\n res.writeHead(404).end();\n }\n });\n\n await new Promise((resolve) => {\n httpServer.listen(port, host, () => {\n resolve(undefined);\n });\n });\n\n return {\n close: async () => {\n for (const transport of Object.values(activeSSETransports)) {\n await transport.close();\n }\n\n for (const transport of Object.values(activeStreamTransports)) {\n await transport.transport.close();\n }\n\n return new Promise((resolve, reject) => {\n httpServer.close((error) => {\n if (error) {\n reject(error);\n\n return;\n }\n\n resolve();\n });\n });\n },\n };\n};\n"],"mappings":"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","names":[]}
|