mcp-proxy 2.0.1 → 2.1.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.
@@ -1,4 +1,3 @@
1
- import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
2
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
2
  import { ServerCapabilities, JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
4
3
  import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
@@ -29,12 +28,15 @@ declare const proxyServer: ({ server, client, serverCapabilities, }: {
29
28
  type SSEServer = {
30
29
  close: () => Promise<void>;
31
30
  };
32
- declare const startSSEServer: ({ port, createServer, endpoint, onConnect, onClose, }: {
31
+ type ServerLike = {
32
+ connect: Server['connect'];
33
+ };
34
+ declare const startSSEServer: <T extends ServerLike>({ port, createServer, endpoint, onConnect, onClose, }: {
33
35
  port: number;
34
36
  endpoint: string;
35
- createServer: (transport: SSEServerTransport) => Promise<Server>;
36
- onConnect?: (server: Server) => void;
37
- onClose?: (server: Server) => void;
37
+ createServer: () => Promise<T>;
38
+ onConnect?: (server: T) => void;
39
+ onClose?: (server: T) => void;
38
40
  }) => Promise<SSEServer>;
39
41
 
40
42
  export { type SSEServer, proxyServer, startSSEServer, tapTransport };
package/dist/MCPProxy.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  proxyServer,
3
3
  startSSEServer,
4
4
  tapTransport
5
- } from "./chunk-QXFLPSO5.js";
5
+ } from "./chunk-AEY3ZUXJ.js";
6
6
  export {
7
7
  proxyServer,
8
8
  startSSEServer,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  proxyServer,
4
4
  startSSEServer
5
- } from "../chunk-QXFLPSO5.js";
5
+ } from "../chunk-AEY3ZUXJ.js";
6
6
 
7
7
  // src/bin/mcp-proxy.ts
8
8
  import yargs from "yargs";
@@ -109,11 +109,6 @@ var proxyServer = async ({
109
109
  };
110
110
  var startSending = async (transport) => {
111
111
  try {
112
- await transport.send({
113
- jsonrpc: "2.0",
114
- method: "sse/connection",
115
- params: { message: "SSE Connection established" }
116
- });
117
112
  let messageCount = 0;
118
113
  const interval = setInterval(async () => {
119
114
  messageCount++;
@@ -158,17 +153,21 @@ var startSSEServer = async ({
158
153
  }
159
154
  if (req.method === "GET" && req.url === endpoint) {
160
155
  const transport = new SSEServerTransport("/messages", res);
161
- const server = await createServer(transport);
156
+ const server = await createServer();
162
157
  activeTransports[transport.sessionId] = transport;
163
158
  await server.connect(transport);
159
+ await transport.send({
160
+ jsonrpc: "2.0",
161
+ method: "sse/connection",
162
+ params: { message: "SSE Connection established" }
163
+ });
164
+ onConnect?.(server);
164
165
  res.on("close", () => {
165
166
  console.log("SSE connection closed");
166
167
  delete activeTransports[transport.sessionId];
167
168
  onClose?.(server);
168
169
  });
169
- startSending(transport).then(() => {
170
- onConnect?.(server);
171
- });
170
+ startSending(transport);
172
171
  return;
173
172
  }
174
173
  if (req.method === "POST" && req.url?.startsWith("/messages")) {
@@ -217,4 +216,4 @@ export {
217
216
  proxyServer,
218
217
  startSSEServer
219
218
  };
220
- //# sourceMappingURL=chunk-QXFLPSO5.js.map
219
+ //# sourceMappingURL=chunk-AEY3ZUXJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/MCPProxy.ts"],"sourcesContent":["import { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport http from \"http\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n CallToolRequestSchema,\n CompleteRequestSchema,\n GetPromptRequestSchema,\n JSONRPCMessage,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n LoggingMessageNotificationSchema,\n ReadResourceRequestSchema,\n ServerCapabilities,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\n\ntype TransportEvent =\n | {\n type: \"close\";\n }\n | {\n type: \"onclose\";\n }\n | {\n type: \"onerror\";\n error: Error;\n }\n | {\n type: \"onmessage\";\n message: JSONRPCMessage;\n }\n | {\n type: \"send\";\n message: JSONRPCMessage;\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 type: \"onerror\",\n error,\n });\n\n return originalOnError?.(error);\n };\n\n transport.onmessage = async (message: JSONRPCMessage) => {\n eventHandler({\n type: \"onmessage\",\n message,\n });\n\n return originalOnMessage?.(message);\n };\n\n transport.send = async (message: JSONRPCMessage) => {\n eventHandler({\n type: \"send\",\n message,\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\nexport const proxyServer = async ({\n server,\n client,\n serverCapabilities,\n}: {\n server: Server;\n client: Client;\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\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\n/**\n * @author https://dev.classmethod.jp/articles/mcp-sse/\n */\nconst startSending = async (transport: SSEServerTransport) => {\n try {\n let messageCount = 0;\n const interval = setInterval(async () => {\n messageCount++;\n\n const message = `Message ${messageCount} at ${new Date().toISOString()}`;\n\n try {\n await transport.send({\n jsonrpc: \"2.0\",\n method: \"sse/message\",\n params: { data: message },\n });\n\n console.log(`Sent: ${message}`);\n\n if (messageCount === 10) {\n clearInterval(interval);\n\n await transport.send({\n jsonrpc: \"2.0\",\n method: \"sse/complete\",\n params: { message: \"Stream completed\" },\n });\n console.log(\"Stream completed\");\n }\n } catch (error) {\n console.error(\"Error sending message:\", error);\n clearInterval(interval);\n }\n }, 1000);\n } catch (error) {\n console.error(\"Error in startSending:\", error);\n }\n};\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype ServerLike = {\n connect: Server['connect'];\n};\n\nexport const startSSEServer = async <T extends ServerLike>({\n port,\n createServer,\n endpoint,\n onConnect,\n onClose,\n}: {\n port: number;\n endpoint: string;\n createServer: () => Promise<T>;\n onConnect?: (server: T) => void;\n onClose?: (server: T) => void;\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.method === \"GET\" && req.url === `/ping`) {\n res.writeHead(200).end(\"pong\");\n\n return;\n }\n\n if (req.method === \"GET\" && req.url === endpoint) {\n const transport = new SSEServerTransport(\"/messages\", res);\n\n const server = await createServer();\n\n activeTransports[transport.sessionId] = transport;\n\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\n res.on(\"close\", () => {\n console.log(\"SSE connection closed\");\n\n delete activeTransports[transport.sessionId];\n\n onClose?.(server);\n });\n\n startSending(transport);\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 res.writeHead(404).end();\n });\n\n httpServer.listen(port, \"::\");\n\n console.error(\n `server is running on SSE at http://localhost:${port}${endpoint}`,\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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-proxy",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "main": "dist/MCPProxy.js",
5
5
  "scripts": {
6
6
  "build": "tsup",
package/src/MCPProxy.ts CHANGED
@@ -170,12 +170,6 @@ export const proxyServer = async ({
170
170
  */
171
171
  const startSending = async (transport: SSEServerTransport) => {
172
172
  try {
173
- await transport.send({
174
- jsonrpc: "2.0",
175
- method: "sse/connection",
176
- params: { message: "SSE Connection established" },
177
- });
178
-
179
173
  let messageCount = 0;
180
174
  const interval = setInterval(async () => {
181
175
  messageCount++;
@@ -215,7 +209,11 @@ export type SSEServer = {
215
209
  close: () => Promise<void>;
216
210
  };
217
211
 
218
- export const startSSEServer = async ({
212
+ type ServerLike = {
213
+ connect: Server['connect'];
214
+ };
215
+
216
+ export const startSSEServer = async <T extends ServerLike>({
219
217
  port,
220
218
  createServer,
221
219
  endpoint,
@@ -224,9 +222,9 @@ export const startSSEServer = async ({
224
222
  }: {
225
223
  port: number;
226
224
  endpoint: string;
227
- createServer: (transport: SSEServerTransport) => Promise<Server>;
228
- onConnect?: (server: Server) => void;
229
- onClose?: (server: Server) => void;
225
+ createServer: () => Promise<T>;
226
+ onConnect?: (server: T) => void;
227
+ onClose?: (server: T) => void;
230
228
  }): Promise<SSEServer> => {
231
229
  const activeTransports: Record<string, SSEServerTransport> = {};
232
230
 
@@ -243,12 +241,20 @@ export const startSSEServer = async ({
243
241
  if (req.method === "GET" && req.url === endpoint) {
244
242
  const transport = new SSEServerTransport("/messages", res);
245
243
 
246
- const server = await createServer(transport);
244
+ const server = await createServer();
247
245
 
248
246
  activeTransports[transport.sessionId] = transport;
249
247
 
250
248
  await server.connect(transport);
251
249
 
250
+ await transport.send({
251
+ jsonrpc: "2.0",
252
+ method: "sse/connection",
253
+ params: { message: "SSE Connection established" },
254
+ });
255
+
256
+ onConnect?.(server);
257
+
252
258
  res.on("close", () => {
253
259
  console.log("SSE connection closed");
254
260
 
@@ -257,9 +263,7 @@ export const startSSEServer = async ({
257
263
  onClose?.(server);
258
264
  });
259
265
 
260
- startSending(transport).then(() => {
261
- onConnect?.(server);
262
- });
266
+ startSending(transport);
263
267
 
264
268
  return;
265
269
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/MCPProxy.ts"],"sourcesContent":["import { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport http from \"http\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n CallToolRequestSchema,\n CompleteRequestSchema,\n GetPromptRequestSchema,\n JSONRPCMessage,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n LoggingMessageNotificationSchema,\n ReadResourceRequestSchema,\n ServerCapabilities,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\n\ntype TransportEvent =\n | {\n type: \"close\";\n }\n | {\n type: \"onclose\";\n }\n | {\n type: \"onerror\";\n error: Error;\n }\n | {\n type: \"onmessage\";\n message: JSONRPCMessage;\n }\n | {\n type: \"send\";\n message: JSONRPCMessage;\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 type: \"onerror\",\n error,\n });\n\n return originalOnError?.(error);\n };\n\n transport.onmessage = async (message: JSONRPCMessage) => {\n eventHandler({\n type: \"onmessage\",\n message,\n });\n\n return originalOnMessage?.(message);\n };\n\n transport.send = async (message: JSONRPCMessage) => {\n eventHandler({\n type: \"send\",\n message,\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\nexport const proxyServer = async ({\n server,\n client,\n serverCapabilities,\n}: {\n server: Server;\n client: Client;\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\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\n/**\n * @author https://dev.classmethod.jp/articles/mcp-sse/\n */\nconst startSending = async (transport: SSEServerTransport) => {\n try {\n await transport.send({\n jsonrpc: \"2.0\",\n method: \"sse/connection\",\n params: { message: \"SSE Connection established\" },\n });\n\n let messageCount = 0;\n const interval = setInterval(async () => {\n messageCount++;\n\n const message = `Message ${messageCount} at ${new Date().toISOString()}`;\n\n try {\n await transport.send({\n jsonrpc: \"2.0\",\n method: \"sse/message\",\n params: { data: message },\n });\n\n console.log(`Sent: ${message}`);\n\n if (messageCount === 10) {\n clearInterval(interval);\n\n await transport.send({\n jsonrpc: \"2.0\",\n method: \"sse/complete\",\n params: { message: \"Stream completed\" },\n });\n console.log(\"Stream completed\");\n }\n } catch (error) {\n console.error(\"Error sending message:\", error);\n clearInterval(interval);\n }\n }, 1000);\n } catch (error) {\n console.error(\"Error in startSending:\", error);\n }\n};\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\nexport const startSSEServer = async ({\n port,\n createServer,\n endpoint,\n onConnect,\n onClose,\n}: {\n port: number;\n endpoint: string;\n createServer: (transport: SSEServerTransport) => Promise<Server>;\n onConnect?: (server: Server) => void;\n onClose?: (server: Server) => void;\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.method === \"GET\" && req.url === `/ping`) {\n res.writeHead(200).end(\"pong\");\n\n return;\n }\n\n if (req.method === \"GET\" && req.url === endpoint) {\n const transport = new SSEServerTransport(\"/messages\", res);\n\n const server = await createServer(transport);\n\n activeTransports[transport.sessionId] = transport;\n\n await server.connect(transport);\n\n res.on(\"close\", () => {\n console.log(\"SSE connection closed\");\n\n delete activeTransports[transport.sessionId];\n\n onClose?.(server);\n });\n\n startSending(transport).then(() => {\n onConnect?.(server);\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 res.writeHead(404).end();\n });\n\n httpServer.listen(port, \"::\");\n\n console.error(\n `server is running on SSE at http://localhost:${port}${endpoint}`,\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":[]}