mcp-proxy 2.13.1 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,6 +98,19 @@ const { close } = await startHTTPStreamServer({
98
98
  close();
99
99
  ```
100
100
 
101
+ #### `startStdioServer`
102
+
103
+ Starts a proxy that listens on a `stdio`, and sends messages to the attached `sse` or `streamable` server.
104
+
105
+ ```ts
106
+ import { ServerType, startStdioServer } from "./startStdioServer.js";
107
+
108
+ await startStdioServer({
109
+ serverType: ServerType.SSE,
110
+ url: "http://127.0.0.1:3000/sse",
111
+ });
112
+ ```
113
+
101
114
  #### `tapTransport`
102
115
 
103
116
  Taps into a transport and logs events.
@@ -4,7 +4,7 @@ import {
4
4
  proxyServer,
5
5
  startHTTPStreamServer,
6
6
  startSSEServer
7
- } from "../chunk-F2LFKNGG.js";
7
+ } from "../chunk-FMSNG7MS.js";
8
8
 
9
9
  // src/bin/mcp-proxy.ts
10
10
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
@@ -87,6 +87,12 @@ var proxyServer = async ({
87
87
  return client.notification(args);
88
88
  }
89
89
  );
90
+ client.setNotificationHandler(
91
+ LoggingMessageNotificationSchema,
92
+ async (args) => {
93
+ return server.notification(args);
94
+ }
95
+ );
90
96
  }
91
97
  if (serverCapabilities?.prompts) {
92
98
  server.setRequestHandler(GetPromptRequestSchema, async (args) => {
@@ -462,4 +468,4 @@ export {
462
468
  startHTTPStreamServer,
463
469
  startSSEServer
464
470
  };
465
- //# sourceMappingURL=chunk-F2LFKNGG.js.map
471
+ //# sourceMappingURL=chunk-FMSNG7MS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/InMemoryEventStore.ts","../src/proxyServer.ts","../src/startHTTPStreamServer.ts","../src/startSSEServer.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 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 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 this.events.set(eventId, { message, streamId });\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 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}) => {\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 {\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\nexport const startHTTPStreamServer = async <T extends ServerLike>({\n createServer,\n endpoint,\n eventStore,\n onClose,\n onConnect,\n onUnhandledRequest,\n port,\n}: {\n createServer: (request: http.IncomingMessage) => Promise<T>;\n endpoint: string;\n eventStore?: EventStore;\n onClose?: (server: T) => void;\n onConnect?: (server: T) => void;\n onUnhandledRequest?: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ) => Promise<void>;\n port: number;\n}): Promise<SSEServer> => {\n const activeTransports: 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 } catch (error) {\n console.error(\"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 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 let transport: StreamableHTTPServerTransport;\n let server: T;\n\n const body = await getBody(req);\n\n if (sessionId && activeTransports[sessionId]) {\n transport = activeTransports[sessionId].transport;\n server = activeTransports[sessionId].server;\n } else if (!sessionId && isInitializeRequest(body)) {\n // Create a new transport for the session\n transport = new StreamableHTTPServerTransport({\n eventStore: eventStore || new InMemoryEventStore(),\n onsessioninitialized: (_sessionId) => {\n // add only when the id Sesison id is generated\n activeTransports[_sessionId] = {\n server,\n transport,\n };\n },\n sessionIdGenerator: randomUUID,\n });\n\n // Handle the server close event\n transport.onclose = async () => {\n const sid = transport.sessionId;\n if (sid && activeTransports[sid]) {\n onClose?.(server);\n try {\n await server.close();\n } catch (error) {\n console.error(\"Error closing server:\", error);\n }\n delete activeTransports[sid];\n }\n };\n\n // Create the server\n try {\n server = await createServer(req);\n } catch (error) {\n if (error instanceof Response) {\n res.writeHead(error.status).end(error.statusText);\n return;\n }\n res.writeHead(500).end(\"Error creating server\");\n return;\n }\n\n server.connect(transport);\n onConnect?.(server);\n\n await transport.handleRequest(req, res, body);\n return;\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 res.writeHead(400).end(\n JSON.stringify({\n error: {\n code: -32000,\n message: \"Bad Request: No valid session ID provided\",\n },\n id: null,\n jsonrpc: \"2.0\",\n }),\n );\n\n return;\n }\n\n // Handle ther request if the server is already created\n await transport.handleRequest(req, res, body);\n } catch (error) {\n console.error(\"Error handling request:\", error);\n res.setHeader(\"Content-Type\", \"application/json\");\n res.writeHead(500).end(\n JSON.stringify({\n error: { code: -32603, message: \"Internal Server Error\" },\n id: null,\n jsonrpc: \"2.0\",\n }),\n );\n }\n return;\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 return;\n }\n\n if (!activeTransport) {\n res.writeHead(400).end(\"No active transport\");\n return;\n }\n\n const lastEventId = req.headers[\"last-event-id\"] as string | undefined;\n if (lastEventId) {\n console.log(`Client reconnecting with Last-Event-ID: ${lastEventId}`);\n } else {\n console.log(`Establishing new SSE stream for session ${sessionId}`);\n }\n\n await activeTransport.transport.handleRequest(req, res);\n return;\n }\n\n if (\n req.method === \"DELETE\" &&\n new URL(req.url!, \"http://localhost\").pathname === endpoint\n ) {\n console.log(\"received delete request\");\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n if (!sessionId) {\n res.writeHead(400).end(\"Invalid or missing sessionId\");\n return;\n }\n\n console.log(\"received delete request for session\", sessionId);\n\n const { server, transport } = activeTransports[sessionId];\n if (!transport) {\n res.writeHead(400).end(\"No active transport\");\n return;\n }\n\n try {\n await transport.handleRequest(req, res);\n onClose?.(server);\n } catch (error) {\n console.error(\"Error handling delete request:\", error);\n res.writeHead(500).end(\"Error handling delete request\");\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, \"::\", () => {\n resolve(undefined);\n });\n });\n\n return {\n close: async () => {\n for (const transport of Object.values(activeTransports)) {\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\nfunction 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 resolve(JSON.parse(body));\n });\n });\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport http from \"http\";\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype ServerLike = {\n close: Server[\"close\"];\n connect: Server[\"connect\"];\n};\n\nexport const startSSEServer = async <T extends ServerLike>({\n createServer,\n endpoint,\n onClose,\n onConnect,\n onUnhandledRequest,\n port,\n}: {\n createServer: (request: http.IncomingMessage) => Promise<T>;\n endpoint: string;\n onClose?: (server: T) => void;\n onConnect?: (server: T) => void;\n onUnhandledRequest?: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ) => Promise<void>;\n port: number;\n}): Promise<SSEServer> => {\n const activeTransports: Record<string, SSEServerTransport> = {};\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 } catch (error) {\n console.error(\"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 === \"/health\") {\n res.writeHead(200, { \"Content-Type\": \"text/plain\" }).end(\"OK\");\n return;\n }\n\n if (req.method === \"GET\" && req.url === `/ping`) {\n res.writeHead(200).end(\"pong\");\n\n return;\n }\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 (error instanceof Response) {\n res.writeHead(error.status).end(error.statusText);\n\n return;\n }\n\n res.writeHead(500).end(\"Error creating server\");\n\n return;\n }\n\n activeTransports[transport.sessionId] = transport;\n\n let closed = false;\n\n res.on(\"close\", async () => {\n closed = true;\n\n try {\n await server.close();\n } catch (error) {\n console.error(\"Error closing server:\", error);\n }\n\n delete activeTransports[transport.sessionId];\n\n onClose?.(server);\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 onConnect?.(server);\n } catch (error) {\n if (!closed) {\n console.error(\"Error connecting to server:\", error);\n\n res.writeHead(500).end(\"Error connecting to server\");\n }\n }\n\n return;\n }\n\n if (req.method === \"POST\" && req.url?.startsWith(\"/messages\")) {\n const sessionId = new URL(\n req.url,\n \"https://example.com\",\n ).searchParams.get(\"sessionId\");\n\n if (!sessionId) {\n res.writeHead(400).end(\"No sessionId\");\n\n return;\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;\n }\n\n await activeTransport.handlePostMessage(req, res);\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, \"::\", () => {\n resolve(undefined);\n });\n });\n\n return {\n close: async () => {\n for (const transport of Object.values(activeTransports)) {\n await 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":["http"]}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,8 @@ import { JSONRPCMessage, ServerCapabilities } from '@modelcontextprotocol/sdk/ty
3
3
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4
4
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
5
  import http from 'http';
6
+ import { SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';
7
+ import { StreamableHTTPClientTransportOptions } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
6
8
  import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
7
9
 
8
10
  /**
@@ -78,6 +80,18 @@ declare const startSSEServer: <T extends ServerLike>({ createServer, endpoint, o
78
80
  port: number;
79
81
  }) => Promise<SSEServer>;
80
82
 
83
+ declare enum ServerType {
84
+ HTTPStream = "HTTPStream",
85
+ SSE = "SSE"
86
+ }
87
+ declare const startStdioServer: ({ initStdioServer, initStreamClient, serverType, transportOptions, url, }: {
88
+ initStdioServer?: () => Promise<Server>;
89
+ initStreamClient?: () => Promise<Client>;
90
+ serverType: ServerType;
91
+ transportOptions?: SSEClientTransportOptions | StreamableHTTPClientTransportOptions;
92
+ url: string;
93
+ }) => Promise<Server>;
94
+
81
95
  type TransportEvent = {
82
96
  error: Error;
83
97
  type: "onerror";
@@ -96,4 +110,4 @@ type TransportEvent = {
96
110
  };
97
111
  declare const tapTransport: (transport: Transport, eventHandler: (event: TransportEvent) => void) => Transport;
98
112
 
99
- export { InMemoryEventStore, proxyServer, startHTTPStreamServer, startSSEServer, tapTransport };
113
+ export { InMemoryEventStore, ServerType, proxyServer, startHTTPStreamServer, startSSEServer, startStdioServer, tapTransport };
package/dist/index.js CHANGED
@@ -3,7 +3,61 @@ import {
3
3
  proxyServer,
4
4
  startHTTPStreamServer,
5
5
  startSSEServer
6
- } from "./chunk-F2LFKNGG.js";
6
+ } from "./chunk-FMSNG7MS.js";
7
+
8
+ // src/startStdioServer.ts
9
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
10
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
11
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
12
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
13
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
14
+ var ServerType = /* @__PURE__ */ ((ServerType2) => {
15
+ ServerType2["HTTPStream"] = "HTTPStream";
16
+ ServerType2["SSE"] = "SSE";
17
+ return ServerType2;
18
+ })(ServerType || {});
19
+ var startStdioServer = async ({
20
+ initStdioServer,
21
+ initStreamClient,
22
+ serverType,
23
+ transportOptions = {},
24
+ url
25
+ }) => {
26
+ let transport;
27
+ switch (serverType) {
28
+ case "SSE" /* SSE */:
29
+ transport = new SSEClientTransport(new URL(url), transportOptions);
30
+ break;
31
+ default:
32
+ transport = new StreamableHTTPClientTransport(
33
+ new URL(url),
34
+ transportOptions
35
+ );
36
+ }
37
+ const streamClient = initStreamClient ? await initStreamClient() : new Client(
38
+ {
39
+ name: "mcp-proxy",
40
+ version: "1.0.0"
41
+ },
42
+ {
43
+ capabilities: {}
44
+ }
45
+ );
46
+ await streamClient.connect(transport);
47
+ const serverVersion = streamClient.getServerVersion();
48
+ const serverCapabilities = streamClient.getServerCapabilities();
49
+ const stdioServer = initStdioServer ? await initStdioServer() : new Server(serverVersion, {
50
+ capabilities: serverCapabilities
51
+ });
52
+ const stdioTransport = new StdioServerTransport();
53
+ await stdioServer.connect(stdioTransport);
54
+ await proxyServer({
55
+ client: streamClient,
56
+ server: stdioServer,
57
+ serverCapabilities
58
+ });
59
+ return stdioServer;
60
+ };
7
61
 
8
62
  // src/tapTransport.ts
9
63
  var tapTransport = (transport, eventHandler) => {
@@ -56,9 +110,11 @@ var tapTransport = (transport, eventHandler) => {
56
110
  };
57
111
  export {
58
112
  InMemoryEventStore,
113
+ ServerType,
59
114
  proxyServer,
60
115
  startHTTPStreamServer,
61
116
  startSSEServer,
117
+ startStdioServer,
62
118
  tapTransport
63
119
  };
64
120
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tapTransport.ts"],"sourcesContent":["import { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\n\ntype TransportEvent =\n | {\n error: Error;\n type: \"onerror\";\n }\n | {\n message: JSONRPCMessage;\n type: \"onmessage\";\n }\n | {\n message: JSONRPCMessage;\n type: \"send\";\n }\n | {\n type: \"close\";\n }\n | {\n type: \"onclose\";\n }\n | {\n type: \"start\";\n };\n\nexport const tapTransport = (\n transport: Transport,\n eventHandler: (event: TransportEvent) => void,\n) => {\n const originalClose = transport.close.bind(transport);\n const originalOnClose = transport.onclose?.bind(transport);\n const originalOnError = transport.onerror?.bind(transport);\n const originalOnMessage = transport.onmessage?.bind(transport);\n const originalSend = transport.send.bind(transport);\n const originalStart = transport.start.bind(transport);\n\n transport.close = async () => {\n eventHandler({\n type: \"close\",\n });\n\n return originalClose?.();\n };\n\n transport.onclose = async () => {\n eventHandler({\n type: \"onclose\",\n });\n\n return originalOnClose?.();\n };\n\n transport.onerror = async (error: Error) => {\n eventHandler({\n error,\n type: \"onerror\",\n });\n\n return originalOnError?.(error);\n };\n\n transport.onmessage = async (message: JSONRPCMessage) => {\n eventHandler({\n message,\n type: \"onmessage\",\n });\n\n return originalOnMessage?.(message);\n };\n\n transport.send = async (message: JSONRPCMessage) => {\n eventHandler({\n message,\n type: \"send\",\n });\n\n return originalSend?.(message);\n };\n\n transport.start = async () => {\n eventHandler({\n type: \"start\",\n });\n\n return originalStart?.();\n };\n\n return transport;\n};\n"],"mappings":";;;;;;;;AA0BO,IAAM,eAAe,CAC1B,WACA,iBACG;AACH,QAAM,gBAAgB,UAAU,MAAM,KAAK,SAAS;AACpD,QAAM,kBAAkB,UAAU,SAAS,KAAK,SAAS;AACzD,QAAM,kBAAkB,UAAU,SAAS,KAAK,SAAS;AACzD,QAAM,oBAAoB,UAAU,WAAW,KAAK,SAAS;AAC7D,QAAM,eAAe,UAAU,KAAK,KAAK,SAAS;AAClD,QAAM,gBAAgB,UAAU,MAAM,KAAK,SAAS;AAEpD,YAAU,QAAQ,YAAY;AAC5B,iBAAa;AAAA,MACX,MAAM;AAAA,IACR,CAAC;AAED,WAAO,gBAAgB;AAAA,EACzB;AAEA,YAAU,UAAU,YAAY;AAC9B,iBAAa;AAAA,MACX,MAAM;AAAA,IACR,CAAC;AAED,WAAO,kBAAkB;AAAA,EAC3B;AAEA,YAAU,UAAU,OAAO,UAAiB;AAC1C,iBAAa;AAAA,MACX;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAED,WAAO,kBAAkB,KAAK;AAAA,EAChC;AAEA,YAAU,YAAY,OAAO,YAA4B;AACvD,iBAAa;AAAA,MACX;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAED,WAAO,oBAAoB,OAAO;AAAA,EACpC;AAEA,YAAU,OAAO,OAAO,YAA4B;AAClD,iBAAa;AAAA,MACX;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAED,WAAO,eAAe,OAAO;AAAA,EAC/B;AAEA,YAAU,QAAQ,YAAY;AAC5B,iBAAa;AAAA,MACX,MAAM;AAAA,IACR,CAAC;AAED,WAAO,gBAAgB;AAAA,EACzB;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/startStdioServer.ts","../src/tapTransport.ts"],"sourcesContent":["import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransportOptions } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { proxyServer } from \"./proxyServer.js\";\n\nexport enum ServerType {\n HTTPStream = \"HTTPStream\",\n SSE = \"SSE\",\n}\n\nexport const startStdioServer = async ({\n initStdioServer,\n initStreamClient,\n serverType,\n transportOptions = {},\n url,\n}: {\n initStdioServer?: () => Promise<Server>;\n initStreamClient?: () => Promise<Client>;\n serverType: ServerType;\n transportOptions?:\n | SSEClientTransportOptions\n | StreamableHTTPClientTransportOptions;\n url: string;\n}): Promise<Server> => {\n let transport: SSEClientTransport | StreamableHTTPClientTransport;\n switch (serverType) {\n case ServerType.SSE:\n transport = new SSEClientTransport(new URL(url), transportOptions);\n break;\n default:\n transport = new StreamableHTTPClientTransport(\n new URL(url),\n transportOptions,\n );\n }\n const streamClient = initStreamClient\n ? await initStreamClient()\n : new Client(\n {\n name: \"mcp-proxy\",\n version: \"1.0.0\",\n },\n {\n capabilities: {},\n },\n );\n await streamClient.connect(transport);\n\n const serverVersion = streamClient.getServerVersion() as {\n name: string;\n version: string;\n };\n\n const serverCapabilities = streamClient.getServerCapabilities() as {\n capabilities: Record<string, unknown>;\n };\n\n const stdioServer = initStdioServer\n ? await initStdioServer()\n : new Server(serverVersion, {\n capabilities: serverCapabilities,\n });\n\n const stdioTransport = new StdioServerTransport();\n\n await stdioServer.connect(stdioTransport);\n\n await proxyServer({\n client: streamClient,\n server: stdioServer,\n serverCapabilities,\n });\n\n return stdioServer;\n};\n","import { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\n\ntype TransportEvent =\n | {\n error: Error;\n type: \"onerror\";\n }\n | {\n message: JSONRPCMessage;\n type: \"onmessage\";\n }\n | {\n message: JSONRPCMessage;\n type: \"send\";\n }\n | {\n type: \"close\";\n }\n | {\n type: \"onclose\";\n }\n | {\n type: \"start\";\n };\n\nexport const tapTransport = (\n transport: Transport,\n eventHandler: (event: TransportEvent) => void,\n) => {\n const originalClose = transport.close.bind(transport);\n const originalOnClose = transport.onclose?.bind(transport);\n const originalOnError = transport.onerror?.bind(transport);\n const originalOnMessage = transport.onmessage?.bind(transport);\n const originalSend = transport.send.bind(transport);\n const originalStart = transport.start.bind(transport);\n\n transport.close = async () => {\n eventHandler({\n type: \"close\",\n });\n\n return originalClose?.();\n };\n\n transport.onclose = async () => {\n eventHandler({\n type: \"onclose\",\n });\n\n return originalOnClose?.();\n };\n\n transport.onerror = async (error: Error) => {\n eventHandler({\n error,\n type: \"onerror\",\n });\n\n return originalOnError?.(error);\n };\n\n transport.onmessage = async (message: JSONRPCMessage) => {\n eventHandler({\n message,\n type: \"onmessage\",\n });\n\n return originalOnMessage?.(message);\n };\n\n transport.send = async (message: JSONRPCMessage) => {\n eventHandler({\n message,\n type: \"send\",\n });\n\n return originalSend?.(message);\n };\n\n transport.start = async () => {\n eventHandler({\n type: \"start\",\n });\n\n return originalStart?.();\n };\n\n return transport;\n};\n"],"mappings":";;;;;;;;AAAA,SAAS,cAAc;AAEvB,SAAS,0BAA0B;AAEnC,SAAS,qCAAqC;AAC9C,SAAS,cAAc;AACvB,SAAS,4BAA4B;AAI9B,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,YAAA,gBAAa;AACb,EAAAA,YAAA,SAAM;AAFI,SAAAA;AAAA,GAAA;AAKL,IAAM,mBAAmB,OAAO;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB,CAAC;AAAA,EACpB;AACF,MAQuB;AACrB,MAAI;AACJ,UAAQ,YAAY;AAAA,IAClB,KAAK;AACH,kBAAY,IAAI,mBAAmB,IAAI,IAAI,GAAG,GAAG,gBAAgB;AACjE;AAAA,IACF;AACE,kBAAY,IAAI;AAAA,QACd,IAAI,IAAI,GAAG;AAAA,QACX;AAAA,MACF;AAAA,EACJ;AACA,QAAM,eAAe,mBACjB,MAAM,iBAAiB,IACvB,IAAI;AAAA,IACF;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,cAAc,CAAC;AAAA,IACjB;AAAA,EACF;AACJ,QAAM,aAAa,QAAQ,SAAS;AAEpC,QAAM,gBAAgB,aAAa,iBAAiB;AAKpD,QAAM,qBAAqB,aAAa,sBAAsB;AAI9D,QAAM,cAAc,kBAChB,MAAM,gBAAgB,IACtB,IAAI,OAAO,eAAe;AAAA,IACxB,cAAc;AAAA,EAChB,CAAC;AAEL,QAAM,iBAAiB,IAAI,qBAAqB;AAEhD,QAAM,YAAY,QAAQ,cAAc;AAExC,QAAM,YAAY;AAAA,IAChB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;ACtDO,IAAM,eAAe,CAC1B,WACA,iBACG;AACH,QAAM,gBAAgB,UAAU,MAAM,KAAK,SAAS;AACpD,QAAM,kBAAkB,UAAU,SAAS,KAAK,SAAS;AACzD,QAAM,kBAAkB,UAAU,SAAS,KAAK,SAAS;AACzD,QAAM,oBAAoB,UAAU,WAAW,KAAK,SAAS;AAC7D,QAAM,eAAe,UAAU,KAAK,KAAK,SAAS;AAClD,QAAM,gBAAgB,UAAU,MAAM,KAAK,SAAS;AAEpD,YAAU,QAAQ,YAAY;AAC5B,iBAAa;AAAA,MACX,MAAM;AAAA,IACR,CAAC;AAED,WAAO,gBAAgB;AAAA,EACzB;AAEA,YAAU,UAAU,YAAY;AAC9B,iBAAa;AAAA,MACX,MAAM;AAAA,IACR,CAAC;AAED,WAAO,kBAAkB;AAAA,EAC3B;AAEA,YAAU,UAAU,OAAO,UAAiB;AAC1C,iBAAa;AAAA,MACX;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAED,WAAO,kBAAkB,KAAK;AAAA,EAChC;AAEA,YAAU,YAAY,OAAO,YAA4B;AACvD,iBAAa;AAAA,MACX;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAED,WAAO,oBAAoB,OAAO;AAAA,EACpC;AAEA,YAAU,OAAO,OAAO,YAA4B;AAClD,iBAAa;AAAA,MACX;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAED,WAAO,eAAe,OAAO;AAAA,EAC/B;AAEA,YAAU,QAAQ,YAAY;AAC5B,iBAAa;AAAA,MACX,MAAM;AAAA,IACR,CAAC;AAED,WAAO,gBAAgB;AAAA,EACzB;AAEA,SAAO;AACT;","names":["ServerType"]}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "mcp-proxy",
3
- "version": "2.13.1",
3
+ "version": "2.14.0",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "build": "tsup",
7
- "test": "vitest run && tsc",
7
+ "test": "vitest run && tsc && prettier --check . && eslint .",
8
8
  "format": "prettier --write . && eslint --fix ."
9
9
  },
10
10
  "bin": {
@@ -45,11 +45,13 @@
45
45
  "@eslint/js": "^9.25.1",
46
46
  "@sebbo2002/semantic-release-jsr": "^2.0.5",
47
47
  "@tsconfig/node22": "^22.0.1",
48
+ "@types/express": "^5.0.0",
48
49
  "@types/node": "^22.14.1",
49
50
  "@types/yargs": "^17.0.33",
50
51
  "eslint": "^9.25.0",
51
52
  "eslint-config-prettier": "^10.1.2",
52
53
  "eslint-plugin-perfectionist": "^4.11.0",
54
+ "express": "^5.0.1",
53
55
  "get-port-please": "^3.1.2",
54
56
  "jiti": "^2.4.2",
55
57
  "prettier": "^3.5.3",
package/src/index.ts CHANGED
@@ -2,4 +2,5 @@ export { InMemoryEventStore } from "./InMemoryEventStore.js";
2
2
  export { proxyServer } from "./proxyServer.js";
3
3
  export { startHTTPStreamServer } from "./startHTTPStreamServer.js";
4
4
  export { startSSEServer } from "./startSSEServer.js";
5
+ export { ServerType, startStdioServer } from "./startStdioServer.js";
5
6
  export { tapTransport } from "./tapTransport.js";
@@ -32,6 +32,12 @@ export const proxyServer = async ({
32
32
  return client.notification(args);
33
33
  },
34
34
  );
35
+ client.setNotificationHandler(
36
+ LoggingMessageNotificationSchema,
37
+ async (args) => {
38
+ return server.notification(args);
39
+ },
40
+ );
35
41
  }
36
42
 
37
43
  if (serverCapabilities?.prompts) {
@@ -0,0 +1,3 @@
1
+ import { startStdioServer } from "./startStdioServer.js";
2
+
3
+ await startStdioServer(JSON.parse(process.argv[2]));
@@ -0,0 +1,228 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
+ import {
4
+ CallToolResultSchema,
5
+ LoggingMessageNotificationSchema,
6
+ } from "@modelcontextprotocol/sdk/types.js";
7
+ import { EventSource } from "eventsource";
8
+ import { ChildProcess, fork } from "node:child_process";
9
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
10
+
11
+ import { ServerType } from "./startStdioServer.js";
12
+
13
+ if (!("EventSource" in global)) {
14
+ // @ts-expect-error - figure out how to use --experimental-eventsource with vitest
15
+ global.EventSource = EventSource;
16
+ }
17
+
18
+ describe("startStdioServer.test.ts", () => {
19
+ let proc: ChildProcess;
20
+
21
+ beforeEach(async () => {
22
+ const serverPath = require.resolve(
23
+ "@modelcontextprotocol/sdk/examples/server/sseAndStreamableHttpCompatibleServer.js",
24
+ );
25
+ proc = fork(serverPath, [], {
26
+ stdio: "pipe",
27
+ });
28
+ await new Promise((resolve) => {
29
+ proc.stdout?.on("data", (data) => {
30
+ console.log(data.toString());
31
+ data
32
+ .toString()
33
+ .includes("Backwards compatible MCP server listening on port");
34
+ resolve(null);
35
+ });
36
+ });
37
+ });
38
+
39
+ afterEach(async () => {
40
+ proc.kill();
41
+ });
42
+
43
+ it("proxies messages between stdio and sse servers", async () => {
44
+ const stdioTransport = new StdioClientTransport({
45
+ args: [
46
+ "src/simple-stdio-proxy-server.ts",
47
+ JSON.stringify({
48
+ serverType: ServerType.SSE,
49
+ url: "http://127.0.0.1:3000/sse",
50
+ }),
51
+ ],
52
+ command: "tsx",
53
+ });
54
+
55
+ const stdioClient = new Client(
56
+ {
57
+ name: "mcp-proxy",
58
+ version: "1.0.0",
59
+ },
60
+ {
61
+ capabilities: {},
62
+ },
63
+ );
64
+
65
+ let notificationCount = 0;
66
+
67
+ stdioClient.setNotificationHandler(
68
+ LoggingMessageNotificationSchema,
69
+ (notification) => {
70
+ console.log(
71
+ `Notification: ${notification.params.level} - ${notification.params.data}`,
72
+ );
73
+ notificationCount++;
74
+ },
75
+ );
76
+
77
+ await stdioClient.connect(stdioTransport);
78
+
79
+ const result = await stdioClient.listTools();
80
+
81
+ expect(result).toEqual({
82
+ tools: [
83
+ {
84
+ description:
85
+ "Starts sending periodic notifications for testing resumability",
86
+ inputSchema: {
87
+ $schema: "http://json-schema.org/draft-07/schema#",
88
+ additionalProperties: false,
89
+ properties: {
90
+ count: {
91
+ default: 50,
92
+ description: "Number of notifications to send (0 for 100)",
93
+ type: "number",
94
+ },
95
+ interval: {
96
+ default: 100,
97
+ description: "Interval in milliseconds between notifications",
98
+ type: "number",
99
+ },
100
+ },
101
+ type: "object",
102
+ },
103
+ name: "start-notification-stream",
104
+ },
105
+ ],
106
+ });
107
+ const request = {
108
+ method: "tools/call",
109
+ params: {
110
+ arguments: {
111
+ count: 2, // Send 5 notifications
112
+ interval: 1000, // 1 second between notifications
113
+ },
114
+ name: "start-notification-stream",
115
+ },
116
+ };
117
+ const notificationResult = await stdioClient.request(
118
+ request,
119
+ CallToolResultSchema,
120
+ );
121
+
122
+ expect(notificationResult).toEqual({
123
+ content: [
124
+ {
125
+ text: "Started sending periodic notifications every 1000ms",
126
+ type: "text",
127
+ },
128
+ ],
129
+ });
130
+
131
+ expect(notificationCount).toEqual(2);
132
+
133
+ await stdioClient.close();
134
+ });
135
+
136
+ it("proxies messages between stdio and stream able servers", async () => {
137
+ const stdioTransport = new StdioClientTransport({
138
+ args: [
139
+ "src/simple-stdio-proxy-server.ts",
140
+ JSON.stringify({
141
+ serverType: ServerType.HTTPStream,
142
+ url: "http://127.0.0.1:3000/mcp",
143
+ }),
144
+ ],
145
+ command: "tsx",
146
+ });
147
+
148
+ const stdioClient = new Client(
149
+ {
150
+ name: "mcp-proxy",
151
+ version: "1.0.0",
152
+ },
153
+ {
154
+ capabilities: {},
155
+ },
156
+ );
157
+
158
+ let notificationCount = 0;
159
+
160
+ stdioClient.setNotificationHandler(
161
+ LoggingMessageNotificationSchema,
162
+ (notification) => {
163
+ console.log(
164
+ `Notification: ${notification.params.level} - ${notification.params.data}`,
165
+ );
166
+ notificationCount++;
167
+ },
168
+ );
169
+
170
+ await stdioClient.connect(stdioTransport);
171
+
172
+ const result = await stdioClient.listTools();
173
+
174
+ expect(result).toEqual({
175
+ tools: [
176
+ {
177
+ description:
178
+ "Starts sending periodic notifications for testing resumability",
179
+ inputSchema: {
180
+ $schema: "http://json-schema.org/draft-07/schema#",
181
+ additionalProperties: false,
182
+ properties: {
183
+ count: {
184
+ default: 50,
185
+ description: "Number of notifications to send (0 for 100)",
186
+ type: "number",
187
+ },
188
+ interval: {
189
+ default: 100,
190
+ description: "Interval in milliseconds between notifications",
191
+ type: "number",
192
+ },
193
+ },
194
+ type: "object",
195
+ },
196
+ name: "start-notification-stream",
197
+ },
198
+ ],
199
+ });
200
+ const request = {
201
+ method: "tools/call",
202
+ params: {
203
+ arguments: {
204
+ count: 2, // Send 5 notifications
205
+ interval: 1000, // 1 second between notifications
206
+ },
207
+ name: "start-notification-stream",
208
+ },
209
+ };
210
+ const notificationResult = await stdioClient.request(
211
+ request,
212
+ CallToolResultSchema,
213
+ );
214
+
215
+ expect(notificationResult).toEqual({
216
+ content: [
217
+ {
218
+ text: "Started sending periodic notifications every 1000ms",
219
+ type: "text",
220
+ },
221
+ ],
222
+ });
223
+
224
+ expect(notificationCount).toEqual(2);
225
+
226
+ await stdioClient.close();
227
+ });
228
+ });
@@ -0,0 +1,81 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.js";
3
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
4
+ import { StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
6
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+
9
+ import { proxyServer } from "./proxyServer.js";
10
+
11
+ export enum ServerType {
12
+ HTTPStream = "HTTPStream",
13
+ SSE = "SSE",
14
+ }
15
+
16
+ export const startStdioServer = async ({
17
+ initStdioServer,
18
+ initStreamClient,
19
+ serverType,
20
+ transportOptions = {},
21
+ url,
22
+ }: {
23
+ initStdioServer?: () => Promise<Server>;
24
+ initStreamClient?: () => Promise<Client>;
25
+ serverType: ServerType;
26
+ transportOptions?:
27
+ | SSEClientTransportOptions
28
+ | StreamableHTTPClientTransportOptions;
29
+ url: string;
30
+ }): Promise<Server> => {
31
+ let transport: SSEClientTransport | StreamableHTTPClientTransport;
32
+ switch (serverType) {
33
+ case ServerType.SSE:
34
+ transport = new SSEClientTransport(new URL(url), transportOptions);
35
+ break;
36
+ default:
37
+ transport = new StreamableHTTPClientTransport(
38
+ new URL(url),
39
+ transportOptions,
40
+ );
41
+ }
42
+ const streamClient = initStreamClient
43
+ ? await initStreamClient()
44
+ : new Client(
45
+ {
46
+ name: "mcp-proxy",
47
+ version: "1.0.0",
48
+ },
49
+ {
50
+ capabilities: {},
51
+ },
52
+ );
53
+ await streamClient.connect(transport);
54
+
55
+ const serverVersion = streamClient.getServerVersion() as {
56
+ name: string;
57
+ version: string;
58
+ };
59
+
60
+ const serverCapabilities = streamClient.getServerCapabilities() as {
61
+ capabilities: Record<string, unknown>;
62
+ };
63
+
64
+ const stdioServer = initStdioServer
65
+ ? await initStdioServer()
66
+ : new Server(serverVersion, {
67
+ capabilities: serverCapabilities,
68
+ });
69
+
70
+ const stdioTransport = new StdioServerTransport();
71
+
72
+ await stdioServer.connect(stdioTransport);
73
+
74
+ await proxyServer({
75
+ client: streamClient,
76
+ server: stdioServer,
77
+ serverCapabilities,
78
+ });
79
+
80
+ return stdioServer;
81
+ };
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/InMemoryEventStore.ts","../src/proxyServer.ts","../src/startHTTPStreamServer.ts","../src/startSSEServer.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 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 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 this.events.set(eventId, { message, streamId });\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 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}) => {\n if (serverCapabilities?.logging) {\n server.setNotificationHandler(\n LoggingMessageNotificationSchema,\n async (args) => {\n return client.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 {\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\nexport const startHTTPStreamServer = async <T extends ServerLike>({\n createServer,\n endpoint,\n eventStore,\n onClose,\n onConnect,\n onUnhandledRequest,\n port,\n}: {\n createServer: (request: http.IncomingMessage) => Promise<T>;\n endpoint: string;\n eventStore?: EventStore;\n onClose?: (server: T) => void;\n onConnect?: (server: T) => void;\n onUnhandledRequest?: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ) => Promise<void>;\n port: number;\n}): Promise<SSEServer> => {\n const activeTransports: 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 } catch (error) {\n console.error(\"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 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 let transport: StreamableHTTPServerTransport;\n let server: T;\n\n const body = await getBody(req);\n\n if (sessionId && activeTransports[sessionId]) {\n transport = activeTransports[sessionId].transport;\n server = activeTransports[sessionId].server;\n } else if (!sessionId && isInitializeRequest(body)) {\n // Create a new transport for the session\n transport = new StreamableHTTPServerTransport({\n eventStore: eventStore || new InMemoryEventStore(),\n onsessioninitialized: (_sessionId) => {\n // add only when the id Sesison id is generated\n activeTransports[_sessionId] = {\n server,\n transport,\n };\n },\n sessionIdGenerator: randomUUID,\n });\n\n // Handle the server close event\n transport.onclose = async () => {\n const sid = transport.sessionId;\n if (sid && activeTransports[sid]) {\n onClose?.(server);\n try {\n await server.close();\n } catch (error) {\n console.error(\"Error closing server:\", error);\n }\n delete activeTransports[sid];\n }\n };\n\n // Create the server\n try {\n server = await createServer(req);\n } catch (error) {\n if (error instanceof Response) {\n res.writeHead(error.status).end(error.statusText);\n return;\n }\n res.writeHead(500).end(\"Error creating server\");\n return;\n }\n\n server.connect(transport);\n onConnect?.(server);\n\n await transport.handleRequest(req, res, body);\n return;\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 res.writeHead(400).end(\n JSON.stringify({\n error: {\n code: -32000,\n message: \"Bad Request: No valid session ID provided\",\n },\n id: null,\n jsonrpc: \"2.0\",\n }),\n );\n\n return;\n }\n\n // Handle ther request if the server is already created\n await transport.handleRequest(req, res, body);\n } catch (error) {\n console.error(\"Error handling request:\", error);\n res.setHeader(\"Content-Type\", \"application/json\");\n res.writeHead(500).end(\n JSON.stringify({\n error: { code: -32603, message: \"Internal Server Error\" },\n id: null,\n jsonrpc: \"2.0\",\n }),\n );\n }\n return;\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 return;\n }\n\n if (!activeTransport) {\n res.writeHead(400).end(\"No active transport\");\n return;\n }\n\n const lastEventId = req.headers[\"last-event-id\"] as string | undefined;\n if (lastEventId) {\n console.log(`Client reconnecting with Last-Event-ID: ${lastEventId}`);\n } else {\n console.log(`Establishing new SSE stream for session ${sessionId}`);\n }\n\n await activeTransport.transport.handleRequest(req, res);\n return;\n }\n\n if (\n req.method === \"DELETE\" &&\n new URL(req.url!, \"http://localhost\").pathname === endpoint\n ) {\n console.log(\"received delete request\");\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n if (!sessionId) {\n res.writeHead(400).end(\"Invalid or missing sessionId\");\n return;\n }\n\n console.log(\"received delete request for session\", sessionId);\n\n const { server, transport } = activeTransports[sessionId];\n if (!transport) {\n res.writeHead(400).end(\"No active transport\");\n return;\n }\n\n try {\n await transport.handleRequest(req, res);\n onClose?.(server);\n } catch (error) {\n console.error(\"Error handling delete request:\", error);\n res.writeHead(500).end(\"Error handling delete request\");\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, \"::\", () => {\n resolve(undefined);\n });\n });\n\n return {\n close: async () => {\n for (const transport of Object.values(activeTransports)) {\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\nfunction 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 resolve(JSON.parse(body));\n });\n });\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport http from \"http\";\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype ServerLike = {\n close: Server[\"close\"];\n connect: Server[\"connect\"];\n};\n\nexport const startSSEServer = async <T extends ServerLike>({\n createServer,\n endpoint,\n onClose,\n onConnect,\n onUnhandledRequest,\n port,\n}: {\n createServer: (request: http.IncomingMessage) => Promise<T>;\n endpoint: string;\n onClose?: (server: T) => void;\n onConnect?: (server: T) => void;\n onUnhandledRequest?: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ) => Promise<void>;\n port: number;\n}): Promise<SSEServer> => {\n const activeTransports: Record<string, SSEServerTransport> = {};\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 } catch (error) {\n console.error(\"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 === \"/health\") {\n res.writeHead(200, { \"Content-Type\": \"text/plain\" }).end(\"OK\");\n return;\n }\n\n if (req.method === \"GET\" && req.url === `/ping`) {\n res.writeHead(200).end(\"pong\");\n\n return;\n }\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 (error instanceof Response) {\n res.writeHead(error.status).end(error.statusText);\n\n return;\n }\n\n res.writeHead(500).end(\"Error creating server\");\n\n return;\n }\n\n activeTransports[transport.sessionId] = transport;\n\n let closed = false;\n\n res.on(\"close\", async () => {\n closed = true;\n\n try {\n await server.close();\n } catch (error) {\n console.error(\"Error closing server:\", error);\n }\n\n delete activeTransports[transport.sessionId];\n\n onClose?.(server);\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 onConnect?.(server);\n } catch (error) {\n if (!closed) {\n console.error(\"Error connecting to server:\", error);\n\n res.writeHead(500).end(\"Error connecting to server\");\n }\n }\n\n return;\n }\n\n if (req.method === \"POST\" && req.url?.startsWith(\"/messages\")) {\n const sessionId = new URL(\n req.url,\n \"https://example.com\",\n ).searchParams.get(\"sessionId\");\n\n if (!sessionId) {\n res.writeHead(400).end(\"No sessionId\");\n\n return;\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;\n }\n\n await activeTransport.handlePostMessage(req, res);\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, \"::\", () => {\n resolve(undefined);\n });\n });\n\n return {\n close: async () => {\n for (const transport of Object.values(activeTransports)) {\n await 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":["http"]}