mcp-proxy 2.8.1 → 2.9.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/dist/mcp-proxy.js +405 -0
- package/dist/mcp-proxy.js.map +1 -0
- package/package.json +3 -4
- package/src/StdioClientTransport.ts +226 -0
- package/src/bin/mcp-proxy.ts +49 -60
- package/src/index.ts +3 -0
- package/src/proxyServer.ts +74 -0
- package/src/{MCPProxy.test.ts → startSSEServer.test.ts} +2 -1
- package/src/{MCPProxy.ts → startSSEServer.ts} +1 -164
- package/src/tapTransport.ts +90 -0
- package/dist/MCPProxy.d.ts +0 -44
- package/dist/MCPProxy.js +0 -11
- package/dist/MCPProxy.js.map +0 -1
- package/dist/bin/mcp-proxy.js +0 -105
- package/dist/bin/mcp-proxy.js.map +0 -1
- package/dist/chunk-A5VUTWBC.js +0 -227
- package/dist/chunk-A5VUTWBC.js.map +0 -1
- /package/dist/{bin/mcp-proxy.d.ts → mcp-proxy.d.ts} +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
2
|
+
import { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
|
|
4
|
+
type TransportEvent =
|
|
5
|
+
| {
|
|
6
|
+
type: "close";
|
|
7
|
+
}
|
|
8
|
+
| {
|
|
9
|
+
type: "onclose";
|
|
10
|
+
}
|
|
11
|
+
| {
|
|
12
|
+
type: "onerror";
|
|
13
|
+
error: Error;
|
|
14
|
+
}
|
|
15
|
+
| {
|
|
16
|
+
type: "onmessage";
|
|
17
|
+
message: JSONRPCMessage;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
type: "send";
|
|
21
|
+
message: JSONRPCMessage;
|
|
22
|
+
}
|
|
23
|
+
| {
|
|
24
|
+
type: "start";
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const tapTransport = (
|
|
28
|
+
transport: Transport,
|
|
29
|
+
eventHandler: (event: TransportEvent) => void,
|
|
30
|
+
) => {
|
|
31
|
+
const originalClose = transport.close.bind(transport);
|
|
32
|
+
const originalOnClose = transport.onclose?.bind(transport);
|
|
33
|
+
const originalOnError = transport.onerror?.bind(transport);
|
|
34
|
+
const originalOnMessage = transport.onmessage?.bind(transport);
|
|
35
|
+
const originalSend = transport.send.bind(transport);
|
|
36
|
+
const originalStart = transport.start.bind(transport);
|
|
37
|
+
|
|
38
|
+
transport.close = async () => {
|
|
39
|
+
eventHandler({
|
|
40
|
+
type: "close",
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return originalClose?.();
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
transport.onclose = async () => {
|
|
47
|
+
eventHandler({
|
|
48
|
+
type: "onclose",
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return originalOnClose?.();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
transport.onerror = async (error: Error) => {
|
|
55
|
+
eventHandler({
|
|
56
|
+
type: "onerror",
|
|
57
|
+
error,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return originalOnError?.(error);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
transport.onmessage = async (message: JSONRPCMessage) => {
|
|
64
|
+
eventHandler({
|
|
65
|
+
type: "onmessage",
|
|
66
|
+
message,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return originalOnMessage?.(message);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
transport.send = async (message: JSONRPCMessage) => {
|
|
73
|
+
eventHandler({
|
|
74
|
+
type: "send",
|
|
75
|
+
message,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return originalSend?.(message);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
transport.start = async () => {
|
|
82
|
+
eventHandler({
|
|
83
|
+
type: "start",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return originalStart?.();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return transport;
|
|
90
|
+
};
|
package/dist/MCPProxy.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import http from 'http';
|
|
2
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
-
import { JSONRPCMessage, ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
-
import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
5
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
6
|
-
|
|
7
|
-
type TransportEvent = {
|
|
8
|
-
type: "close";
|
|
9
|
-
} | {
|
|
10
|
-
type: "onclose";
|
|
11
|
-
} | {
|
|
12
|
-
type: "onerror";
|
|
13
|
-
error: Error;
|
|
14
|
-
} | {
|
|
15
|
-
type: "onmessage";
|
|
16
|
-
message: JSONRPCMessage;
|
|
17
|
-
} | {
|
|
18
|
-
type: "send";
|
|
19
|
-
message: JSONRPCMessage;
|
|
20
|
-
} | {
|
|
21
|
-
type: "start";
|
|
22
|
-
};
|
|
23
|
-
declare const tapTransport: (transport: Transport, eventHandler: (event: TransportEvent) => void) => Transport;
|
|
24
|
-
declare const proxyServer: ({ server, client, serverCapabilities, }: {
|
|
25
|
-
server: Server;
|
|
26
|
-
client: Client;
|
|
27
|
-
serverCapabilities: ServerCapabilities;
|
|
28
|
-
}) => Promise<void>;
|
|
29
|
-
type SSEServer = {
|
|
30
|
-
close: () => Promise<void>;
|
|
31
|
-
};
|
|
32
|
-
type ServerLike = {
|
|
33
|
-
connect: Server["connect"];
|
|
34
|
-
close: Server["close"];
|
|
35
|
-
};
|
|
36
|
-
declare const startSSEServer: <T extends ServerLike>({ port, createServer, endpoint, onConnect, onClose, }: {
|
|
37
|
-
port: number;
|
|
38
|
-
endpoint: string;
|
|
39
|
-
createServer: (request: http.IncomingMessage) => Promise<T>;
|
|
40
|
-
onConnect?: (server: T) => void;
|
|
41
|
-
onClose?: (server: T) => void;
|
|
42
|
-
}) => Promise<SSEServer>;
|
|
43
|
-
|
|
44
|
-
export { type SSEServer, proxyServer, startSSEServer, tapTransport };
|
package/dist/MCPProxy.js
DELETED
package/dist/MCPProxy.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/bin/mcp-proxy.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
proxyServer,
|
|
4
|
-
startSSEServer
|
|
5
|
-
} from "../chunk-A5VUTWBC.js";
|
|
6
|
-
|
|
7
|
-
// src/bin/mcp-proxy.ts
|
|
8
|
-
import yargs from "yargs";
|
|
9
|
-
import { hideBin } from "yargs/helpers";
|
|
10
|
-
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
11
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
12
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
13
|
-
import { EventSource } from "eventsource";
|
|
14
|
-
import { setTimeout } from "node:timers/promises";
|
|
15
|
-
import multiline from "multiline-ts";
|
|
16
|
-
if (!("EventSource" in global)) {
|
|
17
|
-
global.EventSource = EventSource;
|
|
18
|
-
}
|
|
19
|
-
var argv = await yargs(hideBin(process.argv)).scriptName("mcp-proxy").command("$0 <command> [args...]", "Run a command with MCP arguments").positional("command", {
|
|
20
|
-
type: "string",
|
|
21
|
-
describe: "The command to run",
|
|
22
|
-
demandOption: true
|
|
23
|
-
}).positional("args", {
|
|
24
|
-
type: "string",
|
|
25
|
-
array: true,
|
|
26
|
-
describe: "The arguments to pass to the command"
|
|
27
|
-
}).options({
|
|
28
|
-
debug: {
|
|
29
|
-
type: "boolean",
|
|
30
|
-
describe: "Enable debug logging",
|
|
31
|
-
default: false
|
|
32
|
-
},
|
|
33
|
-
endpoint: {
|
|
34
|
-
type: "string",
|
|
35
|
-
describe: "The endpoint to listen on for SSE",
|
|
36
|
-
default: "/sse"
|
|
37
|
-
},
|
|
38
|
-
port: {
|
|
39
|
-
type: "number",
|
|
40
|
-
describe: "The port to listen on for SSE",
|
|
41
|
-
default: 8080
|
|
42
|
-
}
|
|
43
|
-
}).help().parseAsync();
|
|
44
|
-
var transport = new StdioClientTransport({
|
|
45
|
-
command: argv.command,
|
|
46
|
-
args: argv.args,
|
|
47
|
-
env: process.env,
|
|
48
|
-
stderr: "pipe"
|
|
49
|
-
});
|
|
50
|
-
var client = new Client(
|
|
51
|
-
{
|
|
52
|
-
name: "mcp-proxy",
|
|
53
|
-
version: "1.0.0"
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
capabilities: {}
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
var stderrOutput = "";
|
|
60
|
-
try {
|
|
61
|
-
console.info("connecting to the MCP server...");
|
|
62
|
-
const connectionPromise = client.connect(transport);
|
|
63
|
-
transport?.stderr?.on("data", (chunk) => {
|
|
64
|
-
stderrOutput += chunk.toString();
|
|
65
|
-
});
|
|
66
|
-
await connectionPromise;
|
|
67
|
-
console.info("connected to the MCP server");
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error(multiline`
|
|
70
|
-
could not connect to the MCP server
|
|
71
|
-
|
|
72
|
-
--- error ---
|
|
73
|
-
${String(error)}
|
|
74
|
-
|
|
75
|
-
--- stderr output ---
|
|
76
|
-
${stderrOutput}
|
|
77
|
-
`);
|
|
78
|
-
await setTimeout(1e3);
|
|
79
|
-
process.exit(1);
|
|
80
|
-
}
|
|
81
|
-
var serverVersion = client.getServerVersion();
|
|
82
|
-
var serverCapabilities = client.getServerCapabilities();
|
|
83
|
-
try {
|
|
84
|
-
console.info("starting the SSE server on port %d", argv.port);
|
|
85
|
-
await startSSEServer({
|
|
86
|
-
createServer: async () => {
|
|
87
|
-
const server = new Server(serverVersion, {
|
|
88
|
-
capabilities: serverCapabilities
|
|
89
|
-
});
|
|
90
|
-
proxyServer({
|
|
91
|
-
server,
|
|
92
|
-
client,
|
|
93
|
-
serverCapabilities
|
|
94
|
-
});
|
|
95
|
-
return server;
|
|
96
|
-
},
|
|
97
|
-
port: argv.port,
|
|
98
|
-
endpoint: argv.endpoint
|
|
99
|
-
});
|
|
100
|
-
} catch (error) {
|
|
101
|
-
console.error("could not start the SSE server", error);
|
|
102
|
-
await setTimeout(1e3);
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
|
-
//# sourceMappingURL=mcp-proxy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/mcp-proxy.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { proxyServer, startSSEServer } from \"../MCPProxy.js\";\nimport { EventSource } from \"eventsource\";\nimport { setTimeout } from \"node:timers/promises\";\nimport multiline from 'multiline-ts';\n\nif (!(\"EventSource\" in global)) {\n // @ts-expect-error - figure out how to use --experimental-eventsource with vitest\n global.EventSource = EventSource;\n}\n\nconst argv = await yargs(hideBin(process.argv))\n .scriptName(\"mcp-proxy\")\n .command(\"$0 <command> [args...]\", \"Run a command with MCP arguments\")\n .positional(\"command\", {\n type: \"string\",\n describe: \"The command to run\",\n demandOption: true,\n })\n .positional(\"args\", {\n type: \"string\",\n array: true,\n describe: \"The arguments to pass to the command\",\n })\n .options({\n debug: {\n type: \"boolean\",\n describe: \"Enable debug logging\",\n default: false,\n },\n endpoint: {\n type: \"string\",\n describe: \"The endpoint to listen on for SSE\",\n default: \"/sse\",\n },\n port: {\n type: \"number\",\n describe: \"The port to listen on for SSE\",\n default: 8080,\n },\n })\n .help()\n .parseAsync();\n\nconst transport = new StdioClientTransport({\n command: argv.command,\n args: argv.args,\n env: process.env as Record<string, string>,\n stderr: 'pipe',\n});\n\nconst client = new Client(\n {\n name: \"mcp-proxy\",\n version: \"1.0.0\",\n },\n {\n capabilities: {},\n },\n);\n\n\nlet stderrOutput = '';\n\ntry {\n console.info('connecting to the MCP server...');\n\n const connectionPromise = client.connect(transport);\n\n transport?.stderr?.on('data', (chunk) => {\n stderrOutput += chunk.toString();\n });\n\n await connectionPromise;\n\n console.info('connected to the MCP server');\n} catch (error) {\n console.error(multiline`\n could not connect to the MCP server\n\n --- error ---\n ${String(error)}\n\n --- stderr output ---\n ${stderrOutput}\n`);\n\n await setTimeout(1000);\n\n process.exit(1);\n}\n\nconst serverVersion = client.getServerVersion() as {\n name: string;\n version: string;\n};\n\nconst serverCapabilities = client.getServerCapabilities() as {};\n\ntry {\n console.info('starting the SSE server on port %d', argv.port);\n\n await startSSEServer({\n createServer: async () => {\n const server = new Server(serverVersion, {\n capabilities: serverCapabilities,\n });\n \n proxyServer({\n server,\n client,\n serverCapabilities,\n });\n \n return server;\n },\n port: argv.port,\n endpoint: argv.endpoint as `/${string}`,\n });\n} catch (error) {\n console.error('could not start the SSE server', error);\n\n await setTimeout(1000);\n\n process.exit(1);\n}\n"],"mappings":";;;;;;;AAEA,OAAO,WAAW;AAClB,SAAS,eAAe;AACxB,SAAS,4BAA4B;AACrC,SAAS,cAAc;AACvB,SAAS,cAAc;AAEvB,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,OAAO,eAAe;AAEtB,IAAI,EAAE,iBAAiB,SAAS;AAE9B,SAAO,cAAc;AACvB;AAEA,IAAM,OAAO,MAAM,MAAM,QAAQ,QAAQ,IAAI,CAAC,EAC3C,WAAW,WAAW,EACtB,QAAQ,0BAA0B,kCAAkC,EACpE,WAAW,WAAW;AAAA,EACrB,MAAM;AAAA,EACN,UAAU;AAAA,EACV,cAAc;AAChB,CAAC,EACA,WAAW,QAAQ;AAAA,EAClB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AACZ,CAAC,EACA,QAAQ;AAAA,EACP,OAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AACF,CAAC,EACA,KAAK,EACL,WAAW;AAEd,IAAM,YAAY,IAAI,qBAAqB;AAAA,EACzC,SAAS,KAAK;AAAA,EACd,MAAM,KAAK;AAAA,EACX,KAAK,QAAQ;AAAA,EACb,QAAQ;AACV,CAAC;AAED,IAAM,SAAS,IAAI;AAAA,EACjB;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,cAAc,CAAC;AAAA,EACjB;AACF;AAGA,IAAI,eAAe;AAEnB,IAAI;AACF,UAAQ,KAAK,iCAAiC;AAE9C,QAAM,oBAAoB,OAAO,QAAQ,SAAS;AAElD,aAAW,QAAQ,GAAG,QAAQ,CAAC,UAAU;AACvC,oBAAgB,MAAM,SAAS;AAAA,EACjC,CAAC;AAED,QAAM;AAEN,UAAQ,KAAK,6BAA6B;AAC5C,SAAS,OAAO;AACd,UAAQ,MAAM;AAAA;AAAA;AAAA;AAAA,MAIV,OAAO,KAAK,CAAC;AAAA;AAAA;AAAA,MAGb,YAAY;AAAA,CACjB;AAEC,QAAM,WAAW,GAAI;AAErB,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,gBAAgB,OAAO,iBAAiB;AAK9C,IAAM,qBAAqB,OAAO,sBAAsB;AAExD,IAAI;AACF,UAAQ,KAAK,sCAAsC,KAAK,IAAI;AAE5D,QAAM,eAAe;AAAA,IACnB,cAAc,YAAY;AACxB,YAAM,SAAS,IAAI,OAAO,eAAe;AAAA,QACvC,cAAc;AAAA,MAChB,CAAC;AAED,kBAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT;AAAA,IACA,MAAM,KAAK;AAAA,IACX,UAAU,KAAK;AAAA,EACjB,CAAC;AACH,SAAS,OAAO;AACd,UAAQ,MAAM,kCAAkC,KAAK;AAErD,QAAM,WAAW,GAAI;AAErB,UAAQ,KAAK,CAAC;AAChB;","names":[]}
|
package/dist/chunk-A5VUTWBC.js
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
// src/MCPProxy.ts
|
|
2
|
-
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
3
|
-
import http from "http";
|
|
4
|
-
import {
|
|
5
|
-
CallToolRequestSchema,
|
|
6
|
-
CompleteRequestSchema,
|
|
7
|
-
GetPromptRequestSchema,
|
|
8
|
-
ListPromptsRequestSchema,
|
|
9
|
-
ListResourcesRequestSchema,
|
|
10
|
-
ListResourceTemplatesRequestSchema,
|
|
11
|
-
ListToolsRequestSchema,
|
|
12
|
-
LoggingMessageNotificationSchema,
|
|
13
|
-
ReadResourceRequestSchema
|
|
14
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
15
|
-
var tapTransport = (transport, eventHandler) => {
|
|
16
|
-
const originalClose = transport.close.bind(transport);
|
|
17
|
-
const originalOnClose = transport.onclose?.bind(transport);
|
|
18
|
-
const originalOnError = transport.onerror?.bind(transport);
|
|
19
|
-
const originalOnMessage = transport.onmessage?.bind(transport);
|
|
20
|
-
const originalSend = transport.send.bind(transport);
|
|
21
|
-
const originalStart = transport.start.bind(transport);
|
|
22
|
-
transport.close = async () => {
|
|
23
|
-
eventHandler({
|
|
24
|
-
type: "close"
|
|
25
|
-
});
|
|
26
|
-
return originalClose?.();
|
|
27
|
-
};
|
|
28
|
-
transport.onclose = async () => {
|
|
29
|
-
eventHandler({
|
|
30
|
-
type: "onclose"
|
|
31
|
-
});
|
|
32
|
-
return originalOnClose?.();
|
|
33
|
-
};
|
|
34
|
-
transport.onerror = async (error) => {
|
|
35
|
-
eventHandler({
|
|
36
|
-
type: "onerror",
|
|
37
|
-
error
|
|
38
|
-
});
|
|
39
|
-
return originalOnError?.(error);
|
|
40
|
-
};
|
|
41
|
-
transport.onmessage = async (message) => {
|
|
42
|
-
eventHandler({
|
|
43
|
-
type: "onmessage",
|
|
44
|
-
message
|
|
45
|
-
});
|
|
46
|
-
return originalOnMessage?.(message);
|
|
47
|
-
};
|
|
48
|
-
transport.send = async (message) => {
|
|
49
|
-
eventHandler({
|
|
50
|
-
type: "send",
|
|
51
|
-
message
|
|
52
|
-
});
|
|
53
|
-
return originalSend?.(message);
|
|
54
|
-
};
|
|
55
|
-
transport.start = async () => {
|
|
56
|
-
eventHandler({
|
|
57
|
-
type: "start"
|
|
58
|
-
});
|
|
59
|
-
return originalStart?.();
|
|
60
|
-
};
|
|
61
|
-
return transport;
|
|
62
|
-
};
|
|
63
|
-
var proxyServer = async ({
|
|
64
|
-
server,
|
|
65
|
-
client,
|
|
66
|
-
serverCapabilities
|
|
67
|
-
}) => {
|
|
68
|
-
if (serverCapabilities?.logging) {
|
|
69
|
-
server.setNotificationHandler(
|
|
70
|
-
LoggingMessageNotificationSchema,
|
|
71
|
-
async (args) => {
|
|
72
|
-
return client.notification(args);
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
if (serverCapabilities?.prompts) {
|
|
77
|
-
server.setRequestHandler(GetPromptRequestSchema, async (args) => {
|
|
78
|
-
return client.getPrompt(args.params);
|
|
79
|
-
});
|
|
80
|
-
server.setRequestHandler(ListPromptsRequestSchema, async (args) => {
|
|
81
|
-
return client.listPrompts(args.params);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
if (serverCapabilities?.resources) {
|
|
85
|
-
server.setRequestHandler(ListResourcesRequestSchema, async (args) => {
|
|
86
|
-
return client.listResources(args.params);
|
|
87
|
-
});
|
|
88
|
-
server.setRequestHandler(
|
|
89
|
-
ListResourceTemplatesRequestSchema,
|
|
90
|
-
async (args) => {
|
|
91
|
-
return client.listResourceTemplates(args.params);
|
|
92
|
-
}
|
|
93
|
-
);
|
|
94
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (args) => {
|
|
95
|
-
return client.readResource(args.params);
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
if (serverCapabilities?.tools) {
|
|
99
|
-
server.setRequestHandler(CallToolRequestSchema, async (args) => {
|
|
100
|
-
return client.callTool(args.params);
|
|
101
|
-
});
|
|
102
|
-
server.setRequestHandler(ListToolsRequestSchema, async (args) => {
|
|
103
|
-
return client.listTools(args.params);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
server.setRequestHandler(CompleteRequestSchema, async (args) => {
|
|
107
|
-
return client.complete(args.params);
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
var startSSEServer = async ({
|
|
111
|
-
port,
|
|
112
|
-
createServer,
|
|
113
|
-
endpoint,
|
|
114
|
-
onConnect,
|
|
115
|
-
onClose
|
|
116
|
-
}) => {
|
|
117
|
-
const activeTransports = {};
|
|
118
|
-
const httpServer = http.createServer(async (req, res) => {
|
|
119
|
-
if (req.headers.origin) {
|
|
120
|
-
try {
|
|
121
|
-
const origin = new URL(req.headers.origin);
|
|
122
|
-
res.setHeader("Access-Control-Allow-Origin", origin.origin);
|
|
123
|
-
res.setHeader("Access-Control-Allow-Credentials", "true");
|
|
124
|
-
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
125
|
-
res.setHeader("Access-Control-Allow-Headers", "*");
|
|
126
|
-
} catch (error) {
|
|
127
|
-
console.error("Error parsing origin:", error);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
if (req.method === "OPTIONS") {
|
|
131
|
-
res.writeHead(204);
|
|
132
|
-
res.end();
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
if (req.method === "GET" && req.url === `/ping`) {
|
|
136
|
-
res.writeHead(200).end("pong");
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (req.method === "GET" && req.url === endpoint) {
|
|
140
|
-
const transport = new SSEServerTransport("/messages", res);
|
|
141
|
-
let server;
|
|
142
|
-
try {
|
|
143
|
-
server = await createServer(req);
|
|
144
|
-
} catch (error) {
|
|
145
|
-
if (error instanceof Response) {
|
|
146
|
-
res.writeHead(error.status).end(error.statusText);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
res.writeHead(500).end("Error creating server");
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
activeTransports[transport.sessionId] = transport;
|
|
153
|
-
let closed = false;
|
|
154
|
-
res.on("close", async () => {
|
|
155
|
-
closed = true;
|
|
156
|
-
try {
|
|
157
|
-
await server.close();
|
|
158
|
-
} catch (error) {
|
|
159
|
-
console.error("Error closing server:", error);
|
|
160
|
-
}
|
|
161
|
-
delete activeTransports[transport.sessionId];
|
|
162
|
-
onClose?.(server);
|
|
163
|
-
});
|
|
164
|
-
try {
|
|
165
|
-
await server.connect(transport);
|
|
166
|
-
await transport.send({
|
|
167
|
-
jsonrpc: "2.0",
|
|
168
|
-
method: "sse/connection",
|
|
169
|
-
params: { message: "SSE Connection established" }
|
|
170
|
-
});
|
|
171
|
-
onConnect?.(server);
|
|
172
|
-
} catch (error) {
|
|
173
|
-
if (!closed) {
|
|
174
|
-
console.error("Error connecting to server:", error);
|
|
175
|
-
res.writeHead(500).end("Error connecting to server");
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
if (req.method === "POST" && req.url?.startsWith("/messages")) {
|
|
181
|
-
const sessionId = new URL(
|
|
182
|
-
req.url,
|
|
183
|
-
"https://example.com"
|
|
184
|
-
).searchParams.get("sessionId");
|
|
185
|
-
if (!sessionId) {
|
|
186
|
-
res.writeHead(400).end("No sessionId");
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
const activeTransport = activeTransports[sessionId];
|
|
190
|
-
if (!activeTransport) {
|
|
191
|
-
res.writeHead(400).end("No active transport");
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
await activeTransport.handlePostMessage(req, res);
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
res.writeHead(404).end();
|
|
198
|
-
});
|
|
199
|
-
await new Promise((resolve) => {
|
|
200
|
-
httpServer.listen(port, "::", () => {
|
|
201
|
-
resolve(void 0);
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
return {
|
|
205
|
-
close: async () => {
|
|
206
|
-
for (const transport of Object.values(activeTransports)) {
|
|
207
|
-
await transport.close();
|
|
208
|
-
}
|
|
209
|
-
return new Promise((resolve, reject) => {
|
|
210
|
-
httpServer.close((error) => {
|
|
211
|
-
if (error) {
|
|
212
|
-
reject(error);
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
resolve();
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
export {
|
|
223
|
-
tapTransport,
|
|
224
|
-
proxyServer,
|
|
225
|
-
startSSEServer
|
|
226
|
-
};
|
|
227
|
-
//# sourceMappingURL=chunk-A5VUTWBC.js.map
|
|
@@ -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\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype ServerLike = {\n connect: Server[\"connect\"];\n close: Server[\"close\"];\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: (request: http.IncomingMessage) => 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.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\n return;\n }\n\n if (req.method === \"GET\" && req.url === endpoint) {\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 res.writeHead(404).end();\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":[]}
|
|
File without changes
|