@ai-ecoverse/mcpcat 0.18.0 → 0.18.2

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.
@@ -11905,7 +11905,40 @@ function parseRequestLine(buf, endPos) {
11905
11905
  return { method, target, headers, headerEnd: endPos + 4 };
11906
11906
  }
11907
11907
  async function handleConnection(readable, writable, handler) {
11908
- const reader = readable.getReader();
11908
+ const raw = readable.getReader();
11909
+ let ahead = null;
11910
+ const parked = [];
11911
+ const reader = {
11912
+ read() {
11913
+ const queued = parked.shift();
11914
+ if (queued) return Promise.resolve(queued);
11915
+ const next = ahead ?? raw.read();
11916
+ ahead = null;
11917
+ return next;
11918
+ }
11919
+ };
11920
+ const watch = async (live, disconnect) => {
11921
+ let held = 0;
11922
+ while (held <= MAX_HEADER_SIZE + MAX_BODY_SIZE) {
11923
+ const pending = ahead ?? raw.read();
11924
+ ahead = pending;
11925
+ let result;
11926
+ try {
11927
+ result = await pending;
11928
+ } catch {
11929
+ if (live.on) disconnect.abort();
11930
+ return;
11931
+ }
11932
+ if (!live.on) return;
11933
+ ahead = null;
11934
+ parked.push(result);
11935
+ if (result.done) {
11936
+ disconnect.abort();
11937
+ return;
11938
+ }
11939
+ held += result.value.length;
11940
+ }
11941
+ };
11909
11942
  const writer = writable.getWriter();
11910
11943
  let buf = new Uint8Array(4096);
11911
11944
  let bufLen = 0;
@@ -11951,7 +11984,16 @@ async function handleConnection(readable, writable, handler) {
11951
11984
  headers: parsed.headers,
11952
11985
  body
11953
11986
  };
11954
- const response = await handler(request);
11987
+ const disconnect = new AbortController();
11988
+ const live = { on: true };
11989
+ void watch(live, disconnect);
11990
+ let response;
11991
+ try {
11992
+ response = await handler(request, disconnect.signal);
11993
+ } finally {
11994
+ live.on = false;
11995
+ }
11996
+ if (disconnect.signal.aborted) break;
11955
11997
  await writeResponse(writer, response);
11956
11998
  const connectionHeader = (parsed.headers.connection ?? "").toLowerCase();
11957
11999
  if (connectionHeader === "close") break;
@@ -11968,7 +12010,7 @@ async function handleConnection(readable, writable, handler) {
11968
12010
  }
11969
12011
  }
11970
12012
  } finally {
11971
- reader.releaseLock();
12013
+ raw.releaseLock();
11972
12014
  try {
11973
12015
  await writer.close();
11974
12016
  } catch {
@@ -12821,7 +12863,8 @@ function capOutput(value, limit) {
12821
12863
  ${value.slice(value.length - half)}`;
12822
12864
  }
12823
12865
  var inflightProcs = /* @__PURE__ */ new Set();
12824
- async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd, signal) {
12866
+ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd, signal, cancel) {
12867
+ if (cancel?.aborted) return { stdout: "", stderr: "cancelled", exitCode: 124 };
12825
12868
  let proc;
12826
12869
  try {
12827
12870
  proc = await platform2.spawn({
@@ -12834,16 +12877,14 @@ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs,
12834
12877
  return { stdout: "", stderr: `spawn failed: ${err.message}`, exitCode: 127 };
12835
12878
  }
12836
12879
  inflightProcs.add(proc);
12837
- if (stdin !== void 0) {
12880
+ const feedStdin = async () => {
12838
12881
  const writer = proc.stdin.getWriter();
12839
- await writer.write(new TextEncoder().encode(stdin));
12840
- await writer.close();
12841
- } else {
12842
12882
  try {
12843
- await proc.stdin.getWriter().close();
12883
+ if (stdin !== void 0) await writer.write(new TextEncoder().encode(stdin));
12884
+ await writer.close();
12844
12885
  } catch {
12845
12886
  }
12846
- }
12887
+ };
12847
12888
  const stdoutChunks = [];
12848
12889
  const stderrChunks = [];
12849
12890
  const readStream3 = async (stream, into) => {
@@ -12858,38 +12899,54 @@ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs,
12858
12899
  r.releaseLock();
12859
12900
  }
12860
12901
  };
12861
- const timer = new Promise(
12862
- (resolve) => setTimeout(() => resolve("timeout"), timeoutMs)
12863
- );
12902
+ let timerId;
12903
+ let onAbort;
12904
+ let onCancel;
12905
+ const timer = new Promise((resolve) => {
12906
+ timerId = setTimeout(() => resolve("timeout"), timeoutMs);
12907
+ });
12864
12908
  const abortPromise = signal ? new Promise((resolve) => {
12865
12909
  if (signal.aborted) {
12866
12910
  resolve("timeout");
12867
12911
  return;
12868
12912
  }
12869
- signal.addEventListener("abort", () => resolve("timeout"), { once: true });
12913
+ onAbort = () => resolve("timeout");
12914
+ signal.addEventListener("abort", onAbort, { once: true });
12915
+ }) : null;
12916
+ const cancelPromise = cancel ? new Promise((resolve) => {
12917
+ if (cancel.aborted) {
12918
+ resolve("cancel");
12919
+ return;
12920
+ }
12921
+ onCancel = () => resolve("cancel");
12922
+ cancel.addEventListener("abort", onCancel, { once: true });
12870
12923
  }) : null;
12871
12924
  const work = Promise.all([
12872
12925
  readStream3(proc.stdout, stdoutChunks),
12873
12926
  readStream3(proc.stderr, stderrChunks),
12874
- proc.wait()
12927
+ proc.wait(),
12928
+ feedStdin()
12875
12929
  ]);
12876
- const racers = [
12877
- work,
12878
- timer
12879
- ];
12930
+ const racers = [work, timer];
12880
12931
  if (abortPromise !== null) racers.push(abortPromise);
12881
- const result = await Promise.race(racers);
12882
- if (result === "timeout") {
12883
- await proc.kill("SIGTERM");
12884
- if (!signal?.aborted) {
12885
- await new Promise((resolve) => setTimeout(resolve, 5e3));
12886
- try {
12887
- await proc.kill("SIGKILL");
12888
- } catch {
12889
- }
12932
+ if (cancelPromise !== null) racers.push(cancelPromise);
12933
+ let result;
12934
+ try {
12935
+ result = await Promise.race(racers);
12936
+ } finally {
12937
+ clearTimeout(timerId);
12938
+ if (onAbort) signal?.removeEventListener("abort", onAbort);
12939
+ if (onCancel) cancel?.removeEventListener("abort", onCancel);
12940
+ }
12941
+ if (result === "timeout" || result === "cancel") {
12942
+ if (signal?.aborted) {
12943
+ await proc.kill("SIGTERM");
12944
+ } else {
12945
+ await terminate(proc, CALL_KILL_GRACE_MS);
12890
12946
  }
12891
12947
  inflightProcs.delete(proc);
12892
- return { stdout: "", stderr: "timed out", exitCode: 124 };
12948
+ const stderr = result === "cancel" ? "cancelled" : "timed out";
12949
+ return { stdout: "", stderr, exitCode: 124 };
12893
12950
  }
12894
12951
  inflightProcs.delete(proc);
12895
12952
  try {
@@ -12915,6 +12972,31 @@ function concat(chunks) {
12915
12972
  return out;
12916
12973
  }
12917
12974
  var KILL_GRACE_MS = 2e3;
12975
+ var CALL_KILL_GRACE_MS = 5e3;
12976
+ async function terminate(proc, graceMs) {
12977
+ try {
12978
+ await proc.kill("SIGTERM");
12979
+ } catch {
12980
+ }
12981
+ let graceId;
12982
+ let exited;
12983
+ try {
12984
+ exited = await Promise.race([
12985
+ proc.wait().then(() => true),
12986
+ new Promise((r) => {
12987
+ graceId = setTimeout(() => r(false), graceMs);
12988
+ })
12989
+ ]);
12990
+ } finally {
12991
+ clearTimeout(graceId);
12992
+ }
12993
+ if (!exited) {
12994
+ try {
12995
+ await proc.kill("SIGKILL");
12996
+ } catch {
12997
+ }
12998
+ }
12999
+ }
12918
13000
  var SIGNAL_EXIT = { SIGINT: 130, SIGTERM: 143, SIGHUP: 129 };
12919
13001
  async function trapShutdown(platform2, handler) {
12920
13002
  await Promise.all(
@@ -12926,24 +13008,7 @@ async function trapShutdown(platform2, handler) {
12926
13008
  async function killInflight() {
12927
13009
  const procs = [...inflightProcs];
12928
13010
  if (procs.length === 0) return;
12929
- await Promise.all(
12930
- procs.map(async (proc) => {
12931
- try {
12932
- await proc.kill("SIGTERM");
12933
- } catch {
12934
- }
12935
- const exited = await Promise.race([
12936
- proc.wait().then(() => true),
12937
- new Promise((r) => setTimeout(() => r(false), KILL_GRACE_MS))
12938
- ]);
12939
- if (!exited) {
12940
- try {
12941
- await proc.kill("SIGKILL");
12942
- } catch {
12943
- }
12944
- }
12945
- })
12946
- );
13011
+ await Promise.all(procs.map((proc) => terminate(proc, KILL_GRACE_MS)));
12947
13012
  inflightProcs.clear();
12948
13013
  }
12949
13014
  async function runHelpForCli(platform2, filePath, childEnv, cwd, signal) {
@@ -13040,7 +13105,7 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
13040
13105
  );
13041
13106
  return run2;
13042
13107
  }
13043
- function invokeTemplateTool(tool, args2) {
13108
+ function invokeTemplateTool(tool, args2, cancel) {
13044
13109
  const templateArgs = {};
13045
13110
  if (args2 && typeof args2 === "object") {
13046
13111
  for (const [k, v] of Object.entries(args2)) {
@@ -13058,11 +13123,13 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
13058
13123
  void 0,
13059
13124
  options.callTimeout,
13060
13125
  options.maxOutput,
13061
- serveCwd
13126
+ serveCwd,
13127
+ void 0,
13128
+ cancel
13062
13129
  )
13063
13130
  );
13064
13131
  }
13065
- async function executeTool(tool, cli, args2) {
13132
+ async function executeTool(tool, cli, args2, cancel) {
13066
13133
  if (tool.kind === "help") {
13067
13134
  const result = await runCommand(
13068
13135
  platform2,
@@ -13072,7 +13139,9 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
13072
13139
  void 0,
13073
13140
  options.callTimeout,
13074
13141
  options.maxOutput,
13075
- serveCwd
13142
+ serveCwd,
13143
+ void 0,
13144
+ cancel
13076
13145
  );
13077
13146
  if (result.exitCode === 0) return result;
13078
13147
  return runCommand(
@@ -13083,7 +13152,9 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
13083
13152
  void 0,
13084
13153
  options.callTimeout,
13085
13154
  options.maxOutput,
13086
- serveCwd
13155
+ serveCwd,
13156
+ void 0,
13157
+ cancel
13087
13158
  );
13088
13159
  }
13089
13160
  if (tool.kind === "invoke") {
@@ -13098,7 +13169,9 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
13098
13169
  parsed2.stdin,
13099
13170
  options.callTimeout,
13100
13171
  options.maxOutput,
13101
- serveCwd
13172
+ serveCwd,
13173
+ void 0,
13174
+ cancel
13102
13175
  );
13103
13176
  }
13104
13177
  const parsed = readToolArguments(args2 ?? {});
@@ -13114,18 +13187,20 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
13114
13187
  planned.stdin,
13115
13188
  options.callTimeout,
13116
13189
  options.maxOutput,
13117
- serveCwd
13190
+ serveCwd,
13191
+ void 0,
13192
+ cancel
13118
13193
  );
13119
13194
  }
13120
- async function invoke(name, args2) {
13195
+ async function invoke(name, args2, cancel) {
13121
13196
  const tool = allTools.find((t) => t.name === name);
13122
13197
  if (!tool) return { stdout: "", stderr: `unknown tool ${name}`, exitCode: 1 };
13123
13198
  if (tool.cli === "" && tool.commandPath.length === 0) {
13124
- return invokeTemplateTool(tool, args2);
13199
+ return invokeTemplateTool(tool, args2, cancel);
13125
13200
  }
13126
13201
  const cli = clis.find((c) => c.name === tool.cli);
13127
13202
  if (!cli) return { stdout: "", stderr: `unknown cli ${tool.cli}`, exitCode: 1 };
13128
- return enqueue(cli.name, () => executeTool(tool, cli, args2));
13203
+ return enqueue(cli.name, () => executeTool(tool, cli, args2, cancel));
13129
13204
  }
13130
13205
  return { invoke, rpcTools };
13131
13206
  }
@@ -13869,10 +13944,13 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
13869
13944
  let tokenFilePath;
13870
13945
  let shutdownRequested = false;
13871
13946
  let inflightDone;
13947
+ const stopCalls = new AbortController();
13948
+ const activeCalls = /* @__PURE__ */ new Set();
13872
13949
  const shutdown = () => {
13873
13950
  if (shutdownRequested) return;
13874
13951
  shutdownRequested = true;
13875
13952
  listener.close();
13953
+ stopCalls.abort();
13876
13954
  inflightDone = killInflight();
13877
13955
  if (tokenFilePath) {
13878
13956
  platform2.fs.unlink?.(tokenFilePath).catch(() => {
@@ -13902,17 +13980,30 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
13902
13980
  await platform2.write(2, `mcpcat serve: listening on ${listenUrl}
13903
13981
  `);
13904
13982
  }
13905
- const handler = (request) => handleMcpRequest(
13906
- request,
13907
- tools,
13908
- call,
13909
- serverName,
13910
- version,
13911
- serverOrigins,
13912
- allowedOrigins,
13913
- allowedHosts,
13914
- resolvedBearer
13915
- );
13983
+ const handler = (request, signal) => {
13984
+ const cancel = new AbortController();
13985
+ const relay = () => cancel.abort();
13986
+ signal.addEventListener("abort", relay, { once: true });
13987
+ stopCalls.signal.addEventListener("abort", relay, { once: true });
13988
+ if (signal.aborted || stopCalls.signal.aborted) relay();
13989
+ const pending = handleMcpRequest(
13990
+ request,
13991
+ tools,
13992
+ (name, args2) => call(name, args2, cancel.signal),
13993
+ serverName,
13994
+ version,
13995
+ serverOrigins,
13996
+ allowedOrigins,
13997
+ allowedHosts,
13998
+ resolvedBearer
13999
+ ).finally(() => {
14000
+ signal.removeEventListener("abort", relay);
14001
+ stopCalls.signal.removeEventListener("abort", relay);
14002
+ activeCalls.delete(pending);
14003
+ });
14004
+ activeCalls.add(pending);
14005
+ return pending;
14006
+ };
13916
14007
  try {
13917
14008
  for await (const connection of listener) {
13918
14009
  if (shutdownRequested) break;
@@ -13934,6 +14025,7 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
13934
14025
  } catch {
13935
14026
  }
13936
14027
  }
14028
+ await Promise.allSettled([...activeCalls]);
13937
14029
  return 0;
13938
14030
  }
13939
14031
  async function handleMcpRequest(request, tools, call, serverName, version, serverOrigins, allowedOrigins, allowedHosts, resolvedBearer) {
@@ -17096,5 +17188,5 @@ try {
17096
17188
  });
17097
17189
  } catch {
17098
17190
  }
17099
- var code = await run(platform, "0.18.0", args);
17191
+ var code = await run(platform, "0.18.2", args);
17100
17192
  process.exit(code);
@@ -11526,7 +11526,40 @@ function parseRequestLine(buf, endPos) {
11526
11526
  return { method, target, headers, headerEnd: endPos + 4 };
11527
11527
  }
11528
11528
  async function handleConnection(readable, writable, handler) {
11529
- const reader = readable.getReader();
11529
+ const raw = readable.getReader();
11530
+ let ahead = null;
11531
+ const parked = [];
11532
+ const reader = {
11533
+ read() {
11534
+ const queued = parked.shift();
11535
+ if (queued) return Promise.resolve(queued);
11536
+ const next = ahead ?? raw.read();
11537
+ ahead = null;
11538
+ return next;
11539
+ }
11540
+ };
11541
+ const watch = async (live, disconnect) => {
11542
+ let held = 0;
11543
+ while (held <= MAX_HEADER_SIZE + MAX_BODY_SIZE) {
11544
+ const pending = ahead ?? raw.read();
11545
+ ahead = pending;
11546
+ let result;
11547
+ try {
11548
+ result = await pending;
11549
+ } catch {
11550
+ if (live.on) disconnect.abort();
11551
+ return;
11552
+ }
11553
+ if (!live.on) return;
11554
+ ahead = null;
11555
+ parked.push(result);
11556
+ if (result.done) {
11557
+ disconnect.abort();
11558
+ return;
11559
+ }
11560
+ held += result.value.length;
11561
+ }
11562
+ };
11530
11563
  const writer = writable.getWriter();
11531
11564
  let buf = new Uint8Array(4096);
11532
11565
  let bufLen = 0;
@@ -11572,7 +11605,16 @@ async function handleConnection(readable, writable, handler) {
11572
11605
  headers: parsed.headers,
11573
11606
  body
11574
11607
  };
11575
- const response = await handler(request);
11608
+ const disconnect = new AbortController();
11609
+ const live = { on: true };
11610
+ void watch(live, disconnect);
11611
+ let response;
11612
+ try {
11613
+ response = await handler(request, disconnect.signal);
11614
+ } finally {
11615
+ live.on = false;
11616
+ }
11617
+ if (disconnect.signal.aborted) break;
11576
11618
  await writeResponse(writer, response);
11577
11619
  const connectionHeader = (parsed.headers.connection ?? "").toLowerCase();
11578
11620
  if (connectionHeader === "close") break;
@@ -11589,7 +11631,7 @@ async function handleConnection(readable, writable, handler) {
11589
11631
  }
11590
11632
  }
11591
11633
  } finally {
11592
- reader.releaseLock();
11634
+ raw.releaseLock();
11593
11635
  try {
11594
11636
  await writer.close();
11595
11637
  } catch {
@@ -12442,7 +12484,8 @@ function capOutput(value, limit) {
12442
12484
  ${value.slice(value.length - half)}`;
12443
12485
  }
12444
12486
  var inflightProcs = /* @__PURE__ */ new Set();
12445
- async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd, signal) {
12487
+ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd, signal, cancel) {
12488
+ if (cancel?.aborted) return { stdout: "", stderr: "cancelled", exitCode: 124 };
12446
12489
  let proc;
12447
12490
  try {
12448
12491
  proc = await platform2.spawn({
@@ -12455,16 +12498,14 @@ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs,
12455
12498
  return { stdout: "", stderr: `spawn failed: ${err.message}`, exitCode: 127 };
12456
12499
  }
12457
12500
  inflightProcs.add(proc);
12458
- if (stdin !== void 0) {
12501
+ const feedStdin = async () => {
12459
12502
  const writer = proc.stdin.getWriter();
12460
- await writer.write(new TextEncoder().encode(stdin));
12461
- await writer.close();
12462
- } else {
12463
12503
  try {
12464
- await proc.stdin.getWriter().close();
12504
+ if (stdin !== void 0) await writer.write(new TextEncoder().encode(stdin));
12505
+ await writer.close();
12465
12506
  } catch {
12466
12507
  }
12467
- }
12508
+ };
12468
12509
  const stdoutChunks = [];
12469
12510
  const stderrChunks = [];
12470
12511
  const readStream3 = async (stream, into) => {
@@ -12479,38 +12520,54 @@ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs,
12479
12520
  r.releaseLock();
12480
12521
  }
12481
12522
  };
12482
- const timer = new Promise(
12483
- (resolve2) => setTimeout(() => resolve2("timeout"), timeoutMs)
12484
- );
12523
+ let timerId;
12524
+ let onAbort;
12525
+ let onCancel;
12526
+ const timer = new Promise((resolve2) => {
12527
+ timerId = setTimeout(() => resolve2("timeout"), timeoutMs);
12528
+ });
12485
12529
  const abortPromise = signal ? new Promise((resolve2) => {
12486
12530
  if (signal.aborted) {
12487
12531
  resolve2("timeout");
12488
12532
  return;
12489
12533
  }
12490
- signal.addEventListener("abort", () => resolve2("timeout"), { once: true });
12534
+ onAbort = () => resolve2("timeout");
12535
+ signal.addEventListener("abort", onAbort, { once: true });
12536
+ }) : null;
12537
+ const cancelPromise = cancel ? new Promise((resolve2) => {
12538
+ if (cancel.aborted) {
12539
+ resolve2("cancel");
12540
+ return;
12541
+ }
12542
+ onCancel = () => resolve2("cancel");
12543
+ cancel.addEventListener("abort", onCancel, { once: true });
12491
12544
  }) : null;
12492
12545
  const work = Promise.all([
12493
12546
  readStream3(proc.stdout, stdoutChunks),
12494
12547
  readStream3(proc.stderr, stderrChunks),
12495
- proc.wait()
12548
+ proc.wait(),
12549
+ feedStdin()
12496
12550
  ]);
12497
- const racers = [
12498
- work,
12499
- timer
12500
- ];
12551
+ const racers = [work, timer];
12501
12552
  if (abortPromise !== null) racers.push(abortPromise);
12502
- const result = await Promise.race(racers);
12503
- if (result === "timeout") {
12504
- await proc.kill("SIGTERM");
12505
- if (!signal?.aborted) {
12506
- await new Promise((resolve2) => setTimeout(resolve2, 5e3));
12507
- try {
12508
- await proc.kill("SIGKILL");
12509
- } catch {
12510
- }
12553
+ if (cancelPromise !== null) racers.push(cancelPromise);
12554
+ let result;
12555
+ try {
12556
+ result = await Promise.race(racers);
12557
+ } finally {
12558
+ clearTimeout(timerId);
12559
+ if (onAbort) signal?.removeEventListener("abort", onAbort);
12560
+ if (onCancel) cancel?.removeEventListener("abort", onCancel);
12561
+ }
12562
+ if (result === "timeout" || result === "cancel") {
12563
+ if (signal?.aborted) {
12564
+ await proc.kill("SIGTERM");
12565
+ } else {
12566
+ await terminate(proc, CALL_KILL_GRACE_MS);
12511
12567
  }
12512
12568
  inflightProcs.delete(proc);
12513
- return { stdout: "", stderr: "timed out", exitCode: 124 };
12569
+ const stderr = result === "cancel" ? "cancelled" : "timed out";
12570
+ return { stdout: "", stderr, exitCode: 124 };
12514
12571
  }
12515
12572
  inflightProcs.delete(proc);
12516
12573
  try {
@@ -12536,6 +12593,31 @@ function concat(chunks) {
12536
12593
  return out;
12537
12594
  }
12538
12595
  var KILL_GRACE_MS = 2e3;
12596
+ var CALL_KILL_GRACE_MS = 5e3;
12597
+ async function terminate(proc, graceMs) {
12598
+ try {
12599
+ await proc.kill("SIGTERM");
12600
+ } catch {
12601
+ }
12602
+ let graceId;
12603
+ let exited;
12604
+ try {
12605
+ exited = await Promise.race([
12606
+ proc.wait().then(() => true),
12607
+ new Promise((r) => {
12608
+ graceId = setTimeout(() => r(false), graceMs);
12609
+ })
12610
+ ]);
12611
+ } finally {
12612
+ clearTimeout(graceId);
12613
+ }
12614
+ if (!exited) {
12615
+ try {
12616
+ await proc.kill("SIGKILL");
12617
+ } catch {
12618
+ }
12619
+ }
12620
+ }
12539
12621
  var SIGNAL_EXIT = { SIGINT: 130, SIGTERM: 143, SIGHUP: 129 };
12540
12622
  async function trapShutdown(platform2, handler) {
12541
12623
  await Promise.all(
@@ -12547,24 +12629,7 @@ async function trapShutdown(platform2, handler) {
12547
12629
  async function killInflight() {
12548
12630
  const procs = [...inflightProcs];
12549
12631
  if (procs.length === 0) return;
12550
- await Promise.all(
12551
- procs.map(async (proc) => {
12552
- try {
12553
- await proc.kill("SIGTERM");
12554
- } catch {
12555
- }
12556
- const exited = await Promise.race([
12557
- proc.wait().then(() => true),
12558
- new Promise((r) => setTimeout(() => r(false), KILL_GRACE_MS))
12559
- ]);
12560
- if (!exited) {
12561
- try {
12562
- await proc.kill("SIGKILL");
12563
- } catch {
12564
- }
12565
- }
12566
- })
12567
- );
12632
+ await Promise.all(procs.map((proc) => terminate(proc, KILL_GRACE_MS)));
12568
12633
  inflightProcs.clear();
12569
12634
  }
12570
12635
  async function runHelpForCli(platform2, filePath, childEnv, cwd, signal) {
@@ -12661,7 +12726,7 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12661
12726
  );
12662
12727
  return run2;
12663
12728
  }
12664
- function invokeTemplateTool(tool, args) {
12729
+ function invokeTemplateTool(tool, args, cancel) {
12665
12730
  const templateArgs = {};
12666
12731
  if (args && typeof args === "object") {
12667
12732
  for (const [k, v] of Object.entries(args)) {
@@ -12679,11 +12744,13 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12679
12744
  void 0,
12680
12745
  options.callTimeout,
12681
12746
  options.maxOutput,
12682
- serveCwd
12747
+ serveCwd,
12748
+ void 0,
12749
+ cancel
12683
12750
  )
12684
12751
  );
12685
12752
  }
12686
- async function executeTool(tool, cli, args) {
12753
+ async function executeTool(tool, cli, args, cancel) {
12687
12754
  if (tool.kind === "help") {
12688
12755
  const result = await runCommand(
12689
12756
  platform2,
@@ -12693,7 +12760,9 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12693
12760
  void 0,
12694
12761
  options.callTimeout,
12695
12762
  options.maxOutput,
12696
- serveCwd
12763
+ serveCwd,
12764
+ void 0,
12765
+ cancel
12697
12766
  );
12698
12767
  if (result.exitCode === 0) return result;
12699
12768
  return runCommand(
@@ -12704,7 +12773,9 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12704
12773
  void 0,
12705
12774
  options.callTimeout,
12706
12775
  options.maxOutput,
12707
- serveCwd
12776
+ serveCwd,
12777
+ void 0,
12778
+ cancel
12708
12779
  );
12709
12780
  }
12710
12781
  if (tool.kind === "invoke") {
@@ -12719,7 +12790,9 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12719
12790
  parsed2.stdin,
12720
12791
  options.callTimeout,
12721
12792
  options.maxOutput,
12722
- serveCwd
12793
+ serveCwd,
12794
+ void 0,
12795
+ cancel
12723
12796
  );
12724
12797
  }
12725
12798
  const parsed = readToolArguments(args ?? {});
@@ -12735,18 +12808,20 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12735
12808
  planned.stdin,
12736
12809
  options.callTimeout,
12737
12810
  options.maxOutput,
12738
- serveCwd
12811
+ serveCwd,
12812
+ void 0,
12813
+ cancel
12739
12814
  );
12740
12815
  }
12741
- async function invoke(name, args) {
12816
+ async function invoke(name, args, cancel) {
12742
12817
  const tool = allTools.find((t) => t.name === name);
12743
12818
  if (!tool) return { stdout: "", stderr: `unknown tool ${name}`, exitCode: 1 };
12744
12819
  if (tool.cli === "" && tool.commandPath.length === 0) {
12745
- return invokeTemplateTool(tool, args);
12820
+ return invokeTemplateTool(tool, args, cancel);
12746
12821
  }
12747
12822
  const cli = clis.find((c) => c.name === tool.cli);
12748
12823
  if (!cli) return { stdout: "", stderr: `unknown cli ${tool.cli}`, exitCode: 1 };
12749
- return enqueue(cli.name, () => executeTool(tool, cli, args));
12824
+ return enqueue(cli.name, () => executeTool(tool, cli, args, cancel));
12750
12825
  }
12751
12826
  return { invoke, rpcTools };
12752
12827
  }
@@ -13490,10 +13565,13 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
13490
13565
  let tokenFilePath;
13491
13566
  let shutdownRequested = false;
13492
13567
  let inflightDone;
13568
+ const stopCalls = new AbortController();
13569
+ const activeCalls = /* @__PURE__ */ new Set();
13493
13570
  const shutdown = () => {
13494
13571
  if (shutdownRequested) return;
13495
13572
  shutdownRequested = true;
13496
13573
  listener.close();
13574
+ stopCalls.abort();
13497
13575
  inflightDone = killInflight();
13498
13576
  if (tokenFilePath) {
13499
13577
  platform2.fs.unlink?.(tokenFilePath).catch(() => {
@@ -13523,17 +13601,30 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
13523
13601
  await platform2.write(2, `mcpcat serve: listening on ${listenUrl}
13524
13602
  `);
13525
13603
  }
13526
- const handler = (request) => handleMcpRequest(
13527
- request,
13528
- tools,
13529
- call,
13530
- serverName,
13531
- version,
13532
- serverOrigins,
13533
- allowedOrigins,
13534
- allowedHosts,
13535
- resolvedBearer
13536
- );
13604
+ const handler = (request, signal) => {
13605
+ const cancel = new AbortController();
13606
+ const relay = () => cancel.abort();
13607
+ signal.addEventListener("abort", relay, { once: true });
13608
+ stopCalls.signal.addEventListener("abort", relay, { once: true });
13609
+ if (signal.aborted || stopCalls.signal.aborted) relay();
13610
+ const pending = handleMcpRequest(
13611
+ request,
13612
+ tools,
13613
+ (name, args) => call(name, args, cancel.signal),
13614
+ serverName,
13615
+ version,
13616
+ serverOrigins,
13617
+ allowedOrigins,
13618
+ allowedHosts,
13619
+ resolvedBearer
13620
+ ).finally(() => {
13621
+ signal.removeEventListener("abort", relay);
13622
+ stopCalls.signal.removeEventListener("abort", relay);
13623
+ activeCalls.delete(pending);
13624
+ });
13625
+ activeCalls.add(pending);
13626
+ return pending;
13627
+ };
13537
13628
  try {
13538
13629
  for await (const connection of listener) {
13539
13630
  if (shutdownRequested) break;
@@ -13555,6 +13646,7 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
13555
13646
  } catch {
13556
13647
  }
13557
13648
  }
13649
+ await Promise.allSettled([...activeCalls]);
13558
13650
  return 0;
13559
13651
  }
13560
13652
  async function handleMcpRequest(request, tools, call, serverName, version, serverOrigins, allowedOrigins, allowedHosts, resolvedBearer) {
@@ -16818,7 +16910,7 @@ async function main(ctx) {
16818
16910
  packageDir: "/node_modules/@ai-ecoverse/mcpcat"
16819
16911
  });
16820
16912
  const args = ctx.argv.slice(1);
16821
- return run(platform2, "0.18.0", args);
16913
+ return run(platform2, "0.18.2", args);
16822
16914
  }
16823
16915
  export {
16824
16916
  main as default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/mcpcat",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "description": "A curl for the Model Context Protocol",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -62,14 +62,14 @@
62
62
  },
63
63
  "devDependencies": {
64
64
  "@ai-ecoverse/slicc-bios": "1.38.0",
65
- "@ai-ecoverse/slicc-kernel": "1.143.1",
66
- "@ai-ecoverse/slicc-shared-web": "1.29.16",
65
+ "@ai-ecoverse/slicc-kernel": "1.143.4",
66
+ "@ai-ecoverse/slicc-shared-web": "1.30.3",
67
67
  "@biomejs/biome": "2.5.15",
68
68
  "@earendil-works/pi-codemode": "1.2.0",
69
69
  "@earendil-works/pi-mcp": "1.2.0",
70
70
  "@types/node": "26.6.5",
71
71
  "esbuild": "0.28.2",
72
- "kernel-cert-new": "npm:@ai-ecoverse/slicc-kernel@1.143.1",
72
+ "kernel-cert-new": "npm:@ai-ecoverse/slicc-kernel@1.143.4",
73
73
  "lefthook": "2.2.2",
74
74
  "monocart-coverage-reports": "2.13.2",
75
75
  "proper-lockfile": "4.1.2",