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,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forked from https://github.com/modelcontextprotocol/typescript-sdk/blob/66e1508162d37c0b83b0637ebcd7f07946e3d210/src/client/stdio.ts#L90
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
ReadBuffer,
|
|
7
|
+
serializeMessage,
|
|
8
|
+
} from "@modelcontextprotocol/sdk/shared/stdio.js";
|
|
9
|
+
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
10
|
+
import { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
|
|
11
|
+
import { ChildProcess, IOType, spawn } from "node:child_process";
|
|
12
|
+
import { Stream } from "node:stream";
|
|
13
|
+
|
|
14
|
+
type TransportEvent =
|
|
15
|
+
| {
|
|
16
|
+
type: "close";
|
|
17
|
+
}
|
|
18
|
+
| {
|
|
19
|
+
type: "error";
|
|
20
|
+
error: Error;
|
|
21
|
+
}
|
|
22
|
+
| {
|
|
23
|
+
type: "data";
|
|
24
|
+
chunk: string;
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
type: "message";
|
|
28
|
+
message: JSONRPCMessage;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type StdioServerParameters = {
|
|
32
|
+
/**
|
|
33
|
+
* The executable to run to start the server.
|
|
34
|
+
*/
|
|
35
|
+
command: string;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Command line arguments to pass to the executable.
|
|
39
|
+
*/
|
|
40
|
+
args?: string[];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The environment to use when spawning the process.
|
|
44
|
+
*
|
|
45
|
+
* If not specified, the result of getDefaultEnvironment() will be used.
|
|
46
|
+
*/
|
|
47
|
+
env: Record<string, string>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* How to handle stderr of the child process. This matches the semantics of Node's `child_process.spawn`.
|
|
51
|
+
*
|
|
52
|
+
* The default is "inherit", meaning messages to stderr will be printed to the parent process's stderr.
|
|
53
|
+
*/
|
|
54
|
+
stderr?: IOType | Stream | number;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The working directory to use when spawning the process.
|
|
58
|
+
*
|
|
59
|
+
* If not specified, the current working directory will be inherited.
|
|
60
|
+
*/
|
|
61
|
+
cwd?: string;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A function to call when an event occurs.
|
|
65
|
+
*/
|
|
66
|
+
onEvent?: (event: TransportEvent) => void;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
|
|
71
|
+
*
|
|
72
|
+
* This transport is only available in Node.js environments.
|
|
73
|
+
*/
|
|
74
|
+
export class StdioClientTransport implements Transport {
|
|
75
|
+
private process?: ChildProcess;
|
|
76
|
+
private abortController: AbortController = new AbortController();
|
|
77
|
+
private readBuffer: ReadBuffer = new ReadBuffer();
|
|
78
|
+
private serverParams: StdioServerParameters;
|
|
79
|
+
private onEvent?: (event: TransportEvent) => void;
|
|
80
|
+
|
|
81
|
+
onclose?: () => void;
|
|
82
|
+
onerror?: (error: Error) => void;
|
|
83
|
+
onmessage?: (message: JSONRPCMessage) => void;
|
|
84
|
+
|
|
85
|
+
constructor(server: StdioServerParameters) {
|
|
86
|
+
this.serverParams = server;
|
|
87
|
+
this.onEvent = server.onEvent;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Starts the server process and prepares to communicate with it.
|
|
92
|
+
*/
|
|
93
|
+
async start(): Promise<void> {
|
|
94
|
+
if (this.process) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
"StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.",
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
this.process = spawn(
|
|
102
|
+
this.serverParams.command,
|
|
103
|
+
this.serverParams.args ?? [],
|
|
104
|
+
{
|
|
105
|
+
env: this.serverParams.env,
|
|
106
|
+
stdio: ["pipe", "pipe", this.serverParams.stderr ?? "inherit"],
|
|
107
|
+
shell: false,
|
|
108
|
+
signal: this.abortController.signal,
|
|
109
|
+
cwd: this.serverParams.cwd,
|
|
110
|
+
},
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
this.process.on("error", (error) => {
|
|
114
|
+
if (error.name === "AbortError") {
|
|
115
|
+
// Expected when close() is called.
|
|
116
|
+
this.onclose?.();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
reject(error);
|
|
121
|
+
this.onerror?.(error);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
this.process.on("spawn", () => {
|
|
125
|
+
resolve();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
this.process.on("close", (_code) => {
|
|
129
|
+
this.onEvent?.({
|
|
130
|
+
type: "close",
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
this.process = undefined;
|
|
134
|
+
this.onclose?.();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
this.process.stdin?.on("error", (error) => {
|
|
138
|
+
this.onEvent?.({
|
|
139
|
+
type: "error",
|
|
140
|
+
error,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
this.onerror?.(error);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
this.process.stdout?.on("data", (chunk) => {
|
|
147
|
+
this.onEvent?.({
|
|
148
|
+
type: "data",
|
|
149
|
+
chunk: chunk.toString(),
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
this.readBuffer.append(chunk);
|
|
153
|
+
this.processReadBuffer();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
this.process.stdout?.on("error", (error) => {
|
|
157
|
+
this.onEvent?.({
|
|
158
|
+
type: "error",
|
|
159
|
+
error,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
this.onerror?.(error);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* The stderr stream of the child process, if `StdioServerParameters.stderr` was set to "pipe" or "overlapped".
|
|
169
|
+
*
|
|
170
|
+
* This is only available after the process has been started.
|
|
171
|
+
*/
|
|
172
|
+
get stderr(): Stream | null {
|
|
173
|
+
return this.process?.stderr ?? null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private processReadBuffer() {
|
|
177
|
+
while (true) {
|
|
178
|
+
try {
|
|
179
|
+
const message = this.readBuffer.readMessage();
|
|
180
|
+
|
|
181
|
+
if (message === null) {
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
this.onEvent?.({
|
|
186
|
+
type: "message",
|
|
187
|
+
message,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
this.onmessage?.(message);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
this.onEvent?.({
|
|
193
|
+
type: "error",
|
|
194
|
+
error: error as Error,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
this.onerror?.(error as Error);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async close(): Promise<void> {
|
|
203
|
+
this.onEvent?.({
|
|
204
|
+
type: "close",
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
this.abortController.abort();
|
|
208
|
+
this.process = undefined;
|
|
209
|
+
this.readBuffer.clear();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
send(message: JSONRPCMessage): Promise<void> {
|
|
213
|
+
return new Promise((resolve) => {
|
|
214
|
+
if (!this.process?.stdin) {
|
|
215
|
+
throw new Error("Not connected");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const json = serializeMessage(message);
|
|
219
|
+
if (this.process.stdin.write(json)) {
|
|
220
|
+
resolve();
|
|
221
|
+
} else {
|
|
222
|
+
this.process.stdin.once("drain", resolve);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
package/src/bin/mcp-proxy.ts
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import yargs from "yargs";
|
|
4
4
|
import { hideBin } from "yargs/helpers";
|
|
5
|
-
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
6
5
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
7
6
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8
|
-
import { proxyServer, startSSEServer } from "../MCPProxy.js";
|
|
9
7
|
import { EventSource } from "eventsource";
|
|
10
8
|
import { setTimeout } from "node:timers/promises";
|
|
11
|
-
import
|
|
9
|
+
import { StdioClientTransport } from "../StdioClientTransport.js";
|
|
10
|
+
import util from "node:util";
|
|
11
|
+
import { startSSEServer } from "../startSSEServer.js";
|
|
12
|
+
import { proxyServer } from "../proxyServer.js";
|
|
13
|
+
|
|
14
|
+
util.inspect.defaultOptions.depth = 8;
|
|
12
15
|
|
|
13
16
|
if (!("EventSource" in global)) {
|
|
14
17
|
// @ts-expect-error - figure out how to use --experimental-eventsource with vitest
|
|
@@ -48,85 +51,71 @@ const argv = await yargs(hideBin(process.argv))
|
|
|
48
51
|
.help()
|
|
49
52
|
.parseAsync();
|
|
50
53
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
name: "mcp-proxy",
|
|
61
|
-
version: "1.0.0",
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
capabilities: {},
|
|
65
|
-
},
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
let stderrOutput = '';
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
console.info('connecting to the MCP server...');
|
|
73
|
-
|
|
74
|
-
const connectionPromise = client.connect(transport);
|
|
75
|
-
|
|
76
|
-
transport?.stderr?.on('data', (chunk) => {
|
|
77
|
-
stderrOutput += chunk.toString();
|
|
54
|
+
const connect = async (client: Client) => {
|
|
55
|
+
const transport = new StdioClientTransport({
|
|
56
|
+
command: argv.command,
|
|
57
|
+
args: argv.args,
|
|
58
|
+
env: process.env as Record<string, string>,
|
|
59
|
+
stderr: "pipe",
|
|
60
|
+
onEvent: (event) => {
|
|
61
|
+
console.debug("transport event", event);
|
|
62
|
+
},
|
|
78
63
|
});
|
|
79
64
|
|
|
80
|
-
await
|
|
81
|
-
|
|
82
|
-
console.info('connected to the MCP server');
|
|
83
|
-
} catch (error) {
|
|
84
|
-
console.error(multiline`
|
|
85
|
-
could not connect to the MCP server
|
|
86
|
-
|
|
87
|
-
--- error ---
|
|
88
|
-
${String(error)}
|
|
89
|
-
|
|
90
|
-
--- stderr output ---
|
|
91
|
-
${stderrOutput}
|
|
92
|
-
`);
|
|
65
|
+
await client.connect(transport);
|
|
66
|
+
};
|
|
93
67
|
|
|
94
|
-
|
|
68
|
+
const proxy = async () => {
|
|
69
|
+
const client = new Client(
|
|
70
|
+
{
|
|
71
|
+
name: "mcp-proxy",
|
|
72
|
+
version: "1.0.0",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
capabilities: {},
|
|
76
|
+
},
|
|
77
|
+
);
|
|
95
78
|
|
|
96
|
-
|
|
97
|
-
}
|
|
79
|
+
await connect(client);
|
|
98
80
|
|
|
99
|
-
const serverVersion = client.getServerVersion() as {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
};
|
|
81
|
+
const serverVersion = client.getServerVersion() as {
|
|
82
|
+
name: string;
|
|
83
|
+
version: string;
|
|
84
|
+
};
|
|
103
85
|
|
|
104
|
-
const serverCapabilities = client.getServerCapabilities() as {};
|
|
86
|
+
const serverCapabilities = client.getServerCapabilities() as {};
|
|
105
87
|
|
|
106
|
-
|
|
107
|
-
console.info('starting the SSE server on port %d', argv.port);
|
|
88
|
+
console.info("starting the SSE server on port %d", argv.port);
|
|
108
89
|
|
|
109
90
|
await startSSEServer({
|
|
110
91
|
createServer: async () => {
|
|
111
92
|
const server = new Server(serverVersion, {
|
|
112
93
|
capabilities: serverCapabilities,
|
|
113
94
|
});
|
|
114
|
-
|
|
95
|
+
|
|
115
96
|
proxyServer({
|
|
116
97
|
server,
|
|
117
98
|
client,
|
|
118
99
|
serverCapabilities,
|
|
119
100
|
});
|
|
120
|
-
|
|
101
|
+
|
|
121
102
|
return server;
|
|
122
103
|
},
|
|
123
104
|
port: argv.port,
|
|
124
105
|
endpoint: argv.endpoint as `/${string}`,
|
|
125
106
|
});
|
|
126
|
-
}
|
|
127
|
-
console.error('could not start the SSE server', error);
|
|
107
|
+
};
|
|
128
108
|
|
|
129
|
-
|
|
109
|
+
const main = async () => {
|
|
110
|
+
try {
|
|
111
|
+
await proxy();
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error("could not start the proxy", error);
|
|
130
114
|
|
|
131
|
-
|
|
132
|
-
|
|
115
|
+
await setTimeout(1000);
|
|
116
|
+
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
await main();
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import {
|
|
3
|
+
CallToolRequestSchema,
|
|
4
|
+
CompleteRequestSchema,
|
|
5
|
+
GetPromptRequestSchema,
|
|
6
|
+
ListPromptsRequestSchema,
|
|
7
|
+
ListResourcesRequestSchema,
|
|
8
|
+
ListResourceTemplatesRequestSchema,
|
|
9
|
+
ListToolsRequestSchema,
|
|
10
|
+
LoggingMessageNotificationSchema,
|
|
11
|
+
ReadResourceRequestSchema,
|
|
12
|
+
ServerCapabilities,
|
|
13
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
14
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
15
|
+
|
|
16
|
+
export const proxyServer = async ({
|
|
17
|
+
server,
|
|
18
|
+
client,
|
|
19
|
+
serverCapabilities,
|
|
20
|
+
}: {
|
|
21
|
+
server: Server;
|
|
22
|
+
client: Client;
|
|
23
|
+
serverCapabilities: ServerCapabilities;
|
|
24
|
+
}) => {
|
|
25
|
+
if (serverCapabilities?.logging) {
|
|
26
|
+
server.setNotificationHandler(
|
|
27
|
+
LoggingMessageNotificationSchema,
|
|
28
|
+
async (args) => {
|
|
29
|
+
return client.notification(args);
|
|
30
|
+
},
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (serverCapabilities?.prompts) {
|
|
35
|
+
server.setRequestHandler(GetPromptRequestSchema, async (args) => {
|
|
36
|
+
return client.getPrompt(args.params);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
server.setRequestHandler(ListPromptsRequestSchema, async (args) => {
|
|
40
|
+
return client.listPrompts(args.params);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (serverCapabilities?.resources) {
|
|
45
|
+
server.setRequestHandler(ListResourcesRequestSchema, async (args) => {
|
|
46
|
+
return client.listResources(args.params);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
server.setRequestHandler(
|
|
50
|
+
ListResourceTemplatesRequestSchema,
|
|
51
|
+
async (args) => {
|
|
52
|
+
return client.listResourceTemplates(args.params);
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (args) => {
|
|
57
|
+
return client.readResource(args.params);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (serverCapabilities?.tools) {
|
|
62
|
+
server.setRequestHandler(CallToolRequestSchema, async (args) => {
|
|
63
|
+
return client.callTool(args.params);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
server.setRequestHandler(ListToolsRequestSchema, async (args) => {
|
|
67
|
+
return client.listTools(args.params);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
server.setRequestHandler(CompleteRequestSchema, async (args) => {
|
|
72
|
+
return client.complete(args.params);
|
|
73
|
+
});
|
|
74
|
+
};
|
|
@@ -2,11 +2,12 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
2
2
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
3
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
4
|
import { it, expect, vi } from "vitest";
|
|
5
|
-
import {
|
|
5
|
+
import { startSSEServer } from "./startSSEServer.js";
|
|
6
6
|
import { getRandomPort } from "get-port-please";
|
|
7
7
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
8
8
|
import { EventSource } from "eventsource";
|
|
9
9
|
import { setTimeout as delay } from "node:timers/promises";
|
|
10
|
+
import { proxyServer } from "./proxyServer.js";
|
|
10
11
|
|
|
11
12
|
if (!("EventSource" in global)) {
|
|
12
13
|
// @ts-expect-error - figure out how to use --experimental-eventsource with vitest
|
|
@@ -1,169 +1,6 @@
|
|
|
1
1
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
2
2
|
import http from "http";
|
|
3
3
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
-
import {
|
|
5
|
-
CallToolRequestSchema,
|
|
6
|
-
CompleteRequestSchema,
|
|
7
|
-
GetPromptRequestSchema,
|
|
8
|
-
JSONRPCMessage,
|
|
9
|
-
ListPromptsRequestSchema,
|
|
10
|
-
ListResourcesRequestSchema,
|
|
11
|
-
ListResourceTemplatesRequestSchema,
|
|
12
|
-
ListToolsRequestSchema,
|
|
13
|
-
LoggingMessageNotificationSchema,
|
|
14
|
-
ReadResourceRequestSchema,
|
|
15
|
-
ServerCapabilities,
|
|
16
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
17
|
-
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
18
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
19
|
-
|
|
20
|
-
type TransportEvent =
|
|
21
|
-
| {
|
|
22
|
-
type: "close";
|
|
23
|
-
}
|
|
24
|
-
| {
|
|
25
|
-
type: "onclose";
|
|
26
|
-
}
|
|
27
|
-
| {
|
|
28
|
-
type: "onerror";
|
|
29
|
-
error: Error;
|
|
30
|
-
}
|
|
31
|
-
| {
|
|
32
|
-
type: "onmessage";
|
|
33
|
-
message: JSONRPCMessage;
|
|
34
|
-
}
|
|
35
|
-
| {
|
|
36
|
-
type: "send";
|
|
37
|
-
message: JSONRPCMessage;
|
|
38
|
-
}
|
|
39
|
-
| {
|
|
40
|
-
type: "start";
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const tapTransport = (
|
|
44
|
-
transport: Transport,
|
|
45
|
-
eventHandler: (event: TransportEvent) => void,
|
|
46
|
-
) => {
|
|
47
|
-
const originalClose = transport.close.bind(transport);
|
|
48
|
-
const originalOnClose = transport.onclose?.bind(transport);
|
|
49
|
-
const originalOnError = transport.onerror?.bind(transport);
|
|
50
|
-
const originalOnMessage = transport.onmessage?.bind(transport);
|
|
51
|
-
const originalSend = transport.send.bind(transport);
|
|
52
|
-
const originalStart = transport.start.bind(transport);
|
|
53
|
-
|
|
54
|
-
transport.close = async () => {
|
|
55
|
-
eventHandler({
|
|
56
|
-
type: "close",
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
return originalClose?.();
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
transport.onclose = async () => {
|
|
63
|
-
eventHandler({
|
|
64
|
-
type: "onclose",
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
return originalOnClose?.();
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
transport.onerror = async (error: Error) => {
|
|
71
|
-
eventHandler({
|
|
72
|
-
type: "onerror",
|
|
73
|
-
error,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
return originalOnError?.(error);
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
transport.onmessage = async (message: JSONRPCMessage) => {
|
|
80
|
-
eventHandler({
|
|
81
|
-
type: "onmessage",
|
|
82
|
-
message,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
return originalOnMessage?.(message);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
transport.send = async (message: JSONRPCMessage) => {
|
|
89
|
-
eventHandler({
|
|
90
|
-
type: "send",
|
|
91
|
-
message,
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
return originalSend?.(message);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
transport.start = async () => {
|
|
98
|
-
eventHandler({
|
|
99
|
-
type: "start",
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
return originalStart?.();
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
return transport;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
export const proxyServer = async ({
|
|
109
|
-
server,
|
|
110
|
-
client,
|
|
111
|
-
serverCapabilities,
|
|
112
|
-
}: {
|
|
113
|
-
server: Server;
|
|
114
|
-
client: Client;
|
|
115
|
-
serverCapabilities: ServerCapabilities;
|
|
116
|
-
}) => {
|
|
117
|
-
if (serverCapabilities?.logging) {
|
|
118
|
-
server.setNotificationHandler(
|
|
119
|
-
LoggingMessageNotificationSchema,
|
|
120
|
-
async (args) => {
|
|
121
|
-
return client.notification(args);
|
|
122
|
-
},
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (serverCapabilities?.prompts) {
|
|
127
|
-
server.setRequestHandler(GetPromptRequestSchema, async (args) => {
|
|
128
|
-
return client.getPrompt(args.params);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
server.setRequestHandler(ListPromptsRequestSchema, async (args) => {
|
|
132
|
-
return client.listPrompts(args.params);
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (serverCapabilities?.resources) {
|
|
137
|
-
server.setRequestHandler(ListResourcesRequestSchema, async (args) => {
|
|
138
|
-
return client.listResources(args.params);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
server.setRequestHandler(
|
|
142
|
-
ListResourceTemplatesRequestSchema,
|
|
143
|
-
async (args) => {
|
|
144
|
-
return client.listResourceTemplates(args.params);
|
|
145
|
-
},
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (args) => {
|
|
149
|
-
return client.readResource(args.params);
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (serverCapabilities?.tools) {
|
|
154
|
-
server.setRequestHandler(CallToolRequestSchema, async (args) => {
|
|
155
|
-
return client.callTool(args.params);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
server.setRequestHandler(ListToolsRequestSchema, async (args) => {
|
|
159
|
-
return client.listTools(args.params);
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
server.setRequestHandler(CompleteRequestSchema, async (args) => {
|
|
164
|
-
return client.complete(args.params);
|
|
165
|
-
});
|
|
166
|
-
};
|
|
167
4
|
|
|
168
5
|
export type SSEServer = {
|
|
169
6
|
close: () => Promise<void>;
|
|
@@ -268,7 +105,7 @@ export const startSSEServer = async <T extends ServerLike>({
|
|
|
268
105
|
} catch (error) {
|
|
269
106
|
if (!closed) {
|
|
270
107
|
console.error("Error connecting to server:", error);
|
|
271
|
-
|
|
108
|
+
|
|
272
109
|
res.writeHead(500).end("Error connecting to server");
|
|
273
110
|
}
|
|
274
111
|
}
|