mcp-proxy 2.13.0 → 2.13.1

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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { JSONRPCMessage, ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
2
1
  import { EventStore } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { JSONRPCMessage, ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
4
3
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
5
  import http from 'http';
6
6
  import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
7
7
 
@@ -18,30 +18,30 @@ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
18
18
  declare class InMemoryEventStore implements EventStore {
19
19
  private events;
20
20
  /**
21
- * Generates a unique event ID for a given stream ID
22
- */
23
- private generateEventId;
24
- /**
25
- * Extracts the stream ID from an event ID
21
+ * Replays events that occurred after a specific event ID
22
+ * Implements EventStore.replayEventsAfter
26
23
  */
27
- private getStreamIdFromEventId;
24
+ replayEventsAfter(lastEventId: string, { send, }: {
25
+ send: (eventId: string, message: JSONRPCMessage) => Promise<void>;
26
+ }): Promise<string>;
28
27
  /**
29
28
  * Stores an event with a generated event ID
30
29
  * Implements EventStore.storeEvent
31
30
  */
32
31
  storeEvent(streamId: string, message: JSONRPCMessage): Promise<string>;
33
32
  /**
34
- * Replays events that occurred after a specific event ID
35
- * Implements EventStore.replayEventsAfter
33
+ * Generates a unique event ID for a given stream ID
36
34
  */
37
- replayEventsAfter(lastEventId: string, { send, }: {
38
- send: (eventId: string, message: JSONRPCMessage) => Promise<void>;
39
- }): Promise<string>;
35
+ private generateEventId;
36
+ /**
37
+ * Extracts the stream ID from an event ID
38
+ */
39
+ private getStreamIdFromEventId;
40
40
  }
41
41
 
42
- declare const proxyServer: ({ server, client, serverCapabilities, }: {
43
- server: Server;
42
+ declare const proxyServer: ({ client, server, serverCapabilities, }: {
44
43
  client: Client;
44
+ server: Server;
45
45
  serverCapabilities: ServerCapabilities;
46
46
  }) => Promise<void>;
47
47
 
@@ -49,48 +49,48 @@ type SSEServer$1 = {
49
49
  close: () => Promise<void>;
50
50
  };
51
51
  type ServerLike$1 = {
52
- connect: Server["connect"];
53
52
  close: Server["close"];
53
+ connect: Server["connect"];
54
54
  };
55
- declare const startHTTPStreamServer: <T extends ServerLike$1>({ port, createServer, endpoint, eventStore, onConnect, onClose, onUnhandledRequest, }: {
56
- port: number;
57
- endpoint: string;
55
+ declare const startHTTPStreamServer: <T extends ServerLike$1>({ createServer, endpoint, eventStore, onClose, onConnect, onUnhandledRequest, port, }: {
58
56
  createServer: (request: http.IncomingMessage) => Promise<T>;
57
+ endpoint: string;
59
58
  eventStore?: EventStore;
60
- onConnect?: (server: T) => void;
61
59
  onClose?: (server: T) => void;
60
+ onConnect?: (server: T) => void;
62
61
  onUnhandledRequest?: (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
62
+ port: number;
63
63
  }) => Promise<SSEServer$1>;
64
64
 
65
65
  type SSEServer = {
66
66
  close: () => Promise<void>;
67
67
  };
68
68
  type ServerLike = {
69
- connect: Server["connect"];
70
69
  close: Server["close"];
70
+ connect: Server["connect"];
71
71
  };
72
- declare const startSSEServer: <T extends ServerLike>({ port, createServer, endpoint, onConnect, onClose, onUnhandledRequest, }: {
73
- port: number;
74
- endpoint: string;
72
+ declare const startSSEServer: <T extends ServerLike>({ createServer, endpoint, onClose, onConnect, onUnhandledRequest, port, }: {
75
73
  createServer: (request: http.IncomingMessage) => Promise<T>;
76
- onConnect?: (server: T) => void;
74
+ endpoint: string;
77
75
  onClose?: (server: T) => void;
76
+ onConnect?: (server: T) => void;
78
77
  onUnhandledRequest?: (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
78
+ port: number;
79
79
  }) => Promise<SSEServer>;
80
80
 
81
81
  type TransportEvent = {
82
- type: "close";
83
- } | {
84
- type: "onclose";
85
- } | {
86
- type: "onerror";
87
82
  error: Error;
83
+ type: "onerror";
88
84
  } | {
89
- type: "onmessage";
90
85
  message: JSONRPCMessage;
86
+ type: "onmessage";
91
87
  } | {
92
- type: "send";
93
88
  message: JSONRPCMessage;
89
+ type: "send";
90
+ } | {
91
+ type: "close";
92
+ } | {
93
+ type: "onclose";
94
94
  } | {
95
95
  type: "start";
96
96
  };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  proxyServer,
4
4
  startHTTPStreamServer,
5
5
  startSSEServer
6
- } from "./chunk-BLDWVJ5G.js";
6
+ } from "./chunk-F2LFKNGG.js";
7
7
 
8
8
  // src/tapTransport.ts
9
9
  var tapTransport = (transport, eventHandler) => {
@@ -27,22 +27,22 @@ var tapTransport = (transport, eventHandler) => {
27
27
  };
28
28
  transport.onerror = async (error) => {
29
29
  eventHandler({
30
- type: "onerror",
31
- error
30
+ error,
31
+ type: "onerror"
32
32
  });
33
33
  return originalOnError?.(error);
34
34
  };
35
35
  transport.onmessage = async (message) => {
36
36
  eventHandler({
37
- type: "onmessage",
38
- message
37
+ message,
38
+ type: "onmessage"
39
39
  });
40
40
  return originalOnMessage?.(message);
41
41
  };
42
42
  transport.send = async (message) => {
43
43
  eventHandler({
44
- type: "send",
45
- message
44
+ message,
45
+ type: "send"
46
46
  });
47
47
  return originalSend?.(message);
48
48
  };
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 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"],"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,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAED,WAAO,kBAAkB,KAAK;AAAA,EAChC;AAEA,YAAU,YAAY,OAAO,YAA4B;AACvD,iBAAa;AAAA,MACX,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAED,WAAO,oBAAoB,OAAO;AAAA,EACpC;AAEA,YAAU,OAAO,OAAO,YAA4B;AAClD,iBAAa;AAAA,MACX,MAAM;AAAA,MACN;AAAA,IACF,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/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":[]}
@@ -0,0 +1,14 @@
1
+ import eslint from "@eslint/js";
2
+ import eslintConfigPrettier from "eslint-config-prettier/flat";
3
+ import perfectionist from "eslint-plugin-perfectionist";
4
+ import tseslint from "typescript-eslint";
5
+
6
+ export default tseslint.config(
7
+ eslint.configs.recommended,
8
+ tseslint.configs.recommended,
9
+ perfectionist.configs["recommended-alphabetical"],
10
+ eslintConfigPrettier,
11
+ {
12
+ ignores: ["**/*.js"],
13
+ },
14
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-proxy",
3
- "version": "2.13.0",
3
+ "version": "2.13.1",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "build": "tsup",
@@ -42,18 +42,22 @@
42
42
  ]
43
43
  },
44
44
  "devDependencies": {
45
+ "@eslint/js": "^9.25.1",
45
46
  "@sebbo2002/semantic-release-jsr": "^2.0.5",
46
47
  "@tsconfig/node22": "^22.0.1",
47
48
  "@types/node": "^22.14.1",
48
49
  "@types/yargs": "^17.0.33",
49
50
  "eslint": "^9.25.0",
51
+ "eslint-config-prettier": "^10.1.2",
50
52
  "eslint-plugin-perfectionist": "^4.11.0",
51
53
  "get-port-please": "^3.1.2",
54
+ "jiti": "^2.4.2",
52
55
  "prettier": "^3.5.3",
53
56
  "semantic-release": "^24.2.3",
54
57
  "tsup": "^8.4.0",
55
58
  "tsx": "^4.19.3",
56
59
  "typescript": "^5.8.3",
60
+ "typescript-eslint": "^8.31.1",
57
61
  "vitest": "^3.1.1"
58
62
  },
59
63
  "tsup": {
@@ -3,8 +3,8 @@
3
3
  * https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/inMemoryEventStore.ts
4
4
  */
5
5
 
6
- import type { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
7
6
  import type { EventStore } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7
+ import type { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
8
8
 
9
9
  /**
10
10
  * Simple in-memory implementation of the EventStore interface for resumability
@@ -12,34 +12,9 @@ import type { EventStore } from "@modelcontextprotocol/sdk/server/streamableHttp
12
12
  * where a persistent storage solution would be more appropriate.
13
13
  */
14
14
  export class InMemoryEventStore implements EventStore {
15
- private events: Map<string, { streamId: string; message: JSONRPCMessage }> =
15
+ private events: Map<string, { message: JSONRPCMessage; streamId: string }> =
16
16
  new Map();
17
17
 
18
- /**
19
- * Generates a unique event ID for a given stream ID
20
- */
21
- private generateEventId(streamId: string): string {
22
- return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
23
- }
24
-
25
- /**
26
- * Extracts the stream ID from an event ID
27
- */
28
- private getStreamIdFromEventId(eventId: string): string {
29
- const parts = eventId.split("_");
30
- return parts.length > 0 ? parts[0] : "";
31
- }
32
-
33
- /**
34
- * Stores an event with a generated event ID
35
- * Implements EventStore.storeEvent
36
- */
37
- async storeEvent(streamId: string, message: JSONRPCMessage): Promise<string> {
38
- const eventId = this.generateEventId(streamId);
39
- this.events.set(eventId, { streamId, message });
40
- return eventId;
41
- }
42
-
43
18
  /**
44
19
  * Replays events that occurred after a specific event ID
45
20
  * Implements EventStore.replayEventsAfter
@@ -48,7 +23,7 @@ export class InMemoryEventStore implements EventStore {
48
23
  lastEventId: string,
49
24
  {
50
25
  send,
51
- }: { send: (eventId: string, message: JSONRPCMessage) => Promise<void> }
26
+ }: { send: (eventId: string, message: JSONRPCMessage) => Promise<void> },
52
27
  ): Promise<string> {
53
28
  if (!lastEventId || !this.events.has(lastEventId)) {
54
29
  return "";
@@ -64,12 +39,12 @@ export class InMemoryEventStore implements EventStore {
64
39
 
65
40
  // Sort events by eventId for chronological ordering
66
41
  const sortedEvents = [...this.events.entries()].sort((a, b) =>
67
- a[0].localeCompare(b[0])
42
+ a[0].localeCompare(b[0]),
68
43
  );
69
44
 
70
45
  for (const [
71
46
  eventId,
72
- { streamId: eventStreamId, message },
47
+ { message, streamId: eventStreamId },
73
48
  ] of sortedEvents) {
74
49
  // Only include events from the same stream
75
50
  if (eventStreamId !== streamId) {
@@ -88,4 +63,29 @@ export class InMemoryEventStore implements EventStore {
88
63
  }
89
64
  return streamId;
90
65
  }
66
+
67
+ /**
68
+ * Stores an event with a generated event ID
69
+ * Implements EventStore.storeEvent
70
+ */
71
+ async storeEvent(streamId: string, message: JSONRPCMessage): Promise<string> {
72
+ const eventId = this.generateEventId(streamId);
73
+ this.events.set(eventId, { message, streamId });
74
+ return eventId;
75
+ }
76
+
77
+ /**
78
+ * Generates a unique event ID for a given stream ID
79
+ */
80
+ private generateEventId(streamId: string): string {
81
+ return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
82
+ }
83
+
84
+ /**
85
+ * Extracts the stream ID from an event ID
86
+ */
87
+ private getStreamIdFromEventId(eventId: string): string {
88
+ const parts = eventId.split("_");
89
+ return parts.length > 0 ? parts[0] : "";
90
+ }
91
91
  }
@@ -11,33 +11,23 @@ import { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
11
11
  import { ChildProcess, IOType, spawn } from "node:child_process";
12
12
  import { Stream } from "node:stream";
13
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
14
  export type StdioServerParameters = {
15
+ /**
16
+ * Command line arguments to pass to the executable.
17
+ */
18
+ args?: string[];
19
+
32
20
  /**
33
21
  * The executable to run to start the server.
34
22
  */
35
23
  command: string;
36
24
 
37
25
  /**
38
- * Command line arguments to pass to the executable.
26
+ * The working directory to use when spawning the process.
27
+ *
28
+ * If not specified, the current working directory will be inherited.
39
29
  */
40
- args?: string[];
30
+ cwd?: string;
41
31
 
42
32
  /**
43
33
  * The environment to use when spawning the process.
@@ -47,46 +37,90 @@ export type StdioServerParameters = {
47
37
  env: Record<string, string>;
48
38
 
49
39
  /**
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.
40
+ * A function to call when an event occurs.
53
41
  */
54
- stderr?: IOType | Stream | number;
42
+ onEvent?: (event: TransportEvent) => void;
55
43
 
56
44
  /**
57
- * The working directory to use when spawning the process.
45
+ * How to handle stderr of the child process. This matches the semantics of Node's `child_process.spawn`.
58
46
  *
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.
47
+ * The default is "inherit", meaning messages to stderr will be printed to the parent process's stderr.
65
48
  */
66
- onEvent?: (event: TransportEvent) => void;
49
+ stderr?: IOType | number | Stream;
67
50
  };
68
51
 
52
+ type TransportEvent =
53
+ | {
54
+ chunk: string;
55
+ type: "data";
56
+ }
57
+ | {
58
+ error: Error;
59
+ type: "error";
60
+ }
61
+ | {
62
+ message: JSONRPCMessage;
63
+ type: "message";
64
+ }
65
+ | {
66
+ type: "close";
67
+ };
68
+
69
69
  /**
70
70
  * Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
71
71
  *
72
72
  * This transport is only available in Node.js environments.
73
73
  */
74
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
75
  onclose?: () => void;
82
76
  onerror?: (error: Error) => void;
83
77
  onmessage?: (message: JSONRPCMessage) => void;
78
+ /**
79
+ * The stderr stream of the child process, if `StdioServerParameters.stderr` was set to "pipe" or "overlapped".
80
+ *
81
+ * This is only available after the process has been started.
82
+ */
83
+ get stderr(): null | Stream {
84
+ return this.process?.stderr ?? null;
85
+ }
86
+ private abortController: AbortController = new AbortController();
87
+
88
+ private onEvent?: (event: TransportEvent) => void;
89
+ private process?: ChildProcess;
90
+ private readBuffer: ReadBuffer = new ReadBuffer();
91
+
92
+ private serverParams: StdioServerParameters;
84
93
 
85
94
  constructor(server: StdioServerParameters) {
86
95
  this.serverParams = server;
87
96
  this.onEvent = server.onEvent;
88
97
  }
89
98
 
99
+ async close(): Promise<void> {
100
+ this.onEvent?.({
101
+ type: "close",
102
+ });
103
+
104
+ this.abortController.abort();
105
+ this.process = undefined;
106
+ this.readBuffer.clear();
107
+ }
108
+
109
+ send(message: JSONRPCMessage): Promise<void> {
110
+ return new Promise((resolve) => {
111
+ if (!this.process?.stdin) {
112
+ throw new Error("Not connected");
113
+ }
114
+
115
+ const json = serializeMessage(message);
116
+ if (this.process.stdin.write(json)) {
117
+ resolve();
118
+ } else {
119
+ this.process.stdin.once("drain", resolve);
120
+ }
121
+ });
122
+ }
123
+
90
124
  /**
91
125
  * Starts the server process and prepares to communicate with it.
92
126
  */
@@ -102,11 +136,11 @@ export class StdioClientTransport implements Transport {
102
136
  this.serverParams.command,
103
137
  this.serverParams.args ?? [],
104
138
  {
139
+ cwd: this.serverParams.cwd,
105
140
  env: this.serverParams.env,
106
- stdio: ["pipe", "pipe", this.serverParams.stderr ?? "inherit"],
107
141
  shell: false,
108
142
  signal: this.abortController.signal,
109
- cwd: this.serverParams.cwd,
143
+ stdio: ["pipe", "pipe", this.serverParams.stderr ?? "inherit"],
110
144
  },
111
145
  );
112
146
 
@@ -125,6 +159,7 @@ export class StdioClientTransport implements Transport {
125
159
  resolve();
126
160
  });
127
161
 
162
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
128
163
  this.process.on("close", (_code) => {
129
164
  this.onEvent?.({
130
165
  type: "close",
@@ -136,8 +171,8 @@ export class StdioClientTransport implements Transport {
136
171
 
137
172
  this.process.stdin?.on("error", (error) => {
138
173
  this.onEvent?.({
139
- type: "error",
140
174
  error,
175
+ type: "error",
141
176
  });
142
177
 
143
178
  this.onerror?.(error);
@@ -145,8 +180,8 @@ export class StdioClientTransport implements Transport {
145
180
 
146
181
  this.process.stdout?.on("data", (chunk) => {
147
182
  this.onEvent?.({
148
- type: "data",
149
183
  chunk: chunk.toString(),
184
+ type: "data",
150
185
  });
151
186
 
152
187
  this.readBuffer.append(chunk);
@@ -155,8 +190,8 @@ export class StdioClientTransport implements Transport {
155
190
 
156
191
  this.process.stdout?.on("error", (error) => {
157
192
  this.onEvent?.({
158
- type: "error",
159
193
  error,
194
+ type: "error",
160
195
  });
161
196
 
162
197
  this.onerror?.(error);
@@ -164,15 +199,6 @@ export class StdioClientTransport implements Transport {
164
199
  });
165
200
  }
166
201
 
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
202
  private processReadBuffer() {
177
203
  while (true) {
178
204
  try {
@@ -183,44 +209,19 @@ export class StdioClientTransport implements Transport {
183
209
  }
184
210
 
185
211
  this.onEvent?.({
186
- type: "message",
187
212
  message,
213
+ type: "message",
188
214
  });
189
215
 
190
216
  this.onmessage?.(message);
191
217
  } catch (error) {
192
218
  this.onEvent?.({
193
- type: "error",
194
219
  error: error as Error,
220
+ type: "error",
195
221
  });
196
222
 
197
223
  this.onerror?.(error as Error);
198
224
  }
199
225
  }
200
226
  }
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
227
  }