@wrongstack/mcp 0.1.3 → 0.1.7
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/LICENSE +17 -13
- package/dist/index.d.ts +12 -1
- package/dist/index.js +84 -26
- package/dist/index.js.map +1 -1
- package/package.json +17 -4
package/LICENSE
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
Version 2.0, January 2004
|
|
3
|
-
http://www.apache.org/licenses/
|
|
1
|
+
MIT License
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
Copyright (c) 2026 ECOSTACK TECHNOLOGY OÜ
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
CHANGED
|
@@ -39,6 +39,11 @@ declare class MCPClient {
|
|
|
39
39
|
private state;
|
|
40
40
|
private child?;
|
|
41
41
|
private nextId;
|
|
42
|
+
/**
|
|
43
|
+
* In-flight JSON-RPC calls keyed by id. `resolve` settles the call; `reject`
|
|
44
|
+
* is invoked from {@link failPending} when the underlying transport dies
|
|
45
|
+
* (stdio child exit, `close()`) so callers don't hang forever.
|
|
46
|
+
*/
|
|
42
47
|
private readonly pending;
|
|
43
48
|
private rxBuffer;
|
|
44
49
|
private _tools;
|
|
@@ -78,6 +83,12 @@ declare class MCPClient {
|
|
|
78
83
|
callTool(name: string, input: unknown): Promise<ToolCallResult>;
|
|
79
84
|
close(): Promise<void>;
|
|
80
85
|
private request;
|
|
86
|
+
/**
|
|
87
|
+
* Reject every in-flight {@link request} call. Used when the underlying
|
|
88
|
+
* transport dies — without this, callers awaiting `tools/call` over a
|
|
89
|
+
* killed stdio child or a closed transport would hang indefinitely.
|
|
90
|
+
*/
|
|
91
|
+
private failPending;
|
|
81
92
|
private notify;
|
|
82
93
|
private onData;
|
|
83
94
|
private onLine;
|
|
@@ -190,7 +201,7 @@ declare class SSETransport {
|
|
|
190
201
|
private headers;
|
|
191
202
|
private timeout;
|
|
192
203
|
private nextId;
|
|
193
|
-
private
|
|
204
|
+
private readonly _reservedPending;
|
|
194
205
|
private tools;
|
|
195
206
|
private abortController?;
|
|
196
207
|
private reader?;
|
package/dist/index.js
CHANGED
|
@@ -54,7 +54,12 @@ var SSETransport = class {
|
|
|
54
54
|
headers;
|
|
55
55
|
timeout;
|
|
56
56
|
nextId = 1;
|
|
57
|
-
|
|
57
|
+
// NOTE: id-correlation via this map was scaffolded but never populated by
|
|
58
|
+
// `httpPost` — JSON-RPC responses come back synchronously over HTTP, not
|
|
59
|
+
// via the SSE stream. Keep the field reserved for future bidirectional-
|
|
60
|
+
// streaming support; do not wire callsites to it without first deciding
|
|
61
|
+
// who is responsible for clearing it on transport teardown.
|
|
62
|
+
_reservedPending = /* @__PURE__ */ new Map();
|
|
58
63
|
tools = [];
|
|
59
64
|
abortController;
|
|
60
65
|
reader;
|
|
@@ -123,13 +128,6 @@ var SSETransport = class {
|
|
|
123
128
|
const sseReader = new SSEReader();
|
|
124
129
|
this.readLoopAbort = new AbortController();
|
|
125
130
|
sseReader.onMessage((msg) => {
|
|
126
|
-
if (msg.id !== void 0) {
|
|
127
|
-
const resolve = this.pending.get(msg.id);
|
|
128
|
-
if (resolve) {
|
|
129
|
-
this.pending.delete(msg.id);
|
|
130
|
-
resolve({ jsonrpc: "2.0", id: msg.id, result: msg.params });
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
131
|
if (msg.method && !msg.id) {
|
|
134
132
|
if (msg.method === "notifications/tools/list_changed") {
|
|
135
133
|
void this.handleToolsListChanged();
|
|
@@ -145,7 +143,7 @@ var SSETransport = class {
|
|
|
145
143
|
const initRes = await this.httpPost("initialize", {
|
|
146
144
|
protocolVersion: "2024-11-05",
|
|
147
145
|
capabilities: { tools: {} },
|
|
148
|
-
clientInfo: { name: "wrongstack", version: "0.1.
|
|
146
|
+
clientInfo: { name: "wrongstack", version: "0.1.6" }
|
|
149
147
|
});
|
|
150
148
|
if (initRes.error) {
|
|
151
149
|
throw new Error(`initialize failed: ${initRes.error.message}`);
|
|
@@ -212,11 +210,22 @@ var SSETransport = class {
|
|
|
212
210
|
signal: this.abortController?.signal
|
|
213
211
|
});
|
|
214
212
|
if (!res.ok) {
|
|
215
|
-
|
|
213
|
+
const body2 = await res.text();
|
|
214
|
+
const cap = 1024;
|
|
215
|
+
const snippet = body2.length > cap ? `${body2.slice(0, cap)}\u2026 [${body2.length} bytes total]` : body2;
|
|
216
|
+
throw new Error(`HTTP ${res.status}: ${snippet}`);
|
|
217
|
+
}
|
|
218
|
+
let data;
|
|
219
|
+
try {
|
|
220
|
+
data = await res.json();
|
|
221
|
+
} catch (err) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
`Invalid JSON-RPC response: ${err instanceof Error ? err.message : "parse failed"}`,
|
|
224
|
+
{ cause: err }
|
|
225
|
+
);
|
|
216
226
|
}
|
|
217
|
-
const data = await res.json();
|
|
218
227
|
if (!isJsonRpcResult(data)) {
|
|
219
|
-
throw new Error("Invalid JSON-RPC response");
|
|
228
|
+
throw new Error("Invalid JSON-RPC response: not a JSON-RPC envelope");
|
|
220
229
|
}
|
|
221
230
|
return data;
|
|
222
231
|
}
|
|
@@ -321,7 +330,7 @@ var StreamableHTTPTransport = class {
|
|
|
321
330
|
params: {
|
|
322
331
|
protocolVersion: "2024-11-05",
|
|
323
332
|
capabilities: { tools: {} },
|
|
324
|
-
clientInfo: { name: "wrongstack", version: "0.1.
|
|
333
|
+
clientInfo: { name: "wrongstack", version: "0.1.6" }
|
|
325
334
|
}
|
|
326
335
|
}),
|
|
327
336
|
signal
|
|
@@ -345,7 +354,6 @@ var StreamableHTTPTransport = class {
|
|
|
345
354
|
break;
|
|
346
355
|
}
|
|
347
356
|
} catch {
|
|
348
|
-
continue;
|
|
349
357
|
}
|
|
350
358
|
}
|
|
351
359
|
}
|
|
@@ -398,7 +406,6 @@ var StreamableHTTPTransport = class {
|
|
|
398
406
|
const parsed = JSON.parse(line);
|
|
399
407
|
if (isJsonRpcResult(parsed)) return parsed;
|
|
400
408
|
} catch {
|
|
401
|
-
continue;
|
|
402
409
|
}
|
|
403
410
|
}
|
|
404
411
|
throw new Error("Could not parse response as JSON-RPC");
|
|
@@ -440,6 +447,11 @@ var MCPClient = class {
|
|
|
440
447
|
state = "idle";
|
|
441
448
|
child;
|
|
442
449
|
nextId = 1;
|
|
450
|
+
/**
|
|
451
|
+
* In-flight JSON-RPC calls keyed by id. `resolve` settles the call; `reject`
|
|
452
|
+
* is invoked from {@link failPending} when the underlying transport dies
|
|
453
|
+
* (stdio child exit, `close()`) so callers don't hang forever.
|
|
454
|
+
*/
|
|
443
455
|
pending = /* @__PURE__ */ new Map();
|
|
444
456
|
rxBuffer = "";
|
|
445
457
|
_tools = [];
|
|
@@ -504,6 +516,7 @@ var MCPClient = class {
|
|
|
504
516
|
this.state = "failed";
|
|
505
517
|
throw new Error('MCP stdio transport requires "command"');
|
|
506
518
|
}
|
|
519
|
+
this.rxBuffer = "";
|
|
507
520
|
const child = spawn(this.opts.command, this.opts.args ?? [], {
|
|
508
521
|
env: { ...process.env, ...this.opts.env },
|
|
509
522
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -514,6 +527,7 @@ var MCPClient = class {
|
|
|
514
527
|
});
|
|
515
528
|
child.on("exit", (code, signal) => {
|
|
516
529
|
this.state = "disconnected";
|
|
530
|
+
this.failPending(`MCP "${this.opts.name}" child exited (code=${code ?? "null"} signal=${signal ?? "null"})`);
|
|
517
531
|
for (const listener of this.exitListeners) {
|
|
518
532
|
try {
|
|
519
533
|
listener(this.opts.name, code, signal);
|
|
@@ -529,7 +543,7 @@ var MCPClient = class {
|
|
|
529
543
|
this.request("initialize", {
|
|
530
544
|
protocolVersion: "2024-11-05",
|
|
531
545
|
capabilities: { tools: {} },
|
|
532
|
-
clientInfo: { name: "wrongstack", version: "0.1.
|
|
546
|
+
clientInfo: { name: "wrongstack", version: "0.1.6" }
|
|
533
547
|
}),
|
|
534
548
|
new Promise(
|
|
535
549
|
(_, rej) => setTimeout(() => rej(new Error("MCP initialize timeout")), timeout)
|
|
@@ -659,25 +673,39 @@ var MCPClient = class {
|
|
|
659
673
|
async close() {
|
|
660
674
|
if (this.child) {
|
|
661
675
|
const child = this.child;
|
|
662
|
-
const
|
|
676
|
+
const isAlive = child.exitCode === null && child.signalCode === null;
|
|
677
|
+
const exitPromise = isAlive ? new Promise((resolve) => child.once("exit", () => resolve())) : Promise.resolve();
|
|
663
678
|
try {
|
|
664
679
|
child.kill();
|
|
665
680
|
} catch {
|
|
666
681
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
682
|
+
const GRACEFUL_MS = 800;
|
|
683
|
+
const FORCE_TIMEOUT_MS = 1200;
|
|
684
|
+
const gracefulRace = await Promise.race([
|
|
685
|
+
exitPromise.then(() => "exited"),
|
|
686
|
+
new Promise((resolve) => setTimeout(() => resolve("timeout"), GRACEFUL_MS))
|
|
670
687
|
]);
|
|
688
|
+
if (gracefulRace === "timeout" && isAlive) {
|
|
689
|
+
try {
|
|
690
|
+
child.kill("SIGKILL");
|
|
691
|
+
} catch {
|
|
692
|
+
}
|
|
693
|
+
await Promise.race([
|
|
694
|
+
exitPromise,
|
|
695
|
+
new Promise((resolve) => setTimeout(resolve, FORCE_TIMEOUT_MS))
|
|
696
|
+
]);
|
|
697
|
+
}
|
|
671
698
|
}
|
|
672
699
|
this.sseTransport?.close();
|
|
673
700
|
this.httpTransport?.close();
|
|
701
|
+
this.failPending(`MCP "${this.opts.name}" closed`);
|
|
674
702
|
this.state = "disconnected";
|
|
675
703
|
}
|
|
676
704
|
request(method, params) {
|
|
677
705
|
const id = this.nextId++;
|
|
678
706
|
const req = { jsonrpc: "2.0", id, method, params };
|
|
679
707
|
return new Promise((resolve, reject) => {
|
|
680
|
-
this.pending.set(id, resolve);
|
|
708
|
+
this.pending.set(id, { resolve, reject });
|
|
681
709
|
try {
|
|
682
710
|
this.child?.stdin?.write(JSON.stringify(req) + "\n");
|
|
683
711
|
} catch (err) {
|
|
@@ -686,6 +714,22 @@ var MCPClient = class {
|
|
|
686
714
|
}
|
|
687
715
|
});
|
|
688
716
|
}
|
|
717
|
+
/**
|
|
718
|
+
* Reject every in-flight {@link request} call. Used when the underlying
|
|
719
|
+
* transport dies — without this, callers awaiting `tools/call` over a
|
|
720
|
+
* killed stdio child or a closed transport would hang indefinitely.
|
|
721
|
+
*/
|
|
722
|
+
failPending(reason) {
|
|
723
|
+
if (this.pending.size === 0) return;
|
|
724
|
+
const err = new Error(reason);
|
|
725
|
+
for (const [, entry] of this.pending) {
|
|
726
|
+
try {
|
|
727
|
+
entry.reject(err);
|
|
728
|
+
} catch {
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
this.pending.clear();
|
|
732
|
+
}
|
|
689
733
|
async notify(method, params) {
|
|
690
734
|
const req = { jsonrpc: "2.0", method, params };
|
|
691
735
|
const encoded = JSON.stringify(req) + "\n";
|
|
@@ -739,9 +783,9 @@ var MCPClient = class {
|
|
|
739
783
|
return;
|
|
740
784
|
}
|
|
741
785
|
if (msg.id !== void 0 && this.pending.has(msg.id)) {
|
|
742
|
-
const
|
|
786
|
+
const entry = this.pending.get(msg.id);
|
|
743
787
|
this.pending.delete(msg.id);
|
|
744
|
-
resolve
|
|
788
|
+
entry?.resolve(msg);
|
|
745
789
|
return;
|
|
746
790
|
}
|
|
747
791
|
if (typeof msg.method === "string" && msg.method === "notifications/tools/list_changed") {
|
|
@@ -863,10 +907,12 @@ var MCPRegistry = class _MCPRegistry {
|
|
|
863
907
|
slot.reconnectPending = false;
|
|
864
908
|
if (slot.client) {
|
|
865
909
|
slot.client.removeExitListener(this.onChildExit);
|
|
866
|
-
slot.client.removeDisconnectListener(
|
|
910
|
+
if (slot.onDisconnect) slot.client.removeDisconnectListener(slot.onDisconnect);
|
|
867
911
|
slot.client.removeToolsChangedListener(this.onToolsChanged);
|
|
868
912
|
await slot.client.close();
|
|
913
|
+
slot.client = void 0;
|
|
869
914
|
}
|
|
915
|
+
slot.onDisconnect = void 0;
|
|
870
916
|
for (const t of slot.toolNames) this.toolRegistry.unregister(t);
|
|
871
917
|
slot.toolNames = [];
|
|
872
918
|
slot.state = "disconnected";
|
|
@@ -1011,6 +1057,7 @@ var MCPRegistry = class _MCPRegistry {
|
|
|
1011
1057
|
slot.state = attempt === 1 ? "connecting" : "reconnecting";
|
|
1012
1058
|
slot.attempts = attempt;
|
|
1013
1059
|
let client;
|
|
1060
|
+
let boundDisconnect;
|
|
1014
1061
|
try {
|
|
1015
1062
|
client = new MCPClient({
|
|
1016
1063
|
name: slot.cfg.name,
|
|
@@ -1025,11 +1072,22 @@ var MCPRegistry = class _MCPRegistry {
|
|
|
1025
1072
|
if (slot.cfg.transport === "stdio") {
|
|
1026
1073
|
client.addExitListener(this.onChildExit);
|
|
1027
1074
|
} else {
|
|
1028
|
-
|
|
1075
|
+
boundDisconnect = () => this.onTransportDisconnect(slot.cfg.name);
|
|
1076
|
+
client.addDisconnectListener(boundDisconnect);
|
|
1029
1077
|
}
|
|
1030
1078
|
client.addToolsChangedListener(this.onToolsChanged);
|
|
1031
1079
|
await client.connect();
|
|
1080
|
+
if (slot.client && slot.client !== client) {
|
|
1081
|
+
const prior = slot.client;
|
|
1082
|
+
const priorDisconnect = slot.onDisconnect;
|
|
1083
|
+
slot.client.removeExitListener(this.onChildExit);
|
|
1084
|
+
if (priorDisconnect) prior.removeDisconnectListener(priorDisconnect);
|
|
1085
|
+
prior.removeToolsChangedListener(this.onToolsChanged);
|
|
1086
|
+
prior.close().catch(() => {
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1032
1089
|
slot.client = client;
|
|
1090
|
+
slot.onDisconnect = boundDisconnect;
|
|
1033
1091
|
const isReconnect = attempt > 1;
|
|
1034
1092
|
slot.state = "connected";
|
|
1035
1093
|
slot.reconnectCycles = 0;
|
|
@@ -1055,7 +1113,7 @@ var MCPRegistry = class _MCPRegistry {
|
|
|
1055
1113
|
this.log.warn(`MCP server "${slot.cfg.name}" connect attempt ${attempt} failed`, err);
|
|
1056
1114
|
if (client) {
|
|
1057
1115
|
client.removeExitListener(this.onChildExit);
|
|
1058
|
-
|
|
1116
|
+
if (boundDisconnect) client.removeDisconnectListener(boundDisconnect);
|
|
1059
1117
|
client.removeToolsChangedListener(this.onToolsChanged);
|
|
1060
1118
|
await client.close().catch(() => {
|
|
1061
1119
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transport.ts","../src/client.ts","../src/wrap-tool.ts","../src/registry.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ConnectionState, MCPTool, ToolCallResult } from './client.js';\n\nexport type JsonRpcResult = { jsonrpc: string; id?: number; result?: unknown; error?: { code: number; message: string; data?: unknown } };\n\nexport interface HttpTransportOptions {\n name: string;\n url: string;\n headers?: Record<string, string>;\n startupTimeoutMs?: number;\n}\n\n/**\n * SSE-based MCP transport using native fetch.\n *\n * Communication pattern:\n * - Client connects to SSE endpoint to receive server messages (JSON-RPC events)\n * - Client sends JSON-RPC requests via HTTP POST to the same or separate endpoint\n * - Server sends results/errors via the SSE stream\n *\n * The SSE reader parses the SSE protocol (event:, data:, blank line to dispatch).\n */\nexport class SSEReader {\n private buffer = '';\n private listeners: Array<(event: { jsonrpc?: string; method?: string; params?: unknown; id?: number }) => void> = [];\n\n onMessage(cb: (data: { jsonrpc?: string; method?: string; params?: unknown; id?: number }) => void): () => void {\n this.listeners.push(cb);\n return () => {\n const idx = this.listeners.indexOf(cb);\n if (idx >= 0) this.listeners.splice(idx, 1);\n };\n }\n\n feed(chunk: string): void {\n this.buffer += chunk;\n let idx = this.buffer.indexOf('\\n');\n while (idx !== -1) {\n const line = this.buffer.slice(0, idx);\n this.buffer = this.buffer.slice(idx + 1);\n idx = this.buffer.indexOf('\\n');\n\n if (line.startsWith('event:')) {\n // track event type, ignore for now\n } else if (line.startsWith('data:')) {\n const data = line.slice(5).trim();\n if (data) {\n try {\n const parsed = JSON.parse(data) as { jsonrpc?: string; method?: string; params?: unknown; id?: number };\n this.dispatch(parsed);\n } catch {\n // ignore parse errors\n }\n }\n }\n }\n }\n\n private dispatch(msg: { jsonrpc?: string; method?: string; params?: unknown; id?: number }): void {\n for (const cb of this.listeners) {\n try { cb(msg); } catch { /* ignore */ }\n }\n }\n\n reset(): void {\n this.buffer = '';\n this.listeners = [];\n }\n}\n\nfunction isJsonRpcResult(v: unknown): v is JsonRpcResult {\n return typeof v === 'object' && v !== null && 'jsonrpc' in v;\n}\n\n/**\n * SSE transport for MCP over HTTP.\n *\n * Uses native fetch API with ReadableStream to consume SSE events.\n * HTTP POST is used to send JSON-RPC requests.\n */\nexport class SSETransport {\n private state: ConnectionState = 'idle';\n private url: string;\n private headers: Record<string, string>;\n private timeout: number;\n private nextId = 1;\n private pending = new Map<number, (res: JsonRpcResult) => void>();\n private tools: MCPTool[] = [];\n private abortController?: AbortController;\n private reader?: globalThis.ReadableStreamDefaultReader<string>;\n private readerDone = false;\n private disconnectHandlers: Array<() => void> = [];\n private readLoopAbort?: AbortController;\n private readonly toolsChangedListeners = new Set<(tools: MCPTool[]) => void>();\n\n constructor(opts: HttpTransportOptions) {\n this.url = opts.url;\n this.headers = { ...opts.headers };\n this.timeout = opts.startupTimeoutMs ?? 10_000;\n }\n\n getState(): ConnectionState {\n return this.state;\n }\n\n listTools(): MCPTool[] {\n return [...this.tools];\n }\n\n onDisconnect(cb: () => void): () => void {\n this.disconnectHandlers.push(cb);\n return () => {\n const idx = this.disconnectHandlers.indexOf(cb);\n if (idx >= 0) this.disconnectHandlers.splice(idx, 1);\n };\n }\n\n onToolsChanged(cb: (tools: MCPTool[]) => void): () => void {\n this.toolsChangedListeners.add(cb);\n return () => { this.toolsChangedListeners.delete(cb); };\n }\n\n /** Refresh tool list when server sends notifications/tools/list_changed. */\n private async handleToolsListChanged(): Promise<void> {\n try {\n const res = await this.httpPost('tools/list', {});\n if (!res.error) {\n this.tools = ((res.result as { tools?: MCPTool[] } | undefined)?.tools ?? []);\n for (const cb of this.toolsChangedListeners) {\n try { cb([...this.tools]); } catch { /* ignore */ }\n }\n }\n } catch { /* ignore transient failures */ }\n }\n\n async connect(): Promise<void> {\n this.state = 'connecting';\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n const startupTimer = setTimeout(() => this.abortController?.abort(), this.timeout);\n\n try {\n const sseUrl = this.buildSSEUrl();\n const response = await fetch(sseUrl, {\n headers: this.headers,\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`SSE connect HTTP ${response.status}: ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('SSE response has no body');\n }\n\n const textDecoder = new TextDecoder();\n const sseReader = new SSEReader();\n this.readLoopAbort = new AbortController();\n\n sseReader.onMessage((msg) => {\n if (msg.id !== undefined) {\n const resolve = this.pending.get(msg.id);\n if (resolve) {\n this.pending.delete(msg.id);\n resolve({ jsonrpc: '2.0', id: msg.id, result: msg.params });\n }\n }\n // Server-initiated notifications (no id). Handle list_changed for L2-C.\n if (msg.method && !msg.id) {\n if (msg.method === 'notifications/tools/list_changed') {\n void this.handleToolsListChanged();\n }\n }\n });\n\n const reader = response.body.getReader();\n this.reader = {\n cancel: () => reader.cancel(),\n releaseLock: () => reader.releaseLock(),\n } as globalThis.ReadableStreamDefaultReader<string>;\n\n this.readSSEBody(reader, textDecoder, sseReader);\n\n const initRes = await this.httpPost('initialize', {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n clientInfo: { name: 'wrongstack', version: '0.1.1' },\n });\n\n if (initRes.error) {\n throw new Error(`initialize failed: ${initRes.error.message}`);\n }\n\n try {\n await this.httpPost('notifications/initialized', {});\n } catch {\n // servers may not require it\n }\n\n const toolsRes = await this.httpPost('tools/list', {});\n if (toolsRes.error) {\n this.tools = [];\n } else {\n const result = toolsRes.result as { tools?: MCPTool[] } | undefined;\n this.tools = result?.tools ?? [];\n }\n\n this.state = 'connected';\n clearTimeout(startupTimer);\n } catch (err) {\n clearTimeout(startupTimer);\n this.state = 'failed';\n this.abortController.abort();\n throw err;\n }\n }\n\n private async readSSEBody(\n reader: globalThis.ReadableStreamDefaultReader<Uint8Array>,\n decoder: InstanceType<typeof TextDecoder>,\n sseReader: SSEReader,\n ): Promise<void> {\n try {\n while (!this.readerDone) {\n const { done, value } = await reader.read();\n if (done) break;\n const chunk = decoder.decode(value, { stream: true });\n sseReader.feed(chunk);\n }\n } catch {\n // SSE read error — connection lost. Transition to disconnected so\n // callTool and health checks see the correct state, then notify\n // disconnect handlers so the registry can schedule a reconnect.\n if (this.state !== 'disconnected' && this.state !== 'failed') {\n this.state = 'disconnected';\n for (const cb of this.disconnectHandlers) {\n try { cb(); } catch { /* ignore */ }\n }\n }\n }\n }\n\n private buildSSEUrl(): string {\n try {\n const url = new URL(this.url);\n url.searchParams.set('session', String(Date.now()));\n return url.toString();\n } catch {\n return this.url;\n }\n }\n\n private async httpPost(method: string, params: unknown): Promise<JsonRpcResult> {\n const id = this.nextId++;\n const body = JSON.stringify({ jsonrpc: '2.0', id, method, params });\n\n const res = await fetch(this.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this.headers,\n },\n body,\n signal: this.abortController?.signal,\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}: ${await res.text()}`);\n }\n\n const data = await res.json();\n if (!isJsonRpcResult(data)) {\n throw new Error('Invalid JSON-RPC response');\n }\n return data;\n }\n\n async callTool(name: string, input: unknown): Promise<ToolCallResult> {\n if (this.state !== 'connected') {\n throw new Error(`SSE transport not connected (state=${this.state})`);\n }\n const res = await this.httpPost('tools/call', { name, arguments: input });\n if (res.error) {\n return { content: res.error.message, isError: true };\n }\n const result = res.result as { content?: unknown; isError?: boolean } | undefined;\n return {\n content: result?.content ?? '',\n isError: Boolean(result?.isError),\n };\n }\n\n async close(): Promise<void> {\n // Idempotent — safe to call multiple times.\n if (this.state === 'disconnected') return;\n this.readerDone = true;\n this.readLoopAbort?.abort();\n try { this.reader?.cancel(); } catch { /* ignore */ }\n try { this.reader?.releaseLock(); } catch { /* ignore */ }\n this.abortController?.abort();\n this.disconnectHandlers = [];\n this.state = 'disconnected';\n }\n}\n\n/**\n * Streamable HTTP transport for MCP.\n *\n * Uses session-based HTTP with NDJSON responses.\n */\nexport class StreamableHTTPTransport {\n private state: ConnectionState = 'idle';\n private url: string;\n private headers: Record<string, string>;\n private timeout: number;\n private nextId = 1;\n private tools: MCPTool[] = [];\n private abortController?: AbortController;\n private sessionId?: string;\n private disconnectHandlers: Array<() => void> = [];\n private readonly toolsChangedListeners = new Set<(tools: MCPTool[]) => void>();\n\n constructor(opts: HttpTransportOptions) {\n this.url = opts.url;\n this.headers = { ...opts.headers };\n this.timeout = opts.startupTimeoutMs ?? 10_000;\n }\n\n getState(): ConnectionState {\n return this.state;\n }\n\n listTools(): MCPTool[] {\n return [...this.tools];\n }\n\n onDisconnect(cb: () => void): () => void {\n this.disconnectHandlers.push(cb);\n return () => {\n const idx = this.disconnectHandlers.indexOf(cb);\n if (idx >= 0) this.disconnectHandlers.splice(idx, 1);\n };\n }\n\n onToolsChanged(cb: (tools: MCPTool[]) => void): () => void {\n this.toolsChangedListeners.add(cb);\n return () => { this.toolsChangedListeners.delete(cb); };\n }\n\n private async handleToolsListChanged(): Promise<void> {\n try {\n const res = await this.postRaw('tools/list', {});\n if (!res.error) {\n this.tools = ((res.result as { tools?: MCPTool[] } | undefined)?.tools ?? []);\n for (const cb of this.toolsChangedListeners) {\n try { cb([...this.tools]); } catch { /* ignore */ }\n }\n }\n } catch { /* ignore transient failures */ }\n }\n\n async connect(): Promise<void> {\n this.state = 'connecting';\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n const startupTimer = setTimeout(() => this.abortController?.abort(), this.timeout);\n\n try {\n const initRes = await fetch(this.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json, text/event-stream',\n ...this.headers,\n },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: this.nextId++,\n method: 'initialize',\n params: {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n clientInfo: { name: 'wrongstack', version: '0.1.1' },\n },\n }),\n signal,\n });\n\n if (!initRes.ok) {\n throw new Error(`initialize HTTP ${initRes.status}: ${initRes.statusText}`);\n }\n\n const contentType = initRes.headers.get('content-type') ?? '';\n let data: JsonRpcResult | undefined;\n\n if (contentType.includes('application/json')) {\n const parsed = await initRes.json();\n if (isJsonRpcResult(parsed)) data = parsed;\n } else {\n const text = await initRes.text();\n const lines = text.split('\\n').filter(l => l.trim());\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line);\n if (isJsonRpcResult(parsed)) {\n data = parsed;\n break;\n }\n } catch {\n continue;\n }\n }\n }\n\n if (!data) {\n throw new Error('Could not parse initialize response');\n }\n\n if (data.error) {\n throw new Error(`initialize failed: ${data.error.message}`);\n }\n\n this.sessionId = (initRes.headers.get('x-mcp-session') ?? undefined) as string | undefined;\n await this.postRaw('notifications/initialized', {});\n\n const toolsRes = await this.postRaw('tools/list', {});\n if (toolsRes.error) {\n this.tools = [];\n } else {\n const result = toolsRes.result as { tools?: MCPTool[] } | undefined;\n this.tools = result?.tools ?? [];\n }\n\n this.state = 'connected';\n clearTimeout(startupTimer);\n } catch (err) {\n clearTimeout(startupTimer);\n this.state = 'failed';\n this.abortController.abort();\n throw err;\n }\n }\n\n private async postRaw(method: string, params: unknown): Promise<JsonRpcResult> {\n const id = this.nextId++;\n const body = JSON.stringify({ jsonrpc: '2.0', id, method, params });\n\n const url = this.sessionId\n ? `${this.url}${this.url.includes('?') ? '&' : '?'}session=${this.sessionId}`\n : this.url;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json, text/event-stream',\n ...(this.sessionId ? { 'x-mcp-session': this.sessionId } : {}),\n ...this.headers,\n },\n body,\n signal: this.abortController?.signal,\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}: ${res.statusText}`);\n }\n\n const text = await res.text();\n const lines = text.split('\\n').filter(l => l.trim());\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line);\n if (isJsonRpcResult(parsed)) return parsed;\n } catch {\n continue;\n }\n }\n throw new Error('Could not parse response as JSON-RPC');\n }\n\n async callTool(name: string, input: unknown): Promise<ToolCallResult> {\n if (this.state !== 'connected') {\n throw new Error(`streamable-http transport not connected (state=${this.state})`);\n }\n const res = await this.postRaw('tools/call', { name, arguments: input });\n if (res.error) {\n return { content: res.error.message, isError: true };\n }\n const result = res.result as { content?: unknown; isError?: boolean } | undefined;\n return {\n content: result?.content ?? '',\n isError: Boolean(result?.isError),\n };\n }\n\n async close(): Promise<void> {\n if (this.state === 'disconnected') return;\n this.state = 'disconnected';\n this.abortController?.abort();\n for (const cb of this.disconnectHandlers) {\n try { cb(); } catch { /* ignore */ }\n }\n this.disconnectHandlers = [];\n }\n}","import { spawn, type ChildProcess } from 'node:child_process';\r\nimport { SSETransport, StreamableHTTPTransport, type HttpTransportOptions } from './transport.js';\r\n\r\nexport type Transport = 'stdio' | 'sse' | 'streamable-http';\r\n\r\nexport interface MCPClientOptions {\r\n name: string;\r\n transport: Transport;\r\n command?: string;\r\n args?: string[];\r\n env?: Record<string, string>;\r\n url?: string;\r\n headers?: Record<string, string>;\r\n startupTimeoutMs?: number;\r\n}\r\n\r\nexport type ConnectionState =\r\n | 'idle'\r\n | 'connecting'\r\n | 'connected'\r\n | 'disconnected'\r\n | 'reconnecting'\r\n | 'failed';\r\n\r\nexport interface MCPTool {\r\n name: string;\r\n description?: string;\r\n inputSchema: Record<string, unknown>;\r\n}\r\n\r\nexport interface ToolCallResult {\r\n content: unknown;\r\n isError: boolean;\r\n}\r\n\r\ninterface JsonRpcRequest {\r\n jsonrpc: '2.0';\r\n id: number;\r\n method: string;\r\n params?: unknown;\r\n}\r\n\r\ninterface JsonRpcResponse {\r\n jsonrpc: '2.0';\r\n id: number;\r\n result?: unknown;\r\n error?: { code: number; message: string; data?: unknown };\r\n}\r\n\r\ntype ExitListener = (name: string, code: number | null, signal: string | null) => void;\r\n/**\r\n * Fired when the server sends `notifications/tools/list_changed`. The\r\n * client refreshes its cached tool list before invoking listeners, so\r\n * subscribers can call `listTools()` for the fresh set.\r\n */\r\ntype ToolsChangedListener = (name: string, tools: MCPTool[]) => void;\r\n\r\n/**\r\n * Lightweight MCP client supporting three transport types:\r\n * - stdio: spawns a child process and communicates over pipes\r\n * - sse: connects to an HTTP SSE endpoint for server events, POST for requests\r\n * - streamable-http: session-based HTTP transport with NDJSON responses\r\n */\r\nexport class MCPClient {\r\n private state: ConnectionState = 'idle';\r\n private child?: ChildProcess;\r\n private nextId = 1;\r\n private readonly pending = new Map<number, (res: JsonRpcResponse) => void>();\r\n private rxBuffer = '';\r\n private _tools: MCPTool[] = [];\r\n /** Cached tool list — survives reconnects so the registry can re-register without re-discovering. */\r\n private _toolsCache?: MCPTool[];\r\n private _drainPending = false;\r\n private _lastNotifySkipped = false;\r\n // HTTP transports\r\n private sseTransport?: SSETransport;\r\n private httpTransport?: StreamableHTTPTransport;\r\n /** Notified when the stdio child process exits so the registry can attempt reconnect. */\r\n private readonly exitListeners = new Set<ExitListener>();\r\n /** Notified when the server announces a tools/list_changed notification. */\r\n private readonly toolsChangedListeners = new Set<ToolsChangedListener>();\r\n /** Notified when an HTTP transport (SSE or streamable-http) disconnects. */\r\n private readonly disconnectListeners = new Set<() => void>();\r\n\r\n constructor(public readonly opts: MCPClientOptions) {}\r\n\r\n getState(): ConnectionState {\r\n return this.state;\r\n }\r\n\r\n listTools(): MCPTool[] {\r\n return this._tools.length > 0 ? [...this._tools] : this._toolsCache ? [...this._toolsCache] : [];\r\n }\r\n\r\n /** Returns true if a prior notify() call was skipped due to backpressure. */\r\n hadNotifySkipped(): boolean {\r\n return this._lastNotifySkipped;\r\n }\r\n\r\n /**\r\n * Register a listener for child-process exit events.\r\n * The registry uses this to trigger reconnection.\r\n */\r\n addExitListener(listener: ExitListener): void {\r\n this.exitListeners.add(listener);\r\n }\r\n\r\n removeExitListener(listener: ExitListener): void {\r\n this.exitListeners.delete(listener);\r\n }\r\n\r\n /**\r\n * Register a listener for transport disconnect events (SSE / streamable-http).\r\n * Used by the registry to trigger reconnection for HTTP-based servers.\r\n */\r\n addDisconnectListener(listener: () => void): void {\r\n this.disconnectListeners.add(listener);\r\n }\r\n\r\n removeDisconnectListener(listener: () => void): void {\r\n this.disconnectListeners.delete(listener);\r\n }\r\n\r\n async connect(): Promise<void> {\r\n this.state = 'connecting';\r\n\r\n if (this.opts.transport === 'stdio') {\r\n await this.connectStdio();\r\n } else if (this.opts.transport === 'sse') {\r\n await this.connectSSE();\r\n } else if (this.opts.transport === 'streamable-http') {\r\n await this.connectStreamableHTTP();\r\n } else {\r\n this.state = 'failed';\r\n throw new Error(`Unknown transport \"${this.opts.transport}\"`);\r\n }\r\n }\r\n\r\n private async connectStdio(): Promise<void> {\r\n if (!this.opts.command) {\r\n this.state = 'failed';\r\n throw new Error('MCP stdio transport requires \"command\"');\r\n }\r\n\r\n const child = spawn(this.opts.command, this.opts.args ?? [], {\r\n env: { ...process.env, ...this.opts.env },\r\n stdio: ['pipe', 'pipe', 'pipe'],\r\n });\r\n this.child = child;\r\n\r\n child.stdout?.on('data', (chunk: Buffer) => this.onData(chunk.toString()));\r\n child.stderr?.on('data', () => {\r\n // intentionally discard stderr noise from server\r\n });\r\n child.on('exit', (code, signal) => {\r\n this.state = 'disconnected';\r\n for (const listener of this.exitListeners) {\r\n try { listener(this.opts.name, code, signal); } catch { /* ignore */ }\r\n }\r\n });\r\n child.on('error', () => {\r\n this.state = 'failed';\r\n });\r\n\r\n const timeout = this.opts.startupTimeoutMs ?? 10_000;\r\n const initialize = await Promise.race([\r\n this.request('initialize', {\r\n protocolVersion: '2024-11-05',\r\n capabilities: { tools: {} },\r\n clientInfo: { name: 'wrongstack', version: '0.1.1' },\r\n }),\r\n new Promise<JsonRpcResponse>((_, rej) =>\r\n setTimeout(() => rej(new Error('MCP initialize timeout')), timeout),\r\n ),\r\n ]);\r\n if (initialize.error) {\r\n this.state = 'failed';\r\n throw new Error(`MCP initialize failed: ${initialize.error.message}`);\r\n }\r\n try {\r\n await this.notify('notifications/initialized', {});\r\n } catch (err) {\r\n console.warn(\r\n '[MCP] notify(\"notifications/initialized\") failed for \"' + this.opts.name + '\": ' + (err instanceof Error ? err.message : String(err)),\r\n );\r\n }\r\n const toolsRes = await this.request('tools/list', {});\r\n if (toolsRes.error) {\r\n this._tools = [];\r\n } else {\r\n const result = toolsRes.result as { tools?: MCPTool[] } | undefined;\r\n this._tools = result?.tools ?? [];\r\n }\r\n // Cache tools so reconnect can re-register without re-discovering\r\n this._toolsCache = this._tools;\r\n this.state = 'connected';\r\n }\r\n\r\n private async connectSSE(): Promise<void> {\r\n if (!this.opts.url) {\r\n this.state = 'failed';\r\n throw new Error('MCP SSE transport requires \"url\"');\r\n }\r\n const httpOpts: HttpTransportOptions = {\r\n name: this.opts.name,\r\n url: this.opts.url,\r\n headers: this.opts.headers,\r\n startupTimeoutMs: this.opts.startupTimeoutMs,\r\n };\r\n this.sseTransport = new SSETransport(httpOpts);\r\n this.sseTransport.onDisconnect(() => {\r\n this.state = 'disconnected';\r\n for (const cb of this.disconnectListeners) {\r\n try { cb(); } catch { /* ignore */ }\r\n }\r\n });\r\n this.sseTransport.onToolsChanged((tools) => {\r\n this._tools = tools;\r\n for (const cb of this.toolsChangedListeners) {\r\n try { cb(this.opts.name, tools); } catch { /* ignore */ }\r\n }\r\n });\r\n try {\r\n await this.sseTransport.connect();\r\n } catch (err) {\r\n this.state = 'failed';\r\n throw err;\r\n }\r\n this._tools = this.sseTransport.listTools();\r\n this._toolsCache = this._tools;\r\n this.state = 'connected';\r\n }\r\n\r\n private async connectStreamableHTTP(): Promise<void> {\r\n if (!this.opts.url) {\r\n this.state = 'failed';\r\n throw new Error('MCP streamable-http transport requires \"url\"');\r\n }\r\n const httpOpts: HttpTransportOptions = {\r\n name: this.opts.name,\r\n url: this.opts.url,\r\n headers: this.opts.headers,\r\n startupTimeoutMs: this.opts.startupTimeoutMs,\r\n };\r\n this.httpTransport = new StreamableHTTPTransport(httpOpts);\r\n this.httpTransport.onDisconnect(() => {\r\n this.state = 'disconnected';\r\n for (const cb of this.disconnectListeners) {\r\n try { cb(); } catch { /* ignore */ }\r\n }\r\n });\r\n this.httpTransport.onToolsChanged((tools) => {\r\n this._tools = tools;\r\n for (const cb of this.toolsChangedListeners) {\r\n try { cb(this.opts.name, tools); } catch { /* ignore */ }\r\n }\r\n });\r\n try {\r\n await this.httpTransport.connect();\r\n } catch (err) {\r\n this.state = 'failed';\r\n throw err;\r\n }\r\n this._tools = this.httpTransport.listTools();\r\n this._toolsCache = this._tools;\r\n this.state = 'connected';\r\n }\r\n\r\n async callTool(name: string, input: unknown): Promise<ToolCallResult> {\r\n if (this.state !== 'connected') {\r\n throw new Error(`MCP client \"${this.opts.name}\" not connected (state=${this.state})`);\r\n }\r\n // Delegate to the active transport\r\n if (this.sseTransport) {\r\n return this.sseTransport.callTool(name, input);\r\n }\r\n if (this.httpTransport) {\r\n return this.httpTransport.callTool(name, input);\r\n }\r\n // stdio\r\n const res = await this.request('tools/call', { name, arguments: input });\r\n if (res.error) {\r\n return { content: res.error.message, isError: true };\r\n }\r\n const result = res.result as { content?: unknown; isError?: boolean } | undefined;\r\n return {\r\n content: result?.content ?? '',\r\n isError: Boolean(result?.isError),\r\n };\r\n }\r\n\r\n async close(): Promise<void> {\r\n if (this.child) {\r\n const child = this.child;\r\n const exitPromise = child.exitCode === null && child.signalCode === null\r\n ? new Promise<void>((resolve) => child.once('exit', () => resolve()))\r\n : Promise.resolve();\r\n try {\r\n child.kill();\r\n } catch {\r\n // ignore\r\n }\r\n // Wait for actual exit so exit-listener consumers see the event before\r\n // close() resolves. Cap the wait so a hung child can't pin us forever.\r\n await Promise.race([\r\n exitPromise,\r\n new Promise<void>((resolve) => setTimeout(resolve, 1000)),\r\n ]);\r\n }\r\n this.sseTransport?.close();\r\n this.httpTransport?.close();\r\n this.state = 'disconnected';\r\n }\r\n\r\n private request(method: string, params: unknown): Promise<JsonRpcResponse> {\r\n const id = this.nextId++;\r\n const req: JsonRpcRequest = { jsonrpc: '2.0', id, method, params };\r\n return new Promise((resolve, reject) => {\r\n this.pending.set(id, resolve);\r\n try {\r\n this.child?.stdin?.write(JSON.stringify(req) + '\\n');\r\n } catch (err) {\r\n this.pending.delete(id);\r\n reject(err);\r\n }\r\n });\r\n }\r\n\r\n private async notify(method: string, params: unknown): Promise<void> {\r\n const req = { jsonrpc: '2.0', method, params };\r\n const encoded = JSON.stringify(req) + '\\n';\r\n try {\r\n const ok = this.child?.stdin?.write(encoded);\r\n if (!ok) {\r\n // Only the first caller waits for drain; others just warn and return.\r\n // This avoids a race where two concurrent notify() calls each start\r\n // their own drain-wait, then both resolve and the buffer is still full.\r\n if (this._drainPending) {\r\n this._lastNotifySkipped = true;\r\n process.emitWarning(\r\n `[MCP] notify(\"${method}\") skipped: stdin buffer backpressure (already waiting for drain)`,\r\n );\r\n return;\r\n }\r\n this._drainPending = true;\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(() => {\r\n this._drainPending = false;\r\n reject(new Error(`MCP notify(\"${method}\") drain timeout`));\r\n }, 500);\r\n this.child?.stdin?.once('drain', () => {\r\n clearTimeout(timeout);\r\n this._drainPending = false;\r\n resolve();\r\n });\r\n this.child?.stdin?.once('error', (err) => {\r\n clearTimeout(timeout);\r\n this._drainPending = false;\r\n reject(err);\r\n });\r\n });\r\n }\r\n } catch (err) {\r\n throw new Error(`[MCP] notify(\"${method}\") failed: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n\r\n private onData(s: string): void {\r\n this.rxBuffer += s;\r\n let idx = this.rxBuffer.indexOf('\\n');\r\n while (idx !== -1) {\r\n const line = this.rxBuffer.slice(0, idx).trim();\r\n this.rxBuffer = this.rxBuffer.slice(idx + 1);\r\n if (line) this.onLine(line);\r\n idx = this.rxBuffer.indexOf('\\n');\r\n }\r\n }\r\n\r\n private onLine(line: string): void {\r\n let msg: JsonRpcResponse & { method?: string; params?: unknown };\r\n try {\r\n msg = JSON.parse(line) as JsonRpcResponse & { method?: string; params?: unknown };\r\n } catch {\r\n return;\r\n }\r\n if (msg.id !== undefined && this.pending.has(msg.id)) {\r\n const resolve = this.pending.get(msg.id);\r\n this.pending.delete(msg.id);\r\n resolve?.(msg);\r\n return;\r\n }\r\n // Notifications have a `method` but no `id`. The MCP spec defines\r\n // `notifications/tools/list_changed` for tool-set invalidation —\r\n // refresh the cache asynchronously and fire listeners so the\r\n // registry can re-register the wrapped tools.\r\n if (typeof msg.method === 'string' && msg.method === 'notifications/tools/list_changed') {\r\n void this.handleToolsListChanged();\r\n }\r\n }\r\n\r\n /**\r\n * L2-C: refresh the cached tool list when the server announces a\r\n * `tools/list_changed`. Listeners (the registry) re-wrap and\r\n * re-register. Failures are swallowed — a stale cache is preferable\r\n * to a hard crash on a transient notification glitch.\r\n */\r\n private async handleToolsListChanged(): Promise<void> {\r\n try {\r\n const toolsRes = await this.request('tools/list', {});\r\n const tools = ((toolsRes.result as { tools?: MCPTool[] } | undefined)?.tools ?? []).filter(\r\n (t): t is MCPTool => !!t && typeof t.name === 'string',\r\n );\r\n this._tools = tools;\r\n this._toolsCache = tools;\r\n for (const listener of this.toolsChangedListeners) {\r\n try {\r\n listener(this.opts.name, [...tools]);\r\n } catch {\r\n // listeners must be best-effort\r\n }\r\n }\r\n } catch {\r\n // ignore — keep the existing cache\r\n }\r\n }\r\n\r\n addToolsChangedListener(listener: ToolsChangedListener): void {\r\n this.toolsChangedListeners.add(listener);\r\n }\r\n\r\n removeToolsChangedListener(listener: ToolsChangedListener): void {\r\n this.toolsChangedListeners.delete(listener);\r\n }\r\n}","import type { Tool, Permission } from '@wrongstack/core';\r\nimport type { MCPClient, MCPTool } from './client.js';\r\n\r\n/**\r\n * Keywords that indicate a mutating operation.\r\n * Applied to both the tool name and its inputSchema property names.\r\n */\r\nconst MUTATING_RE = /create|update|delete|write|send|set|put|post|patch|remove|rename|move/i;\r\n\r\nfunction isMutatingTool(mcpTool: MCPTool): boolean {\r\n if (MUTATING_RE.test(mcpTool.name)) return true;\r\n // Check property names in the input schema for mutating intent.\r\n // e.g. { properties: { createTable: {...}, dropIndex: {...} } }\r\n const schema = mcpTool.inputSchema;\r\n if (schema && typeof schema === 'object') {\r\n const props = (schema as { properties?: Record<string, unknown> }).properties;\r\n if (props) {\r\n for (const key of Object.keys(props)) {\r\n if (MUTATING_RE.test(key)) return true;\r\n }\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport function wrapMCPTool(\r\n serverName: string,\r\n mcpTool: MCPTool,\r\n client: MCPClient,\r\n permission: Permission = 'confirm',\r\n): Tool {\r\n const qualifiedName = `mcp__${serverName}__${mcpTool.name}`;\r\n return {\r\n name: qualifiedName,\r\n description: mcpTool.description ?? `${qualifiedName} (MCP tool)`,\r\n usageHint: `Tool provided by MCP server \"${serverName}\". ${mcpTool.description ?? ''}`,\r\n permission,\r\n mutating: isMutatingTool(mcpTool),\r\n inputSchema: mcpTool.inputSchema ?? { type: 'object', properties: {} },\r\n async execute(input, ctx, opts) {\r\n const res = await client.callTool(mcpTool.name, input);\r\n if (res.isError) {\r\n throw new Error(stringify(res.content));\r\n }\r\n return stringify(res.content);\r\n },\r\n };\r\n}\r\n\r\nfunction stringify(c: unknown): string {\r\n if (typeof c === 'string') return c;\r\n if (Array.isArray(c)) {\r\n return c\r\n .map((item) => {\r\n if (item && typeof item === 'object') {\r\n const t = (item as { type?: string; text?: string }).type;\r\n if (t === 'text') return (item as { text?: string }).text ?? '';\r\n return JSON.stringify(item);\r\n }\r\n return String(item);\r\n })\r\n .join('\\n');\r\n }\r\n if (c && typeof c === 'object') {\r\n if ('text' in (c as Record<string, unknown>)) {\r\n return String((c as Record<string, unknown>).text);\r\n }\r\n return JSON.stringify(c);\r\n }\r\n return String(c ?? '');\r\n}\r\n","import type { EventBus, MCPServerConfig, ToolRegistry, Logger } from '@wrongstack/core';\r\nimport { MCPClient, type ConnectionState } from './client.js';\r\nimport { wrapMCPTool } from './wrap-tool.js';\r\n\r\ninterface ServerSlot {\r\n cfg: MCPServerConfig;\r\n client?: MCPClient;\r\n state: ConnectionState;\r\n toolNames: string[];\r\n attempts: number;\r\n /** Set when a reconnect cycle is already running for this slot. */\r\n reconnectPending: boolean;\r\n /**\r\n * L2-B: number of full reconnect *cycles* (where one cycle = one\r\n * `attemptConnect` invocation, which itself can try multiple times\r\n * before giving up). After `MAX_RECONNECT_CYCLES`, the slot stays\r\n * `failed` until a manual `restart()` resets it.\r\n */\r\n reconnectCycles: number;\r\n}\r\n\r\nexport interface MCPRegistryOptions {\r\n toolRegistry: ToolRegistry;\r\n events: EventBus;\r\n log: Logger;\r\n}\r\n\r\nexport class MCPRegistry {\r\n private readonly servers = new Map<string, ServerSlot>();\r\n private readonly toolRegistry: ToolRegistry;\r\n private readonly events: EventBus;\r\n private readonly log: Logger;\r\n\r\n constructor(opts: MCPRegistryOptions) {\r\n this.toolRegistry = opts.toolRegistry;\r\n this.events = opts.events;\r\n this.log = opts.log;\r\n }\r\n\r\n async start(cfg: MCPServerConfig): Promise<void> {\r\n if (cfg.enabled === false) return;\r\n const slot: ServerSlot = {\r\n cfg,\r\n state: 'idle',\r\n toolNames: [],\r\n attempts: 0,\r\n reconnectPending: false,\r\n reconnectCycles: 0,\r\n };\r\n this.servers.set(cfg.name, slot);\r\n await this.attemptConnect(slot);\r\n }\r\n\r\n async stop(name: string): Promise<void> {\r\n const slot = this.servers.get(name);\r\n if (!slot) return;\r\n slot.reconnectPending = false;\r\n if (slot.client) {\r\n slot.client.removeExitListener(this.onChildExit);\r\n slot.client.removeDisconnectListener(() => this.onTransportDisconnect(slot.cfg.name));\r\n slot.client.removeToolsChangedListener(this.onToolsChanged);\r\n await slot.client.close();\r\n }\r\n for (const t of slot.toolNames) this.toolRegistry.unregister(t);\r\n slot.toolNames = [];\r\n slot.state = 'disconnected';\r\n this.events.emit('mcp.server.disconnected', { name, reason: 'stop' });\r\n }\r\n\r\n async restart(name: string): Promise<void> {\r\n const slot = this.servers.get(name);\r\n if (!slot) throw new Error(`MCP server \"${name}\" not registered`);\r\n await this.stop(name);\r\n slot.attempts = 0;\r\n slot.reconnectCycles = 0; // user intent: start fresh\r\n await this.attemptConnect(slot);\r\n }\r\n\r\n list(): { name: string; state: ConnectionState; toolCount: number }[] {\r\n return Array.from(this.servers.values()).map((s) => ({\r\n name: s.cfg.name,\r\n state: s.state,\r\n toolCount: s.toolNames.length,\r\n }));\r\n }\r\n\r\n async stopAll(): Promise<void> {\r\n for (const name of Array.from(this.servers.keys())) {\r\n await this.stop(name);\r\n }\r\n }\r\n\r\n /**\r\n * Health check — returns 'ok' for connected servers, the current state otherwise.\r\n * For HTTP-based transports this could also ping the server.\r\n */\r\n health(): { name: string; alive: boolean; latencyMs?: number }[] {\r\n return Array.from(this.servers.values()).map((s) => ({\r\n name: s.cfg.name,\r\n alive: s.state === 'connected',\r\n }));\r\n }\r\n\r\n /**\r\n * L2-C: handle `notifications/tools/list_changed` from the server.\r\n * Unregister the previous wrapper set, then re-register the fresh\r\n * tool list. The client has already refreshed its cache before\r\n * dispatching — we just need to re-wrap and re-register.\r\n */\r\n private readonly onToolsChanged = (name: string, _tools: { name: string }[]): void => {\r\n const slot = this.servers.get(name);\r\n if (!slot || !slot.client) return;\r\n for (const t of slot.toolNames) {\r\n try { this.toolRegistry.unregister(t); } catch { /* ignore */ }\r\n }\r\n slot.toolNames = [];\r\n const allowed = slot.cfg.allowedTools;\r\n const wrapped = slot.client\r\n .listTools()\r\n .filter((t) => !allowed || allowed.includes(t.name))\r\n .map((t) => wrapMCPTool(slot.cfg.name, t, slot.client!, slot.cfg.permission ?? 'confirm'));\r\n for (const tool of wrapped) {\r\n try {\r\n this.toolRegistry.register(tool, `mcp:${slot.cfg.name}`);\r\n slot.toolNames.push(tool.name);\r\n } catch (err) {\r\n this.log.warn(`MCP tool \"${tool.name}\" not re-registered after list_changed`, err);\r\n }\r\n }\r\n this.events.emit('mcp.server.connected', {\r\n name: slot.cfg.name,\r\n toolCount: slot.toolNames.length,\r\n });\r\n this.log.info(\r\n `MCP server \"${slot.cfg.name}\" tools refreshed (${slot.toolNames.length} active)`,\r\n );\r\n };\r\n\r\n private readonly onChildExit = (name: string, code: number | null, _signal: string | null): void => {\r\n const slot = this.servers.get(name);\r\n if (!slot) return;\r\n for (const t of slot.toolNames) {\r\n try { this.toolRegistry.unregister(t); } catch { /* ignore */ }\r\n }\r\n slot.toolNames = [];\r\n slot.state = 'disconnected';\r\n this.events.emit('mcp.server.disconnected', { name, reason: `exit:${code ?? 'unknown'}` });\r\n this.scheduleReconnect(slot);\r\n };\r\n\r\n /** Handles SSE / streamable-http disconnect — same recovery as stdio child exit. */\r\n private readonly onTransportDisconnect = (name: string): void => {\r\n const slot = this.servers.get(name);\r\n if (!slot) return;\r\n for (const t of slot.toolNames) {\r\n try { this.toolRegistry.unregister(t); } catch { /* ignore */ }\r\n }\r\n slot.toolNames = [];\r\n slot.state = 'disconnected';\r\n this.events.emit('mcp.server.disconnected', { name, reason: 'http-disconnect' });\r\n this.scheduleReconnect(slot);\r\n };\r\n\r\n /**\r\n * L2-B: maximum number of reconnect cycles before staying `failed`.\r\n * One cycle = one full `attemptConnect` (which itself may try up to 3\r\n * times). Caps total reconnect storm at ~5 cycles, then the slot\r\n * needs an explicit `restart()` to re-engage.\r\n */\r\n private static readonly MAX_RECONNECT_CYCLES = 5;\r\n /** Base delay between cycles, in ms. Real delay adds jitter. */\r\n private static readonly BASE_RECONNECT_DELAY_MS = 1000;\r\n /** Hard ceiling on the inter-cycle delay so the user doesn't wait minutes. */\r\n private static readonly MAX_RECONNECT_DELAY_MS = 30_000;\r\n\r\n private scheduleReconnect(slot: ServerSlot): void {\r\n if (slot.reconnectPending) return;\r\n if (slot.reconnectCycles >= MCPRegistry.MAX_RECONNECT_CYCLES) {\r\n slot.state = 'failed';\r\n this.log.error(\r\n `MCP server \"${slot.cfg.name}\" giving up after ${slot.reconnectCycles} reconnect cycles. Use \\`/mcp restart ${slot.cfg.name}\\` to retry.`,\r\n );\r\n this.events.emit('mcp.server.disconnected', {\r\n name: slot.cfg.name,\r\n reason: `reconnect-exhausted:${slot.reconnectCycles}`,\r\n });\r\n return;\r\n }\r\n slot.reconnectPending = true;\r\n // Exponential backoff with light jitter: 1s, 2s, 4s, 8s, 16s, capped\r\n // at 30s. The ±20% jitter avoids reconnect stampedes when many\r\n // servers crash together.\r\n const base = Math.min(\r\n MCPRegistry.BASE_RECONNECT_DELAY_MS * 2 ** slot.reconnectCycles,\r\n MCPRegistry.MAX_RECONNECT_DELAY_MS,\r\n );\r\n const jitter = base * 0.2 * (Math.random() * 2 - 1);\r\n const delay = Math.max(100, Math.round(base + jitter));\r\n setTimeout(() => this.attemptReconnect(slot), delay);\r\n }\r\n\r\n private async attemptReconnect(slot: ServerSlot): Promise<void> {\r\n slot.reconnectPending = false;\r\n slot.reconnectCycles++;\r\n await this.attemptConnect(slot);\r\n }\r\n\r\n private async attemptConnect(slot: ServerSlot): Promise<void> {\r\n const MAX_ATTEMPTS = 3;\r\n let attempt = 0;\r\n while (attempt < MAX_ATTEMPTS) {\r\n attempt++;\r\n slot.state = attempt === 1 ? 'connecting' : 'reconnecting';\r\n slot.attempts = attempt;\r\n let client: MCPClient | undefined;\r\n try {\r\n client = new MCPClient({\r\n name: slot.cfg.name,\r\n transport: slot.cfg.transport,\r\n command: slot.cfg.command,\r\n args: slot.cfg.args,\r\n env: slot.cfg.env,\r\n url: slot.cfg.url,\r\n headers: slot.cfg.headers,\r\n startupTimeoutMs: slot.cfg.startupTimeoutMs,\r\n });\r\n if (slot.cfg.transport === 'stdio') {\r\n client.addExitListener(this.onChildExit);\r\n } else {\r\n // SSE / streamable-http — wire transport disconnect to registry reconnect\r\n client.addDisconnectListener(() => this.onTransportDisconnect(slot.cfg.name));\r\n }\r\n // L2-C: react to server-side tool changes by re-registering wrappers.\r\n client.addToolsChangedListener(this.onToolsChanged);\r\n await client.connect();\r\n slot.client = client;\r\n const isReconnect = attempt > 1;\r\n slot.state = 'connected';\r\n // L2-B: a healthy connect resets the cycle counter so future\r\n // crashes get the full reconnect budget again.\r\n slot.reconnectCycles = 0;\r\n const allowed = slot.cfg.allowedTools;\r\n // Prefer cached tools to avoid a round-trip to the server on reconnect.\r\n // The cache is populated by client.listTools() on first connect.\r\n const mc = client as MCPClient;\r\n const candidateTools = mc.listTools();\r\n const toWrap = candidateTools.length > 0\r\n ? candidateTools\r\n : mc.listTools(); // fallback — in practice both return the same list\r\n const wrapped = toWrap\r\n .filter((t) => !allowed || allowed.includes(t.name))\r\n .map((t) => wrapMCPTool(slot.cfg.name, t, mc, slot.cfg.permission ?? 'confirm'));\r\n for (const tool of wrapped) {\r\n try {\r\n this.toolRegistry.register(tool, `mcp:${slot.cfg.name}`);\r\n slot.toolNames.push(tool.name);\r\n } catch (err) {\r\n this.log.warn(`MCP tool \"${tool.name}\" not registered`, err);\r\n }\r\n }\r\n this.events.emit(isReconnect ? 'mcp.server.reconnected' : 'mcp.server.connected', {\r\n name: slot.cfg.name,\r\n toolCount: slot.toolNames.length,\r\n });\r\n return; // success\r\n } catch (err) {\r\n this.log.warn(`MCP server \"${slot.cfg.name}\" connect attempt ${attempt} failed`, err);\r\n if (client) {\r\n client.removeExitListener(this.onChildExit);\r\n client.removeDisconnectListener(() => this.onTransportDisconnect(slot.cfg.name));\r\n client.removeToolsChangedListener(this.onToolsChanged);\r\n await client.close().catch(() => {/* ignore */});\r\n }\r\n if (attempt >= MAX_ATTEMPTS) {\r\n this.log.error(`MCP server \"${slot.cfg.name}\" connect exhausted after ${MAX_ATTEMPTS} attempts`, err);\r\n slot.state = 'failed';\r\n slot.client = undefined;\r\n this.events.emit('mcp.server.disconnected', {\r\n name: slot.cfg.name,\r\n reason: err instanceof Error ? err.message : 'unknown',\r\n });\r\n return;\r\n }\r\n const delay = 500 * 2 ** attempt;\r\n await new Promise((r) => setTimeout(r, delay));\r\n }\r\n }\r\n }\r\n}"]}
|
|
1
|
+
{"version":3,"sources":["../src/transport.ts","../src/client.ts","../src/wrap-tool.ts","../src/registry.ts"],"names":["body"],"mappings":"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","file":"index.js","sourcesContent":["import type { ConnectionState, MCPTool, ToolCallResult } from './client.js';\n\nexport type JsonRpcResult = { jsonrpc: string; id?: number; result?: unknown; error?: { code: number; message: string; data?: unknown } };\n\nexport interface HttpTransportOptions {\n name: string;\n url: string;\n headers?: Record<string, string>;\n startupTimeoutMs?: number;\n}\n\n/**\n * SSE-based MCP transport using native fetch.\n *\n * Communication pattern:\n * - Client connects to SSE endpoint to receive server messages (JSON-RPC events)\n * - Client sends JSON-RPC requests via HTTP POST to the same or separate endpoint\n * - Server sends results/errors via the SSE stream\n *\n * The SSE reader parses the SSE protocol (event:, data:, blank line to dispatch).\n */\nexport class SSEReader {\n private buffer = '';\n private listeners: Array<(event: { jsonrpc?: string; method?: string; params?: unknown; id?: number }) => void> = [];\n\n onMessage(cb: (data: { jsonrpc?: string; method?: string; params?: unknown; id?: number }) => void): () => void {\n this.listeners.push(cb);\n return () => {\n const idx = this.listeners.indexOf(cb);\n if (idx >= 0) this.listeners.splice(idx, 1);\n };\n }\n\n feed(chunk: string): void {\n this.buffer += chunk;\n let idx = this.buffer.indexOf('\\n');\n while (idx !== -1) {\n const line = this.buffer.slice(0, idx);\n this.buffer = this.buffer.slice(idx + 1);\n idx = this.buffer.indexOf('\\n');\n\n if (line.startsWith('event:')) {\n // track event type, ignore for now\n } else if (line.startsWith('data:')) {\n const data = line.slice(5).trim();\n if (data) {\n try {\n const parsed = JSON.parse(data) as { jsonrpc?: string; method?: string; params?: unknown; id?: number };\n this.dispatch(parsed);\n } catch {\n // ignore parse errors\n }\n }\n }\n }\n }\n\n private dispatch(msg: { jsonrpc?: string; method?: string; params?: unknown; id?: number }): void {\n for (const cb of this.listeners) {\n try { cb(msg); } catch { /* ignore */ }\n }\n }\n\n reset(): void {\n this.buffer = '';\n this.listeners = [];\n }\n}\n\nfunction isJsonRpcResult(v: unknown): v is JsonRpcResult {\n return typeof v === 'object' && v !== null && 'jsonrpc' in v;\n}\n\n/**\n * SSE transport for MCP over HTTP.\n *\n * Uses native fetch API with ReadableStream to consume SSE events.\n * HTTP POST is used to send JSON-RPC requests.\n */\nexport class SSETransport {\n private state: ConnectionState = 'idle';\n private url: string;\n private headers: Record<string, string>;\n private timeout: number;\n private nextId = 1;\n // NOTE: id-correlation via this map was scaffolded but never populated by\n // `httpPost` — JSON-RPC responses come back synchronously over HTTP, not\n // via the SSE stream. Keep the field reserved for future bidirectional-\n // streaming support; do not wire callsites to it without first deciding\n // who is responsible for clearing it on transport teardown.\n private readonly _reservedPending = new Map<number, (res: JsonRpcResult) => void>();\n private tools: MCPTool[] = [];\n private abortController?: AbortController;\n private reader?: globalThis.ReadableStreamDefaultReader<string>;\n private readerDone = false;\n private disconnectHandlers: Array<() => void> = [];\n private readLoopAbort?: AbortController;\n private readonly toolsChangedListeners = new Set<(tools: MCPTool[]) => void>();\n\n constructor(opts: HttpTransportOptions) {\n this.url = opts.url;\n this.headers = { ...opts.headers };\n this.timeout = opts.startupTimeoutMs ?? 10_000;\n }\n\n getState(): ConnectionState {\n return this.state;\n }\n\n listTools(): MCPTool[] {\n return [...this.tools];\n }\n\n onDisconnect(cb: () => void): () => void {\n this.disconnectHandlers.push(cb);\n return () => {\n const idx = this.disconnectHandlers.indexOf(cb);\n if (idx >= 0) this.disconnectHandlers.splice(idx, 1);\n };\n }\n\n onToolsChanged(cb: (tools: MCPTool[]) => void): () => void {\n this.toolsChangedListeners.add(cb);\n return () => { this.toolsChangedListeners.delete(cb); };\n }\n\n /** Refresh tool list when server sends notifications/tools/list_changed. */\n private async handleToolsListChanged(): Promise<void> {\n try {\n const res = await this.httpPost('tools/list', {});\n if (!res.error) {\n this.tools = ((res.result as { tools?: MCPTool[] } | undefined)?.tools ?? []);\n for (const cb of this.toolsChangedListeners) {\n try { cb([...this.tools]); } catch { /* ignore */ }\n }\n }\n } catch { /* ignore transient failures */ }\n }\n\n async connect(): Promise<void> {\n this.state = 'connecting';\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n const startupTimer = setTimeout(() => this.abortController?.abort(), this.timeout);\n\n try {\n const sseUrl = this.buildSSEUrl();\n const response = await fetch(sseUrl, {\n headers: this.headers,\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`SSE connect HTTP ${response.status}: ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('SSE response has no body');\n }\n\n const textDecoder = new TextDecoder();\n const sseReader = new SSEReader();\n this.readLoopAbort = new AbortController();\n\n sseReader.onMessage((msg) => {\n // Future: if the spec evolves to send JSON-RPC responses over SSE\n // (rather than as HTTP POST replies), wire id-correlation here via\n // `_reservedPending`. Today httpPost owns response routing.\n // Server-initiated notifications (no id). Handle list_changed for L2-C.\n if (msg.method && !msg.id) {\n if (msg.method === 'notifications/tools/list_changed') {\n void this.handleToolsListChanged();\n }\n }\n });\n\n const reader = response.body.getReader();\n this.reader = {\n cancel: () => reader.cancel(),\n releaseLock: () => reader.releaseLock(),\n } as globalThis.ReadableStreamDefaultReader<string>;\n\n this.readSSEBody(reader, textDecoder, sseReader);\n\n const initRes = await this.httpPost('initialize', {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n clientInfo: { name: 'wrongstack', version: '0.1.6' },\n });\n\n if (initRes.error) {\n throw new Error(`initialize failed: ${initRes.error.message}`);\n }\n\n try {\n await this.httpPost('notifications/initialized', {});\n } catch {\n // servers may not require it\n }\n\n const toolsRes = await this.httpPost('tools/list', {});\n if (toolsRes.error) {\n this.tools = [];\n } else {\n const result = toolsRes.result as { tools?: MCPTool[] } | undefined;\n this.tools = result?.tools ?? [];\n }\n\n this.state = 'connected';\n clearTimeout(startupTimer);\n } catch (err) {\n clearTimeout(startupTimer);\n this.state = 'failed';\n this.abortController.abort();\n throw err;\n }\n }\n\n private async readSSEBody(\n reader: globalThis.ReadableStreamDefaultReader<Uint8Array>,\n decoder: InstanceType<typeof TextDecoder>,\n sseReader: SSEReader,\n ): Promise<void> {\n try {\n while (!this.readerDone) {\n const { done, value } = await reader.read();\n if (done) break;\n const chunk = decoder.decode(value, { stream: true });\n sseReader.feed(chunk);\n }\n } catch {\n // SSE read error — connection lost. Transition to disconnected so\n // callTool and health checks see the correct state, then notify\n // disconnect handlers so the registry can schedule a reconnect.\n if (this.state !== 'disconnected' && this.state !== 'failed') {\n this.state = 'disconnected';\n for (const cb of this.disconnectHandlers) {\n try { cb(); } catch { /* ignore */ }\n }\n }\n }\n }\n\n private buildSSEUrl(): string {\n try {\n const url = new URL(this.url);\n url.searchParams.set('session', String(Date.now()));\n return url.toString();\n } catch {\n return this.url;\n }\n }\n\n private async httpPost(method: string, params: unknown): Promise<JsonRpcResult> {\n const id = this.nextId++;\n const body = JSON.stringify({ jsonrpc: '2.0', id, method, params });\n\n const res = await fetch(this.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this.headers,\n },\n body,\n signal: this.abortController?.signal,\n });\n\n if (!res.ok) {\n // Cap the body — a misbehaving server could return megabytes of\n // HTML and that's not useful in an error message anyway.\n const body = await res.text();\n const cap = 1024;\n const snippet = body.length > cap ? `${body.slice(0, cap)}… [${body.length} bytes total]` : body;\n throw new Error(`HTTP ${res.status}: ${snippet}`);\n }\n\n let data: unknown;\n try {\n data = await res.json();\n } catch (err) {\n throw new Error(\n `Invalid JSON-RPC response: ${err instanceof Error ? err.message : 'parse failed'}`,\n { cause: err },\n );\n }\n if (!isJsonRpcResult(data)) {\n throw new Error('Invalid JSON-RPC response: not a JSON-RPC envelope');\n }\n return data;\n }\n\n async callTool(name: string, input: unknown): Promise<ToolCallResult> {\n if (this.state !== 'connected') {\n throw new Error(`SSE transport not connected (state=${this.state})`);\n }\n const res = await this.httpPost('tools/call', { name, arguments: input });\n if (res.error) {\n return { content: res.error.message, isError: true };\n }\n const result = res.result as { content?: unknown; isError?: boolean } | undefined;\n return {\n content: result?.content ?? '',\n isError: Boolean(result?.isError),\n };\n }\n\n async close(): Promise<void> {\n // Idempotent — safe to call multiple times.\n if (this.state === 'disconnected') return;\n this.readerDone = true;\n this.readLoopAbort?.abort();\n try { this.reader?.cancel(); } catch { /* ignore */ }\n try { this.reader?.releaseLock(); } catch { /* ignore */ }\n this.abortController?.abort();\n this.disconnectHandlers = [];\n this.state = 'disconnected';\n }\n}\n\n/**\n * Streamable HTTP transport for MCP.\n *\n * Uses session-based HTTP with NDJSON responses.\n */\nexport class StreamableHTTPTransport {\n private state: ConnectionState = 'idle';\n private url: string;\n private headers: Record<string, string>;\n private timeout: number;\n private nextId = 1;\n private tools: MCPTool[] = [];\n private abortController?: AbortController;\n private sessionId?: string;\n private disconnectHandlers: Array<() => void> = [];\n private readonly toolsChangedListeners = new Set<(tools: MCPTool[]) => void>();\n\n constructor(opts: HttpTransportOptions) {\n this.url = opts.url;\n this.headers = { ...opts.headers };\n this.timeout = opts.startupTimeoutMs ?? 10_000;\n }\n\n getState(): ConnectionState {\n return this.state;\n }\n\n listTools(): MCPTool[] {\n return [...this.tools];\n }\n\n onDisconnect(cb: () => void): () => void {\n this.disconnectHandlers.push(cb);\n return () => {\n const idx = this.disconnectHandlers.indexOf(cb);\n if (idx >= 0) this.disconnectHandlers.splice(idx, 1);\n };\n }\n\n onToolsChanged(cb: (tools: MCPTool[]) => void): () => void {\n this.toolsChangedListeners.add(cb);\n return () => { this.toolsChangedListeners.delete(cb); };\n }\n\n private async handleToolsListChanged(): Promise<void> {\n try {\n const res = await this.postRaw('tools/list', {});\n if (!res.error) {\n this.tools = ((res.result as { tools?: MCPTool[] } | undefined)?.tools ?? []);\n for (const cb of this.toolsChangedListeners) {\n try { cb([...this.tools]); } catch { /* ignore */ }\n }\n }\n } catch { /* ignore transient failures */ }\n }\n\n async connect(): Promise<void> {\n this.state = 'connecting';\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n const startupTimer = setTimeout(() => this.abortController?.abort(), this.timeout);\n\n try {\n const initRes = await fetch(this.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json, text/event-stream',\n ...this.headers,\n },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: this.nextId++,\n method: 'initialize',\n params: {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n clientInfo: { name: 'wrongstack', version: '0.1.6' },\n },\n }),\n signal,\n });\n\n if (!initRes.ok) {\n throw new Error(`initialize HTTP ${initRes.status}: ${initRes.statusText}`);\n }\n\n const contentType = initRes.headers.get('content-type') ?? '';\n let data: JsonRpcResult | undefined;\n\n if (contentType.includes('application/json')) {\n const parsed = await initRes.json();\n if (isJsonRpcResult(parsed)) data = parsed;\n } else {\n const text = await initRes.text();\n const lines = text.split('\\n').filter(l => l.trim());\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line);\n if (isJsonRpcResult(parsed)) {\n data = parsed;\n break;\n }\n } catch {}\n }\n }\n\n if (!data) {\n throw new Error('Could not parse initialize response');\n }\n\n if (data.error) {\n throw new Error(`initialize failed: ${data.error.message}`);\n }\n\n this.sessionId = (initRes.headers.get('x-mcp-session') ?? undefined) as string | undefined;\n await this.postRaw('notifications/initialized', {});\n\n const toolsRes = await this.postRaw('tools/list', {});\n if (toolsRes.error) {\n this.tools = [];\n } else {\n const result = toolsRes.result as { tools?: MCPTool[] } | undefined;\n this.tools = result?.tools ?? [];\n }\n\n this.state = 'connected';\n clearTimeout(startupTimer);\n } catch (err) {\n clearTimeout(startupTimer);\n this.state = 'failed';\n this.abortController.abort();\n throw err;\n }\n }\n\n private async postRaw(method: string, params: unknown): Promise<JsonRpcResult> {\n const id = this.nextId++;\n const body = JSON.stringify({ jsonrpc: '2.0', id, method, params });\n\n const url = this.sessionId\n ? `${this.url}${this.url.includes('?') ? '&' : '?'}session=${this.sessionId}`\n : this.url;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json, text/event-stream',\n ...(this.sessionId ? { 'x-mcp-session': this.sessionId } : {}),\n ...this.headers,\n },\n body,\n signal: this.abortController?.signal,\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}: ${res.statusText}`);\n }\n\n const text = await res.text();\n const lines = text.split('\\n').filter(l => l.trim());\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line);\n if (isJsonRpcResult(parsed)) return parsed;\n } catch {}\n }\n throw new Error('Could not parse response as JSON-RPC');\n }\n\n async callTool(name: string, input: unknown): Promise<ToolCallResult> {\n if (this.state !== 'connected') {\n throw new Error(`streamable-http transport not connected (state=${this.state})`);\n }\n const res = await this.postRaw('tools/call', { name, arguments: input });\n if (res.error) {\n return { content: res.error.message, isError: true };\n }\n const result = res.result as { content?: unknown; isError?: boolean } | undefined;\n return {\n content: result?.content ?? '',\n isError: Boolean(result?.isError),\n };\n }\n\n async close(): Promise<void> {\n if (this.state === 'disconnected') return;\n this.state = 'disconnected';\n this.abortController?.abort();\n for (const cb of this.disconnectHandlers) {\n try { cb(); } catch { /* ignore */ }\n }\n this.disconnectHandlers = [];\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\r\nimport { SSETransport, StreamableHTTPTransport, type HttpTransportOptions } from './transport.js';\r\n\r\nexport type Transport = 'stdio' | 'sse' | 'streamable-http';\r\n\r\nexport interface MCPClientOptions {\r\n name: string;\r\n transport: Transport;\r\n command?: string;\r\n args?: string[];\r\n env?: Record<string, string>;\r\n url?: string;\r\n headers?: Record<string, string>;\r\n startupTimeoutMs?: number;\r\n}\r\n\r\nexport type ConnectionState =\r\n | 'idle'\r\n | 'connecting'\r\n | 'connected'\r\n | 'disconnected'\r\n | 'reconnecting'\r\n | 'failed';\r\n\r\nexport interface MCPTool {\r\n name: string;\r\n description?: string;\r\n inputSchema: Record<string, unknown>;\r\n}\r\n\r\nexport interface ToolCallResult {\r\n content: unknown;\r\n isError: boolean;\r\n}\r\n\r\ninterface JsonRpcRequest {\r\n jsonrpc: '2.0';\r\n id: number;\r\n method: string;\r\n params?: unknown;\r\n}\r\n\r\ninterface JsonRpcResponse {\r\n jsonrpc: '2.0';\r\n id: number;\r\n result?: unknown;\r\n error?: { code: number; message: string; data?: unknown };\r\n}\r\n\r\ntype ExitListener = (name: string, code: number | null, signal: string | null) => void;\r\n/**\r\n * Fired when the server sends `notifications/tools/list_changed`. The\r\n * client refreshes its cached tool list before invoking listeners, so\r\n * subscribers can call `listTools()` for the fresh set.\r\n */\r\ntype ToolsChangedListener = (name: string, tools: MCPTool[]) => void;\r\n\r\n/**\r\n * Lightweight MCP client supporting three transport types:\r\n * - stdio: spawns a child process and communicates over pipes\r\n * - sse: connects to an HTTP SSE endpoint for server events, POST for requests\r\n * - streamable-http: session-based HTTP transport with NDJSON responses\r\n */\r\nexport class MCPClient {\r\n private state: ConnectionState = 'idle';\r\n private child?: ChildProcess;\r\n private nextId = 1;\r\n /**\r\n * In-flight JSON-RPC calls keyed by id. `resolve` settles the call; `reject`\r\n * is invoked from {@link failPending} when the underlying transport dies\r\n * (stdio child exit, `close()`) so callers don't hang forever.\r\n */\r\n private readonly pending = new Map<\r\n number,\r\n { resolve: (res: JsonRpcResponse) => void; reject: (err: Error) => void }\r\n >();\r\n private rxBuffer = '';\r\n private _tools: MCPTool[] = [];\r\n /** Cached tool list — survives reconnects so the registry can re-register without re-discovering. */\r\n private _toolsCache?: MCPTool[];\r\n private _drainPending = false;\r\n private _lastNotifySkipped = false;\r\n // HTTP transports\r\n private sseTransport?: SSETransport;\r\n private httpTransport?: StreamableHTTPTransport;\r\n /** Notified when the stdio child process exits so the registry can attempt reconnect. */\r\n private readonly exitListeners = new Set<ExitListener>();\r\n /** Notified when the server announces a tools/list_changed notification. */\r\n private readonly toolsChangedListeners = new Set<ToolsChangedListener>();\r\n /** Notified when an HTTP transport (SSE or streamable-http) disconnects. */\r\n private readonly disconnectListeners = new Set<() => void>();\r\n\r\n constructor(public readonly opts: MCPClientOptions) {}\r\n\r\n getState(): ConnectionState {\r\n return this.state;\r\n }\r\n\r\n listTools(): MCPTool[] {\r\n return this._tools.length > 0 ? [...this._tools] : this._toolsCache ? [...this._toolsCache] : [];\r\n }\r\n\r\n /** Returns true if a prior notify() call was skipped due to backpressure. */\r\n hadNotifySkipped(): boolean {\r\n return this._lastNotifySkipped;\r\n }\r\n\r\n /**\r\n * Register a listener for child-process exit events.\r\n * The registry uses this to trigger reconnection.\r\n */\r\n addExitListener(listener: ExitListener): void {\r\n this.exitListeners.add(listener);\r\n }\r\n\r\n removeExitListener(listener: ExitListener): void {\r\n this.exitListeners.delete(listener);\r\n }\r\n\r\n /**\r\n * Register a listener for transport disconnect events (SSE / streamable-http).\r\n * Used by the registry to trigger reconnection for HTTP-based servers.\r\n */\r\n addDisconnectListener(listener: () => void): void {\r\n this.disconnectListeners.add(listener);\r\n }\r\n\r\n removeDisconnectListener(listener: () => void): void {\r\n this.disconnectListeners.delete(listener);\r\n }\r\n\r\n async connect(): Promise<void> {\r\n this.state = 'connecting';\r\n\r\n if (this.opts.transport === 'stdio') {\r\n await this.connectStdio();\r\n } else if (this.opts.transport === 'sse') {\r\n await this.connectSSE();\r\n } else if (this.opts.transport === 'streamable-http') {\r\n await this.connectStreamableHTTP();\r\n } else {\r\n this.state = 'failed';\r\n throw new Error(`Unknown transport \"${this.opts.transport}\"`);\r\n }\r\n }\r\n\r\n private async connectStdio(): Promise<void> {\r\n if (!this.opts.command) {\r\n this.state = 'failed';\r\n throw new Error('MCP stdio transport requires \"command\"');\r\n }\r\n\r\n // Defense-in-depth: clear any rx state from a previous connect attempt\r\n // on this instance. The registry normally creates a fresh client per\r\n // (re)connect cycle, but a leftover rxBuffer from a half-initialized\r\n // attempt would corrupt JSON-RPC parsing on the new stream.\r\n this.rxBuffer = '';\r\n\r\n const child = spawn(this.opts.command, this.opts.args ?? [], {\r\n env: { ...process.env, ...this.opts.env },\r\n stdio: ['pipe', 'pipe', 'pipe'],\r\n });\r\n this.child = child;\r\n\r\n child.stdout?.on('data', (chunk: Buffer) => this.onData(chunk.toString()));\r\n child.stderr?.on('data', () => {\r\n // intentionally discard stderr noise from server\r\n });\r\n child.on('exit', (code, signal) => {\r\n this.state = 'disconnected';\r\n // Reject any in-flight JSON-RPC requests — without this, callers\r\n // (e.g. callTool during a tool invocation) await forever on a child\r\n // that has already gone away.\r\n this.failPending(`MCP \"${this.opts.name}\" child exited (code=${code ?? 'null'} signal=${signal ?? 'null'})`);\r\n for (const listener of this.exitListeners) {\r\n try { listener(this.opts.name, code, signal); } catch { /* ignore */ }\r\n }\r\n });\r\n child.on('error', () => {\r\n this.state = 'failed';\r\n });\r\n\r\n const timeout = this.opts.startupTimeoutMs ?? 10_000;\r\n const initialize = await Promise.race([\r\n this.request('initialize', {\r\n protocolVersion: '2024-11-05',\r\n capabilities: { tools: {} },\r\n clientInfo: { name: 'wrongstack', version: '0.1.6' },\r\n }),\r\n new Promise<JsonRpcResponse>((_, rej) =>\r\n setTimeout(() => rej(new Error('MCP initialize timeout')), timeout),\r\n ),\r\n ]);\r\n if (initialize.error) {\r\n this.state = 'failed';\r\n throw new Error(`MCP initialize failed: ${initialize.error.message}`);\r\n }\r\n try {\r\n await this.notify('notifications/initialized', {});\r\n } catch (err) {\r\n console.warn(\r\n '[MCP] notify(\"notifications/initialized\") failed for \"' + this.opts.name + '\": ' + (err instanceof Error ? err.message : String(err)),\r\n );\r\n }\r\n const toolsRes = await this.request('tools/list', {});\r\n if (toolsRes.error) {\r\n this._tools = [];\r\n } else {\r\n const result = toolsRes.result as { tools?: MCPTool[] } | undefined;\r\n this._tools = result?.tools ?? [];\r\n }\r\n // Cache tools so reconnect can re-register without re-discovering\r\n this._toolsCache = this._tools;\r\n this.state = 'connected';\r\n }\r\n\r\n private async connectSSE(): Promise<void> {\r\n if (!this.opts.url) {\r\n this.state = 'failed';\r\n throw new Error('MCP SSE transport requires \"url\"');\r\n }\r\n const httpOpts: HttpTransportOptions = {\r\n name: this.opts.name,\r\n url: this.opts.url,\r\n headers: this.opts.headers,\r\n startupTimeoutMs: this.opts.startupTimeoutMs,\r\n };\r\n this.sseTransport = new SSETransport(httpOpts);\r\n this.sseTransport.onDisconnect(() => {\r\n this.state = 'disconnected';\r\n for (const cb of this.disconnectListeners) {\r\n try { cb(); } catch { /* ignore */ }\r\n }\r\n });\r\n this.sseTransport.onToolsChanged((tools) => {\r\n this._tools = tools;\r\n for (const cb of this.toolsChangedListeners) {\r\n try { cb(this.opts.name, tools); } catch { /* ignore */ }\r\n }\r\n });\r\n try {\r\n await this.sseTransport.connect();\r\n } catch (err) {\r\n this.state = 'failed';\r\n throw err;\r\n }\r\n this._tools = this.sseTransport.listTools();\r\n this._toolsCache = this._tools;\r\n this.state = 'connected';\r\n }\r\n\r\n private async connectStreamableHTTP(): Promise<void> {\r\n if (!this.opts.url) {\r\n this.state = 'failed';\r\n throw new Error('MCP streamable-http transport requires \"url\"');\r\n }\r\n const httpOpts: HttpTransportOptions = {\r\n name: this.opts.name,\r\n url: this.opts.url,\r\n headers: this.opts.headers,\r\n startupTimeoutMs: this.opts.startupTimeoutMs,\r\n };\r\n this.httpTransport = new StreamableHTTPTransport(httpOpts);\r\n this.httpTransport.onDisconnect(() => {\r\n this.state = 'disconnected';\r\n for (const cb of this.disconnectListeners) {\r\n try { cb(); } catch { /* ignore */ }\r\n }\r\n });\r\n this.httpTransport.onToolsChanged((tools) => {\r\n this._tools = tools;\r\n for (const cb of this.toolsChangedListeners) {\r\n try { cb(this.opts.name, tools); } catch { /* ignore */ }\r\n }\r\n });\r\n try {\r\n await this.httpTransport.connect();\r\n } catch (err) {\r\n this.state = 'failed';\r\n throw err;\r\n }\r\n this._tools = this.httpTransport.listTools();\r\n this._toolsCache = this._tools;\r\n this.state = 'connected';\r\n }\r\n\r\n async callTool(name: string, input: unknown): Promise<ToolCallResult> {\r\n if (this.state !== 'connected') {\r\n throw new Error(`MCP client \"${this.opts.name}\" not connected (state=${this.state})`);\r\n }\r\n // Delegate to the active transport\r\n if (this.sseTransport) {\r\n return this.sseTransport.callTool(name, input);\r\n }\r\n if (this.httpTransport) {\r\n return this.httpTransport.callTool(name, input);\r\n }\r\n // stdio\r\n const res = await this.request('tools/call', { name, arguments: input });\r\n if (res.error) {\r\n return { content: res.error.message, isError: true };\r\n }\r\n const result = res.result as { content?: unknown; isError?: boolean } | undefined;\r\n return {\r\n content: result?.content ?? '',\r\n isError: Boolean(result?.isError),\r\n };\r\n }\r\n\r\n async close(): Promise<void> {\r\n if (this.child) {\r\n const child = this.child;\r\n const isAlive = child.exitCode === null && child.signalCode === null;\r\n const exitPromise = isAlive\r\n ? new Promise<void>((resolve) => child.once('exit', () => resolve()))\r\n : Promise.resolve();\r\n try {\r\n // Initial SIGTERM lets the server flush logs / clean up sockets.\r\n child.kill();\r\n } catch {\r\n // ignore\r\n }\r\n // Wait briefly for graceful exit, then escalate to SIGKILL. A stuck\r\n // server that ignores SIGTERM would otherwise stay alive after\r\n // close() returns — orphan child processes accumulate over restarts.\r\n const GRACEFUL_MS = 800;\r\n const FORCE_TIMEOUT_MS = 1200;\r\n const gracefulRace = await Promise.race([\r\n exitPromise.then(() => 'exited' as const),\r\n new Promise<'timeout'>((resolve) => setTimeout(() => resolve('timeout'), GRACEFUL_MS)),\r\n ]);\r\n if (gracefulRace === 'timeout' && isAlive) {\r\n try {\r\n // SIGKILL is ignored by `kill('SIGKILL')` on Windows in older\r\n // Node, but `child.kill('SIGKILL')` maps to TerminateProcess\r\n // under the hood for spawned children since Node 18 — safe to\r\n // call cross-platform.\r\n child.kill('SIGKILL');\r\n } catch {\r\n // ignore\r\n }\r\n await Promise.race([\r\n exitPromise,\r\n new Promise<void>((resolve) => setTimeout(resolve, FORCE_TIMEOUT_MS)),\r\n ]);\r\n }\r\n }\r\n this.sseTransport?.close();\r\n this.httpTransport?.close();\r\n // Reject anything still awaiting the (now-dead) transport. Safe to call\r\n // unconditionally — the stdio exit handler runs failPending too, but\r\n // close() may be invoked on a never-started or HTTP-only client.\r\n this.failPending(`MCP \"${this.opts.name}\" closed`);\r\n this.state = 'disconnected';\r\n }\r\n\r\n private request(method: string, params: unknown): Promise<JsonRpcResponse> {\r\n const id = this.nextId++;\r\n const req: JsonRpcRequest = { jsonrpc: '2.0', id, method, params };\r\n return new Promise((resolve, reject) => {\r\n this.pending.set(id, { resolve, reject });\r\n try {\r\n this.child?.stdin?.write(JSON.stringify(req) + '\\n');\r\n } catch (err) {\r\n this.pending.delete(id);\r\n reject(err);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Reject every in-flight {@link request} call. Used when the underlying\r\n * transport dies — without this, callers awaiting `tools/call` over a\r\n * killed stdio child or a closed transport would hang indefinitely.\r\n */\r\n private failPending(reason: string): void {\r\n if (this.pending.size === 0) return;\r\n const err = new Error(reason);\r\n for (const [, entry] of this.pending) {\r\n try { entry.reject(err); } catch { /* ignore */ }\r\n }\r\n this.pending.clear();\r\n }\r\n\r\n private async notify(method: string, params: unknown): Promise<void> {\r\n const req = { jsonrpc: '2.0', method, params };\r\n const encoded = JSON.stringify(req) + '\\n';\r\n try {\r\n const ok = this.child?.stdin?.write(encoded);\r\n if (!ok) {\r\n // Only the first caller waits for drain; others just warn and return.\r\n // This avoids a race where two concurrent notify() calls each start\r\n // their own drain-wait, then both resolve and the buffer is still full.\r\n if (this._drainPending) {\r\n this._lastNotifySkipped = true;\r\n process.emitWarning(\r\n `[MCP] notify(\"${method}\") skipped: stdin buffer backpressure (already waiting for drain)`,\r\n );\r\n return;\r\n }\r\n this._drainPending = true;\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(() => {\r\n this._drainPending = false;\r\n reject(new Error(`MCP notify(\"${method}\") drain timeout`));\r\n }, 500);\r\n this.child?.stdin?.once('drain', () => {\r\n clearTimeout(timeout);\r\n this._drainPending = false;\r\n resolve();\r\n });\r\n this.child?.stdin?.once('error', (err) => {\r\n clearTimeout(timeout);\r\n this._drainPending = false;\r\n reject(err);\r\n });\r\n });\r\n }\r\n } catch (err) {\r\n throw new Error(`[MCP] notify(\"${method}\") failed: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n\r\n private onData(s: string): void {\r\n this.rxBuffer += s;\r\n let idx = this.rxBuffer.indexOf('\\n');\r\n while (idx !== -1) {\r\n const line = this.rxBuffer.slice(0, idx).trim();\r\n this.rxBuffer = this.rxBuffer.slice(idx + 1);\r\n if (line) this.onLine(line);\r\n idx = this.rxBuffer.indexOf('\\n');\r\n }\r\n }\r\n\r\n private onLine(line: string): void {\r\n let msg: JsonRpcResponse & { method?: string; params?: unknown };\r\n try {\r\n msg = JSON.parse(line) as JsonRpcResponse & { method?: string; params?: unknown };\r\n } catch {\r\n return;\r\n }\r\n if (msg.id !== undefined && this.pending.has(msg.id)) {\r\n const entry = this.pending.get(msg.id);\r\n this.pending.delete(msg.id);\r\n entry?.resolve(msg);\r\n return;\r\n }\r\n // Notifications have a `method` but no `id`. The MCP spec defines\r\n // `notifications/tools/list_changed` for tool-set invalidation —\r\n // refresh the cache asynchronously and fire listeners so the\r\n // registry can re-register the wrapped tools.\r\n if (typeof msg.method === 'string' && msg.method === 'notifications/tools/list_changed') {\r\n void this.handleToolsListChanged();\r\n }\r\n }\r\n\r\n /**\r\n * L2-C: refresh the cached tool list when the server announces a\r\n * `tools/list_changed`. Listeners (the registry) re-wrap and\r\n * re-register. Failures are swallowed — a stale cache is preferable\r\n * to a hard crash on a transient notification glitch.\r\n */\r\n private async handleToolsListChanged(): Promise<void> {\r\n try {\r\n const toolsRes = await this.request('tools/list', {});\r\n const tools = ((toolsRes.result as { tools?: MCPTool[] } | undefined)?.tools ?? []).filter(\r\n (t): t is MCPTool => !!t && typeof t.name === 'string',\r\n );\r\n this._tools = tools;\r\n this._toolsCache = tools;\r\n for (const listener of this.toolsChangedListeners) {\r\n try {\r\n listener(this.opts.name, [...tools]);\r\n } catch {\r\n // listeners must be best-effort\r\n }\r\n }\r\n } catch {\r\n // ignore — keep the existing cache\r\n }\r\n }\r\n\r\n addToolsChangedListener(listener: ToolsChangedListener): void {\r\n this.toolsChangedListeners.add(listener);\r\n }\r\n\r\n removeToolsChangedListener(listener: ToolsChangedListener): void {\r\n this.toolsChangedListeners.delete(listener);\r\n }\r\n}","import type { Tool, Permission } from '@wrongstack/core';\r\nimport type { MCPClient, MCPTool } from './client.js';\r\n\r\n/**\r\n * Keywords that indicate a mutating operation.\r\n * Applied to both the tool name and its inputSchema property names.\r\n */\r\nconst MUTATING_RE = /create|update|delete|write|send|set|put|post|patch|remove|rename|move/i;\r\n\r\nfunction isMutatingTool(mcpTool: MCPTool): boolean {\r\n if (MUTATING_RE.test(mcpTool.name)) return true;\r\n // Check property names in the input schema for mutating intent.\r\n // e.g. { properties: { createTable: {...}, dropIndex: {...} } }\r\n const schema = mcpTool.inputSchema;\r\n if (schema && typeof schema === 'object') {\r\n const props = (schema as { properties?: Record<string, unknown> }).properties;\r\n if (props) {\r\n for (const key of Object.keys(props)) {\r\n if (MUTATING_RE.test(key)) return true;\r\n }\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport function wrapMCPTool(\r\n serverName: string,\r\n mcpTool: MCPTool,\r\n client: MCPClient,\r\n permission: Permission = 'confirm',\r\n): Tool {\r\n const qualifiedName = `mcp__${serverName}__${mcpTool.name}`;\r\n return {\r\n name: qualifiedName,\r\n description: mcpTool.description ?? `${qualifiedName} (MCP tool)`,\r\n usageHint: `Tool provided by MCP server \"${serverName}\". ${mcpTool.description ?? ''}`,\r\n permission,\r\n mutating: isMutatingTool(mcpTool),\r\n inputSchema: mcpTool.inputSchema ?? { type: 'object', properties: {} },\r\n async execute(input, ctx, opts) {\r\n const res = await client.callTool(mcpTool.name, input);\r\n if (res.isError) {\r\n throw new Error(stringify(res.content));\r\n }\r\n return stringify(res.content);\r\n },\r\n };\r\n}\r\n\r\nfunction stringify(c: unknown): string {\r\n if (typeof c === 'string') return c;\r\n if (Array.isArray(c)) {\r\n return c\r\n .map((item) => {\r\n if (item && typeof item === 'object') {\r\n const t = (item as { type?: string; text?: string }).type;\r\n if (t === 'text') return (item as { text?: string }).text ?? '';\r\n return JSON.stringify(item);\r\n }\r\n return String(item);\r\n })\r\n .join('\\n');\r\n }\r\n if (c && typeof c === 'object') {\r\n if ('text' in (c as Record<string, unknown>)) {\r\n return String((c as Record<string, unknown>).text);\r\n }\r\n return JSON.stringify(c);\r\n }\r\n return String(c ?? '');\r\n}\r\n","import type { EventBus, MCPServerConfig, ToolRegistry, Logger } from '@wrongstack/core';\r\nimport { MCPClient, type ConnectionState } from './client.js';\r\nimport { wrapMCPTool } from './wrap-tool.js';\r\n\r\ninterface ServerSlot {\r\n cfg: MCPServerConfig;\r\n client?: MCPClient;\r\n state: ConnectionState;\r\n toolNames: string[];\r\n attempts: number;\r\n /** Set when a reconnect cycle is already running for this slot. */\r\n reconnectPending: boolean;\r\n /**\r\n * L2-B: number of full reconnect *cycles* (where one cycle = one\r\n * `attemptConnect` invocation, which itself can try multiple times\r\n * before giving up). After `MAX_RECONNECT_CYCLES`, the slot stays\r\n * `failed` until a manual `restart()` resets it.\r\n */\r\n reconnectCycles: number;\r\n /**\r\n * Slot-scoped, bound disconnect callback. Stored so the matching\r\n * `removeDisconnectListener` call can hand back the *same* reference —\r\n * a fresh arrow `() => onTransportDisconnect(slot.cfg.name)` would\r\n * not match the one we added and the set-based listener registry\r\n * would silently keep the old handler, causing duplicate reconnect\r\n * cycles after a few transport flaps.\r\n */\r\n onDisconnect?: () => void;\r\n}\r\n\r\nexport interface MCPRegistryOptions {\r\n toolRegistry: ToolRegistry;\r\n events: EventBus;\r\n log: Logger;\r\n}\r\n\r\nexport class MCPRegistry {\r\n private readonly servers = new Map<string, ServerSlot>();\r\n private readonly toolRegistry: ToolRegistry;\r\n private readonly events: EventBus;\r\n private readonly log: Logger;\r\n\r\n constructor(opts: MCPRegistryOptions) {\r\n this.toolRegistry = opts.toolRegistry;\r\n this.events = opts.events;\r\n this.log = opts.log;\r\n }\r\n\r\n async start(cfg: MCPServerConfig): Promise<void> {\r\n if (cfg.enabled === false) return;\r\n const slot: ServerSlot = {\r\n cfg,\r\n state: 'idle',\r\n toolNames: [],\r\n attempts: 0,\r\n reconnectPending: false,\r\n reconnectCycles: 0,\r\n };\r\n this.servers.set(cfg.name, slot);\r\n await this.attemptConnect(slot);\r\n }\r\n\r\n async stop(name: string): Promise<void> {\r\n const slot = this.servers.get(name);\r\n if (!slot) return;\r\n slot.reconnectPending = false;\r\n if (slot.client) {\r\n slot.client.removeExitListener(this.onChildExit);\r\n if (slot.onDisconnect) slot.client.removeDisconnectListener(slot.onDisconnect);\r\n slot.client.removeToolsChangedListener(this.onToolsChanged);\r\n await slot.client.close();\r\n slot.client = undefined;\r\n }\r\n slot.onDisconnect = undefined;\r\n for (const t of slot.toolNames) this.toolRegistry.unregister(t);\r\n slot.toolNames = [];\r\n slot.state = 'disconnected';\r\n this.events.emit('mcp.server.disconnected', { name, reason: 'stop' });\r\n }\r\n\r\n async restart(name: string): Promise<void> {\r\n const slot = this.servers.get(name);\r\n if (!slot) throw new Error(`MCP server \"${name}\" not registered`);\r\n await this.stop(name);\r\n slot.attempts = 0;\r\n slot.reconnectCycles = 0; // user intent: start fresh\r\n await this.attemptConnect(slot);\r\n }\r\n\r\n list(): { name: string; state: ConnectionState; toolCount: number }[] {\r\n return Array.from(this.servers.values()).map((s) => ({\r\n name: s.cfg.name,\r\n state: s.state,\r\n toolCount: s.toolNames.length,\r\n }));\r\n }\r\n\r\n async stopAll(): Promise<void> {\r\n for (const name of Array.from(this.servers.keys())) {\r\n await this.stop(name);\r\n }\r\n }\r\n\r\n /**\r\n * Health check — returns 'ok' for connected servers, the current state otherwise.\r\n * For HTTP-based transports this could also ping the server.\r\n */\r\n health(): { name: string; alive: boolean; latencyMs?: number }[] {\r\n return Array.from(this.servers.values()).map((s) => ({\r\n name: s.cfg.name,\r\n alive: s.state === 'connected',\r\n }));\r\n }\r\n\r\n /**\r\n * L2-C: handle `notifications/tools/list_changed` from the server.\r\n * Unregister the previous wrapper set, then re-register the fresh\r\n * tool list. The client has already refreshed its cache before\r\n * dispatching — we just need to re-wrap and re-register.\r\n */\r\n private readonly onToolsChanged = (name: string, _tools: { name: string }[]): void => {\r\n const slot = this.servers.get(name);\r\n if (!slot || !slot.client) return;\r\n for (const t of slot.toolNames) {\r\n try { this.toolRegistry.unregister(t); } catch { /* ignore */ }\r\n }\r\n slot.toolNames = [];\r\n const allowed = slot.cfg.allowedTools;\r\n const wrapped = slot.client\r\n .listTools()\r\n .filter((t) => !allowed || allowed.includes(t.name))\r\n .map((t) => wrapMCPTool(slot.cfg.name, t, slot.client!, slot.cfg.permission ?? 'confirm'));\r\n for (const tool of wrapped) {\r\n try {\r\n this.toolRegistry.register(tool, `mcp:${slot.cfg.name}`);\r\n slot.toolNames.push(tool.name);\r\n } catch (err) {\r\n this.log.warn(`MCP tool \"${tool.name}\" not re-registered after list_changed`, err);\r\n }\r\n }\r\n this.events.emit('mcp.server.connected', {\r\n name: slot.cfg.name,\r\n toolCount: slot.toolNames.length,\r\n });\r\n this.log.info(\r\n `MCP server \"${slot.cfg.name}\" tools refreshed (${slot.toolNames.length} active)`,\r\n );\r\n };\r\n\r\n private readonly onChildExit = (name: string, code: number | null, _signal: string | null): void => {\r\n const slot = this.servers.get(name);\r\n if (!slot) return;\r\n for (const t of slot.toolNames) {\r\n try { this.toolRegistry.unregister(t); } catch { /* ignore */ }\r\n }\r\n slot.toolNames = [];\r\n slot.state = 'disconnected';\r\n this.events.emit('mcp.server.disconnected', { name, reason: `exit:${code ?? 'unknown'}` });\r\n this.scheduleReconnect(slot);\r\n };\r\n\r\n /** Handles SSE / streamable-http disconnect — same recovery as stdio child exit. */\r\n private readonly onTransportDisconnect = (name: string): void => {\r\n const slot = this.servers.get(name);\r\n if (!slot) return;\r\n for (const t of slot.toolNames) {\r\n try { this.toolRegistry.unregister(t); } catch { /* ignore */ }\r\n }\r\n slot.toolNames = [];\r\n slot.state = 'disconnected';\r\n this.events.emit('mcp.server.disconnected', { name, reason: 'http-disconnect' });\r\n this.scheduleReconnect(slot);\r\n };\r\n\r\n /**\r\n * L2-B: maximum number of reconnect cycles before staying `failed`.\r\n * One cycle = one full `attemptConnect` (which itself may try up to 3\r\n * times). Caps total reconnect storm at ~5 cycles, then the slot\r\n * needs an explicit `restart()` to re-engage.\r\n */\r\n private static readonly MAX_RECONNECT_CYCLES = 5;\r\n /** Base delay between cycles, in ms. Real delay adds jitter. */\r\n private static readonly BASE_RECONNECT_DELAY_MS = 1000;\r\n /** Hard ceiling on the inter-cycle delay so the user doesn't wait minutes. */\r\n private static readonly MAX_RECONNECT_DELAY_MS = 30_000;\r\n\r\n private scheduleReconnect(slot: ServerSlot): void {\r\n if (slot.reconnectPending) return;\r\n if (slot.reconnectCycles >= MCPRegistry.MAX_RECONNECT_CYCLES) {\r\n slot.state = 'failed';\r\n this.log.error(\r\n `MCP server \"${slot.cfg.name}\" giving up after ${slot.reconnectCycles} reconnect cycles. Use \\`/mcp restart ${slot.cfg.name}\\` to retry.`,\r\n );\r\n this.events.emit('mcp.server.disconnected', {\r\n name: slot.cfg.name,\r\n reason: `reconnect-exhausted:${slot.reconnectCycles}`,\r\n });\r\n return;\r\n }\r\n slot.reconnectPending = true;\r\n // Exponential backoff with light jitter: 1s, 2s, 4s, 8s, 16s, capped\r\n // at 30s. The ±20% jitter avoids reconnect stampedes when many\r\n // servers crash together.\r\n const base = Math.min(\r\n MCPRegistry.BASE_RECONNECT_DELAY_MS * 2 ** slot.reconnectCycles,\r\n MCPRegistry.MAX_RECONNECT_DELAY_MS,\r\n );\r\n const jitter = base * 0.2 * (Math.random() * 2 - 1);\r\n const delay = Math.max(100, Math.round(base + jitter));\r\n setTimeout(() => this.attemptReconnect(slot), delay);\r\n }\r\n\r\n private async attemptReconnect(slot: ServerSlot): Promise<void> {\r\n slot.reconnectPending = false;\r\n slot.reconnectCycles++;\r\n await this.attemptConnect(slot);\r\n }\r\n\r\n private async attemptConnect(slot: ServerSlot): Promise<void> {\r\n const MAX_ATTEMPTS = 3;\r\n let attempt = 0;\r\n while (attempt < MAX_ATTEMPTS) {\r\n attempt++;\r\n slot.state = attempt === 1 ? 'connecting' : 'reconnecting';\r\n slot.attempts = attempt;\r\n let client: MCPClient | undefined;\r\n let boundDisconnect: (() => void) | undefined;\r\n try {\r\n client = new MCPClient({\r\n name: slot.cfg.name,\r\n transport: slot.cfg.transport,\r\n command: slot.cfg.command,\r\n args: slot.cfg.args,\r\n env: slot.cfg.env,\r\n url: slot.cfg.url,\r\n headers: slot.cfg.headers,\r\n startupTimeoutMs: slot.cfg.startupTimeoutMs,\r\n });\r\n if (slot.cfg.transport === 'stdio') {\r\n client.addExitListener(this.onChildExit);\r\n } else {\r\n // SSE / streamable-http — wire transport disconnect to registry reconnect.\r\n // Capture the bound function so we can hand the same reference to\r\n // removeDisconnectListener on cleanup paths.\r\n boundDisconnect = () => this.onTransportDisconnect(slot.cfg.name);\r\n client.addDisconnectListener(boundDisconnect);\r\n }\r\n // L2-C: react to server-side tool changes by re-registering wrappers.\r\n client.addToolsChangedListener(this.onToolsChanged);\r\n await client.connect();\r\n // Close any prior client before swapping refs so the old transport\r\n // can release its abort controller, child process, and listeners\r\n // instead of being held until GC.\r\n if (slot.client && slot.client !== client) {\r\n const prior = slot.client;\r\n const priorDisconnect = slot.onDisconnect;\r\n slot.client.removeExitListener(this.onChildExit);\r\n if (priorDisconnect) prior.removeDisconnectListener(priorDisconnect);\r\n prior.removeToolsChangedListener(this.onToolsChanged);\r\n prior.close().catch(() => { /* best-effort */ });\r\n }\r\n slot.client = client;\r\n slot.onDisconnect = boundDisconnect;\r\n const isReconnect = attempt > 1;\r\n slot.state = 'connected';\r\n // L2-B: a healthy connect resets the cycle counter so future\r\n // crashes get the full reconnect budget again.\r\n slot.reconnectCycles = 0;\r\n const allowed = slot.cfg.allowedTools;\r\n // Prefer cached tools to avoid a round-trip to the server on reconnect.\r\n // The cache is populated by client.listTools() on first connect.\r\n const mc = client as MCPClient;\r\n const candidateTools = mc.listTools();\r\n const toWrap = candidateTools.length > 0\r\n ? candidateTools\r\n : mc.listTools(); // fallback — in practice both return the same list\r\n const wrapped = toWrap\r\n .filter((t) => !allowed || allowed.includes(t.name))\r\n .map((t) => wrapMCPTool(slot.cfg.name, t, mc, slot.cfg.permission ?? 'confirm'));\r\n for (const tool of wrapped) {\r\n try {\r\n this.toolRegistry.register(tool, `mcp:${slot.cfg.name}`);\r\n slot.toolNames.push(tool.name);\r\n } catch (err) {\r\n this.log.warn(`MCP tool \"${tool.name}\" not registered`, err);\r\n }\r\n }\r\n this.events.emit(isReconnect ? 'mcp.server.reconnected' : 'mcp.server.connected', {\r\n name: slot.cfg.name,\r\n toolCount: slot.toolNames.length,\r\n });\r\n return; // success\r\n } catch (err) {\r\n this.log.warn(`MCP server \"${slot.cfg.name}\" connect attempt ${attempt} failed`, err);\r\n if (client) {\r\n client.removeExitListener(this.onChildExit);\r\n if (boundDisconnect) client.removeDisconnectListener(boundDisconnect);\r\n client.removeToolsChangedListener(this.onToolsChanged);\r\n await client.close().catch(() => {/* ignore */});\r\n }\r\n if (attempt >= MAX_ATTEMPTS) {\r\n this.log.error(`MCP server \"${slot.cfg.name}\" connect exhausted after ${MAX_ATTEMPTS} attempts`, err);\r\n slot.state = 'failed';\r\n slot.client = undefined;\r\n this.events.emit('mcp.server.disconnected', {\r\n name: slot.cfg.name,\r\n reason: err instanceof Error ? err.message : 'unknown',\r\n });\r\n return;\r\n }\r\n const delay = 500 * 2 ** attempt;\r\n await new Promise((r) => setTimeout(r, delay));\r\n }\r\n }\r\n }\r\n}"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "WrongStack Model Context Protocol client and registry: stdio, SSE, and streamable HTTP transports.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/WrongStack/WrongStack.git",
|
|
9
|
+
"directory": "packages/mcp"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/WrongStack/WrongStack#readme",
|
|
12
|
+
"bugs": "https://github.com/WrongStack/WrongStack/issues",
|
|
13
|
+
"author": "ECOSTACK TECHNOLOGY OÜ",
|
|
4
14
|
"type": "module",
|
|
5
15
|
"main": "./dist/index.js",
|
|
6
16
|
"types": "./dist/index.d.ts",
|
|
@@ -15,14 +25,17 @@
|
|
|
15
25
|
"dist"
|
|
16
26
|
],
|
|
17
27
|
"dependencies": {
|
|
18
|
-
"@wrongstack/core": "0.1.
|
|
28
|
+
"@wrongstack/core": "0.1.7"
|
|
19
29
|
},
|
|
20
30
|
"devDependencies": {
|
|
21
31
|
"@types/node": "^22.19.19",
|
|
22
|
-
"tsup": "^8.
|
|
23
|
-
"typescript": "^5.
|
|
32
|
+
"tsup": "^8.5.1",
|
|
33
|
+
"typescript": "^5.9.3",
|
|
24
34
|
"vitest": "^4.1.6"
|
|
25
35
|
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
26
39
|
"scripts": {
|
|
27
40
|
"build": "tsup",
|
|
28
41
|
"typecheck": "tsc --noEmit -p tsconfig.test.json",
|