@ai-ecoverse/mcpcat 0.14.2 → 0.14.3

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
@@ -14,7 +14,7 @@ Or via npm:
14
14
  npm install -g @ai-ecoverse/mcpcat
15
15
  ```
16
16
 
17
- mcpcat runs natively on macOS, Linux and Windows (Node ≥ 24), and inside Sliccy Seven as a kernel program, with the same flags, the same output and the same config file in both places.
17
+ mcpcat runs natively on macOS, Linux and Windows (Node ≥ 24), and inside Sliccy Seven as a kernel program, with the same flags, the same output and the same config file in both places. Orphan-free shutdown of stdio server trees in the kernel needs slicc-kernel ≥ 1.74.0; on older kernels only the direct child is signalled.
18
18
 
19
19
  ## Quick start
20
20
 
@@ -8011,6 +8011,40 @@ var StreamableHttpTransport = class extends TransportEvents {
8011
8011
  }
8012
8012
  };
8013
8013
 
8014
+ // src/client/stdio-registry.ts
8015
+ var GRACE_MS = 2e3;
8016
+ var registry = /* @__PURE__ */ new Set();
8017
+ function trackStdio(proc) {
8018
+ registry.add(proc);
8019
+ void proc.wait().then(
8020
+ () => registry.delete(proc),
8021
+ () => registry.delete(proc)
8022
+ );
8023
+ }
8024
+ async function killAllStdio() {
8025
+ const procs = [...registry];
8026
+ if (procs.length === 0) return;
8027
+ await Promise.all(
8028
+ procs.map(async (proc) => {
8029
+ try {
8030
+ await proc.kill("SIGTERM");
8031
+ } catch {
8032
+ }
8033
+ const exited = await Promise.race([
8034
+ proc.wait().then(() => true),
8035
+ new Promise((r) => setTimeout(() => r(false), GRACE_MS))
8036
+ ]);
8037
+ if (!exited) {
8038
+ try {
8039
+ await proc.kill("SIGKILL");
8040
+ } catch {
8041
+ }
8042
+ }
8043
+ })
8044
+ );
8045
+ registry.clear();
8046
+ }
8047
+
8014
8048
  // src/client/platform-stdio-transport.ts
8015
8049
  var DEFAULT_MAX_MESSAGE_BYTES2 = 4 * 1024 * 1024;
8016
8050
  var DEFAULT_MAX_STDERR_BYTES2 = 64 * 1024;
@@ -8067,16 +8101,21 @@ var PlatformStdioTransport = class {
8067
8101
  if (this.started) throw new Error("MCP stdio transport already started");
8068
8102
  if (this.closed) throw new Error("MCP connection closed");
8069
8103
  this.started = true;
8070
- const env = this.options.inheritEnv === false ? { ...this.options.env ?? {} } : {
8071
- ...this.options.platform.env,
8072
- ...this.options.env
8073
- };
8074
- this.process = await this.options.platform.spawn({
8075
- argv: [this.options.command, ...this.options.args ?? []],
8076
- env,
8077
- cwd: this.options.cwd
8078
- });
8079
- void this.readStdout();
8104
+ if (this.options.existingProcess) {
8105
+ this.process = this.options.existingProcess;
8106
+ } else {
8107
+ const env = this.options.inheritEnv === false ? { ...this.options.env ?? {} } : {
8108
+ ...this.options.platform.env,
8109
+ ...this.options.env
8110
+ };
8111
+ this.process = await this.options.platform.spawn({
8112
+ argv: [this.options.command, ...this.options.args ?? []],
8113
+ env,
8114
+ cwd: this.options.cwd
8115
+ });
8116
+ trackStdio(this.process);
8117
+ }
8118
+ void this.readStdout(this.options.pendingStdout);
8080
8119
  void this.readStderr();
8081
8120
  void this.waitForExit();
8082
8121
  }
@@ -8109,22 +8148,22 @@ var PlatformStdioTransport = class {
8109
8148
  }
8110
8149
  const exited = await Promise.race([done, delay(grace)]);
8111
8150
  if (!exited) {
8112
- proc.kill("SIGTERM");
8151
+ await proc.kill("SIGTERM");
8113
8152
  const exitedAfterTerm = await Promise.race([done, delay(closeTimeoutMs)]);
8114
8153
  if (!exitedAfterTerm) {
8115
- proc.kill("SIGKILL");
8154
+ await proc.kill("SIGKILL");
8116
8155
  await done;
8117
8156
  }
8118
8157
  }
8119
- proc.kill("SIGTERM");
8158
+ await proc.kill("SIGTERM");
8120
8159
  this.emitClose();
8121
8160
  }
8122
- async readStdout() {
8161
+ async readStdout(pending) {
8123
8162
  const proc = this.process;
8124
8163
  if (!proc) return;
8125
8164
  const reader = proc.stdout.getReader();
8126
8165
  const maxBytes = this.options.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES2;
8127
- let buffer = "";
8166
+ let buffer = pending ?? "";
8128
8167
  try {
8129
8168
  for (; ; ) {
8130
8169
  const { done, value } = await reader.read();
@@ -8184,6 +8223,10 @@ var PlatformStdioTransport = class {
8184
8223
  await proc.wait();
8185
8224
  } catch {
8186
8225
  }
8226
+ try {
8227
+ await proc.kill("SIGTERM");
8228
+ } catch {
8229
+ }
8187
8230
  if (!this.closed) {
8188
8231
  this.emitClose();
8189
8232
  }
@@ -8525,7 +8568,9 @@ function buildTransport(options) {
8525
8568
  cwd: options.cwd,
8526
8569
  inheritEnv: true,
8527
8570
  platform: options.platform,
8528
- onStderr: buildStderrHandler(options)
8571
+ onStderr: buildStderrHandler(options),
8572
+ existingProcess: options.existingProcess?.proc,
8573
+ pendingStdout: options.existingProcess?.pendingStdout
8529
8574
  });
8530
8575
  }
8531
8576
  return new StdioTransport({
@@ -8712,6 +8757,9 @@ function createStdioJsonRpc(proc, platform2, options) {
8712
8757
  reader.releaseLock();
8713
8758
  } catch {
8714
8759
  }
8760
+ },
8761
+ pendingBuffer() {
8762
+ return readBuffer;
8715
8763
  }
8716
8764
  };
8717
8765
  }
@@ -8764,13 +8812,13 @@ function buildConnectionMethods(rpc, discoverResult2, proc) {
8764
8812
  async close() {
8765
8813
  rpc.close();
8766
8814
  try {
8767
- proc.kill("SIGTERM");
8815
+ await proc.kill("SIGTERM");
8768
8816
  } catch {
8769
8817
  }
8770
8818
  }
8771
8819
  };
8772
8820
  }
8773
- async function createStdioStatelessConnection(options) {
8821
+ async function probeStdioStateless(options) {
8774
8822
  const inheritedEnv = {
8775
8823
  ...options.platform.env,
8776
8824
  ...options.env
@@ -8780,22 +8828,30 @@ async function createStdioStatelessConnection(options) {
8780
8828
  env: inheritedEnv,
8781
8829
  cwd: options.cwd
8782
8830
  });
8783
- void readStderr(proc, options.verbose);
8831
+ trackStdio(proc);
8784
8832
  const rpc = createStdioJsonRpc(proc, options.platform, {
8785
8833
  version: options.version,
8786
8834
  timeoutMs: options.timeoutMs,
8787
8835
  signal: options.signal,
8788
8836
  verbose: options.verbose
8789
8837
  });
8790
- const discoverRaw = await rpc.request("server/discover", {
8791
- protocolVersion: PROTOCOL_VERSION
8792
- });
8838
+ let discoverRaw;
8839
+ try {
8840
+ discoverRaw = await rpc.request("server/discover", {
8841
+ protocolVersion: PROTOCOL_VERSION
8842
+ });
8843
+ } catch (err) {
8844
+ const pending = rpc.pendingBuffer();
8845
+ rpc.close();
8846
+ return { proc, pendingStdout: pending, error: err };
8847
+ }
8848
+ void readStderr(proc, options.verbose);
8793
8849
  const discoverResult2 = discoverRaw;
8794
8850
  const supported = (discoverResult2?.supportedVersions ?? []).filter(
8795
8851
  (v) => typeof v === "string"
8796
8852
  );
8797
8853
  if (!supported.includes(PROTOCOL_VERSION)) {
8798
- proc.kill("SIGTERM");
8854
+ await proc.kill("SIGTERM");
8799
8855
  throw new Error(
8800
8856
  `Server does not support ${PROTOCOL_VERSION} (advertised: ${supported.join(", ") || "none"})`
8801
8857
  );
@@ -8829,25 +8885,37 @@ async function connect(platform2, options) {
8829
8885
  platform: platform2
8830
8886
  };
8831
8887
  if (options.command) {
8888
+ let fallbackProcess;
8832
8889
  if (!options.protocolVersion || options.protocolVersion.startsWith("2026")) {
8833
- try {
8834
- return await createStdioStatelessConnection({
8835
- command: options.command,
8836
- args: options.args,
8837
- env: options.env,
8838
- cwd: options.cwd,
8839
- platform: platform2,
8840
- version: options.version,
8841
- timeoutMs: options.timeoutMs,
8842
- signal: options.signal,
8843
- verbose: options.verbose
8844
- });
8845
- } catch (err) {
8846
- const isMethodNotFound = err instanceof StatelessRpcError && err.code === -32601;
8847
- const isUnsupported = err instanceof Error && err.message.includes("does not support");
8848
- if (options.protocolVersion?.startsWith("2026")) throw err;
8849
- if (!isMethodNotFound && !isUnsupported) throw err;
8890
+ const result = await probeStdioStateless({
8891
+ command: options.command,
8892
+ args: options.args,
8893
+ env: options.env,
8894
+ cwd: options.cwd,
8895
+ platform: platform2,
8896
+ version: options.version,
8897
+ timeoutMs: options.timeoutMs,
8898
+ signal: options.signal,
8899
+ verbose: options.verbose
8900
+ });
8901
+ if (!("proc" in result)) return result;
8902
+ const isMethodNotFound = result.error instanceof StatelessRpcError && result.error.code === -32601;
8903
+ const isUnsupported = result.error.message.includes("does not support");
8904
+ if (options.protocolVersion?.startsWith("2026")) {
8905
+ try {
8906
+ await result.proc.kill("SIGTERM");
8907
+ } catch {
8908
+ }
8909
+ throw result.error;
8910
+ }
8911
+ if (!isMethodNotFound && !isUnsupported) {
8912
+ try {
8913
+ await result.proc.kill("SIGTERM");
8914
+ } catch {
8915
+ }
8916
+ throw result.error;
8850
8917
  }
8918
+ fallbackProcess = { proc: result.proc, pendingStdout: result.pendingStdout };
8851
8919
  }
8852
8920
  return createPiConnection({
8853
8921
  command: options.command,
@@ -8855,6 +8923,7 @@ async function connect(platform2, options) {
8855
8923
  env: options.env,
8856
8924
  cwd: options.cwd,
8857
8925
  roots: options.roots,
8926
+ existingProcess: fallbackProcess,
8858
8927
  ...shared
8859
8928
  });
8860
8929
  }
@@ -12129,7 +12198,7 @@ function capOutput(value, limit) {
12129
12198
  ${value.slice(value.length - half)}`;
12130
12199
  }
12131
12200
  var inflightProcs = /* @__PURE__ */ new Set();
12132
- async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd) {
12201
+ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd, signal) {
12133
12202
  let proc;
12134
12203
  try {
12135
12204
  proc = await platform2.spawn({
@@ -12168,23 +12237,41 @@ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs,
12168
12237
  const timer = new Promise(
12169
12238
  (resolve) => setTimeout(() => resolve("timeout"), timeoutMs)
12170
12239
  );
12240
+ const abortPromise = signal ? new Promise((resolve) => {
12241
+ if (signal.aborted) {
12242
+ resolve("timeout");
12243
+ return;
12244
+ }
12245
+ signal.addEventListener("abort", () => resolve("timeout"), { once: true });
12246
+ }) : null;
12171
12247
  const work = Promise.all([
12172
12248
  readStream3(proc.stdout, stdoutChunks),
12173
12249
  readStream3(proc.stderr, stderrChunks),
12174
12250
  proc.wait()
12175
12251
  ]);
12176
- const result = await Promise.race([work, timer]);
12252
+ const racers = [
12253
+ work,
12254
+ timer
12255
+ ];
12256
+ if (abortPromise !== null) racers.push(abortPromise);
12257
+ const result = await Promise.race(racers);
12177
12258
  if (result === "timeout") {
12178
- proc.kill("SIGTERM");
12179
- await new Promise((resolve) => setTimeout(resolve, 5e3));
12180
- try {
12181
- proc.kill("SIGKILL");
12182
- } catch {
12259
+ await proc.kill("SIGTERM");
12260
+ if (!signal?.aborted) {
12261
+ await new Promise((resolve) => setTimeout(resolve, 5e3));
12262
+ try {
12263
+ await proc.kill("SIGKILL");
12264
+ } catch {
12265
+ }
12183
12266
  }
12184
12267
  inflightProcs.delete(proc);
12185
12268
  return { stdout: "", stderr: "timed out", exitCode: 124 };
12186
12269
  }
12187
12270
  inflightProcs.delete(proc);
12271
+ try {
12272
+ await proc.kill("SIGTERM");
12273
+ } catch {
12274
+ }
12188
12275
  const [, , exitResult] = result;
12189
12276
  const dec = new TextDecoder();
12190
12277
  return {
@@ -12203,25 +12290,31 @@ function concat(chunks) {
12203
12290
  }
12204
12291
  return out;
12205
12292
  }
12293
+ var KILL_GRACE_MS = 2e3;
12206
12294
  async function killInflight() {
12207
- for (const proc of inflightProcs) {
12208
- try {
12209
- proc.kill("SIGTERM");
12210
- } catch {
12211
- }
12212
- }
12213
- if (inflightProcs.size > 0) {
12214
- await new Promise((resolve) => setTimeout(resolve, 5e3));
12215
- for (const proc of inflightProcs) {
12295
+ const procs = [...inflightProcs];
12296
+ if (procs.length === 0) return;
12297
+ await Promise.all(
12298
+ procs.map(async (proc) => {
12216
12299
  try {
12217
- proc.kill("SIGKILL");
12300
+ await proc.kill("SIGTERM");
12218
12301
  } catch {
12219
12302
  }
12220
- }
12221
- }
12303
+ const exited = await Promise.race([
12304
+ proc.wait().then(() => true),
12305
+ new Promise((r) => setTimeout(() => r(false), KILL_GRACE_MS))
12306
+ ]);
12307
+ if (!exited) {
12308
+ try {
12309
+ await proc.kill("SIGKILL");
12310
+ } catch {
12311
+ }
12312
+ }
12313
+ })
12314
+ );
12222
12315
  inflightProcs.clear();
12223
12316
  }
12224
- async function runHelpForCli(platform2, filePath, childEnv, cwd) {
12317
+ async function runHelpForCli(platform2, filePath, childEnv, cwd, signal) {
12225
12318
  const dashed = await runCommand(
12226
12319
  platform2,
12227
12320
  filePath,
@@ -12230,9 +12323,11 @@ async function runHelpForCli(platform2, filePath, childEnv, cwd) {
12230
12323
  void 0,
12231
12324
  1e4,
12232
12325
  MAX_OUTPUT_DEFAULT,
12233
- cwd
12326
+ cwd,
12327
+ signal
12234
12328
  );
12235
12329
  if (dashed.exitCode === 0 && dashed.stdout.trim()) return dashed.stdout;
12330
+ if (signal?.aborted) return "";
12236
12331
  const plain = await runCommand(
12237
12332
  platform2,
12238
12333
  filePath,
@@ -12241,7 +12336,8 @@ async function runHelpForCli(platform2, filePath, childEnv, cwd) {
12241
12336
  void 0,
12242
12337
  1e4,
12243
12338
  MAX_OUTPUT_DEFAULT,
12244
- cwd
12339
+ cwd,
12340
+ signal
12245
12341
  );
12246
12342
  if (plain.exitCode === 0 && plain.stdout.trim()) return plain.stdout;
12247
12343
  return dashed.stdout.trim() ? dashed.stdout : "";
@@ -12268,7 +12364,7 @@ async function expandGroupCommands(platform2, filePath, commands, childEnv, cwd)
12268
12364
  }
12269
12365
  return current;
12270
12366
  }
12271
- async function discoverCli(platform2, filePath, explicitName, childEnv, cwd) {
12367
+ async function discoverCli(platform2, filePath, explicitName, childEnv, cwd, signal) {
12272
12368
  const mcp = await runCommand(
12273
12369
  platform2,
12274
12370
  filePath,
@@ -12277,10 +12373,11 @@ async function discoverCli(platform2, filePath, explicitName, childEnv, cwd) {
12277
12373
  void 0,
12278
12374
  1e4,
12279
12375
  MAX_OUTPUT_DEFAULT,
12280
- cwd
12376
+ cwd,
12377
+ signal
12281
12378
  );
12282
12379
  const override = mcp.exitCode === 0 ? parseMcpOverride(mcp.stdout) : null;
12283
- const helpText2 = override ? "" : await runHelpForCli(platform2, filePath, childEnv, cwd);
12380
+ const helpText2 = override || signal?.aborted ? "" : await runHelpForCli(platform2, filePath, childEnv, cwd, signal);
12284
12381
  if (!override && !helpText2.trim()) {
12285
12382
  throw new Error(`${filePath} did not print help or --mcp descriptor`);
12286
12383
  }
@@ -12400,6 +12497,32 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12400
12497
  }
12401
12498
  return { invoke, rpcTools };
12402
12499
  }
12500
+ async function discoverWithSignal(platform2, commands, childEnv, cwd) {
12501
+ const clis = [];
12502
+ let earlyShutdown = false;
12503
+ let inflightDone;
12504
+ const earlyAbort = new AbortController();
12505
+ const onShutdown = () => {
12506
+ earlyShutdown = true;
12507
+ earlyAbort.abort();
12508
+ inflightDone = killInflight();
12509
+ };
12510
+ platform2.onSignal?.("SIGTERM", onShutdown);
12511
+ platform2.onSignal?.("SIGINT", onShutdown);
12512
+ for (const cmd of commands) {
12513
+ try {
12514
+ const cli = await discoverCli(platform2, cmd.path, cmd.name, childEnv, cwd, earlyAbort.signal);
12515
+ clis.push(cli);
12516
+ } catch (err) {
12517
+ if (earlyShutdown) return { exitCode: 143, inflightDone };
12518
+ await platform2.write(2, `mcpcat serve: ${err.message}
12519
+ `);
12520
+ return { exitCode: 2 };
12521
+ }
12522
+ }
12523
+ if (earlyShutdown) return { exitCode: 143, inflightDone };
12524
+ return { clis };
12525
+ }
12403
12526
  async function runServe(platform2, options, version) {
12404
12527
  let resolvedBearer;
12405
12528
  let generatedBearer = false;
@@ -12443,17 +12566,17 @@ async function runServe(platform2, options, version) {
12443
12566
  }
12444
12567
  const serveCwd = options.cwd ?? platform2.cwd;
12445
12568
  const childEnv = buildChildEnv(platform2, options.envAllow);
12446
- const clis = [];
12447
- for (const cmd of options.commands) {
12448
- try {
12449
- const cli = await discoverCli(platform2, cmd.path, cmd.name, childEnv, serveCwd);
12450
- clis.push(cli);
12451
- } catch (err) {
12452
- await platform2.write(2, `mcpcat serve: ${err.message}
12453
- `);
12454
- return 2;
12569
+ const discovery = await discoverWithSignal(platform2, options.commands, childEnv, serveCwd);
12570
+ if ("exitCode" in discovery) {
12571
+ if (discovery.inflightDone !== void 0) {
12572
+ try {
12573
+ await discovery.inflightDone;
12574
+ } catch {
12575
+ }
12455
12576
  }
12577
+ return discovery.exitCode;
12456
12578
  }
12579
+ const { clis } = discovery;
12457
12580
  const allTools = clis.flatMap((cli) => buildTools(cli.name, cli.commands));
12458
12581
  for (const spec of options.toolTemplates) {
12459
12582
  const tool = parseToolTemplate(spec);
@@ -12679,6 +12802,7 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
12679
12802
  if (platform2.onSignal) {
12680
12803
  platform2.onSignal("SIGINT", shutdown);
12681
12804
  platform2.onSignal("SIGTERM", shutdown);
12805
+ platform2.onSignal("SIGHUP", shutdown);
12682
12806
  }
12683
12807
  const handler = (request) => handleProxyMcpRequest(
12684
12808
  request,
@@ -12838,11 +12962,12 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12838
12962
  await platform2.write(2, `mcpcat serve: listening on ${listenUrl}
12839
12963
  `);
12840
12964
  let shutdownRequested = false;
12965
+ let inflightDone;
12841
12966
  const shutdown = () => {
12842
12967
  if (shutdownRequested) return;
12843
12968
  shutdownRequested = true;
12844
12969
  listener.close();
12845
- void killInflight();
12970
+ inflightDone = killInflight();
12846
12971
  if (tokenFilePath) {
12847
12972
  platform2.fs.unlink?.(tokenFilePath).catch(() => {
12848
12973
  });
@@ -12851,6 +12976,7 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12851
12976
  if (platform2.onSignal) {
12852
12977
  platform2.onSignal("SIGINT", shutdown);
12853
12978
  platform2.onSignal("SIGTERM", shutdown);
12979
+ platform2.onSignal("SIGHUP", shutdown);
12854
12980
  }
12855
12981
  const handler = (request) => handleMcpRequest(
12856
12982
  request,
@@ -12878,6 +13004,12 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12878
13004
  } catch {
12879
13005
  if (!shutdownRequested) throw new Error("listener closed unexpectedly");
12880
13006
  }
13007
+ if (inflightDone !== void 0) {
13008
+ try {
13009
+ await inflightDone;
13010
+ } catch {
13011
+ }
13012
+ }
12881
13013
  return 0;
12882
13014
  }
12883
13015
  async function handleMcpRequest(request, tools, call, serverName, version, serverOrigins, allowedOrigins, allowedHosts, resolvedBearer) {
@@ -15207,6 +15339,10 @@ async function dispatchMultiTarget(platform2, parsed, version) {
15207
15339
  } catch {
15208
15340
  }
15209
15341
  }
15342
+ try {
15343
+ await Promise.race([killAllStdio(), new Promise((r) => setTimeout(r, 3e3))]);
15344
+ } catch {
15345
+ }
15210
15346
  platform2.exit(exitCode);
15211
15347
  }
15212
15348
  platform2.onSignal?.("SIGTERM", () => void killTreeAndExit(143));
@@ -15545,6 +15681,10 @@ async function runClientVerb(platform2, version, parsed) {
15545
15681
  } catch {
15546
15682
  }
15547
15683
  }
15684
+ try {
15685
+ await Promise.race([killAllStdio(), new Promise((r) => setTimeout(r, 3e3))]);
15686
+ } catch {
15687
+ }
15548
15688
  platform2.exit(exitCode);
15549
15689
  }
15550
15690
  platform2.onSignal?.("SIGINT", () => {
@@ -15942,5 +16082,5 @@ try {
15942
16082
  });
15943
16083
  } catch {
15944
16084
  }
15945
- var code = await run(platform, "0.14.2", args);
16085
+ var code = await run(platform, "0.14.3", args);
15946
16086
  process.exit(code);
@@ -7632,6 +7632,40 @@ var StreamableHttpTransport = class extends TransportEvents {
7632
7632
  }
7633
7633
  };
7634
7634
 
7635
+ // src/client/stdio-registry.ts
7636
+ var GRACE_MS = 2e3;
7637
+ var registry = /* @__PURE__ */ new Set();
7638
+ function trackStdio(proc) {
7639
+ registry.add(proc);
7640
+ void proc.wait().then(
7641
+ () => registry.delete(proc),
7642
+ () => registry.delete(proc)
7643
+ );
7644
+ }
7645
+ async function killAllStdio() {
7646
+ const procs = [...registry];
7647
+ if (procs.length === 0) return;
7648
+ await Promise.all(
7649
+ procs.map(async (proc) => {
7650
+ try {
7651
+ await proc.kill("SIGTERM");
7652
+ } catch {
7653
+ }
7654
+ const exited = await Promise.race([
7655
+ proc.wait().then(() => true),
7656
+ new Promise((r) => setTimeout(() => r(false), GRACE_MS))
7657
+ ]);
7658
+ if (!exited) {
7659
+ try {
7660
+ await proc.kill("SIGKILL");
7661
+ } catch {
7662
+ }
7663
+ }
7664
+ })
7665
+ );
7666
+ registry.clear();
7667
+ }
7668
+
7635
7669
  // src/client/platform-stdio-transport.ts
7636
7670
  var DEFAULT_MAX_MESSAGE_BYTES2 = 4 * 1024 * 1024;
7637
7671
  var DEFAULT_MAX_STDERR_BYTES2 = 64 * 1024;
@@ -7688,16 +7722,21 @@ var PlatformStdioTransport = class {
7688
7722
  if (this.started) throw new Error("MCP stdio transport already started");
7689
7723
  if (this.closed) throw new Error("MCP connection closed");
7690
7724
  this.started = true;
7691
- const env2 = this.options.inheritEnv === false ? { ...this.options.env ?? {} } : {
7692
- ...this.options.platform.env,
7693
- ...this.options.env
7694
- };
7695
- this.process = await this.options.platform.spawn({
7696
- argv: [this.options.command, ...this.options.args ?? []],
7697
- env: env2,
7698
- cwd: this.options.cwd
7699
- });
7700
- void this.readStdout();
7725
+ if (this.options.existingProcess) {
7726
+ this.process = this.options.existingProcess;
7727
+ } else {
7728
+ const env2 = this.options.inheritEnv === false ? { ...this.options.env ?? {} } : {
7729
+ ...this.options.platform.env,
7730
+ ...this.options.env
7731
+ };
7732
+ this.process = await this.options.platform.spawn({
7733
+ argv: [this.options.command, ...this.options.args ?? []],
7734
+ env: env2,
7735
+ cwd: this.options.cwd
7736
+ });
7737
+ trackStdio(this.process);
7738
+ }
7739
+ void this.readStdout(this.options.pendingStdout);
7701
7740
  void this.readStderr();
7702
7741
  void this.waitForExit();
7703
7742
  }
@@ -7730,22 +7769,22 @@ var PlatformStdioTransport = class {
7730
7769
  }
7731
7770
  const exited = await Promise.race([done, delay(grace)]);
7732
7771
  if (!exited) {
7733
- proc.kill("SIGTERM");
7772
+ await proc.kill("SIGTERM");
7734
7773
  const exitedAfterTerm = await Promise.race([done, delay(closeTimeoutMs)]);
7735
7774
  if (!exitedAfterTerm) {
7736
- proc.kill("SIGKILL");
7775
+ await proc.kill("SIGKILL");
7737
7776
  await done;
7738
7777
  }
7739
7778
  }
7740
- proc.kill("SIGTERM");
7779
+ await proc.kill("SIGTERM");
7741
7780
  this.emitClose();
7742
7781
  }
7743
- async readStdout() {
7782
+ async readStdout(pending) {
7744
7783
  const proc = this.process;
7745
7784
  if (!proc) return;
7746
7785
  const reader = proc.stdout.getReader();
7747
7786
  const maxBytes = this.options.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES2;
7748
- let buffer = "";
7787
+ let buffer = pending ?? "";
7749
7788
  try {
7750
7789
  for (; ; ) {
7751
7790
  const { done, value } = await reader.read();
@@ -7805,6 +7844,10 @@ var PlatformStdioTransport = class {
7805
7844
  await proc.wait();
7806
7845
  } catch {
7807
7846
  }
7847
+ try {
7848
+ await proc.kill("SIGTERM");
7849
+ } catch {
7850
+ }
7808
7851
  if (!this.closed) {
7809
7852
  this.emitClose();
7810
7853
  }
@@ -8146,7 +8189,9 @@ function buildTransport(options) {
8146
8189
  cwd: options.cwd,
8147
8190
  inheritEnv: true,
8148
8191
  platform: options.platform,
8149
- onStderr: buildStderrHandler(options)
8192
+ onStderr: buildStderrHandler(options),
8193
+ existingProcess: options.existingProcess?.proc,
8194
+ pendingStdout: options.existingProcess?.pendingStdout
8150
8195
  });
8151
8196
  }
8152
8197
  return new StdioTransport({
@@ -8333,6 +8378,9 @@ function createStdioJsonRpc(proc, platform2, options) {
8333
8378
  reader.releaseLock();
8334
8379
  } catch {
8335
8380
  }
8381
+ },
8382
+ pendingBuffer() {
8383
+ return readBuffer;
8336
8384
  }
8337
8385
  };
8338
8386
  }
@@ -8385,13 +8433,13 @@ function buildConnectionMethods(rpc, discoverResult2, proc) {
8385
8433
  async close() {
8386
8434
  rpc.close();
8387
8435
  try {
8388
- proc.kill("SIGTERM");
8436
+ await proc.kill("SIGTERM");
8389
8437
  } catch {
8390
8438
  }
8391
8439
  }
8392
8440
  };
8393
8441
  }
8394
- async function createStdioStatelessConnection(options) {
8442
+ async function probeStdioStateless(options) {
8395
8443
  const inheritedEnv = {
8396
8444
  ...options.platform.env,
8397
8445
  ...options.env
@@ -8401,22 +8449,30 @@ async function createStdioStatelessConnection(options) {
8401
8449
  env: inheritedEnv,
8402
8450
  cwd: options.cwd
8403
8451
  });
8404
- void readStderr(proc, options.verbose);
8452
+ trackStdio(proc);
8405
8453
  const rpc = createStdioJsonRpc(proc, options.platform, {
8406
8454
  version: options.version,
8407
8455
  timeoutMs: options.timeoutMs,
8408
8456
  signal: options.signal,
8409
8457
  verbose: options.verbose
8410
8458
  });
8411
- const discoverRaw = await rpc.request("server/discover", {
8412
- protocolVersion: PROTOCOL_VERSION
8413
- });
8459
+ let discoverRaw;
8460
+ try {
8461
+ discoverRaw = await rpc.request("server/discover", {
8462
+ protocolVersion: PROTOCOL_VERSION
8463
+ });
8464
+ } catch (err) {
8465
+ const pending = rpc.pendingBuffer();
8466
+ rpc.close();
8467
+ return { proc, pendingStdout: pending, error: err };
8468
+ }
8469
+ void readStderr(proc, options.verbose);
8414
8470
  const discoverResult2 = discoverRaw;
8415
8471
  const supported = (discoverResult2?.supportedVersions ?? []).filter(
8416
8472
  (v) => typeof v === "string"
8417
8473
  );
8418
8474
  if (!supported.includes(PROTOCOL_VERSION)) {
8419
- proc.kill("SIGTERM");
8475
+ await proc.kill("SIGTERM");
8420
8476
  throw new Error(
8421
8477
  `Server does not support ${PROTOCOL_VERSION} (advertised: ${supported.join(", ") || "none"})`
8422
8478
  );
@@ -8450,25 +8506,37 @@ async function connect(platform2, options) {
8450
8506
  platform: platform2
8451
8507
  };
8452
8508
  if (options.command) {
8509
+ let fallbackProcess;
8453
8510
  if (!options.protocolVersion || options.protocolVersion.startsWith("2026")) {
8454
- try {
8455
- return await createStdioStatelessConnection({
8456
- command: options.command,
8457
- args: options.args,
8458
- env: options.env,
8459
- cwd: options.cwd,
8460
- platform: platform2,
8461
- version: options.version,
8462
- timeoutMs: options.timeoutMs,
8463
- signal: options.signal,
8464
- verbose: options.verbose
8465
- });
8466
- } catch (err) {
8467
- const isMethodNotFound = err instanceof StatelessRpcError && err.code === -32601;
8468
- const isUnsupported = err instanceof Error && err.message.includes("does not support");
8469
- if (options.protocolVersion?.startsWith("2026")) throw err;
8470
- if (!isMethodNotFound && !isUnsupported) throw err;
8511
+ const result = await probeStdioStateless({
8512
+ command: options.command,
8513
+ args: options.args,
8514
+ env: options.env,
8515
+ cwd: options.cwd,
8516
+ platform: platform2,
8517
+ version: options.version,
8518
+ timeoutMs: options.timeoutMs,
8519
+ signal: options.signal,
8520
+ verbose: options.verbose
8521
+ });
8522
+ if (!("proc" in result)) return result;
8523
+ const isMethodNotFound = result.error instanceof StatelessRpcError && result.error.code === -32601;
8524
+ const isUnsupported = result.error.message.includes("does not support");
8525
+ if (options.protocolVersion?.startsWith("2026")) {
8526
+ try {
8527
+ await result.proc.kill("SIGTERM");
8528
+ } catch {
8529
+ }
8530
+ throw result.error;
8531
+ }
8532
+ if (!isMethodNotFound && !isUnsupported) {
8533
+ try {
8534
+ await result.proc.kill("SIGTERM");
8535
+ } catch {
8536
+ }
8537
+ throw result.error;
8471
8538
  }
8539
+ fallbackProcess = { proc: result.proc, pendingStdout: result.pendingStdout };
8472
8540
  }
8473
8541
  return createPiConnection({
8474
8542
  command: options.command,
@@ -8476,6 +8544,7 @@ async function connect(platform2, options) {
8476
8544
  env: options.env,
8477
8545
  cwd: options.cwd,
8478
8546
  roots: options.roots,
8547
+ existingProcess: fallbackProcess,
8479
8548
  ...shared
8480
8549
  });
8481
8550
  }
@@ -11750,7 +11819,7 @@ function capOutput(value, limit) {
11750
11819
  ${value.slice(value.length - half)}`;
11751
11820
  }
11752
11821
  var inflightProcs = /* @__PURE__ */ new Set();
11753
- async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd) {
11822
+ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd, signal) {
11754
11823
  let proc;
11755
11824
  try {
11756
11825
  proc = await platform2.spawn({
@@ -11789,23 +11858,41 @@ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs,
11789
11858
  const timer = new Promise(
11790
11859
  (resolve2) => setTimeout(() => resolve2("timeout"), timeoutMs)
11791
11860
  );
11861
+ const abortPromise = signal ? new Promise((resolve2) => {
11862
+ if (signal.aborted) {
11863
+ resolve2("timeout");
11864
+ return;
11865
+ }
11866
+ signal.addEventListener("abort", () => resolve2("timeout"), { once: true });
11867
+ }) : null;
11792
11868
  const work = Promise.all([
11793
11869
  readStream3(proc.stdout, stdoutChunks),
11794
11870
  readStream3(proc.stderr, stderrChunks),
11795
11871
  proc.wait()
11796
11872
  ]);
11797
- const result = await Promise.race([work, timer]);
11873
+ const racers = [
11874
+ work,
11875
+ timer
11876
+ ];
11877
+ if (abortPromise !== null) racers.push(abortPromise);
11878
+ const result = await Promise.race(racers);
11798
11879
  if (result === "timeout") {
11799
- proc.kill("SIGTERM");
11800
- await new Promise((resolve2) => setTimeout(resolve2, 5e3));
11801
- try {
11802
- proc.kill("SIGKILL");
11803
- } catch {
11880
+ await proc.kill("SIGTERM");
11881
+ if (!signal?.aborted) {
11882
+ await new Promise((resolve2) => setTimeout(resolve2, 5e3));
11883
+ try {
11884
+ await proc.kill("SIGKILL");
11885
+ } catch {
11886
+ }
11804
11887
  }
11805
11888
  inflightProcs.delete(proc);
11806
11889
  return { stdout: "", stderr: "timed out", exitCode: 124 };
11807
11890
  }
11808
11891
  inflightProcs.delete(proc);
11892
+ try {
11893
+ await proc.kill("SIGTERM");
11894
+ } catch {
11895
+ }
11809
11896
  const [, , exitResult] = result;
11810
11897
  const dec = new TextDecoder();
11811
11898
  return {
@@ -11824,25 +11911,31 @@ function concat(chunks) {
11824
11911
  }
11825
11912
  return out;
11826
11913
  }
11914
+ var KILL_GRACE_MS = 2e3;
11827
11915
  async function killInflight() {
11828
- for (const proc of inflightProcs) {
11829
- try {
11830
- proc.kill("SIGTERM");
11831
- } catch {
11832
- }
11833
- }
11834
- if (inflightProcs.size > 0) {
11835
- await new Promise((resolve2) => setTimeout(resolve2, 5e3));
11836
- for (const proc of inflightProcs) {
11916
+ const procs = [...inflightProcs];
11917
+ if (procs.length === 0) return;
11918
+ await Promise.all(
11919
+ procs.map(async (proc) => {
11837
11920
  try {
11838
- proc.kill("SIGKILL");
11921
+ await proc.kill("SIGTERM");
11839
11922
  } catch {
11840
11923
  }
11841
- }
11842
- }
11924
+ const exited = await Promise.race([
11925
+ proc.wait().then(() => true),
11926
+ new Promise((r) => setTimeout(() => r(false), KILL_GRACE_MS))
11927
+ ]);
11928
+ if (!exited) {
11929
+ try {
11930
+ await proc.kill("SIGKILL");
11931
+ } catch {
11932
+ }
11933
+ }
11934
+ })
11935
+ );
11843
11936
  inflightProcs.clear();
11844
11937
  }
11845
- async function runHelpForCli(platform2, filePath, childEnv, cwd) {
11938
+ async function runHelpForCli(platform2, filePath, childEnv, cwd, signal) {
11846
11939
  const dashed = await runCommand(
11847
11940
  platform2,
11848
11941
  filePath,
@@ -11851,9 +11944,11 @@ async function runHelpForCli(platform2, filePath, childEnv, cwd) {
11851
11944
  void 0,
11852
11945
  1e4,
11853
11946
  MAX_OUTPUT_DEFAULT,
11854
- cwd
11947
+ cwd,
11948
+ signal
11855
11949
  );
11856
11950
  if (dashed.exitCode === 0 && dashed.stdout.trim()) return dashed.stdout;
11951
+ if (signal?.aborted) return "";
11857
11952
  const plain = await runCommand(
11858
11953
  platform2,
11859
11954
  filePath,
@@ -11862,7 +11957,8 @@ async function runHelpForCli(platform2, filePath, childEnv, cwd) {
11862
11957
  void 0,
11863
11958
  1e4,
11864
11959
  MAX_OUTPUT_DEFAULT,
11865
- cwd
11960
+ cwd,
11961
+ signal
11866
11962
  );
11867
11963
  if (plain.exitCode === 0 && plain.stdout.trim()) return plain.stdout;
11868
11964
  return dashed.stdout.trim() ? dashed.stdout : "";
@@ -11889,7 +11985,7 @@ async function expandGroupCommands(platform2, filePath, commands, childEnv, cwd)
11889
11985
  }
11890
11986
  return current;
11891
11987
  }
11892
- async function discoverCli(platform2, filePath, explicitName, childEnv, cwd) {
11988
+ async function discoverCli(platform2, filePath, explicitName, childEnv, cwd, signal) {
11893
11989
  const mcp = await runCommand(
11894
11990
  platform2,
11895
11991
  filePath,
@@ -11898,10 +11994,11 @@ async function discoverCli(platform2, filePath, explicitName, childEnv, cwd) {
11898
11994
  void 0,
11899
11995
  1e4,
11900
11996
  MAX_OUTPUT_DEFAULT,
11901
- cwd
11997
+ cwd,
11998
+ signal
11902
11999
  );
11903
12000
  const override = mcp.exitCode === 0 ? parseMcpOverride(mcp.stdout) : null;
11904
- const helpText2 = override ? "" : await runHelpForCli(platform2, filePath, childEnv, cwd);
12001
+ const helpText2 = override || signal?.aborted ? "" : await runHelpForCli(platform2, filePath, childEnv, cwd, signal);
11905
12002
  if (!override && !helpText2.trim()) {
11906
12003
  throw new Error(`${filePath} did not print help or --mcp descriptor`);
11907
12004
  }
@@ -12021,6 +12118,32 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12021
12118
  }
12022
12119
  return { invoke, rpcTools };
12023
12120
  }
12121
+ async function discoverWithSignal(platform2, commands, childEnv, cwd) {
12122
+ const clis = [];
12123
+ let earlyShutdown = false;
12124
+ let inflightDone;
12125
+ const earlyAbort = new AbortController();
12126
+ const onShutdown = () => {
12127
+ earlyShutdown = true;
12128
+ earlyAbort.abort();
12129
+ inflightDone = killInflight();
12130
+ };
12131
+ platform2.onSignal?.("SIGTERM", onShutdown);
12132
+ platform2.onSignal?.("SIGINT", onShutdown);
12133
+ for (const cmd of commands) {
12134
+ try {
12135
+ const cli = await discoverCli(platform2, cmd.path, cmd.name, childEnv, cwd, earlyAbort.signal);
12136
+ clis.push(cli);
12137
+ } catch (err) {
12138
+ if (earlyShutdown) return { exitCode: 143, inflightDone };
12139
+ await platform2.write(2, `mcpcat serve: ${err.message}
12140
+ `);
12141
+ return { exitCode: 2 };
12142
+ }
12143
+ }
12144
+ if (earlyShutdown) return { exitCode: 143, inflightDone };
12145
+ return { clis };
12146
+ }
12024
12147
  async function runServe(platform2, options, version) {
12025
12148
  let resolvedBearer;
12026
12149
  let generatedBearer = false;
@@ -12064,17 +12187,17 @@ async function runServe(platform2, options, version) {
12064
12187
  }
12065
12188
  const serveCwd = options.cwd ?? platform2.cwd;
12066
12189
  const childEnv = buildChildEnv(platform2, options.envAllow);
12067
- const clis = [];
12068
- for (const cmd of options.commands) {
12069
- try {
12070
- const cli = await discoverCli(platform2, cmd.path, cmd.name, childEnv, serveCwd);
12071
- clis.push(cli);
12072
- } catch (err) {
12073
- await platform2.write(2, `mcpcat serve: ${err.message}
12074
- `);
12075
- return 2;
12190
+ const discovery = await discoverWithSignal(platform2, options.commands, childEnv, serveCwd);
12191
+ if ("exitCode" in discovery) {
12192
+ if (discovery.inflightDone !== void 0) {
12193
+ try {
12194
+ await discovery.inflightDone;
12195
+ } catch {
12196
+ }
12076
12197
  }
12198
+ return discovery.exitCode;
12077
12199
  }
12200
+ const { clis } = discovery;
12078
12201
  const allTools = clis.flatMap((cli) => buildTools(cli.name, cli.commands));
12079
12202
  for (const spec of options.toolTemplates) {
12080
12203
  const tool = parseToolTemplate(spec);
@@ -12300,6 +12423,7 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
12300
12423
  if (platform2.onSignal) {
12301
12424
  platform2.onSignal("SIGINT", shutdown);
12302
12425
  platform2.onSignal("SIGTERM", shutdown);
12426
+ platform2.onSignal("SIGHUP", shutdown);
12303
12427
  }
12304
12428
  const handler = (request) => handleProxyMcpRequest(
12305
12429
  request,
@@ -12459,11 +12583,12 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12459
12583
  await platform2.write(2, `mcpcat serve: listening on ${listenUrl}
12460
12584
  `);
12461
12585
  let shutdownRequested = false;
12586
+ let inflightDone;
12462
12587
  const shutdown = () => {
12463
12588
  if (shutdownRequested) return;
12464
12589
  shutdownRequested = true;
12465
12590
  listener.close();
12466
- void killInflight();
12591
+ inflightDone = killInflight();
12467
12592
  if (tokenFilePath) {
12468
12593
  platform2.fs.unlink?.(tokenFilePath).catch(() => {
12469
12594
  });
@@ -12472,6 +12597,7 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12472
12597
  if (platform2.onSignal) {
12473
12598
  platform2.onSignal("SIGINT", shutdown);
12474
12599
  platform2.onSignal("SIGTERM", shutdown);
12600
+ platform2.onSignal("SIGHUP", shutdown);
12475
12601
  }
12476
12602
  const handler = (request) => handleMcpRequest(
12477
12603
  request,
@@ -12499,6 +12625,12 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12499
12625
  } catch {
12500
12626
  if (!shutdownRequested) throw new Error("listener closed unexpectedly");
12501
12627
  }
12628
+ if (inflightDone !== void 0) {
12629
+ try {
12630
+ await inflightDone;
12631
+ } catch {
12632
+ }
12633
+ }
12502
12634
  return 0;
12503
12635
  }
12504
12636
  async function handleMcpRequest(request, tools, call, serverName, version, serverOrigins, allowedOrigins, allowedHosts, resolvedBearer) {
@@ -14828,6 +14960,10 @@ async function dispatchMultiTarget(platform2, parsed, version) {
14828
14960
  } catch {
14829
14961
  }
14830
14962
  }
14963
+ try {
14964
+ await Promise.race([killAllStdio(), new Promise((r) => setTimeout(r, 3e3))]);
14965
+ } catch {
14966
+ }
14831
14967
  platform2.exit(exitCode);
14832
14968
  }
14833
14969
  platform2.onSignal?.("SIGTERM", () => void killTreeAndExit(143));
@@ -15166,6 +15302,10 @@ async function runClientVerb(platform2, version, parsed) {
15166
15302
  } catch {
15167
15303
  }
15168
15304
  }
15305
+ try {
15306
+ await Promise.race([killAllStdio(), new Promise((r) => setTimeout(r, 3e3))]);
15307
+ } catch {
15308
+ }
15169
15309
  platform2.exit(exitCode);
15170
15310
  }
15171
15311
  platform2.onSignal?.("SIGINT", () => {
@@ -15351,28 +15491,42 @@ function kernelFs(ctx) {
15351
15491
  chmod: ctx.fs.chmod ? (path, mode) => ctx.fs.chmod(path, mode) : void 0
15352
15492
  };
15353
15493
  }
15494
+ var groupSpawnSupported;
15354
15495
  async function kernelSpawn(ctx, options) {
15496
+ const tryGroup = groupSpawnSupported !== false;
15355
15497
  const result = await ctx.spawn({
15356
15498
  argv: options.argv,
15357
15499
  env: options.env,
15358
15500
  cwd: options.cwd,
15359
15501
  stdin: "pipe",
15360
15502
  stdout: "pipe",
15361
- stderr: "pipe"
15503
+ stderr: "pipe",
15504
+ ...tryGroup ? { pgid: 0 } : {}
15362
15505
  });
15363
15506
  const childPid = result.pid;
15507
+ if (groupSpawnSupported === void 0) {
15508
+ try {
15509
+ await ctx.kill(-childPid, "SIGCONT");
15510
+ groupSpawnSupported = true;
15511
+ } catch {
15512
+ groupSpawnSupported = false;
15513
+ }
15514
+ }
15515
+ const useGroupKill = groupSpawnSupported;
15364
15516
  return {
15365
15517
  stdin: result.stdin,
15366
15518
  stdout: result.stdout,
15367
15519
  stderr: result.stderr,
15368
15520
  wait: () => result.wait(),
15369
- kill: (signal) => {
15370
- try {
15371
- ctx.kill(-childPid, signal);
15372
- } catch {
15521
+ kill: async (signal) => {
15522
+ if (useGroupKill) {
15523
+ try {
15524
+ await ctx.kill(-childPid, signal);
15525
+ } catch {
15526
+ }
15373
15527
  }
15374
15528
  try {
15375
- ctx.kill(childPid, signal);
15529
+ await ctx.kill(childPid, signal);
15376
15530
  } catch {
15377
15531
  }
15378
15532
  }
@@ -15592,7 +15746,7 @@ async function main(ctx) {
15592
15746
  packageDir: "/node_modules/@ai-ecoverse/mcpcat"
15593
15747
  });
15594
15748
  const args = ctx.argv.slice(1);
15595
- return run(platform2, "0.14.2", args);
15749
+ return run(platform2, "0.14.3", args);
15596
15750
  }
15597
15751
  export {
15598
15752
  main as default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/mcpcat",
3
- "version": "0.14.2",
3
+ "version": "0.14.3",
4
4
  "description": "A curl for the Model Context Protocol",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -56,7 +56,7 @@
56
56
  "trust:dry": "npx fledgling sync --dry-run -y --skip-publish"
57
57
  },
58
58
  "devDependencies": {
59
- "@ai-ecoverse/slicc-kernel": "1.75.0",
59
+ "@ai-ecoverse/slicc-kernel": "1.76.0",
60
60
  "@ai-ecoverse/slicc-shared-web": "1.13.1",
61
61
  "@biomejs/biome": "2.5.15",
62
62
  "@earendil-works/pi-codemode": "1.2.0",