@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.
- package/dist/host/mcpcat.mjs +161 -69
- package/dist/kernel/mcpcat.mjs +161 -69
- package/package.json +4 -4
package/dist/host/mcpcat.mjs
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
12862
|
-
|
|
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
|
-
|
|
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
|
-
|
|
12882
|
-
|
|
12883
|
-
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
|
|
12887
|
-
|
|
12888
|
-
|
|
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
|
-
|
|
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) =>
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
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.
|
|
17191
|
+
var code = await run(platform, "0.18.2", args);
|
|
17100
17192
|
process.exit(code);
|
package/dist/kernel/mcpcat.mjs
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
12483
|
-
|
|
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
|
-
|
|
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
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
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
|
-
|
|
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) =>
|
|
13527
|
-
|
|
13528
|
-
|
|
13529
|
-
|
|
13530
|
-
|
|
13531
|
-
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
|
|
13535
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
66
|
-
"@ai-ecoverse/slicc-shared-web": "1.
|
|
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.
|
|
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",
|