@wrongstack/mcp 0.295.0 → 0.295.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type ChildProcess } from 'node:child_process';
1
2
  import type { MCPAuthorizationProvider } from './authorization.js';
2
3
  import { type MCPGetPromptResult, type MCPListPromptsResult, type MCPListResourcesResult, type MCPListResourceTemplatesResult, type MCPReadResourceResult, type MCPServerMetadata } from './protocol.js';
3
4
  export type Transport = 'stdio' | 'sse' | 'streamable-http';
@@ -58,6 +59,14 @@ type ExitListener = (name: string, code: number | null, signal: string | null) =
58
59
  */
59
60
  type ToolsChangedListener = (name: string, tools: MCPTool[]) => void;
60
61
  export type MCPListChangedListener = (name: string) => void;
62
+ /**
63
+ * Force-kill a child and its descendants. On Windows a stdio server is launched
64
+ * through a `.cmd` shim with `shell: true`, so `child` is the `cmd.exe` wrapper
65
+ * and the real server (npx→node / uvx) is its grandchild — `child.kill('SIGKILL')`
66
+ * signals only the wrapper and orphans the server, which then accumulates across
67
+ * every close / restart / idle-sleep. `taskkill /T /F` tears down the whole tree.
68
+ */
69
+ export declare function forceKillTree(child: ChildProcess): void;
61
70
  /**
62
71
  * Lightweight MCP client supporting three transport types:
63
72
  * - stdio: spawns a child process and communicates over pipes
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ function parseMcpBearerChallenge(header, resource) {
47
47
  if (!header) return challenge;
48
48
  const bearer = /(?:^|,)\s*Bearer(?:\s+|$)/i.exec(header);
49
49
  if (!bearer) return challenge;
50
- const parameters = header.slice((bearer.index ?? 0) + bearer[0].length);
50
+ const parameters = header.slice(bearer.index + bearer[0].length);
51
51
  const resourceMetadata = challengeParameter(parameters, "resource_metadata");
52
52
  if (resourceMetadata) {
53
53
  const metadataUrl = validateMetadataUrl(resourceMetadata);
@@ -395,7 +395,7 @@ async function requestPinnedJson(rawUrl, options) {
395
395
  };
396
396
  const requestFn = url.protocol === "https:" ? https.request : http.request;
397
397
  const request3 = requestFn(requestOptions, (response) => {
398
- const status = response.statusCode ?? 0;
398
+ const status = response.statusCode;
399
399
  if (status === 404 || status === 410) {
400
400
  response.resume();
401
401
  finish(void 0, void 0);
@@ -739,8 +739,7 @@ function boundedServerName(value) {
739
739
 
740
740
  // src/client.ts
741
741
  import { spawn } from "node:child_process";
742
- import { buildChildEnv } from "@wrongstack/core/utils";
743
- import { toErrorMessage } from "@wrongstack/core/utils";
742
+ import { buildChildEnv, toErrorMessage } from "@wrongstack/core/utils";
744
743
 
745
744
  // src/constants.ts
746
745
  var MCP_CONSTANTS = Object.freeze({
@@ -997,13 +996,15 @@ function normalizeMCPTools(value) {
997
996
  if (typeof t.name !== "string" || t.name.trim().length === 0) continue;
998
997
  const inputSchema = t.inputSchema && typeof t.inputSchema === "object" && !Array.isArray(t.inputSchema) ? t.inputSchema : { type: "object", properties: {} };
999
998
  if (!t.inputSchema || typeof t.inputSchema !== "object" || Array.isArray(t.inputSchema)) {
1000
- console.warn(JSON.stringify({
1001
- level: "warn",
1002
- event: "mcp.tool_schema_invalid",
1003
- tool: t.name,
1004
- message: "no/invalid inputSchema \u2014 defaulting to empty object",
1005
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1006
- }));
999
+ console.warn(
1000
+ JSON.stringify({
1001
+ level: "warn",
1002
+ event: "mcp.tool_schema_invalid",
1003
+ tool: t.name,
1004
+ message: "no/invalid inputSchema \u2014 defaulting to empty object",
1005
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1006
+ })
1007
+ );
1007
1008
  }
1008
1009
  tools.push({
1009
1010
  name: t.name,
@@ -1014,96 +1015,8 @@ function normalizeMCPTools(value) {
1014
1015
  return tools;
1015
1016
  }
1016
1017
 
1017
- // src/transport-jsonrpc.ts
1018
- import { ToolError } from "@wrongstack/core/types";
1019
- function isJsonRpcResult(v) {
1020
- if (typeof v !== "object" || v === null) return false;
1021
- const r = v;
1022
- if (r["jsonrpc"] !== "2.0" || typeof r["id"] !== "number") return false;
1023
- if (Object.hasOwn(r, "method")) return false;
1024
- const hasResult = Object.hasOwn(r, "result");
1025
- const hasError = Object.hasOwn(r, "error");
1026
- if (hasResult === hasError) return false;
1027
- if (hasError) {
1028
- const error = r["error"];
1029
- return typeof error === "object" && error !== null && typeof error["code"] === "number" && typeof error["message"] === "string";
1030
- }
1031
- return true;
1032
- }
1033
- function isJsonRpcMethodEnvelope(v) {
1034
- if (typeof v !== "object" || v === null) return false;
1035
- const envelope = v;
1036
- if (envelope["jsonrpc"] !== "2.0" || typeof envelope["method"] !== "string") return false;
1037
- const id = envelope["id"];
1038
- return id === void 0 || typeof id === "number" || typeof id === "string";
1039
- }
1040
- function extractJsonRpcEnvelopes(text) {
1041
- const out = [];
1042
- let dataBuf = [];
1043
- const flush = () => {
1044
- if (dataBuf.length === 0) return;
1045
- const joined = dataBuf.join("\n").trim();
1046
- dataBuf = [];
1047
- if (!joined) return;
1048
- try {
1049
- const parsed = JSON.parse(joined);
1050
- if (isJsonRpcResult(parsed) || isJsonRpcMethodEnvelope(parsed)) out.push(parsed);
1051
- } catch {
1052
- }
1053
- };
1054
- for (const raw of text.split("\n")) {
1055
- const line = raw.replace(/\r$/, "");
1056
- if (line === "") {
1057
- flush();
1058
- continue;
1059
- }
1060
- if (line.startsWith(":")) continue;
1061
- if (line.startsWith("data:")) {
1062
- let v = line.slice(5);
1063
- if (v.startsWith(" ")) v = v.slice(1);
1064
- dataBuf.push(v);
1065
- continue;
1066
- }
1067
- if (line.startsWith("event:") || line.startsWith("id:") || line.startsWith("retry:")) {
1068
- continue;
1069
- }
1070
- const trimmed = line.trim();
1071
- if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
1072
- try {
1073
- const parsed = JSON.parse(trimmed);
1074
- if (isJsonRpcResult(parsed) || isJsonRpcMethodEnvelope(parsed)) out.push(parsed);
1075
- } catch {
1076
- }
1077
- }
1078
- }
1079
- flush();
1080
- return out;
1081
- }
1082
- function extractJsonRpcResults(text) {
1083
- return extractJsonRpcEnvelopes(text).filter(isJsonRpcResult);
1084
- }
1085
- function assertMatchingJsonRpcResult(data, expectedId, method) {
1086
- if (!isJsonRpcResult(data)) {
1087
- throw new ToolError({
1088
- message: "Invalid JSON-RPC response: not a JSON-RPC 2.0 envelope",
1089
- code: "TOOL_EXECUTION_FAILED",
1090
- toolName: "mcp_transport_jsonrpc",
1091
- context: { method, expectedId, reason: "not-jsonrpc-envelope" }
1092
- });
1093
- }
1094
- if (data.id !== expectedId) {
1095
- throw new ToolError({
1096
- message: `Invalid JSON-RPC response: id mismatch for ${method} (expected ${expectedId}, got ${data.id})`,
1097
- code: "TOOL_EXECUTION_FAILED",
1098
- toolName: "mcp_transport_jsonrpc",
1099
- context: { method, expectedId, actualId: data.id, reason: "id-mismatch" }
1100
- });
1101
- }
1102
- return data;
1103
- }
1104
-
1105
1018
  // src/sse-reader.ts
1106
- import { ToolError as ToolError2 } from "@wrongstack/core/types";
1019
+ import { ToolError } from "@wrongstack/core/types";
1107
1020
  var SSE_READER_MAX_BUFFER = 256 * 1024;
1108
1021
  var SSE_READER_MAX_DATA_LINES = 1024;
1109
1022
  var SSEReader = class {
@@ -1119,7 +1032,7 @@ var SSEReader = class {
1119
1032
  }
1120
1033
  feed(chunk) {
1121
1034
  if (chunk.length > SSE_READER_MAX_BUFFER) {
1122
- throw new ToolError2({
1035
+ throw new ToolError({
1123
1036
  message: `SSE: chunk size ${chunk.length} exceeds max buffer ${SSE_READER_MAX_BUFFER} \u2014 refusing to accumulate`,
1124
1037
  code: "TOOL_EXECUTION_FAILED",
1125
1038
  toolName: "mcp_transport_sse_reader",
@@ -1128,7 +1041,7 @@ var SSEReader = class {
1128
1041
  }
1129
1042
  this.buffer += chunk;
1130
1043
  if (this.buffer.length > SSE_READER_MAX_BUFFER) {
1131
- throw new ToolError2({
1044
+ throw new ToolError({
1132
1045
  message: `SSE: pending line exceeds ${SSE_READER_MAX_BUFFER} bytes \u2014 upstream is not framing events`,
1133
1046
  code: "TOOL_EXECUTION_FAILED",
1134
1047
  toolName: "mcp_transport_sse_reader",
@@ -1163,7 +1076,7 @@ var SSEReader = class {
1163
1076
  if (field === "event") {
1164
1077
  } else if (field === "data") {
1165
1078
  if (this.dataLines.length >= SSE_READER_MAX_DATA_LINES) {
1166
- throw new ToolError2({
1079
+ throw new ToolError({
1167
1080
  message: `SSE: exceeded ${SSE_READER_MAX_DATA_LINES} data lines per event \u2014 upstream is not sending blank-line delimiters`,
1168
1081
  code: "TOOL_EXECUTION_FAILED",
1169
1082
  toolName: "mcp_transport_sse_reader",
@@ -1453,9 +1366,133 @@ var BaseHTTPTransport = class {
1453
1366
  }
1454
1367
  };
1455
1368
 
1369
+ // src/transport-jsonrpc.ts
1370
+ import { ToolError as ToolError2 } from "@wrongstack/core/types";
1371
+ function isJsonRpcResult(v) {
1372
+ if (typeof v !== "object" || v === null) return false;
1373
+ const r = v;
1374
+ if (r["jsonrpc"] !== "2.0" || typeof r["id"] !== "number") return false;
1375
+ if (Object.hasOwn(r, "method")) return false;
1376
+ const hasResult = Object.hasOwn(r, "result");
1377
+ const hasError = Object.hasOwn(r, "error");
1378
+ if (hasResult === hasError) return false;
1379
+ if (hasError) {
1380
+ const error = r["error"];
1381
+ return typeof error === "object" && error !== null && typeof error["code"] === "number" && typeof error["message"] === "string";
1382
+ }
1383
+ return true;
1384
+ }
1385
+ function isJsonRpcMethodEnvelope(v) {
1386
+ if (typeof v !== "object" || v === null) return false;
1387
+ const envelope = v;
1388
+ if (envelope["jsonrpc"] !== "2.0" || typeof envelope["method"] !== "string") return false;
1389
+ const id = envelope["id"];
1390
+ return id === void 0 || typeof id === "number" || typeof id === "string";
1391
+ }
1392
+ function extractJsonRpcEnvelopes(text) {
1393
+ const out = [];
1394
+ let dataBuf = [];
1395
+ const flush = () => {
1396
+ if (dataBuf.length === 0) return;
1397
+ const joined = dataBuf.join("\n").trim();
1398
+ dataBuf = [];
1399
+ if (!joined) return;
1400
+ try {
1401
+ const parsed = JSON.parse(joined);
1402
+ if (isJsonRpcResult(parsed) || isJsonRpcMethodEnvelope(parsed)) out.push(parsed);
1403
+ } catch {
1404
+ }
1405
+ };
1406
+ for (const raw of text.split("\n")) {
1407
+ const line = raw.replace(/\r$/, "");
1408
+ if (line === "") {
1409
+ flush();
1410
+ continue;
1411
+ }
1412
+ if (line.startsWith(":")) continue;
1413
+ if (line.startsWith("data:")) {
1414
+ let v = line.slice(5);
1415
+ if (v.startsWith(" ")) v = v.slice(1);
1416
+ dataBuf.push(v);
1417
+ continue;
1418
+ }
1419
+ if (line.startsWith("event:") || line.startsWith("id:") || line.startsWith("retry:")) {
1420
+ continue;
1421
+ }
1422
+ const trimmed = line.trim();
1423
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
1424
+ try {
1425
+ const parsed = JSON.parse(trimmed);
1426
+ if (isJsonRpcResult(parsed) || isJsonRpcMethodEnvelope(parsed)) out.push(parsed);
1427
+ } catch {
1428
+ }
1429
+ }
1430
+ }
1431
+ flush();
1432
+ return out;
1433
+ }
1434
+ function extractJsonRpcResults(text) {
1435
+ return extractJsonRpcEnvelopes(text).filter(isJsonRpcResult);
1436
+ }
1437
+ function assertMatchingJsonRpcResult(data, expectedId, method) {
1438
+ if (!isJsonRpcResult(data)) {
1439
+ throw new ToolError2({
1440
+ message: "Invalid JSON-RPC response: not a JSON-RPC 2.0 envelope",
1441
+ code: "TOOL_EXECUTION_FAILED",
1442
+ toolName: "mcp_transport_jsonrpc",
1443
+ context: { method, expectedId, reason: "not-jsonrpc-envelope" }
1444
+ });
1445
+ }
1446
+ if (data.id !== expectedId) {
1447
+ throw new ToolError2({
1448
+ message: `Invalid JSON-RPC response: id mismatch for ${method} (expected ${expectedId}, got ${data.id})`,
1449
+ code: "TOOL_EXECUTION_FAILED",
1450
+ toolName: "mcp_transport_jsonrpc",
1451
+ context: { method, expectedId, actualId: data.id, reason: "id-mismatch" }
1452
+ });
1453
+ }
1454
+ return data;
1455
+ }
1456
+
1456
1457
  // src/transport-sse.ts
1457
1458
  import { randomBytes as randomBytes2 } from "node:crypto";
1459
+ import { ToolError as ToolError4 } from "@wrongstack/core/types";
1460
+
1461
+ // src/read-body.ts
1458
1462
  import { ToolError as ToolError3 } from "@wrongstack/core/types";
1463
+ var MAX_MCP_HTTP_BODY_BYTES = 16 * 1024 * 1024;
1464
+ async function readBodyCapped(res, maxBytes = MAX_MCP_HTTP_BODY_BYTES) {
1465
+ const body = res.body;
1466
+ if (!body || typeof body.getReader !== "function") {
1467
+ return await res.text();
1468
+ }
1469
+ const reader = body.getReader();
1470
+ const chunks = [];
1471
+ let total = 0;
1472
+ try {
1473
+ for (; ; ) {
1474
+ const { done, value } = await reader.read();
1475
+ if (done) break;
1476
+ if (!value) continue;
1477
+ total += value.byteLength;
1478
+ if (total > maxBytes) {
1479
+ await reader.cancel().catch(() => void 0);
1480
+ throw new ToolError3({
1481
+ message: `MCP response body exceeded ${maxBytes} bytes \u2014 refusing to buffer`,
1482
+ code: "TOOL_EXECUTION_FAILED",
1483
+ toolName: "mcp_transport",
1484
+ context: { maxBytes, received: total }
1485
+ });
1486
+ }
1487
+ chunks.push(value);
1488
+ }
1489
+ } finally {
1490
+ reader.releaseLock?.();
1491
+ }
1492
+ return Buffer.concat(chunks).toString("utf8");
1493
+ }
1494
+
1495
+ // src/transport-sse.ts
1459
1496
  var SSETransport = class extends BaseHTTPTransport {
1460
1497
  _nextId = 1;
1461
1498
  readerDone = false;
@@ -1502,7 +1539,7 @@ var SSETransport = class extends BaseHTTPTransport {
1502
1539
  this.applyTlsAgent(fetchOpts);
1503
1540
  const response = await this.fetchWithAuthorization(sseUrl, fetchOpts, signal);
1504
1541
  if (!response.ok) {
1505
- throw new ToolError3({
1542
+ throw new ToolError4({
1506
1543
  message: `SSE connect HTTP ${response.status}: ${response.statusText}`,
1507
1544
  code: "TOOL_EXECUTION_FAILED",
1508
1545
  toolName: "mcp_transport_sse_connect",
@@ -1510,7 +1547,7 @@ var SSETransport = class extends BaseHTTPTransport {
1510
1547
  });
1511
1548
  }
1512
1549
  if (!response.body) {
1513
- throw new ToolError3({
1550
+ throw new ToolError4({
1514
1551
  message: "SSE response has no body",
1515
1552
  code: "TOOL_EXECUTION_FAILED",
1516
1553
  toolName: "mcp_transport_sse_connect",
@@ -1543,7 +1580,7 @@ var SSETransport = class extends BaseHTTPTransport {
1543
1580
  clientInfo: MCP_CONSTANTS.CLIENT_INFO
1544
1581
  });
1545
1582
  if (initRes.error) {
1546
- throw new ToolError3({
1583
+ throw new ToolError4({
1547
1584
  message: `initialize failed: ${initRes.error.message}`,
1548
1585
  code: "TOOL_EXECUTION_FAILED",
1549
1586
  toolName: "mcp_transport_initialize",
@@ -1618,7 +1655,7 @@ var SSETransport = class extends BaseHTTPTransport {
1618
1655
  const body2 = await res.text();
1619
1656
  const cap = MCP_CONSTANTS.REQUEST_LOG_CAP;
1620
1657
  const snippet = body2.length > cap ? `${body2.slice(0, cap)}\u2026 [${body2.length} bytes total]` : body2;
1621
- throw new ToolError3({
1658
+ throw new ToolError4({
1622
1659
  message: `HTTP ${res.status}: ${snippet}`,
1623
1660
  code: "TOOL_EXECUTION_FAILED",
1624
1661
  toolName: method,
@@ -1627,9 +1664,9 @@ var SSETransport = class extends BaseHTTPTransport {
1627
1664
  }
1628
1665
  let data;
1629
1666
  try {
1630
- data = await res.json();
1667
+ data = JSON.parse(await readBodyCapped(res));
1631
1668
  } catch (err) {
1632
- throw new ToolError3({
1669
+ throw new ToolError4({
1633
1670
  message: `Invalid JSON-RPC response: ${err instanceof Error ? err.message : "parse failed"}`,
1634
1671
  code: "TOOL_EXECUTION_FAILED",
1635
1672
  toolName: method,
@@ -1654,7 +1691,7 @@ var SSETransport = class extends BaseHTTPTransport {
1654
1691
  }
1655
1692
  async callTool(name, input, opts) {
1656
1693
  if (this.state !== "connected") {
1657
- throw new ToolError3({
1694
+ throw new ToolError4({
1658
1695
  message: `SSE transport not connected (state=${this.state})`,
1659
1696
  code: "TOOL_EXECUTION_FAILED",
1660
1697
  toolName: name,
@@ -1691,7 +1728,7 @@ var SSETransport = class extends BaseHTTPTransport {
1691
1728
  try {
1692
1729
  const res = await this.fetchWithAuthorization(this.url, fetchOpts, timeoutSignal.signal);
1693
1730
  if (!res.ok) {
1694
- throw new ToolError3({
1731
+ throw new ToolError4({
1695
1732
  message: `HTTP ${res.status}: ${res.statusText}`,
1696
1733
  code: "TOOL_EXECUTION_FAILED",
1697
1734
  toolName: method,
@@ -1705,9 +1742,9 @@ var SSETransport = class extends BaseHTTPTransport {
1705
1742
  }
1706
1743
  let data;
1707
1744
  try {
1708
- data = await res.json();
1745
+ data = JSON.parse(await readBodyCapped(res));
1709
1746
  } catch (err) {
1710
- throw new ToolError3({
1747
+ throw new ToolError4({
1711
1748
  message: `Invalid JSON-RPC response: ${err instanceof Error ? err.message : "parse failed"}`,
1712
1749
  code: "TOOL_EXECUTION_FAILED",
1713
1750
  toolName: method,
@@ -1767,7 +1804,7 @@ var StreamableHTTPTransport = class extends BaseHTTPTransport {
1767
1804
  }
1768
1805
  }
1769
1806
  const responses = envelopes.filter(isJsonRpcResult);
1770
- return responses.find((envelope) => envelope.id === requestId) ?? responses.find((envelope) => envelope.id !== void 0) ?? responses[0];
1807
+ return responses.find((envelope) => envelope.id === requestId) ?? responses[0];
1771
1808
  }
1772
1809
  handleNotification(method) {
1773
1810
  if (method === "notifications/resources/list_changed") {
@@ -1886,9 +1923,9 @@ var StreamableHTTPTransport = class extends BaseHTTPTransport {
1886
1923
  }
1887
1924
  if (method.startsWith("notifications/")) {
1888
1925
  await res.text().catch(() => void 0);
1889
- return { jsonrpc: "2.0" };
1926
+ return { jsonrpc: "2.0", id };
1890
1927
  }
1891
- const match = this.consumeResponseText(await res.text(), id);
1928
+ const match = this.consumeResponseText(await readBodyCapped(res), id);
1892
1929
  if (match) {
1893
1930
  return assertMatchingJsonRpcResult(match, id, method);
1894
1931
  }
@@ -1935,7 +1972,7 @@ var StreamableHTTPTransport = class extends BaseHTTPTransport {
1935
1972
  await res.text().catch(() => void 0);
1936
1973
  return { jsonrpc: "2.0", id };
1937
1974
  }
1938
- const parsed = this.consumeResponseText(await res.text(), id);
1975
+ const parsed = this.consumeResponseText(await readBodyCapped(res), id);
1939
1976
  if (parsed) {
1940
1977
  return {
1941
1978
  jsonrpc: "2.0",
@@ -1982,17 +2019,32 @@ var StreamableHTTPTransport = class extends BaseHTTPTransport {
1982
2019
  };
1983
2020
 
1984
2021
  // src/client.ts
1985
- function isJsonRpcResponse(value) {
1986
- if (typeof value !== "object" || value === null) return false;
1987
- const response = value;
1988
- if (response["jsonrpc"] !== "2.0" || typeof response["id"] !== "number") return false;
1989
- if (Object.hasOwn(response, "method")) return false;
1990
- const hasResult = Object.hasOwn(response, "result");
1991
- const hasError = Object.hasOwn(response, "error");
1992
- if (hasResult === hasError) return false;
1993
- if (!hasError) return true;
1994
- const error = response["error"];
1995
- return typeof error === "object" && error !== null && typeof error["code"] === "number" && typeof error["message"] === "string";
2022
+ function forceKillTree(child) {
2023
+ if (child.pid === void 0) {
2024
+ try {
2025
+ child.kill("SIGKILL");
2026
+ } catch {
2027
+ }
2028
+ return;
2029
+ }
2030
+ if (process.platform === "win32") {
2031
+ const killer = spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
2032
+ stdio: "ignore",
2033
+ windowsHide: true
2034
+ });
2035
+ killer.once("error", () => {
2036
+ try {
2037
+ child.kill("SIGKILL");
2038
+ } catch {
2039
+ }
2040
+ });
2041
+ killer.unref();
2042
+ return;
2043
+ }
2044
+ try {
2045
+ child.kill("SIGKILL");
2046
+ } catch {
2047
+ }
1996
2048
  }
1997
2049
  var MCPClient = class _MCPClient {
1998
2050
  constructor(opts) {
@@ -2386,10 +2438,7 @@ var MCPClient = class _MCPClient {
2386
2438
  new Promise((resolve) => setTimeout(() => resolve("timeout"), GRACEFUL_MS))
2387
2439
  ]);
2388
2440
  if (gracefulRace === "timeout") {
2389
- try {
2390
- child.kill("SIGKILL");
2391
- } catch {
2392
- }
2441
+ forceKillTree(child);
2393
2442
  await Promise.race([
2394
2443
  exitPromise,
2395
2444
  new Promise((resolve) => setTimeout(resolve, FORCE_TIMEOUT_MS))
@@ -2618,11 +2667,12 @@ var MCPClient = class _MCPClient {
2618
2667
  }
2619
2668
  return;
2620
2669
  }
2621
- if (!isJsonRpcResponse(msg)) return;
2622
- if (this.pending.has(msg.id)) {
2623
- const entry = this.pending.get(msg.id);
2624
- this.pending.delete(msg.id);
2625
- entry?.resolve(msg);
2670
+ if (!isJsonRpcResult(msg)) return;
2671
+ const response = msg;
2672
+ if (this.pending.has(response.id)) {
2673
+ const entry = this.pending.get(response.id);
2674
+ this.pending.delete(response.id);
2675
+ entry?.resolve(response);
2626
2676
  }
2627
2677
  }
2628
2678
  handleServerRequest(request3) {
@@ -2856,7 +2906,7 @@ async function writeConfig(path2, cfg) {
2856
2906
  try {
2857
2907
  await fs.rename(tmp, path2);
2858
2908
  } catch (err) {
2859
- await fs.rm(tmp, { force: true }).catch(() => void 0);
2909
+ await fs.rm(tmp, { force: true });
2860
2910
  throw err;
2861
2911
  }
2862
2912
  }
@@ -3096,7 +3146,7 @@ function forgetRegistryState(registry, name) {
3096
3146
  }
3097
3147
 
3098
3148
  // src/manifest-cache.ts
3099
- import { createHash as createHash2 } from "node:crypto";
3149
+ import { createHash as createHash2, randomBytes as randomBytes4 } from "node:crypto";
3100
3150
  import * as fs2 from "node:fs/promises";
3101
3151
  import * as path from "node:path";
3102
3152
  function manifestConfigHash(cfg) {
@@ -3144,9 +3194,14 @@ async function writeCapabilityManifest(cacheDir, name, configHash, manifest) {
3144
3194
  const file = manifestFile(cacheDir, name);
3145
3195
  await fs2.mkdir(path.dirname(file), { recursive: true });
3146
3196
  const body = { version: 2, configHash, ...manifest };
3147
- const tmp = `${file}.tmp`;
3148
- await fs2.writeFile(tmp, JSON.stringify(body, null, 2), "utf8");
3149
- await fs2.rename(tmp, file);
3197
+ const tmp = `${file}.${process.pid}.${randomBytes4(6).toString("hex")}.tmp`;
3198
+ try {
3199
+ await fs2.writeFile(tmp, JSON.stringify(body, null, 2), "utf8");
3200
+ await fs2.rename(tmp, file);
3201
+ } catch (err) {
3202
+ await fs2.rm(tmp, { force: true });
3203
+ throw err;
3204
+ }
3150
3205
  } catch {
3151
3206
  }
3152
3207
  }
@@ -3207,7 +3262,10 @@ function evaluateHealthThresholds(operations, thresholds) {
3207
3262
  if (!thresholds) return [];
3208
3263
  const checks = [];
3209
3264
  if (thresholds.connectionLatencyP95Ms !== void 0 && operations.connectionSamples.length > 0) {
3210
- const value = percentile([...operations.connectionSamples].sort((a, b) => a - b), 0.95);
3265
+ const value = percentile(
3266
+ [...operations.connectionSamples].sort((a, b) => a - b),
3267
+ 0.95
3268
+ );
3211
3269
  checks.push({
3212
3270
  name: "connection-latency-p95",
3213
3271
  passed: value <= thresholds.connectionLatencyP95Ms,
@@ -3216,7 +3274,10 @@ function evaluateHealthThresholds(operations, thresholds) {
3216
3274
  });
3217
3275
  }
3218
3276
  if (thresholds.discoveryLatencyP95Ms !== void 0 && operations.discoverySamples.length > 0) {
3219
- const value = percentile([...operations.discoverySamples].sort((a, b) => a - b), 0.95);
3277
+ const value = percentile(
3278
+ [...operations.discoverySamples].sort((a, b) => a - b),
3279
+ 0.95
3280
+ );
3220
3281
  checks.push({
3221
3282
  name: "discovery-latency-p95",
3222
3283
  passed: value <= thresholds.discoveryLatencyP95Ms,
@@ -3225,7 +3286,10 @@ function evaluateHealthThresholds(operations, thresholds) {
3225
3286
  });
3226
3287
  }
3227
3288
  if (thresholds.callLatencyP95Ms !== void 0 && operations.callSamples.length > 0) {
3228
- const value = percentile([...operations.callSamples].sort((a, b) => a - b), 0.95);
3289
+ const value = percentile(
3290
+ [...operations.callSamples].sort((a, b) => a - b),
3291
+ 0.95
3292
+ );
3229
3293
  checks.push({
3230
3294
  name: "call-latency-p95",
3231
3295
  passed: value <= thresholds.callLatencyP95Ms,
@@ -3461,11 +3525,7 @@ var MCPRegistry = class _MCPRegistry {
3461
3525
  * cache yet, do a one-time cold discovery connect to learn + cache the tools.
3462
3526
  */
3463
3527
  async startLazy(slot) {
3464
- const cacheDir = this.cacheDir;
3465
- if (!cacheDir) {
3466
- await this.attemptConnect(slot);
3467
- return;
3468
- }
3528
+ const cacheDir = expectDefined(this.cacheDir);
3469
3529
  const hash = manifestConfigHash(slot.cfg);
3470
3530
  const cached = await readCapabilityManifest(cacheDir, slot.cfg.name, hash);
3471
3531
  if (cached) {
@@ -4303,8 +4363,7 @@ function catalogSnapshot(slot) {
4303
4363
 
4304
4364
  // src/server.ts
4305
4365
  import { createServer } from "node:http";
4306
- import { expectDefined as expectDefined2 } from "@wrongstack/core/utils";
4307
- import { toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
4366
+ import { expectDefined as expectDefined2, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
4308
4367
  var PARSE_ERROR = -32700;
4309
4368
  var INVALID_REQUEST = -32600;
4310
4369
  var METHOD_NOT_FOUND = -32601;
@@ -4629,8 +4688,7 @@ function serveHttp(server, opts = {}) {
4629
4688
  httpServer.once("error", reject);
4630
4689
  httpServer.listen(port, host, () => {
4631
4690
  httpServer.removeListener("error", reject);
4632
- const addr = httpServer.address();
4633
- const boundPort = typeof addr === "object" && addr ? addr.port : port;
4691
+ const boundPort = httpServer.address().port;
4634
4692
  const displayHost = host === "::1" ? "[::1]" : host;
4635
4693
  resolve({
4636
4694
  port: boundPort,
@@ -4662,18 +4720,14 @@ async function handleHttpRequest(server, req, res, token, log) {
4662
4720
  }
4663
4721
  }
4664
4722
  let body = "";
4665
- let tooLarge = false;
4666
4723
  req.on("data", (chunk) => {
4667
- if (tooLarge) return;
4668
4724
  body += chunk.toString("utf8");
4669
4725
  if (body.length > HTTP_BODY_CAP) {
4670
- tooLarge = true;
4671
4726
  send(413, JSON.stringify({ error: "payload too large" }));
4672
4727
  req.destroy();
4673
4728
  }
4674
4729
  });
4675
4730
  req.on("end", () => {
4676
- if (tooLarge) return;
4677
4731
  void server.handleMessage(body).then((out) => {
4678
4732
  if (out === null) return send(202, "");
4679
4733
  return send(200, out);