@wrongstack/mcp 0.3.2 → 0.3.4

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/README.md CHANGED
@@ -72,7 +72,8 @@ wstack mcp list
72
72
  "enabled": true,
73
73
  "permission": "confirm",
74
74
  "allowedTools": ["read", "search"],
75
- "startupTimeoutMs": 10000
75
+ "startupTimeoutMs": 10000,
76
+ "requestTimeoutMs": 60000
76
77
  }
77
78
  }
78
79
  }
@@ -99,6 +100,7 @@ interface MCPServerConfig {
99
100
  allowedTools?: string[]; // whitelist — undefined = all tools
100
101
  permission?: Permission; // 'auto' | 'confirm' | 'deny' (default: 'confirm')
101
102
  startupTimeoutMs?: number; // default: 10000
103
+ requestTimeoutMs?: number; // default: 60000
102
104
  description?: string; // shown in `wstack mcp list`
103
105
  }
104
106
  ```
@@ -140,6 +142,7 @@ Check that:
140
142
  - The `command` is in your `PATH` (or use an absolute path)
141
143
  - `npx -y @modelcontextprotocol/server-filesystem .` works standalone
142
144
  - The `startupTimeoutMs` is sufficient for slow-starting servers
145
+ - The `requestTimeoutMs` is sufficient for long-running tool calls
143
146
 
144
147
  ### Tools not appearing
145
148
 
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ interface MCPClientOptions {
10
10
  url?: string;
11
11
  headers?: Record<string, string>;
12
12
  startupTimeoutMs?: number;
13
+ requestTimeoutMs?: number;
13
14
  }
14
15
  type ConnectionState = 'idle' | 'connecting' | 'connected' | 'disconnected' | 'reconnecting' | 'failed';
15
16
  interface MCPTool {
@@ -165,9 +166,11 @@ interface HttpTransportOptions {
165
166
  url: string;
166
167
  headers?: Record<string, string>;
167
168
  startupTimeoutMs?: number;
169
+ requestTimeoutMs?: number;
168
170
  }
169
171
  declare class SSEReader {
170
172
  private buffer;
173
+ private dataLines;
171
174
  private listeners;
172
175
  onMessage(cb: (data: {
173
176
  jsonrpc?: string;
@@ -176,6 +179,8 @@ declare class SSEReader {
176
179
  id?: number;
177
180
  }) => void): () => void;
178
181
  feed(chunk: string): void;
182
+ private processLine;
183
+ private flush;
179
184
  private dispatch;
180
185
  reset(): void;
181
186
  }
@@ -190,6 +195,7 @@ declare class SSETransport {
190
195
  private url;
191
196
  private headers;
192
197
  private timeout;
198
+ private requestTimeout;
193
199
  private nextId;
194
200
  private readonly _reservedPending;
195
201
  private tools;
@@ -223,6 +229,7 @@ declare class StreamableHTTPTransport {
223
229
  private url;
224
230
  private headers;
225
231
  private timeout;
232
+ private requestTimeout;
226
233
  private nextId;
227
234
  private tools;
228
235
  private abortController?;
package/dist/index.js CHANGED
@@ -1,12 +1,56 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { buildChildEnv } from '@wrongstack/core';
3
+ import * as net from 'net';
3
4
 
4
5
  // src/client.ts
5
6
 
6
- // src/transport.ts
7
+ // src/tool-schema.ts
8
+ function normalizeMCPTools(value) {
9
+ if (!Array.isArray(value)) return [];
10
+ const tools = [];
11
+ for (const raw of value) {
12
+ if (!raw || typeof raw !== "object") continue;
13
+ const t = raw;
14
+ if (typeof t.name !== "string" || t.name.trim().length === 0) continue;
15
+ const inputSchema = t.inputSchema && typeof t.inputSchema === "object" && !Array.isArray(t.inputSchema) ? t.inputSchema : { type: "object", properties: {} };
16
+ tools.push({
17
+ name: t.name,
18
+ ...typeof t.description === "string" ? { description: t.description } : {},
19
+ inputSchema
20
+ });
21
+ }
22
+ return tools;
23
+ }
24
+ function validateTransportUrl(rawUrl) {
25
+ let url;
26
+ try {
27
+ url = new URL(rawUrl);
28
+ } catch {
29
+ throw new Error(`MCP transport: invalid URL "${rawUrl}"`);
30
+ }
31
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
32
+ throw new Error(
33
+ `MCP transport: unsupported protocol "${url.protocol}" \u2014 only http/https allowed`
34
+ );
35
+ }
36
+ const hostname = url.hostname;
37
+ if (hostname === "localhost" || hostname === "0.0.0.0" || hostname === "::" || hostname === "[::1]") {
38
+ return;
39
+ }
40
+ const ipVersion = net.isIP(hostname);
41
+ if (ipVersion === 4) {
42
+ const parts = hostname.split(".").map(Number);
43
+ if (parts[0] === 169 && parts[1] === 254) {
44
+ throw new Error(
45
+ `MCP transport: blocked link-local/IMDS address "${hostname}" \u2014 likely not a valid MCP server`
46
+ );
47
+ }
48
+ }
49
+ }
7
50
  var SSE_READER_MAX_BUFFER = 256 * 1024;
8
51
  var SSEReader = class {
9
52
  buffer = "";
53
+ dataLines = [];
10
54
  listeners = [];
11
55
  onMessage(cb) {
12
56
  this.listeners.push(cb);
@@ -24,19 +68,37 @@ var SSEReader = class {
24
68
  }
25
69
  let idx = this.buffer.indexOf("\n");
26
70
  while (idx !== -1) {
27
- const line = this.buffer.slice(0, idx);
71
+ const line = this.buffer.slice(0, idx).replace(/\r$/, "");
28
72
  this.buffer = this.buffer.slice(idx + 1);
29
73
  idx = this.buffer.indexOf("\n");
30
- if (line.startsWith("event:")) ; else if (line.startsWith("data:")) {
31
- const data = line.slice(5).trim();
32
- if (data) {
33
- try {
34
- const parsed = JSON.parse(data);
35
- this.dispatch(parsed);
36
- } catch {
37
- }
38
- }
39
- }
74
+ this.processLine(line);
75
+ }
76
+ }
77
+ processLine(line) {
78
+ if (line === "") {
79
+ this.flush();
80
+ return;
81
+ }
82
+ if (line.startsWith(":")) return;
83
+ const colonIdx = line.indexOf(":");
84
+ const field = colonIdx === -1 ? line : line.slice(0, colonIdx);
85
+ let value = colonIdx === -1 ? "" : line.slice(colonIdx + 1);
86
+ if (value.startsWith(" ")) value = value.slice(1);
87
+ if (field === "event") ; else if (field === "data") {
88
+ this.dataLines.push(value);
89
+ }
90
+ }
91
+ flush() {
92
+ if (this.dataLines.length === 0) {
93
+ return;
94
+ }
95
+ const data = this.dataLines.join("\n").trim();
96
+ this.dataLines = [];
97
+ if (!data) return;
98
+ try {
99
+ const parsed = JSON.parse(data);
100
+ this.dispatch(parsed);
101
+ } catch {
40
102
  }
41
103
  }
42
104
  dispatch(msg) {
@@ -49,17 +111,39 @@ var SSEReader = class {
49
111
  }
50
112
  reset() {
51
113
  this.buffer = "";
114
+ this.dataLines = [];
52
115
  this.listeners = [];
53
116
  }
54
117
  };
55
118
  function isJsonRpcResult(v) {
56
- return typeof v === "object" && v !== null && "jsonrpc" in v;
119
+ if (typeof v !== "object" || v === null) return false;
120
+ const r = v;
121
+ if (r.jsonrpc !== "2.0") return false;
122
+ if (r.error !== void 0) {
123
+ return typeof r.error === "object" && r.error !== null && typeof r.error.code === "number" && typeof r.error.message === "string";
124
+ }
125
+ return "result" in r || r.id === void 0;
126
+ }
127
+ function assertMatchingJsonRpcResult(data, expectedId, method) {
128
+ if (!isJsonRpcResult(data)) {
129
+ throw new Error("Invalid JSON-RPC response: not a JSON-RPC 2.0 envelope");
130
+ }
131
+ if (data.id !== void 0 && data.id !== expectedId) {
132
+ throw new Error(
133
+ `Invalid JSON-RPC response: id mismatch for ${method} (expected ${expectedId}, got ${data.id})`
134
+ );
135
+ }
136
+ if (data.id === void 0 && !method.startsWith("notifications/")) {
137
+ throw new Error(`Invalid JSON-RPC response: missing id for ${method}`);
138
+ }
139
+ return data;
57
140
  }
58
141
  var SSETransport = class {
59
142
  state = "idle";
60
143
  url;
61
144
  headers;
62
145
  timeout;
146
+ requestTimeout;
63
147
  nextId = 1;
64
148
  // NOTE: id-correlation via this map was scaffolded but never populated by
65
149
  // `httpPost` — JSON-RPC responses come back synchronously over HTTP, not
@@ -75,9 +159,11 @@ var SSETransport = class {
75
159
  readLoopAbort;
76
160
  toolsChangedListeners = /* @__PURE__ */ new Set();
77
161
  constructor(opts) {
162
+ validateTransportUrl(opts.url);
78
163
  this.url = opts.url;
79
164
  this.headers = { ...opts.headers };
80
165
  this.timeout = opts.startupTimeoutMs ?? 1e4;
166
+ this.requestTimeout = opts.requestTimeoutMs ?? 6e4;
81
167
  }
82
168
  getState() {
83
169
  return this.state;
@@ -103,7 +189,7 @@ var SSETransport = class {
103
189
  try {
104
190
  const res = await this.httpPost("tools/list", {});
105
191
  if (!res.error) {
106
- this.tools = res.result?.tools ?? [];
192
+ this.tools = normalizeMCPTools(res.result?.tools);
107
193
  for (const cb of this.toolsChangedListeners) {
108
194
  try {
109
195
  cb([...this.tools]);
@@ -164,7 +250,7 @@ var SSETransport = class {
164
250
  this.tools = [];
165
251
  } else {
166
252
  const result = toolsRes.result;
167
- this.tools = result?.tools ?? [];
253
+ this.tools = normalizeMCPTools(result?.tools);
168
254
  }
169
255
  this.state = "connected";
170
256
  clearTimeout(startupTimer);
@@ -207,34 +293,36 @@ var SSETransport = class {
207
293
  async httpPost(method, params) {
208
294
  const id = this.nextId++;
209
295
  const body = JSON.stringify({ jsonrpc: "2.0", id, method, params });
210
- const res = await fetch(this.url, {
211
- method: "POST",
212
- headers: {
213
- "Content-Type": "application/json",
214
- ...this.headers
215
- },
216
- body,
217
- signal: this.abortController?.signal
218
- });
219
- if (!res.ok) {
220
- const body2 = await res.text();
221
- const cap = 1024;
222
- const snippet = body2.length > cap ? `${body2.slice(0, cap)}\u2026 [${body2.length} bytes total]` : body2;
223
- throw new Error(`HTTP ${res.status}: ${snippet}`);
224
- }
225
- let data;
296
+ const timeoutSignal = createTimeoutSignal(this.abortController?.signal, this.requestTimeout);
226
297
  try {
227
- data = await res.json();
228
- } catch (err) {
229
- throw new Error(
230
- `Invalid JSON-RPC response: ${err instanceof Error ? err.message : "parse failed"}`,
231
- { cause: err }
232
- );
233
- }
234
- if (!isJsonRpcResult(data)) {
235
- throw new Error("Invalid JSON-RPC response: not a JSON-RPC envelope");
298
+ const res = await fetch(this.url, {
299
+ method: "POST",
300
+ headers: {
301
+ "Content-Type": "application/json",
302
+ ...this.headers
303
+ },
304
+ body,
305
+ signal: timeoutSignal.signal
306
+ });
307
+ if (!res.ok) {
308
+ const body2 = await res.text();
309
+ const cap = 1024;
310
+ const snippet = body2.length > cap ? `${body2.slice(0, cap)}\u2026 [${body2.length} bytes total]` : body2;
311
+ throw new Error(`HTTP ${res.status}: ${snippet}`);
312
+ }
313
+ let data;
314
+ try {
315
+ data = await res.json();
316
+ } catch (err) {
317
+ throw new Error(
318
+ `Invalid JSON-RPC response: ${err instanceof Error ? err.message : "parse failed"}`,
319
+ { cause: err }
320
+ );
321
+ }
322
+ return assertMatchingJsonRpcResult(data, id, method);
323
+ } finally {
324
+ timeoutSignal.dispose();
236
325
  }
237
- return data;
238
326
  }
239
327
  async callTool(name, input) {
240
328
  if (this.state !== "connected") {
@@ -272,6 +360,7 @@ var StreamableHTTPTransport = class {
272
360
  url;
273
361
  headers;
274
362
  timeout;
363
+ requestTimeout;
275
364
  nextId = 1;
276
365
  tools = [];
277
366
  abortController;
@@ -279,9 +368,11 @@ var StreamableHTTPTransport = class {
279
368
  disconnectHandlers = [];
280
369
  toolsChangedListeners = /* @__PURE__ */ new Set();
281
370
  constructor(opts) {
371
+ validateTransportUrl(opts.url);
282
372
  this.url = opts.url;
283
373
  this.headers = { ...opts.headers };
284
374
  this.timeout = opts.startupTimeoutMs ?? 1e4;
375
+ this.requestTimeout = opts.requestTimeoutMs ?? 6e4;
285
376
  }
286
377
  getState() {
287
378
  return this.state;
@@ -306,7 +397,7 @@ var StreamableHTTPTransport = class {
306
397
  try {
307
398
  const res = await this.postRaw("tools/list", {});
308
399
  if (!res.error) {
309
- this.tools = res.result?.tools ?? [];
400
+ this.tools = normalizeMCPTools(res.result?.tools);
310
401
  for (const cb of this.toolsChangedListeners) {
311
402
  try {
312
403
  cb([...this.tools]);
@@ -367,6 +458,7 @@ var StreamableHTTPTransport = class {
367
458
  if (!data) {
368
459
  throw new Error("Could not parse initialize response");
369
460
  }
461
+ data = assertMatchingJsonRpcResult(data, this.nextId - 1, "initialize");
370
462
  if (data.error) {
371
463
  throw new Error(`initialize failed: ${data.error.message}`);
372
464
  }
@@ -377,7 +469,7 @@ var StreamableHTTPTransport = class {
377
469
  this.tools = [];
378
470
  } else {
379
471
  const result = toolsRes.result;
380
- this.tools = result?.tools ?? [];
472
+ this.tools = normalizeMCPTools(result?.tools);
381
473
  }
382
474
  this.state = "connected";
383
475
  clearTimeout(startupTimer);
@@ -392,30 +484,38 @@ var StreamableHTTPTransport = class {
392
484
  const id = this.nextId++;
393
485
  const body = JSON.stringify({ jsonrpc: "2.0", id, method, params });
394
486
  const url = this.sessionId ? `${this.url}${this.url.includes("?") ? "&" : "?"}session=${this.sessionId}` : this.url;
395
- const res = await fetch(url, {
396
- method: "POST",
397
- headers: {
398
- "Content-Type": "application/json",
399
- Accept: "application/json, text/event-stream",
400
- ...this.sessionId ? { "x-mcp-session": this.sessionId } : {},
401
- ...this.headers
402
- },
403
- body,
404
- signal: this.abortController?.signal
405
- });
406
- if (!res.ok) {
407
- throw new Error(`HTTP ${res.status}: ${res.statusText}`);
408
- }
409
- const text = await res.text();
410
- const lines = text.split("\n").filter((l) => l.trim());
411
- for (const line of lines) {
412
- try {
413
- const parsed = JSON.parse(line);
414
- if (isJsonRpcResult(parsed)) return parsed;
415
- } catch {
487
+ const timeoutSignal = createTimeoutSignal(this.abortController?.signal, this.requestTimeout);
488
+ try {
489
+ const res = await fetch(url, {
490
+ method: "POST",
491
+ headers: {
492
+ "Content-Type": "application/json",
493
+ Accept: "application/json, text/event-stream",
494
+ ...this.sessionId ? { "x-mcp-session": this.sessionId } : {},
495
+ ...this.headers
496
+ },
497
+ body,
498
+ signal: timeoutSignal.signal
499
+ });
500
+ if (!res.ok) {
501
+ throw new Error(`HTTP ${res.status}: ${res.statusText}`);
502
+ }
503
+ const text = await res.text();
504
+ const lines = text.split("\n").filter((l) => l.trim());
505
+ for (const line of lines) {
506
+ let parsed;
507
+ try {
508
+ parsed = JSON.parse(line);
509
+ } catch {
510
+ }
511
+ if (isJsonRpcResult(parsed)) {
512
+ return assertMatchingJsonRpcResult(parsed, id, method);
513
+ }
416
514
  }
515
+ throw new Error("Could not parse response as JSON-RPC");
516
+ } finally {
517
+ timeoutSignal.dispose();
417
518
  }
418
- throw new Error("Could not parse response as JSON-RPC");
419
519
  }
420
520
  async callTool(name, input) {
421
521
  if (this.state !== "connected") {
@@ -438,6 +538,26 @@ var StreamableHTTPTransport = class {
438
538
  this.disconnectHandlers = [];
439
539
  }
440
540
  };
541
+ function createTimeoutSignal(parent, timeoutMs) {
542
+ const ctrl = new AbortController();
543
+ const onAbort = () => ctrl.abort(parent?.reason);
544
+ if (parent?.aborted) {
545
+ ctrl.abort(parent.reason);
546
+ } else {
547
+ parent?.addEventListener("abort", onAbort, { once: true });
548
+ }
549
+ const timer = setTimeout(
550
+ () => ctrl.abort(new Error(`MCP HTTP request timed out after ${timeoutMs}ms`)),
551
+ timeoutMs
552
+ );
553
+ return {
554
+ signal: ctrl.signal,
555
+ dispose: () => {
556
+ clearTimeout(timer);
557
+ parent?.removeEventListener("abort", onAbort);
558
+ }
559
+ };
560
+ }
441
561
 
442
562
  // src/client.ts
443
563
  var MCPClient = class {
@@ -541,17 +661,15 @@ var MCPClient = class {
541
661
  child.on("error", () => {
542
662
  this.state = "failed";
543
663
  });
544
- const timeout = this.opts.startupTimeoutMs ?? 1e4;
545
- const initialize = await Promise.race([
546
- this.request("initialize", {
664
+ const initialize = await this.request(
665
+ "initialize",
666
+ {
547
667
  protocolVersion: "2024-11-05",
548
668
  capabilities: { tools: {} },
549
669
  clientInfo: { name: "wrongstack", version: "0.1.10" }
550
- }),
551
- new Promise(
552
- (_, rej) => setTimeout(() => rej(new Error("MCP initialize timeout")), timeout)
553
- )
554
- ]);
670
+ },
671
+ this.opts.startupTimeoutMs ?? 1e4
672
+ );
555
673
  if (initialize.error) {
556
674
  this.state = "failed";
557
675
  throw new Error(`MCP initialize failed: ${initialize.error.message}`);
@@ -568,7 +686,7 @@ var MCPClient = class {
568
686
  this._tools = [];
569
687
  } else {
570
688
  const result = toolsRes.result;
571
- this._tools = result?.tools ?? [];
689
+ this._tools = normalizeMCPTools(result?.tools);
572
690
  }
573
691
  this._toolsCache = this._tools;
574
692
  this.state = "connected";
@@ -582,7 +700,8 @@ var MCPClient = class {
582
700
  name: this.opts.name,
583
701
  url: this.opts.url,
584
702
  headers: this.opts.headers,
585
- startupTimeoutMs: this.opts.startupTimeoutMs
703
+ startupTimeoutMs: this.opts.startupTimeoutMs,
704
+ requestTimeoutMs: this.opts.requestTimeoutMs
586
705
  };
587
706
  this.sseTransport = new SSETransport(httpOpts);
588
707
  this.sseTransport.onDisconnect(() => {
@@ -623,7 +742,8 @@ var MCPClient = class {
623
742
  name: this.opts.name,
624
743
  url: this.opts.url,
625
744
  headers: this.opts.headers,
626
- startupTimeoutMs: this.opts.startupTimeoutMs
745
+ startupTimeoutMs: this.opts.startupTimeoutMs,
746
+ requestTimeoutMs: this.opts.requestTimeoutMs
627
747
  };
628
748
  this.httpTransport = new StreamableHTTPTransport(httpOpts);
629
749
  this.httpTransport.onDisconnect(() => {
@@ -706,15 +826,33 @@ var MCPClient = class {
706
826
  this.failPending(`MCP "${this.opts.name}" closed`);
707
827
  this.state = "disconnected";
708
828
  }
709
- request(method, params) {
829
+ request(method, params, timeoutMs = this.opts.requestTimeoutMs ?? 6e4) {
710
830
  const id = this.nextId++;
711
831
  const req = { jsonrpc: "2.0", id, method, params };
712
832
  return new Promise((resolve, reject) => {
713
- this.pending.set(id, { resolve, reject });
833
+ const timer = setTimeout(() => {
834
+ this.pending.delete(id);
835
+ reject(
836
+ new Error(`MCP "${this.opts.name}" request "${method}" timed out after ${timeoutMs}ms`)
837
+ );
838
+ }, timeoutMs);
839
+ this.pending.set(id, {
840
+ resolve: (res) => {
841
+ clearTimeout(timer);
842
+ resolve(res);
843
+ },
844
+ reject: (err) => {
845
+ clearTimeout(timer);
846
+ reject(err);
847
+ },
848
+ timer
849
+ });
714
850
  try {
715
851
  this.child?.stdin?.write(JSON.stringify(req) + "\n");
716
852
  } catch (err) {
853
+ const pending = this.pending.get(id);
717
854
  this.pending.delete(id);
855
+ if (pending) clearTimeout(pending.timer);
718
856
  reject(err);
719
857
  }
720
858
  });
@@ -729,6 +867,7 @@ var MCPClient = class {
729
867
  const err = new Error(reason);
730
868
  for (const [, entry] of this.pending) {
731
869
  try {
870
+ clearTimeout(entry.timer);
732
871
  entry.reject(err);
733
872
  } catch {
734
873
  }
@@ -812,9 +951,7 @@ var MCPClient = class {
812
951
  async handleToolsListChanged() {
813
952
  try {
814
953
  const toolsRes = await this.request("tools/list", {});
815
- const tools = (toolsRes.result?.tools ?? []).filter(
816
- (t) => !!t && typeof t.name === "string"
817
- );
954
+ const tools = normalizeMCPTools(toolsRes.result?.tools);
818
955
  this._tools = tools;
819
956
  this._toolsCache = tools;
820
957
  for (const listener of this.toolsChangedListeners) {
@@ -1078,7 +1215,8 @@ var MCPRegistry = class _MCPRegistry {
1078
1215
  env: slot.cfg.env,
1079
1216
  url: slot.cfg.url,
1080
1217
  headers: slot.cfg.headers,
1081
- startupTimeoutMs: slot.cfg.startupTimeoutMs
1218
+ startupTimeoutMs: slot.cfg.startupTimeoutMs,
1219
+ requestTimeoutMs: slot.cfg.requestTimeoutMs
1082
1220
  });
1083
1221
  if (slot.cfg.transport === "stdio") {
1084
1222
  client.addExitListener(this.onChildExit);
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":["body"],"mappings":"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","file":"index.js","sourcesContent":["import type { ConnectionState, MCPTool, ToolCallResult } from './client.js';\n\nexport type JsonRpcResult = {\n jsonrpc: string;\n id?: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n};\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 */\n/**\n * Cap on the pending-line buffer. The upstream SSE parser\n * (packages/providers/src/sse.ts) already enforces 256 KB; this\n * reader is used only inside MCP HTTP transports, but defense-in-depth\n * says we should never let a malicious stream pin memory.\n */\nconst SSE_READER_MAX_BUFFER = 256 * 1024;\n\nexport class SSEReader {\n private buffer = '';\n private listeners: Array<\n (event: { jsonrpc?: string; method?: string; params?: unknown; id?: number }) => void\n > = [];\n\n onMessage(\n cb: (data: { jsonrpc?: string; method?: string; params?: unknown; id?: number }) => void,\n ): () => 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 if (this.buffer.length > SSE_READER_MAX_BUFFER) {\n throw new Error(\n `SSE: pending line exceeds ${SSE_READER_MAX_BUFFER} bytes — upstream is not framing events`,\n );\n }\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 {\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n id?: number;\n };\n this.dispatch(parsed);\n } catch {\n // ignore parse errors\n }\n }\n }\n }\n }\n\n private dispatch(msg: {\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n id?: number;\n }): void {\n for (const cb of this.listeners) {\n try {\n cb(msg);\n } catch {\n /* ignore */\n }\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 () => {\n this.toolsChangedListeners.delete(cb);\n };\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 {\n cb([...this.tools]);\n } catch {\n /* ignore */\n }\n }\n }\n } catch {\n /* ignore transient failures */\n }\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.10' },\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 {\n cb();\n } catch {\n /* ignore */\n }\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 =\n 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 {\n this.reader?.cancel();\n } catch {\n /* ignore */\n }\n try {\n this.reader?.releaseLock();\n } catch {\n /* ignore */\n }\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 () => {\n this.toolsChangedListeners.delete(cb);\n };\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 {\n cb([...this.tools]);\n } catch {\n /* ignore */\n }\n }\n }\n } catch {\n /* ignore transient failures */\n }\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.10' },\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 // Intentionally do NOT fire disconnect handlers — those trigger\n // reconnection in the registry, which would fight an explicit close().\n this.disconnectHandlers = [];\n }\n}\n","import { type ChildProcess, spawn } from 'node:child_process';\nimport { buildChildEnv } from '@wrongstack/core';\nimport { type HttpTransportOptions, SSETransport, StreamableHTTPTransport } from './transport.js';\n\nexport type Transport = 'stdio' | 'sse' | 'streamable-http';\n\nexport interface MCPClientOptions {\n name: string;\n transport: Transport;\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n startupTimeoutMs?: number;\n}\n\nexport type ConnectionState =\n | 'idle'\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'reconnecting'\n | 'failed';\n\nexport interface MCPTool {\n name: string;\n description?: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ToolCallResult {\n content: unknown;\n isError: boolean;\n}\n\ninterface JsonRpcRequest {\n jsonrpc: '2.0';\n id: number;\n method: string;\n params?: unknown;\n}\n\ninterface JsonRpcResponse {\n jsonrpc: '2.0';\n id: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n}\n\ntype ExitListener = (name: string, code: number | null, signal: string | null) => void;\n/**\n * Fired when the server sends `notifications/tools/list_changed`. The\n * client refreshes its cached tool list before invoking listeners, so\n * subscribers can call `listTools()` for the fresh set.\n */\ntype ToolsChangedListener = (name: string, tools: MCPTool[]) => void;\n\n/**\n * Lightweight MCP client supporting three transport types:\n * - stdio: spawns a child process and communicates over pipes\n * - sse: connects to an HTTP SSE endpoint for server events, POST for requests\n * - streamable-http: session-based HTTP transport with NDJSON responses\n */\nexport class MCPClient {\n private state: ConnectionState = 'idle';\n private child?: ChildProcess;\n private nextId = 1;\n /**\n * In-flight JSON-RPC calls keyed by id. `resolve` settles the call; `reject`\n * is invoked from {@link failPending} when the underlying transport dies\n * (stdio child exit, `close()`) so callers don't hang forever.\n */\n private readonly pending = new Map<\n number,\n { resolve: (res: JsonRpcResponse) => void; reject: (err: Error) => void }\n >();\n private rxBuffer = '';\n private _tools: MCPTool[] = [];\n /** Cached tool list — survives reconnects so the registry can re-register without re-discovering. */\n private _toolsCache?: MCPTool[];\n private _drainPending = false;\n private _lastNotifySkipped = false;\n // HTTP transports\n private sseTransport?: SSETransport;\n private httpTransport?: StreamableHTTPTransport;\n /** Notified when the stdio child process exits so the registry can attempt reconnect. */\n private readonly exitListeners = new Set<ExitListener>();\n /** Notified when the server announces a tools/list_changed notification. */\n private readonly toolsChangedListeners = new Set<ToolsChangedListener>();\n /** Notified when an HTTP transport (SSE or streamable-http) disconnects. */\n private readonly disconnectListeners = new Set<() => void>();\n\n constructor(public readonly opts: MCPClientOptions) {}\n\n getState(): ConnectionState {\n return this.state;\n }\n\n listTools(): MCPTool[] {\n return this._tools.length > 0\n ? [...this._tools]\n : this._toolsCache\n ? [...this._toolsCache]\n : [];\n }\n\n /** Returns true if a prior notify() call was skipped due to backpressure. */\n hadNotifySkipped(): boolean {\n return this._lastNotifySkipped;\n }\n\n /**\n * Register a listener for child-process exit events.\n * The registry uses this to trigger reconnection.\n */\n addExitListener(listener: ExitListener): void {\n this.exitListeners.add(listener);\n }\n\n removeExitListener(listener: ExitListener): void {\n this.exitListeners.delete(listener);\n }\n\n /**\n * Register a listener for transport disconnect events (SSE / streamable-http).\n * Used by the registry to trigger reconnection for HTTP-based servers.\n */\n addDisconnectListener(listener: () => void): void {\n this.disconnectListeners.add(listener);\n }\n\n removeDisconnectListener(listener: () => void): void {\n this.disconnectListeners.delete(listener);\n }\n\n async connect(): Promise<void> {\n this.state = 'connecting';\n\n if (this.opts.transport === 'stdio') {\n await this.connectStdio();\n } else if (this.opts.transport === 'sse') {\n await this.connectSSE();\n } else if (this.opts.transport === 'streamable-http') {\n await this.connectStreamableHTTP();\n } else {\n this.state = 'failed';\n throw new Error(`Unknown transport \"${this.opts.transport}\"`);\n }\n }\n\n private async connectStdio(): Promise<void> {\n if (!this.opts.command) {\n this.state = 'failed';\n throw new Error('MCP stdio transport requires \"command\"');\n }\n\n // Defense-in-depth: clear any rx state from a previous connect attempt\n // on this instance. The registry normally creates a fresh client per\n // (re)connect cycle, but a leftover rxBuffer from a half-initialized\n // attempt would corrupt JSON-RPC parsing on the new stream.\n this.rxBuffer = '';\n\n const child = spawn(this.opts.command, this.opts.args ?? [], {\n env: buildChildEnv({ extra: this.opts.env }),\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n this.child = child;\n\n child.stdout?.on('data', (chunk: Buffer) => this.onData(chunk.toString()));\n child.stderr?.on('data', () => {\n // intentionally discard stderr noise from server\n });\n child.on('exit', (code, signal) => {\n this.state = 'disconnected';\n // Reject any in-flight JSON-RPC requests — without this, callers\n // (e.g. callTool during a tool invocation) await forever on a child\n // that has already gone away.\n this.failPending(\n `MCP \"${this.opts.name}\" child exited (code=${code ?? 'null'} signal=${signal ?? 'null'})`,\n );\n for (const listener of this.exitListeners) {\n try {\n listener(this.opts.name, code, signal);\n } catch {\n /* ignore */\n }\n }\n });\n child.on('error', () => {\n this.state = 'failed';\n });\n\n const timeout = this.opts.startupTimeoutMs ?? 10_000;\n const initialize = await Promise.race([\n this.request('initialize', {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n clientInfo: { name: 'wrongstack', version: '0.1.10' },\n }),\n new Promise<JsonRpcResponse>((_, rej) =>\n setTimeout(() => rej(new Error('MCP initialize timeout')), timeout),\n ),\n ]);\n if (initialize.error) {\n this.state = 'failed';\n throw new Error(`MCP initialize failed: ${initialize.error.message}`);\n }\n try {\n await this.notify('notifications/initialized', {});\n } catch (err) {\n console.warn(\n '[MCP] notify(\"notifications/initialized\") failed for \"' +\n this.opts.name +\n '\": ' +\n (err instanceof Error ? err.message : String(err)),\n );\n }\n const toolsRes = await this.request('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 // Cache tools so reconnect can re-register without re-discovering\n this._toolsCache = this._tools;\n this.state = 'connected';\n }\n\n private async connectSSE(): Promise<void> {\n if (!this.opts.url) {\n this.state = 'failed';\n throw new Error('MCP SSE transport requires \"url\"');\n }\n const httpOpts: HttpTransportOptions = {\n name: this.opts.name,\n url: this.opts.url,\n headers: this.opts.headers,\n startupTimeoutMs: this.opts.startupTimeoutMs,\n };\n this.sseTransport = new SSETransport(httpOpts);\n this.sseTransport.onDisconnect(() => {\n this.state = 'disconnected';\n for (const cb of this.disconnectListeners) {\n try {\n cb();\n } catch {\n /* ignore */\n }\n }\n });\n this.sseTransport.onToolsChanged((tools) => {\n this._tools = tools;\n // Keep the reconnect-recovery cache in sync. Without this, an empty\n // tools update would leave `_toolsCache` pointing at the previous\n // non-empty list, and `listTools()` would serve the stale cache\n // (since it falls back to the cache when `_tools` is empty).\n this._toolsCache = tools;\n for (const cb of this.toolsChangedListeners) {\n try {\n cb(this.opts.name, tools);\n } catch {\n /* ignore */\n }\n }\n });\n try {\n await this.sseTransport.connect();\n } catch (err) {\n this.state = 'failed';\n throw err;\n }\n this._tools = this.sseTransport.listTools();\n this._toolsCache = this._tools;\n this.state = 'connected';\n }\n\n private async connectStreamableHTTP(): Promise<void> {\n if (!this.opts.url) {\n this.state = 'failed';\n throw new Error('MCP streamable-http transport requires \"url\"');\n }\n const httpOpts: HttpTransportOptions = {\n name: this.opts.name,\n url: this.opts.url,\n headers: this.opts.headers,\n startupTimeoutMs: this.opts.startupTimeoutMs,\n };\n this.httpTransport = new StreamableHTTPTransport(httpOpts);\n this.httpTransport.onDisconnect(() => {\n this.state = 'disconnected';\n for (const cb of this.disconnectListeners) {\n try {\n cb();\n } catch {\n /* ignore */\n }\n }\n });\n this.httpTransport.onToolsChanged((tools) => {\n this._tools = tools;\n // Same cache-sync reasoning as the SSE branch above — keep\n // `_toolsCache` in lockstep with `_tools` on every transport\n // update so the empty-list fallback in `listTools()` never serves\n // stale data.\n this._toolsCache = tools;\n for (const cb of this.toolsChangedListeners) {\n try {\n cb(this.opts.name, tools);\n } catch {\n /* ignore */\n }\n }\n });\n try {\n await this.httpTransport.connect();\n } catch (err) {\n this.state = 'failed';\n throw err;\n }\n this._tools = this.httpTransport.listTools();\n this._toolsCache = this._tools;\n this.state = 'connected';\n }\n\n async callTool(name: string, input: unknown): Promise<ToolCallResult> {\n if (this.state !== 'connected') {\n throw new Error(`MCP client \"${this.opts.name}\" not connected (state=${this.state})`);\n }\n // Delegate to the active transport\n if (this.sseTransport) {\n return this.sseTransport.callTool(name, input);\n }\n if (this.httpTransport) {\n return this.httpTransport.callTool(name, input);\n }\n // stdio\n const res = await this.request('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.child) {\n const child = this.child;\n // Use a pre-check on exitCode/signalCode to avoid the race where\n // 'exit' fires between the alive-check and listener attachment.\n const alreadyDead = child.exitCode !== null || child.signalCode !== null;\n const exitPromise = alreadyDead\n ? Promise.resolve()\n : new Promise<void>((resolve) => child.once('exit', () => resolve()));\n try {\n // Initial SIGTERM lets the server flush logs / clean up sockets.\n child.kill();\n } catch {\n // ignore\n }\n // Wait briefly for graceful exit, then escalate to SIGKILL. A stuck\n // server that ignores SIGTERM would otherwise stay alive after\n // close() returns — orphan child processes accumulate over restarts.\n const GRACEFUL_MS = 800;\n const FORCE_TIMEOUT_MS = 1200;\n const gracefulRace = await Promise.race([\n exitPromise.then(() => 'exited' as const),\n new Promise<'timeout'>((resolve) => setTimeout(() => resolve('timeout'), GRACEFUL_MS)),\n ]);\n if (gracefulRace === 'timeout' && !alreadyDead) {\n try {\n // SIGKILL is ignored by `kill('SIGKILL')` on Windows in older\n // Node, but `child.kill('SIGKILL')` maps to TerminateProcess\n // under the hood for spawned children since Node 18 — safe to\n // call cross-platform.\n child.kill('SIGKILL');\n } catch {\n // ignore\n }\n await Promise.race([\n exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, FORCE_TIMEOUT_MS)),\n ]);\n }\n }\n this.sseTransport?.close();\n this.httpTransport?.close();\n // Reject anything still awaiting the (now-dead) transport. Safe to call\n // unconditionally — the stdio exit handler runs failPending too, but\n // close() may be invoked on a never-started or HTTP-only client.\n this.failPending(`MCP \"${this.opts.name}\" closed`);\n this.state = 'disconnected';\n }\n\n private request(method: string, params: unknown): Promise<JsonRpcResponse> {\n const id = this.nextId++;\n const req: JsonRpcRequest = { jsonrpc: '2.0', id, method, params };\n return new Promise((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n try {\n this.child?.stdin?.write(JSON.stringify(req) + '\\n');\n } catch (err) {\n this.pending.delete(id);\n reject(err);\n }\n });\n }\n\n /**\n * Reject every in-flight {@link request} call. Used when the underlying\n * transport dies — without this, callers awaiting `tools/call` over a\n * killed stdio child or a closed transport would hang indefinitely.\n */\n private failPending(reason: string): void {\n if (this.pending.size === 0) return;\n const err = new Error(reason);\n for (const [, entry] of this.pending) {\n try {\n entry.reject(err);\n } catch {\n /* ignore */\n }\n }\n this.pending.clear();\n }\n\n private async notify(method: string, params: unknown): Promise<void> {\n const req = { jsonrpc: '2.0', method, params };\n const encoded = JSON.stringify(req) + '\\n';\n try {\n const ok = this.child?.stdin?.write(encoded);\n if (!ok) {\n // Only the first caller waits for drain; others just warn and return.\n // This avoids a race where two concurrent notify() calls each start\n // their own drain-wait, then both resolve and the buffer is still full.\n if (this._drainPending) {\n this._lastNotifySkipped = true;\n console.warn(\n `[MCP] notify(\"${method}\") skipped: stdin buffer backpressure (already waiting for drain)`,\n );\n return;\n }\n this._drainPending = true;\n await new Promise<void>((resolve, reject) => {\n const onDrain = () => {\n clearTimeout(timeout);\n this._drainPending = false;\n resolve();\n };\n const onError = (err: Error) => {\n clearTimeout(timeout);\n this._drainPending = false;\n reject(err);\n };\n const timeout = setTimeout(() => {\n this.child?.stdin?.removeListener('drain', onDrain);\n this.child?.stdin?.removeListener('error', onError);\n this._drainPending = false;\n reject(new Error(`MCP notify(\"${method}\") drain timeout`));\n }, 500);\n this.child?.stdin?.once('drain', onDrain);\n this.child?.stdin?.once('error', onError);\n });\n }\n } catch (err) {\n throw new Error(\n `[MCP] notify(\"${method}\") failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n private onData(s: string): void {\n this.rxBuffer += s;\n let idx = this.rxBuffer.indexOf('\\n');\n while (idx !== -1) {\n const line = this.rxBuffer.slice(0, idx).trim();\n this.rxBuffer = this.rxBuffer.slice(idx + 1);\n if (line) this.onLine(line);\n idx = this.rxBuffer.indexOf('\\n');\n }\n }\n\n private onLine(line: string): void {\n let msg: JsonRpcResponse & { method?: string; params?: unknown };\n try {\n msg = JSON.parse(line) as JsonRpcResponse & { method?: string; params?: unknown };\n } catch {\n return;\n }\n if (msg.id !== undefined && this.pending.has(msg.id)) {\n const entry = this.pending.get(msg.id);\n this.pending.delete(msg.id);\n entry?.resolve(msg);\n return;\n }\n // Notifications have a `method` but no `id`. The MCP spec defines\n // `notifications/tools/list_changed` for tool-set invalidation —\n // refresh the cache asynchronously and fire listeners so the\n // registry can re-register the wrapped tools.\n if (typeof msg.method === 'string' && msg.method === 'notifications/tools/list_changed') {\n void this.handleToolsListChanged();\n }\n }\n\n /**\n * L2-C: refresh the cached tool list when the server announces a\n * `tools/list_changed`. Listeners (the registry) re-wrap and\n * re-register. Failures are swallowed — a stale cache is preferable\n * to a hard crash on a transient notification glitch.\n */\n private async handleToolsListChanged(): Promise<void> {\n try {\n const toolsRes = await this.request('tools/list', {});\n const tools = ((toolsRes.result as { tools?: MCPTool[] } | undefined)?.tools ?? []).filter(\n (t): t is MCPTool => !!t && typeof t.name === 'string',\n );\n this._tools = tools;\n this._toolsCache = tools;\n for (const listener of this.toolsChangedListeners) {\n try {\n listener(this.opts.name, [...tools]);\n } catch {\n // listeners must be best-effort\n }\n }\n } catch {\n // ignore — keep the existing cache\n }\n }\n\n addToolsChangedListener(listener: ToolsChangedListener): void {\n this.toolsChangedListeners.add(listener);\n }\n\n removeToolsChangedListener(listener: ToolsChangedListener): void {\n this.toolsChangedListeners.delete(listener);\n }\n}\n","import type { Permission, Tool } from '@wrongstack/core';\nimport type { MCPClient, MCPTool } from './client.js';\n\n/**\n * Keywords that indicate a mutating operation.\n * Applied to both the tool name and its inputSchema property names.\n */\nconst MUTATING_RE = /create|update|delete|write|send|set|put|post|patch|remove|rename|move/i;\n\nfunction isMutatingTool(mcpTool: MCPTool): boolean {\n if (MUTATING_RE.test(mcpTool.name)) return true;\n // Check property names in the input schema for mutating intent.\n // e.g. { properties: { createTable: {...}, dropIndex: {...} } }\n const schema = mcpTool.inputSchema;\n if (schema && typeof schema === 'object') {\n const props = (schema as { properties?: Record<string, unknown> }).properties;\n if (props) {\n for (const key of Object.keys(props)) {\n if (MUTATING_RE.test(key)) return true;\n }\n }\n }\n return false;\n}\n\nexport function wrapMCPTool(\n serverName: string,\n mcpTool: MCPTool,\n client: MCPClient,\n permission: Permission = 'confirm',\n): Tool {\n const qualifiedName = `mcp__${serverName}__${mcpTool.name}`;\n return {\n name: qualifiedName,\n description: mcpTool.description ?? `${qualifiedName} (MCP tool)`,\n usageHint: `Tool provided by MCP server \"${serverName}\". ${mcpTool.description ?? ''}`,\n permission,\n mutating: isMutatingTool(mcpTool),\n inputSchema: mcpTool.inputSchema ?? { type: 'object', properties: {} },\n async execute(input, ctx, opts) {\n const res = await client.callTool(mcpTool.name, input);\n if (res.isError) {\n throw new Error(stringify(res.content));\n }\n return stringify(res.content);\n },\n };\n}\n\nfunction stringify(c: unknown): string {\n if (typeof c === 'string') return c;\n if (Array.isArray(c)) {\n return c\n .map((item) => {\n if (item && typeof item === 'object') {\n const t = (item as { type?: string; text?: string }).type;\n if (t === 'text') return (item as { text?: string }).text ?? '';\n return JSON.stringify(item);\n }\n return String(item);\n })\n .join('\\n');\n }\n if (c && typeof c === 'object') {\n if ('text' in (c as Record<string, unknown>)) {\n return String((c as Record<string, unknown>).text);\n }\n return JSON.stringify(c);\n }\n return String(c ?? '');\n}\n","import type { EventBus, Logger, MCPServerConfig, ToolRegistry } from '@wrongstack/core';\nimport { type ConnectionState, MCPClient } from './client.js';\nimport { wrapMCPTool } from './wrap-tool.js';\n\ninterface ServerSlot {\n cfg: MCPServerConfig;\n client?: MCPClient;\n state: ConnectionState;\n toolNames: string[];\n attempts: number;\n /** Set when a reconnect cycle is already running for this slot. */\n reconnectPending: boolean;\n /**\n * L2-B: number of full reconnect *cycles* (where one cycle = one\n * `attemptConnect` invocation, which itself can try multiple times\n * before giving up). After `MAX_RECONNECT_CYCLES`, the slot stays\n * `failed` until a manual `restart()` resets it.\n */\n reconnectCycles: number;\n /**\n * Slot-scoped, bound disconnect callback. Stored so the matching\n * `removeDisconnectListener` call can hand back the *same* reference —\n * a fresh arrow `() => onTransportDisconnect(slot.cfg.name)` would\n * not match the one we added and the set-based listener registry\n * would silently keep the old handler, causing duplicate reconnect\n * cycles after a few transport flaps.\n */\n onDisconnect?: () => void;\n}\n\nexport interface MCPRegistryOptions {\n toolRegistry: ToolRegistry;\n events: EventBus;\n log: Logger;\n}\n\nexport class MCPRegistry {\n private readonly servers = new Map<string, ServerSlot>();\n private readonly toolRegistry: ToolRegistry;\n private readonly events: EventBus;\n private readonly log: Logger;\n\n constructor(opts: MCPRegistryOptions) {\n this.toolRegistry = opts.toolRegistry;\n this.events = opts.events;\n this.log = opts.log;\n }\n\n async start(cfg: MCPServerConfig): Promise<void> {\n if (cfg.enabled === false) return;\n const slot: ServerSlot = {\n cfg,\n state: 'idle',\n toolNames: [],\n attempts: 0,\n reconnectPending: false,\n reconnectCycles: 0,\n };\n this.servers.set(cfg.name, slot);\n await this.attemptConnect(slot);\n }\n\n async stop(name: string): Promise<void> {\n const slot = this.servers.get(name);\n if (!slot) return;\n slot.reconnectPending = false;\n if (slot.client) {\n slot.client.removeExitListener(this.onChildExit);\n if (slot.onDisconnect) slot.client.removeDisconnectListener(slot.onDisconnect);\n slot.client.removeToolsChangedListener(this.onToolsChanged);\n await slot.client.close();\n slot.client = undefined;\n }\n slot.onDisconnect = undefined;\n for (const t of slot.toolNames) this.toolRegistry.unregister(t);\n slot.toolNames = [];\n slot.state = 'disconnected';\n this.events.emit('mcp.server.disconnected', { name, reason: 'stop' });\n }\n\n async restart(name: string): Promise<void> {\n const slot = this.servers.get(name);\n if (!slot) throw new Error(`MCP server \"${name}\" not registered`);\n await this.stop(name);\n slot.attempts = 0;\n slot.reconnectCycles = 0; // user intent: start fresh\n await this.attemptConnect(slot);\n }\n\n list(): { name: string; state: ConnectionState; toolCount: number }[] {\n return Array.from(this.servers.values()).map((s) => ({\n name: s.cfg.name,\n state: s.state,\n toolCount: s.toolNames.length,\n }));\n }\n\n async stopAll(): Promise<void> {\n for (const name of Array.from(this.servers.keys())) {\n await this.stop(name);\n }\n }\n\n /**\n * Health check — returns 'ok' for connected servers, the current state otherwise.\n * For HTTP-based transports this could also ping the server.\n */\n health(): { name: string; alive: boolean; latencyMs?: number }[] {\n return Array.from(this.servers.values()).map((s) => ({\n name: s.cfg.name,\n alive: s.state === 'connected',\n }));\n }\n\n /**\n * L2-C: handle `notifications/tools/list_changed` from the server.\n * Unregister the previous wrapper set, then re-register the fresh\n * tool list. The client has already refreshed its cache before\n * dispatching — we just need to re-wrap and re-register.\n */\n private readonly onToolsChanged = (name: string, _tools: { name: string }[]): void => {\n const slot = this.servers.get(name);\n if (!slot || !slot.client) return;\n for (const t of slot.toolNames) {\n try {\n this.toolRegistry.unregister(t);\n } catch {\n /* ignore */\n }\n }\n slot.toolNames = [];\n const allowed = slot.cfg.allowedTools;\n const wrapped = slot.client\n .listTools()\n .filter((t) => !allowed || allowed.includes(t.name))\n .map((t) => wrapMCPTool(slot.cfg.name, t, slot.client!, slot.cfg.permission ?? 'confirm'));\n for (const tool of wrapped) {\n try {\n this.toolRegistry.register(tool, `mcp:${slot.cfg.name}`);\n slot.toolNames.push(tool.name);\n } catch (err) {\n this.log.warn(`MCP tool \"${tool.name}\" not re-registered after list_changed`, err);\n }\n }\n this.events.emit('mcp.server.connected', {\n name: slot.cfg.name,\n toolCount: slot.toolNames.length,\n });\n this.log.info(\n `MCP server \"${slot.cfg.name}\" tools refreshed (${slot.toolNames.length} active)`,\n );\n };\n\n private readonly onChildExit = (\n name: string,\n code: number | null,\n _signal: string | null,\n ): void => {\n const slot = this.servers.get(name);\n if (!slot) return;\n for (const t of slot.toolNames) {\n try {\n this.toolRegistry.unregister(t);\n } catch {\n /* ignore */\n }\n }\n slot.toolNames = [];\n slot.state = 'disconnected';\n this.events.emit('mcp.server.disconnected', { name, reason: `exit:${code ?? 'unknown'}` });\n this.scheduleReconnect(slot);\n };\n\n /** Handles SSE / streamable-http disconnect — same recovery as stdio child exit. */\n private readonly onTransportDisconnect = (name: string): void => {\n const slot = this.servers.get(name);\n if (!slot) return;\n for (const t of slot.toolNames) {\n try {\n this.toolRegistry.unregister(t);\n } catch {\n /* ignore */\n }\n }\n slot.toolNames = [];\n slot.state = 'disconnected';\n this.events.emit('mcp.server.disconnected', { name, reason: 'http-disconnect' });\n this.scheduleReconnect(slot);\n };\n\n /**\n * L2-B: maximum number of reconnect cycles before staying `failed`.\n * One cycle = one full `attemptConnect` (which itself may try up to 3\n * times). Caps total reconnect storm at ~5 cycles, then the slot\n * needs an explicit `restart()` to re-engage.\n */\n private static readonly MAX_RECONNECT_CYCLES = 5;\n /** Base delay between cycles, in ms. Real delay adds jitter. */\n private static readonly BASE_RECONNECT_DELAY_MS = 1000;\n /** Hard ceiling on the inter-cycle delay so the user doesn't wait minutes. */\n private static readonly MAX_RECONNECT_DELAY_MS = 30_000;\n\n private scheduleReconnect(slot: ServerSlot): void {\n if (slot.reconnectPending) return;\n if (slot.reconnectCycles >= MCPRegistry.MAX_RECONNECT_CYCLES) {\n slot.state = 'failed';\n this.log.error(\n `MCP server \"${slot.cfg.name}\" giving up after ${slot.reconnectCycles} reconnect cycles. Use \\`/mcp restart ${slot.cfg.name}\\` to retry.`,\n );\n this.events.emit('mcp.server.disconnected', {\n name: slot.cfg.name,\n reason: `reconnect-exhausted:${slot.reconnectCycles}`,\n });\n return;\n }\n slot.reconnectPending = true;\n // Exponential backoff with light jitter: 1s, 2s, 4s, 8s, 16s, capped\n // at 30s. The ±20% jitter avoids reconnect stampedes when many\n // servers crash together.\n const base = Math.min(\n MCPRegistry.BASE_RECONNECT_DELAY_MS * 2 ** slot.reconnectCycles,\n MCPRegistry.MAX_RECONNECT_DELAY_MS,\n );\n const jitter = base * 0.2 * (Math.random() * 2 - 1);\n const delay = Math.max(100, Math.round(base + jitter));\n setTimeout(() => this.attemptReconnect(slot), delay);\n }\n\n private async attemptReconnect(slot: ServerSlot): Promise<void> {\n slot.reconnectPending = false;\n slot.reconnectCycles++;\n await this.attemptConnect(slot);\n }\n\n private async attemptConnect(slot: ServerSlot): Promise<void> {\n const MAX_ATTEMPTS = 3;\n let attempt = 0;\n while (attempt < MAX_ATTEMPTS) {\n attempt++;\n slot.state = attempt === 1 ? 'connecting' : 'reconnecting';\n slot.attempts = attempt;\n let client: MCPClient | undefined;\n let boundDisconnect: (() => void) | undefined;\n try {\n client = new MCPClient({\n name: slot.cfg.name,\n transport: slot.cfg.transport,\n command: slot.cfg.command,\n args: slot.cfg.args,\n env: slot.cfg.env,\n url: slot.cfg.url,\n headers: slot.cfg.headers,\n startupTimeoutMs: slot.cfg.startupTimeoutMs,\n });\n if (slot.cfg.transport === 'stdio') {\n client.addExitListener(this.onChildExit);\n } else {\n // SSE / streamable-http — wire transport disconnect to registry reconnect.\n // Capture the bound function so we can hand the same reference to\n // removeDisconnectListener on cleanup paths.\n boundDisconnect = () => this.onTransportDisconnect(slot.cfg.name);\n client.addDisconnectListener(boundDisconnect);\n }\n // L2-C: react to server-side tool changes by re-registering wrappers.\n client.addToolsChangedListener(this.onToolsChanged);\n await client.connect();\n // Close any prior client before swapping refs so the old transport\n // can release its abort controller, child process, and listeners\n // instead of being held until GC.\n if (slot.client && slot.client !== client) {\n const prior = slot.client;\n const priorDisconnect = slot.onDisconnect;\n slot.client.removeExitListener(this.onChildExit);\n if (priorDisconnect) prior.removeDisconnectListener(priorDisconnect);\n prior.removeToolsChangedListener(this.onToolsChanged);\n prior.close().catch(() => {\n /* best-effort */\n });\n }\n slot.client = client;\n slot.onDisconnect = boundDisconnect;\n const isReconnect = attempt > 1;\n slot.state = 'connected';\n // L2-B: a healthy connect resets the cycle counter so future\n // crashes get the full reconnect budget again.\n slot.reconnectCycles = 0;\n const allowed = slot.cfg.allowedTools;\n // Prefer cached tools to avoid a round-trip to the server on reconnect.\n // The cache is populated by client.listTools() on first connect.\n const mc = client as MCPClient;\n const candidateTools = mc.listTools();\n const toWrap = candidateTools.length > 0 ? candidateTools : mc.listTools(); // fallback — in practice both return the same list\n const wrapped = toWrap\n .filter((t) => !allowed || allowed.includes(t.name))\n .map((t) => wrapMCPTool(slot.cfg.name, t, mc, slot.cfg.permission ?? 'confirm'));\n for (const tool of wrapped) {\n try {\n this.toolRegistry.register(tool, `mcp:${slot.cfg.name}`);\n slot.toolNames.push(tool.name);\n } catch (err) {\n this.log.warn(`MCP tool \"${tool.name}\" not registered`, err);\n }\n }\n this.events.emit(isReconnect ? 'mcp.server.reconnected' : 'mcp.server.connected', {\n name: slot.cfg.name,\n toolCount: slot.toolNames.length,\n });\n return; // success\n } catch (err) {\n this.log.warn(`MCP server \"${slot.cfg.name}\" connect attempt ${attempt} failed`, err);\n if (client) {\n client.removeExitListener(this.onChildExit);\n if (boundDisconnect) client.removeDisconnectListener(boundDisconnect);\n client.removeToolsChangedListener(this.onToolsChanged);\n await client.close().catch(() => {\n /* ignore */\n });\n }\n if (attempt >= MAX_ATTEMPTS) {\n this.log.error(\n `MCP server \"${slot.cfg.name}\" connect exhausted after ${MAX_ATTEMPTS} attempts`,\n err,\n );\n slot.state = 'failed';\n slot.client = undefined;\n this.events.emit('mcp.server.disconnected', {\n name: slot.cfg.name,\n reason: err instanceof Error ? err.message : 'unknown',\n });\n return;\n }\n const delay = 500 * 2 ** attempt;\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/tool-schema.ts","../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 { MCPTool } from './client.js';\n\nexport function normalizeMCPTools(value: unknown): MCPTool[] {\n if (!Array.isArray(value)) return [];\n const tools: MCPTool[] = [];\n for (const raw of value) {\n if (!raw || typeof raw !== 'object') continue;\n const t = raw as { name?: unknown; description?: unknown; inputSchema?: unknown };\n if (typeof t.name !== 'string' || t.name.trim().length === 0) continue;\n const inputSchema =\n t.inputSchema && typeof t.inputSchema === 'object' && !Array.isArray(t.inputSchema)\n ? (t.inputSchema as Record<string, unknown>)\n : { type: 'object', properties: {} };\n tools.push({\n name: t.name,\n ...(typeof t.description === 'string' ? { description: t.description } : {}),\n inputSchema,\n });\n }\n return tools;\n}\n","import * as net from 'node:net';\nimport type { ConnectionState, MCPTool, ToolCallResult } from './client.js';\nimport { normalizeMCPTools } from './tool-schema.js';\n\nexport type JsonRpcResult = {\n jsonrpc: string;\n id?: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n};\n\nexport interface HttpTransportOptions {\n name: string;\n url: string;\n headers?: Record<string, string>;\n startupTimeoutMs?: number;\n requestTimeoutMs?: number;\n}\n\n/**\n * Validate that an MCP transport URL is not targeting private/internal\n * addresses. This is a defense-in-depth SSRF check — MCP servers are\n * typically local or LAN, but config manipulation could point to metadata\n * endpoints (169.254.169.254) or internal services.\n *\n * The check is intentionally lighter than fetch.ts's assertNotPrivate:\n * MCP URLs are admin-configured, not LLM-supplied, so we only block\n * the most obvious attack vectors.\n */\nfunction validateTransportUrl(rawUrl: string): void {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n throw new Error(`MCP transport: invalid URL \"${rawUrl}\"`);\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error(\n `MCP transport: unsupported protocol \"${url.protocol}\" — only http/https allowed`,\n );\n }\n\n const hostname = url.hostname;\n\n // Block localhost variants\n if (\n hostname === 'localhost' ||\n hostname === '0.0.0.0' ||\n hostname === '::' ||\n hostname === '[::1]'\n ) {\n return; // localhost is expected for local MCP servers — don't block\n }\n\n // Block cloud metadata endpoints (IMDS) — these are never valid MCP servers\n const ipVersion = net.isIP(hostname);\n if (ipVersion === 4) {\n const parts = hostname.split('.').map(Number);\n // 169.254.x.x (link-local / IMDS)\n if (parts[0] === 169 && parts[1] === 254) {\n throw new Error(\n `MCP transport: blocked link-local/IMDS address \"${hostname}\" — likely not a valid MCP server`,\n );\n }\n }\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 */\n/**\n * Cap on the pending-line buffer. The upstream SSE parser\n * (packages/providers/src/sse.ts) already enforces 256 KB; this\n * reader is used only inside MCP HTTP transports, but defense-in-depth\n * says we should never let a malicious stream pin memory.\n */\nconst SSE_READER_MAX_BUFFER = 256 * 1024;\n\nexport class SSEReader {\n private buffer = '';\n private dataLines: string[] = [];\n private listeners: Array<\n (event: { jsonrpc?: string; method?: string; params?: unknown; id?: number }) => void\n > = [];\n\n onMessage(\n cb: (data: { jsonrpc?: string; method?: string; params?: unknown; id?: number }) => void,\n ): () => 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 if (this.buffer.length > SSE_READER_MAX_BUFFER) {\n throw new Error(\n `SSE: pending line exceeds ${SSE_READER_MAX_BUFFER} bytes — upstream is not framing events`,\n );\n }\n let idx = this.buffer.indexOf('\\n');\n while (idx !== -1) {\n const line = this.buffer.slice(0, idx).replace(/\\r$/, '');\n this.buffer = this.buffer.slice(idx + 1);\n idx = this.buffer.indexOf('\\n');\n\n this.processLine(line);\n }\n }\n\n private processLine(line: string): void {\n if (line === '') {\n this.flush();\n return;\n }\n if (line.startsWith(':')) return;\n\n const colonIdx = line.indexOf(':');\n const field = colonIdx === -1 ? line : line.slice(0, colonIdx);\n let value = colonIdx === -1 ? '' : line.slice(colonIdx + 1);\n if (value.startsWith(' ')) value = value.slice(1);\n\n if (field === 'event') {\n // The current transport only cares about JSON-RPC payloads in data\n // fields. Event names are accepted for spec compatibility.\n } else if (field === 'data') {\n this.dataLines.push(value);\n }\n }\n\n private flush(): void {\n if (this.dataLines.length === 0) {\n return;\n }\n const data = this.dataLines.join('\\n').trim();\n this.dataLines = [];\n if (!data) return;\n try {\n const parsed = JSON.parse(data) as {\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n id?: number;\n };\n this.dispatch(parsed);\n } catch {\n // ignore parse errors\n }\n }\n\n private dispatch(msg: {\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n id?: number;\n }): void {\n for (const cb of this.listeners) {\n try {\n cb(msg);\n } catch {\n /* ignore */\n }\n }\n }\n\n reset(): void {\n this.buffer = '';\n this.dataLines = [];\n this.listeners = [];\n }\n}\n\nfunction isJsonRpcResult(v: unknown): v is JsonRpcResult {\n if (typeof v !== 'object' || v === null) return false;\n const r = v as JsonRpcResult;\n if (r.jsonrpc !== '2.0') return false;\n if (r.error !== undefined) {\n return (\n typeof r.error === 'object' &&\n r.error !== null &&\n typeof r.error.code === 'number' &&\n typeof r.error.message === 'string'\n );\n }\n return 'result' in r || r.id === undefined;\n}\n\nfunction assertMatchingJsonRpcResult(\n data: unknown,\n expectedId: number,\n method: string,\n): JsonRpcResult {\n if (!isJsonRpcResult(data)) {\n throw new Error('Invalid JSON-RPC response: not a JSON-RPC 2.0 envelope');\n }\n if (data.id !== undefined && data.id !== expectedId) {\n throw new Error(\n `Invalid JSON-RPC response: id mismatch for ${method} (expected ${expectedId}, got ${data.id})`,\n );\n }\n if (data.id === undefined && !method.startsWith('notifications/')) {\n throw new Error(`Invalid JSON-RPC response: missing id for ${method}`);\n }\n return data;\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 requestTimeout: 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 validateTransportUrl(opts.url);\n this.url = opts.url;\n this.headers = { ...opts.headers };\n this.timeout = opts.startupTimeoutMs ?? 10_000;\n this.requestTimeout = opts.requestTimeoutMs ?? 60_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 () => {\n this.toolsChangedListeners.delete(cb);\n };\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 = normalizeMCPTools((res.result as { tools?: unknown } | undefined)?.tools);\n for (const cb of this.toolsChangedListeners) {\n try {\n cb([...this.tools]);\n } catch {\n /* ignore */\n }\n }\n }\n } catch {\n /* ignore transient failures */\n }\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.10' },\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?: unknown } | undefined;\n this.tools = normalizeMCPTools(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 {\n cb();\n } catch {\n /* ignore */\n }\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 timeoutSignal = createTimeoutSignal(this.abortController?.signal, this.requestTimeout);\n try {\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: timeoutSignal.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 =\n 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 return assertMatchingJsonRpcResult(data, id, method);\n } finally {\n timeoutSignal.dispose();\n }\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 {\n this.reader?.cancel();\n } catch {\n /* ignore */\n }\n try {\n this.reader?.releaseLock();\n } catch {\n /* ignore */\n }\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 requestTimeout: 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 validateTransportUrl(opts.url);\n this.url = opts.url;\n this.headers = { ...opts.headers };\n this.timeout = opts.startupTimeoutMs ?? 10_000;\n this.requestTimeout = opts.requestTimeoutMs ?? 60_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 () => {\n this.toolsChangedListeners.delete(cb);\n };\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 = normalizeMCPTools((res.result as { tools?: unknown } | undefined)?.tools);\n for (const cb of this.toolsChangedListeners) {\n try {\n cb([...this.tools]);\n } catch {\n /* ignore */\n }\n }\n }\n } catch {\n /* ignore transient failures */\n }\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.10' },\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 data = assertMatchingJsonRpcResult(data, this.nextId - 1, 'initialize');\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?: unknown } | undefined;\n this.tools = normalizeMCPTools(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 timeoutSignal = createTimeoutSignal(this.abortController?.signal, this.requestTimeout);\n try {\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: timeoutSignal.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 let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {}\n if (isJsonRpcResult(parsed)) {\n return assertMatchingJsonRpcResult(parsed, id, method);\n }\n }\n throw new Error('Could not parse response as JSON-RPC');\n } finally {\n timeoutSignal.dispose();\n }\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 // Intentionally do NOT fire disconnect handlers — those trigger\n // reconnection in the registry, which would fight an explicit close().\n this.disconnectHandlers = [];\n }\n}\n\nfunction createTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; dispose: () => void } {\n const ctrl = new AbortController();\n const onAbort = () => ctrl.abort(parent?.reason);\n if (parent?.aborted) {\n ctrl.abort(parent.reason);\n } else {\n parent?.addEventListener('abort', onAbort, { once: true });\n }\n const timer = setTimeout(\n () => ctrl.abort(new Error(`MCP HTTP request timed out after ${timeoutMs}ms`)),\n timeoutMs,\n );\n return {\n signal: ctrl.signal,\n dispose: () => {\n clearTimeout(timer);\n parent?.removeEventListener('abort', onAbort);\n },\n };\n}\n","import { type ChildProcess, spawn } from 'node:child_process';\nimport { buildChildEnv } from '@wrongstack/core';\nimport { normalizeMCPTools } from './tool-schema.js';\nimport { type HttpTransportOptions, SSETransport, StreamableHTTPTransport } from './transport.js';\n\nexport type Transport = 'stdio' | 'sse' | 'streamable-http';\n\nexport interface MCPClientOptions {\n name: string;\n transport: Transport;\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n startupTimeoutMs?: number;\n requestTimeoutMs?: number;\n}\n\nexport type ConnectionState =\n | 'idle'\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'reconnecting'\n | 'failed';\n\nexport interface MCPTool {\n name: string;\n description?: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ToolCallResult {\n content: unknown;\n isError: boolean;\n}\n\ninterface JsonRpcRequest {\n jsonrpc: '2.0';\n id: number;\n method: string;\n params?: unknown;\n}\n\ninterface JsonRpcResponse {\n jsonrpc: '2.0';\n id: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n}\n\ntype ExitListener = (name: string, code: number | null, signal: string | null) => void;\n/**\n * Fired when the server sends `notifications/tools/list_changed`. The\n * client refreshes its cached tool list before invoking listeners, so\n * subscribers can call `listTools()` for the fresh set.\n */\ntype ToolsChangedListener = (name: string, tools: MCPTool[]) => void;\n\n/**\n * Lightweight MCP client supporting three transport types:\n * - stdio: spawns a child process and communicates over pipes\n * - sse: connects to an HTTP SSE endpoint for server events, POST for requests\n * - streamable-http: session-based HTTP transport with NDJSON responses\n */\nexport class MCPClient {\n private state: ConnectionState = 'idle';\n private child?: ChildProcess;\n private nextId = 1;\n /**\n * In-flight JSON-RPC calls keyed by id. `resolve` settles the call; `reject`\n * is invoked from {@link failPending} when the underlying transport dies\n * (stdio child exit, `close()`) so callers don't hang forever.\n */\n private readonly pending = new Map<\n number,\n { resolve: (res: JsonRpcResponse) => void; reject: (err: Error) => void; timer: NodeJS.Timeout }\n >();\n private rxBuffer = '';\n private _tools: MCPTool[] = [];\n /** Cached tool list — survives reconnects so the registry can re-register without re-discovering. */\n private _toolsCache?: MCPTool[];\n private _drainPending = false;\n private _lastNotifySkipped = false;\n // HTTP transports\n private sseTransport?: SSETransport;\n private httpTransport?: StreamableHTTPTransport;\n /** Notified when the stdio child process exits so the registry can attempt reconnect. */\n private readonly exitListeners = new Set<ExitListener>();\n /** Notified when the server announces a tools/list_changed notification. */\n private readonly toolsChangedListeners = new Set<ToolsChangedListener>();\n /** Notified when an HTTP transport (SSE or streamable-http) disconnects. */\n private readonly disconnectListeners = new Set<() => void>();\n\n constructor(public readonly opts: MCPClientOptions) {}\n\n getState(): ConnectionState {\n return this.state;\n }\n\n listTools(): MCPTool[] {\n return this._tools.length > 0\n ? [...this._tools]\n : this._toolsCache\n ? [...this._toolsCache]\n : [];\n }\n\n /** Returns true if a prior notify() call was skipped due to backpressure. */\n hadNotifySkipped(): boolean {\n return this._lastNotifySkipped;\n }\n\n /**\n * Register a listener for child-process exit events.\n * The registry uses this to trigger reconnection.\n */\n addExitListener(listener: ExitListener): void {\n this.exitListeners.add(listener);\n }\n\n removeExitListener(listener: ExitListener): void {\n this.exitListeners.delete(listener);\n }\n\n /**\n * Register a listener for transport disconnect events (SSE / streamable-http).\n * Used by the registry to trigger reconnection for HTTP-based servers.\n */\n addDisconnectListener(listener: () => void): void {\n this.disconnectListeners.add(listener);\n }\n\n removeDisconnectListener(listener: () => void): void {\n this.disconnectListeners.delete(listener);\n }\n\n async connect(): Promise<void> {\n this.state = 'connecting';\n\n if (this.opts.transport === 'stdio') {\n await this.connectStdio();\n } else if (this.opts.transport === 'sse') {\n await this.connectSSE();\n } else if (this.opts.transport === 'streamable-http') {\n await this.connectStreamableHTTP();\n } else {\n this.state = 'failed';\n throw new Error(`Unknown transport \"${this.opts.transport}\"`);\n }\n }\n\n private async connectStdio(): Promise<void> {\n if (!this.opts.command) {\n this.state = 'failed';\n throw new Error('MCP stdio transport requires \"command\"');\n }\n\n // Defense-in-depth: clear any rx state from a previous connect attempt\n // on this instance. The registry normally creates a fresh client per\n // (re)connect cycle, but a leftover rxBuffer from a half-initialized\n // attempt would corrupt JSON-RPC parsing on the new stream.\n this.rxBuffer = '';\n\n const child = spawn(this.opts.command, this.opts.args ?? [], {\n env: buildChildEnv({ extra: this.opts.env }),\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n this.child = child;\n\n child.stdout?.on('data', (chunk: Buffer) => this.onData(chunk.toString()));\n child.stderr?.on('data', () => {\n // intentionally discard stderr noise from server\n });\n child.on('exit', (code, signal) => {\n this.state = 'disconnected';\n // Reject any in-flight JSON-RPC requests — without this, callers\n // (e.g. callTool during a tool invocation) await forever on a child\n // that has already gone away.\n this.failPending(\n `MCP \"${this.opts.name}\" child exited (code=${code ?? 'null'} signal=${signal ?? 'null'})`,\n );\n for (const listener of this.exitListeners) {\n try {\n listener(this.opts.name, code, signal);\n } catch {\n /* ignore */\n }\n }\n });\n child.on('error', () => {\n this.state = 'failed';\n });\n\n const initialize = await this.request(\n 'initialize',\n {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n clientInfo: { name: 'wrongstack', version: '0.1.10' },\n },\n this.opts.startupTimeoutMs ?? 10_000,\n );\n if (initialize.error) {\n this.state = 'failed';\n throw new Error(`MCP initialize failed: ${initialize.error.message}`);\n }\n try {\n await this.notify('notifications/initialized', {});\n } catch (err) {\n console.warn(\n '[MCP] notify(\"notifications/initialized\") failed for \"' +\n this.opts.name +\n '\": ' +\n (err instanceof Error ? err.message : String(err)),\n );\n }\n const toolsRes = await this.request('tools/list', {});\n if (toolsRes.error) {\n this._tools = [];\n } else {\n const result = toolsRes.result as { tools?: MCPTool[] } | undefined;\n this._tools = normalizeMCPTools(result?.tools);\n }\n // Cache tools so reconnect can re-register without re-discovering\n this._toolsCache = this._tools;\n this.state = 'connected';\n }\n\n private async connectSSE(): Promise<void> {\n if (!this.opts.url) {\n this.state = 'failed';\n throw new Error('MCP SSE transport requires \"url\"');\n }\n const httpOpts: HttpTransportOptions = {\n name: this.opts.name,\n url: this.opts.url,\n headers: this.opts.headers,\n startupTimeoutMs: this.opts.startupTimeoutMs,\n requestTimeoutMs: this.opts.requestTimeoutMs,\n };\n this.sseTransport = new SSETransport(httpOpts);\n this.sseTransport.onDisconnect(() => {\n this.state = 'disconnected';\n for (const cb of this.disconnectListeners) {\n try {\n cb();\n } catch {\n /* ignore */\n }\n }\n });\n this.sseTransport.onToolsChanged((tools) => {\n this._tools = tools;\n // Keep the reconnect-recovery cache in sync. Without this, an empty\n // tools update would leave `_toolsCache` pointing at the previous\n // non-empty list, and `listTools()` would serve the stale cache\n // (since it falls back to the cache when `_tools` is empty).\n this._toolsCache = tools;\n for (const cb of this.toolsChangedListeners) {\n try {\n cb(this.opts.name, tools);\n } catch {\n /* ignore */\n }\n }\n });\n try {\n await this.sseTransport.connect();\n } catch (err) {\n this.state = 'failed';\n throw err;\n }\n this._tools = this.sseTransport.listTools();\n this._toolsCache = this._tools;\n this.state = 'connected';\n }\n\n private async connectStreamableHTTP(): Promise<void> {\n if (!this.opts.url) {\n this.state = 'failed';\n throw new Error('MCP streamable-http transport requires \"url\"');\n }\n const httpOpts: HttpTransportOptions = {\n name: this.opts.name,\n url: this.opts.url,\n headers: this.opts.headers,\n startupTimeoutMs: this.opts.startupTimeoutMs,\n requestTimeoutMs: this.opts.requestTimeoutMs,\n };\n this.httpTransport = new StreamableHTTPTransport(httpOpts);\n this.httpTransport.onDisconnect(() => {\n this.state = 'disconnected';\n for (const cb of this.disconnectListeners) {\n try {\n cb();\n } catch {\n /* ignore */\n }\n }\n });\n this.httpTransport.onToolsChanged((tools) => {\n this._tools = tools;\n // Same cache-sync reasoning as the SSE branch above — keep\n // `_toolsCache` in lockstep with `_tools` on every transport\n // update so the empty-list fallback in `listTools()` never serves\n // stale data.\n this._toolsCache = tools;\n for (const cb of this.toolsChangedListeners) {\n try {\n cb(this.opts.name, tools);\n } catch {\n /* ignore */\n }\n }\n });\n try {\n await this.httpTransport.connect();\n } catch (err) {\n this.state = 'failed';\n throw err;\n }\n this._tools = this.httpTransport.listTools();\n this._toolsCache = this._tools;\n this.state = 'connected';\n }\n\n async callTool(name: string, input: unknown): Promise<ToolCallResult> {\n if (this.state !== 'connected') {\n throw new Error(`MCP client \"${this.opts.name}\" not connected (state=${this.state})`);\n }\n // Delegate to the active transport\n if (this.sseTransport) {\n return this.sseTransport.callTool(name, input);\n }\n if (this.httpTransport) {\n return this.httpTransport.callTool(name, input);\n }\n // stdio\n const res = await this.request('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.child) {\n const child = this.child;\n // Use a pre-check on exitCode/signalCode to avoid the race where\n // 'exit' fires between the alive-check and listener attachment.\n const alreadyDead = child.exitCode !== null || child.signalCode !== null;\n const exitPromise = alreadyDead\n ? Promise.resolve()\n : new Promise<void>((resolve) => child.once('exit', () => resolve()));\n try {\n // Initial SIGTERM lets the server flush logs / clean up sockets.\n child.kill();\n } catch {\n // ignore\n }\n // Wait briefly for graceful exit, then escalate to SIGKILL. A stuck\n // server that ignores SIGTERM would otherwise stay alive after\n // close() returns — orphan child processes accumulate over restarts.\n const GRACEFUL_MS = 800;\n const FORCE_TIMEOUT_MS = 1200;\n const gracefulRace = await Promise.race([\n exitPromise.then(() => 'exited' as const),\n new Promise<'timeout'>((resolve) => setTimeout(() => resolve('timeout'), GRACEFUL_MS)),\n ]);\n if (gracefulRace === 'timeout' && !alreadyDead) {\n try {\n // SIGKILL is ignored by `kill('SIGKILL')` on Windows in older\n // Node, but `child.kill('SIGKILL')` maps to TerminateProcess\n // under the hood for spawned children since Node 18 — safe to\n // call cross-platform.\n child.kill('SIGKILL');\n } catch {\n // ignore\n }\n await Promise.race([\n exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, FORCE_TIMEOUT_MS)),\n ]);\n }\n }\n this.sseTransport?.close();\n this.httpTransport?.close();\n // Reject anything still awaiting the (now-dead) transport. Safe to call\n // unconditionally — the stdio exit handler runs failPending too, but\n // close() may be invoked on a never-started or HTTP-only client.\n this.failPending(`MCP \"${this.opts.name}\" closed`);\n this.state = 'disconnected';\n }\n\n private request(\n method: string,\n params: unknown,\n timeoutMs = this.opts.requestTimeoutMs ?? 60_000,\n ): Promise<JsonRpcResponse> {\n const id = this.nextId++;\n const req: JsonRpcRequest = { jsonrpc: '2.0', id, method, params };\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(id);\n reject(\n new Error(`MCP \"${this.opts.name}\" request \"${method}\" timed out after ${timeoutMs}ms`),\n );\n }, timeoutMs);\n this.pending.set(id, {\n resolve: (res) => {\n clearTimeout(timer);\n resolve(res);\n },\n reject: (err) => {\n clearTimeout(timer);\n reject(err);\n },\n timer,\n });\n try {\n this.child?.stdin?.write(JSON.stringify(req) + '\\n');\n } catch (err) {\n const pending = this.pending.get(id);\n this.pending.delete(id);\n if (pending) clearTimeout(pending.timer);\n reject(err);\n }\n });\n }\n\n /**\n * Reject every in-flight {@link request} call. Used when the underlying\n * transport dies — without this, callers awaiting `tools/call` over a\n * killed stdio child or a closed transport would hang indefinitely.\n */\n private failPending(reason: string): void {\n if (this.pending.size === 0) return;\n const err = new Error(reason);\n for (const [, entry] of this.pending) {\n try {\n clearTimeout(entry.timer);\n entry.reject(err);\n } catch {\n /* ignore */\n }\n }\n this.pending.clear();\n }\n\n private async notify(method: string, params: unknown): Promise<void> {\n const req = { jsonrpc: '2.0', method, params };\n const encoded = JSON.stringify(req) + '\\n';\n try {\n const ok = this.child?.stdin?.write(encoded);\n if (!ok) {\n // Only the first caller waits for drain; others just warn and return.\n // This avoids a race where two concurrent notify() calls each start\n // their own drain-wait, then both resolve and the buffer is still full.\n if (this._drainPending) {\n this._lastNotifySkipped = true;\n console.warn(\n `[MCP] notify(\"${method}\") skipped: stdin buffer backpressure (already waiting for drain)`,\n );\n return;\n }\n this._drainPending = true;\n await new Promise<void>((resolve, reject) => {\n const onDrain = () => {\n clearTimeout(timeout);\n this._drainPending = false;\n resolve();\n };\n const onError = (err: Error) => {\n clearTimeout(timeout);\n this._drainPending = false;\n reject(err);\n };\n const timeout = setTimeout(() => {\n this.child?.stdin?.removeListener('drain', onDrain);\n this.child?.stdin?.removeListener('error', onError);\n this._drainPending = false;\n reject(new Error(`MCP notify(\"${method}\") drain timeout`));\n }, 500);\n this.child?.stdin?.once('drain', onDrain);\n this.child?.stdin?.once('error', onError);\n });\n }\n } catch (err) {\n throw new Error(\n `[MCP] notify(\"${method}\") failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n private onData(s: string): void {\n this.rxBuffer += s;\n let idx = this.rxBuffer.indexOf('\\n');\n while (idx !== -1) {\n const line = this.rxBuffer.slice(0, idx).trim();\n this.rxBuffer = this.rxBuffer.slice(idx + 1);\n if (line) this.onLine(line);\n idx = this.rxBuffer.indexOf('\\n');\n }\n }\n\n private onLine(line: string): void {\n let msg: JsonRpcResponse & { method?: string; params?: unknown };\n try {\n msg = JSON.parse(line) as JsonRpcResponse & { method?: string; params?: unknown };\n } catch {\n return;\n }\n if (msg.id !== undefined && this.pending.has(msg.id)) {\n const entry = this.pending.get(msg.id);\n this.pending.delete(msg.id);\n entry?.resolve(msg);\n return;\n }\n // Notifications have a `method` but no `id`. The MCP spec defines\n // `notifications/tools/list_changed` for tool-set invalidation —\n // refresh the cache asynchronously and fire listeners so the\n // registry can re-register the wrapped tools.\n if (typeof msg.method === 'string' && msg.method === 'notifications/tools/list_changed') {\n void this.handleToolsListChanged();\n }\n }\n\n /**\n * L2-C: refresh the cached tool list when the server announces a\n * `tools/list_changed`. Listeners (the registry) re-wrap and\n * re-register. Failures are swallowed — a stale cache is preferable\n * to a hard crash on a transient notification glitch.\n */\n private async handleToolsListChanged(): Promise<void> {\n try {\n const toolsRes = await this.request('tools/list', {});\n const tools = normalizeMCPTools((toolsRes.result as { tools?: unknown } | undefined)?.tools);\n this._tools = tools;\n this._toolsCache = tools;\n for (const listener of this.toolsChangedListeners) {\n try {\n listener(this.opts.name, [...tools]);\n } catch {\n // listeners must be best-effort\n }\n }\n } catch {\n // ignore — keep the existing cache\n }\n }\n\n addToolsChangedListener(listener: ToolsChangedListener): void {\n this.toolsChangedListeners.add(listener);\n }\n\n removeToolsChangedListener(listener: ToolsChangedListener): void {\n this.toolsChangedListeners.delete(listener);\n }\n}\n","import type { Permission, Tool } from '@wrongstack/core';\nimport type { MCPClient, MCPTool } from './client.js';\n\n/**\n * Keywords that indicate a mutating operation.\n * Applied to both the tool name and its inputSchema property names.\n */\nconst MUTATING_RE = /create|update|delete|write|send|set|put|post|patch|remove|rename|move/i;\n\nfunction isMutatingTool(mcpTool: MCPTool): boolean {\n if (MUTATING_RE.test(mcpTool.name)) return true;\n // Check property names in the input schema for mutating intent.\n // e.g. { properties: { createTable: {...}, dropIndex: {...} } }\n const schema = mcpTool.inputSchema;\n if (schema && typeof schema === 'object') {\n const props = (schema as { properties?: Record<string, unknown> }).properties;\n if (props) {\n for (const key of Object.keys(props)) {\n if (MUTATING_RE.test(key)) return true;\n }\n }\n }\n return false;\n}\n\nexport function wrapMCPTool(\n serverName: string,\n mcpTool: MCPTool,\n client: MCPClient,\n permission: Permission = 'confirm',\n): Tool {\n const qualifiedName = `mcp__${serverName}__${mcpTool.name}`;\n return {\n name: qualifiedName,\n description: mcpTool.description ?? `${qualifiedName} (MCP tool)`,\n usageHint: `Tool provided by MCP server \"${serverName}\". ${mcpTool.description ?? ''}`,\n permission,\n mutating: isMutatingTool(mcpTool),\n inputSchema: mcpTool.inputSchema ?? { type: 'object', properties: {} },\n async execute(input, ctx, opts) {\n const res = await client.callTool(mcpTool.name, input);\n if (res.isError) {\n throw new Error(stringify(res.content));\n }\n return stringify(res.content);\n },\n };\n}\n\nfunction stringify(c: unknown): string {\n if (typeof c === 'string') return c;\n if (Array.isArray(c)) {\n return c\n .map((item) => {\n if (item && typeof item === 'object') {\n const t = (item as { type?: string; text?: string }).type;\n if (t === 'text') return (item as { text?: string }).text ?? '';\n return JSON.stringify(item);\n }\n return String(item);\n })\n .join('\\n');\n }\n if (c && typeof c === 'object') {\n if ('text' in (c as Record<string, unknown>)) {\n return String((c as Record<string, unknown>).text);\n }\n return JSON.stringify(c);\n }\n return String(c ?? '');\n}\n","import type { EventBus, Logger, MCPServerConfig, ToolRegistry } from '@wrongstack/core';\nimport { type ConnectionState, MCPClient } from './client.js';\nimport { wrapMCPTool } from './wrap-tool.js';\n\ninterface ServerSlot {\n cfg: MCPServerConfig;\n client?: MCPClient;\n state: ConnectionState;\n toolNames: string[];\n attempts: number;\n /** Set when a reconnect cycle is already running for this slot. */\n reconnectPending: boolean;\n /**\n * L2-B: number of full reconnect *cycles* (where one cycle = one\n * `attemptConnect` invocation, which itself can try multiple times\n * before giving up). After `MAX_RECONNECT_CYCLES`, the slot stays\n * `failed` until a manual `restart()` resets it.\n */\n reconnectCycles: number;\n /**\n * Slot-scoped, bound disconnect callback. Stored so the matching\n * `removeDisconnectListener` call can hand back the *same* reference —\n * a fresh arrow `() => onTransportDisconnect(slot.cfg.name)` would\n * not match the one we added and the set-based listener registry\n * would silently keep the old handler, causing duplicate reconnect\n * cycles after a few transport flaps.\n */\n onDisconnect?: () => void;\n}\n\nexport interface MCPRegistryOptions {\n toolRegistry: ToolRegistry;\n events: EventBus;\n log: Logger;\n}\n\nexport class MCPRegistry {\n private readonly servers = new Map<string, ServerSlot>();\n private readonly toolRegistry: ToolRegistry;\n private readonly events: EventBus;\n private readonly log: Logger;\n\n constructor(opts: MCPRegistryOptions) {\n this.toolRegistry = opts.toolRegistry;\n this.events = opts.events;\n this.log = opts.log;\n }\n\n async start(cfg: MCPServerConfig): Promise<void> {\n if (cfg.enabled === false) return;\n const slot: ServerSlot = {\n cfg,\n state: 'idle',\n toolNames: [],\n attempts: 0,\n reconnectPending: false,\n reconnectCycles: 0,\n };\n this.servers.set(cfg.name, slot);\n await this.attemptConnect(slot);\n }\n\n async stop(name: string): Promise<void> {\n const slot = this.servers.get(name);\n if (!slot) return;\n slot.reconnectPending = false;\n if (slot.client) {\n slot.client.removeExitListener(this.onChildExit);\n if (slot.onDisconnect) slot.client.removeDisconnectListener(slot.onDisconnect);\n slot.client.removeToolsChangedListener(this.onToolsChanged);\n await slot.client.close();\n slot.client = undefined;\n }\n slot.onDisconnect = undefined;\n for (const t of slot.toolNames) this.toolRegistry.unregister(t);\n slot.toolNames = [];\n slot.state = 'disconnected';\n this.events.emit('mcp.server.disconnected', { name, reason: 'stop' });\n }\n\n async restart(name: string): Promise<void> {\n const slot = this.servers.get(name);\n if (!slot) throw new Error(`MCP server \"${name}\" not registered`);\n await this.stop(name);\n slot.attempts = 0;\n slot.reconnectCycles = 0; // user intent: start fresh\n await this.attemptConnect(slot);\n }\n\n list(): { name: string; state: ConnectionState; toolCount: number }[] {\n return Array.from(this.servers.values()).map((s) => ({\n name: s.cfg.name,\n state: s.state,\n toolCount: s.toolNames.length,\n }));\n }\n\n async stopAll(): Promise<void> {\n for (const name of Array.from(this.servers.keys())) {\n await this.stop(name);\n }\n }\n\n /**\n * Health check — returns 'ok' for connected servers, the current state otherwise.\n * For HTTP-based transports this could also ping the server.\n */\n health(): { name: string; alive: boolean; latencyMs?: number }[] {\n return Array.from(this.servers.values()).map((s) => ({\n name: s.cfg.name,\n alive: s.state === 'connected',\n }));\n }\n\n /**\n * L2-C: handle `notifications/tools/list_changed` from the server.\n * Unregister the previous wrapper set, then re-register the fresh\n * tool list. The client has already refreshed its cache before\n * dispatching — we just need to re-wrap and re-register.\n */\n private readonly onToolsChanged = (name: string, _tools: { name: string }[]): void => {\n const slot = this.servers.get(name);\n if (!slot || !slot.client) return;\n for (const t of slot.toolNames) {\n try {\n this.toolRegistry.unregister(t);\n } catch {\n /* ignore */\n }\n }\n slot.toolNames = [];\n const allowed = slot.cfg.allowedTools;\n const wrapped = slot.client\n .listTools()\n .filter((t) => !allowed || allowed.includes(t.name))\n .map((t) => wrapMCPTool(slot.cfg.name, t, slot.client!, slot.cfg.permission ?? 'confirm'));\n for (const tool of wrapped) {\n try {\n this.toolRegistry.register(tool, `mcp:${slot.cfg.name}`);\n slot.toolNames.push(tool.name);\n } catch (err) {\n this.log.warn(`MCP tool \"${tool.name}\" not re-registered after list_changed`, err);\n }\n }\n this.events.emit('mcp.server.connected', {\n name: slot.cfg.name,\n toolCount: slot.toolNames.length,\n });\n this.log.info(\n `MCP server \"${slot.cfg.name}\" tools refreshed (${slot.toolNames.length} active)`,\n );\n };\n\n private readonly onChildExit = (\n name: string,\n code: number | null,\n _signal: string | null,\n ): void => {\n const slot = this.servers.get(name);\n if (!slot) return;\n for (const t of slot.toolNames) {\n try {\n this.toolRegistry.unregister(t);\n } catch {\n /* ignore */\n }\n }\n slot.toolNames = [];\n slot.state = 'disconnected';\n this.events.emit('mcp.server.disconnected', { name, reason: `exit:${code ?? 'unknown'}` });\n this.scheduleReconnect(slot);\n };\n\n /** Handles SSE / streamable-http disconnect — same recovery as stdio child exit. */\n private readonly onTransportDisconnect = (name: string): void => {\n const slot = this.servers.get(name);\n if (!slot) return;\n for (const t of slot.toolNames) {\n try {\n this.toolRegistry.unregister(t);\n } catch {\n /* ignore */\n }\n }\n slot.toolNames = [];\n slot.state = 'disconnected';\n this.events.emit('mcp.server.disconnected', { name, reason: 'http-disconnect' });\n this.scheduleReconnect(slot);\n };\n\n /**\n * L2-B: maximum number of reconnect cycles before staying `failed`.\n * One cycle = one full `attemptConnect` (which itself may try up to 3\n * times). Caps total reconnect storm at ~5 cycles, then the slot\n * needs an explicit `restart()` to re-engage.\n */\n private static readonly MAX_RECONNECT_CYCLES = 5;\n /** Base delay between cycles, in ms. Real delay adds jitter. */\n private static readonly BASE_RECONNECT_DELAY_MS = 1000;\n /** Hard ceiling on the inter-cycle delay so the user doesn't wait minutes. */\n private static readonly MAX_RECONNECT_DELAY_MS = 30_000;\n\n private scheduleReconnect(slot: ServerSlot): void {\n if (slot.reconnectPending) return;\n if (slot.reconnectCycles >= MCPRegistry.MAX_RECONNECT_CYCLES) {\n slot.state = 'failed';\n this.log.error(\n `MCP server \"${slot.cfg.name}\" giving up after ${slot.reconnectCycles} reconnect cycles. Use \\`/mcp restart ${slot.cfg.name}\\` to retry.`,\n );\n this.events.emit('mcp.server.disconnected', {\n name: slot.cfg.name,\n reason: `reconnect-exhausted:${slot.reconnectCycles}`,\n });\n return;\n }\n slot.reconnectPending = true;\n // Exponential backoff with light jitter: 1s, 2s, 4s, 8s, 16s, capped\n // at 30s. The ±20% jitter avoids reconnect stampedes when many\n // servers crash together.\n const base = Math.min(\n MCPRegistry.BASE_RECONNECT_DELAY_MS * 2 ** slot.reconnectCycles,\n MCPRegistry.MAX_RECONNECT_DELAY_MS,\n );\n const jitter = base * 0.2 * (Math.random() * 2 - 1);\n const delay = Math.max(100, Math.round(base + jitter));\n setTimeout(() => this.attemptReconnect(slot), delay);\n }\n\n private async attemptReconnect(slot: ServerSlot): Promise<void> {\n slot.reconnectPending = false;\n slot.reconnectCycles++;\n await this.attemptConnect(slot);\n }\n\n private async attemptConnect(slot: ServerSlot): Promise<void> {\n const MAX_ATTEMPTS = 3;\n let attempt = 0;\n while (attempt < MAX_ATTEMPTS) {\n attempt++;\n slot.state = attempt === 1 ? 'connecting' : 'reconnecting';\n slot.attempts = attempt;\n let client: MCPClient | undefined;\n let boundDisconnect: (() => void) | undefined;\n try {\n client = new MCPClient({\n name: slot.cfg.name,\n transport: slot.cfg.transport,\n command: slot.cfg.command,\n args: slot.cfg.args,\n env: slot.cfg.env,\n url: slot.cfg.url,\n headers: slot.cfg.headers,\n startupTimeoutMs: slot.cfg.startupTimeoutMs,\n requestTimeoutMs: slot.cfg.requestTimeoutMs,\n });\n if (slot.cfg.transport === 'stdio') {\n client.addExitListener(this.onChildExit);\n } else {\n // SSE / streamable-http — wire transport disconnect to registry reconnect.\n // Capture the bound function so we can hand the same reference to\n // removeDisconnectListener on cleanup paths.\n boundDisconnect = () => this.onTransportDisconnect(slot.cfg.name);\n client.addDisconnectListener(boundDisconnect);\n }\n // L2-C: react to server-side tool changes by re-registering wrappers.\n client.addToolsChangedListener(this.onToolsChanged);\n await client.connect();\n // Close any prior client before swapping refs so the old transport\n // can release its abort controller, child process, and listeners\n // instead of being held until GC.\n if (slot.client && slot.client !== client) {\n const prior = slot.client;\n const priorDisconnect = slot.onDisconnect;\n slot.client.removeExitListener(this.onChildExit);\n if (priorDisconnect) prior.removeDisconnectListener(priorDisconnect);\n prior.removeToolsChangedListener(this.onToolsChanged);\n prior.close().catch(() => {\n /* best-effort */\n });\n }\n slot.client = client;\n slot.onDisconnect = boundDisconnect;\n const isReconnect = attempt > 1;\n slot.state = 'connected';\n // L2-B: a healthy connect resets the cycle counter so future\n // crashes get the full reconnect budget again.\n slot.reconnectCycles = 0;\n const allowed = slot.cfg.allowedTools;\n // Prefer cached tools to avoid a round-trip to the server on reconnect.\n // The cache is populated by client.listTools() on first connect.\n const mc = client as MCPClient;\n const candidateTools = mc.listTools();\n const toWrap = candidateTools.length > 0 ? candidateTools : mc.listTools(); // fallback — in practice both return the same list\n const wrapped = toWrap\n .filter((t) => !allowed || allowed.includes(t.name))\n .map((t) => wrapMCPTool(slot.cfg.name, t, mc, slot.cfg.permission ?? 'confirm'));\n for (const tool of wrapped) {\n try {\n this.toolRegistry.register(tool, `mcp:${slot.cfg.name}`);\n slot.toolNames.push(tool.name);\n } catch (err) {\n this.log.warn(`MCP tool \"${tool.name}\" not registered`, err);\n }\n }\n this.events.emit(isReconnect ? 'mcp.server.reconnected' : 'mcp.server.connected', {\n name: slot.cfg.name,\n toolCount: slot.toolNames.length,\n });\n return; // success\n } catch (err) {\n this.log.warn(`MCP server \"${slot.cfg.name}\" connect attempt ${attempt} failed`, err);\n if (client) {\n client.removeExitListener(this.onChildExit);\n if (boundDisconnect) client.removeDisconnectListener(boundDisconnect);\n client.removeToolsChangedListener(this.onToolsChanged);\n await client.close().catch(() => {\n /* ignore */\n });\n }\n if (attempt >= MAX_ATTEMPTS) {\n this.log.error(\n `MCP server \"${slot.cfg.name}\" connect exhausted after ${MAX_ATTEMPTS} attempts`,\n err,\n );\n slot.state = 'failed';\n slot.client = undefined;\n this.events.emit('mcp.server.disconnected', {\n name: slot.cfg.name,\n reason: err instanceof Error ? err.message : 'unknown',\n });\n return;\n }\n const delay = 500 * 2 ** attempt;\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/mcp",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack Model Context Protocol client and registry: stdio, SSE, and streamable HTTP transports.",
6
6
  "repository": {
@@ -25,7 +25,7 @@
25
25
  "dist"
26
26
  ],
27
27
  "dependencies": {
28
- "@wrongstack/core": "0.3.2"
28
+ "@wrongstack/core": "0.3.4"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "^22.19.19",