@ai-ecoverse/mcpcat 0.15.6 → 0.15.8
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 +208 -107
- package/dist/kernel/mcpcat.mjs +210 -109
- package/package.json +4 -3
package/dist/host/mcpcat.mjs
CHANGED
|
@@ -1854,6 +1854,16 @@ var init_version = __esm({
|
|
|
1854
1854
|
});
|
|
1855
1855
|
|
|
1856
1856
|
// node_modules/quickjs-wasi/dist/index.js
|
|
1857
|
+
var dist_exports = {};
|
|
1858
|
+
__export(dist_exports, {
|
|
1859
|
+
CompileFlags: () => CompileFlags,
|
|
1860
|
+
EvalFlags: () => EvalFlags,
|
|
1861
|
+
Intrinsics: () => Intrinsics,
|
|
1862
|
+
JSException: () => JSException,
|
|
1863
|
+
JSValueHandle: () => JSValueHandle,
|
|
1864
|
+
MAX_STACK_SIZE: () => MAX_STACK_SIZE,
|
|
1865
|
+
QuickJS: () => QuickJS
|
|
1866
|
+
});
|
|
1857
1867
|
function stringKeyNeedsValuePath(key) {
|
|
1858
1868
|
return key.includes("\0") || LONE_SURROGATE_RE.test(key);
|
|
1859
1869
|
}
|
|
@@ -5365,8 +5375,8 @@ SOURCE: /[\s\S]+/
|
|
|
5365
5375
|
});
|
|
5366
5376
|
|
|
5367
5377
|
// node_modules/@earendil-works/pi-codemode/dist/index.js
|
|
5368
|
-
var
|
|
5369
|
-
__export(
|
|
5378
|
+
var dist_exports2 = {};
|
|
5379
|
+
__export(dist_exports2, {
|
|
5370
5380
|
CODEMODE_OPTIONS_PREFIX: () => CODEMODE_OPTIONS_PREFIX,
|
|
5371
5381
|
CODEMODE_SOURCE_GRAMMAR: () => CODEMODE_SOURCE_GRAMMAR,
|
|
5372
5382
|
CodemodeSandbox: () => CodemodeSandbox,
|
|
@@ -8109,37 +8119,55 @@ var StreamableHttpTransport = class extends TransportEvents {
|
|
|
8109
8119
|
}
|
|
8110
8120
|
};
|
|
8111
8121
|
|
|
8122
|
+
// src/client/reap.ts
|
|
8123
|
+
var POLL_MS = 25;
|
|
8124
|
+
async function gone(proc, exited, ms) {
|
|
8125
|
+
const end = Date.now() + ms;
|
|
8126
|
+
for (; ; ) {
|
|
8127
|
+
if (exited() && !await proc.groupAlive?.()) return true;
|
|
8128
|
+
if (Date.now() >= end) return false;
|
|
8129
|
+
await new Promise((r) => setTimeout(r, POLL_MS));
|
|
8130
|
+
}
|
|
8131
|
+
}
|
|
8132
|
+
async function reap(proc, graceMs) {
|
|
8133
|
+
let exited = false;
|
|
8134
|
+
void proc.wait().then(
|
|
8135
|
+
() => {
|
|
8136
|
+
exited = true;
|
|
8137
|
+
},
|
|
8138
|
+
() => {
|
|
8139
|
+
exited = true;
|
|
8140
|
+
}
|
|
8141
|
+
);
|
|
8142
|
+
try {
|
|
8143
|
+
await proc.kill("SIGTERM");
|
|
8144
|
+
} catch {
|
|
8145
|
+
}
|
|
8146
|
+
if (await gone(proc, () => exited, graceMs)) return;
|
|
8147
|
+
try {
|
|
8148
|
+
await proc.kill("SIGKILL");
|
|
8149
|
+
} catch {
|
|
8150
|
+
}
|
|
8151
|
+
await gone(proc, () => exited, graceMs);
|
|
8152
|
+
}
|
|
8153
|
+
|
|
8112
8154
|
// src/client/stdio-registry.ts
|
|
8113
8155
|
var GRACE_MS = 2e3;
|
|
8114
8156
|
var registry = /* @__PURE__ */ new Set();
|
|
8115
8157
|
function trackStdio(proc) {
|
|
8116
8158
|
registry.add(proc);
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8159
|
+
}
|
|
8160
|
+
async function reapStdio(proc, graceMs = GRACE_MS) {
|
|
8161
|
+
try {
|
|
8162
|
+
await reap(proc, graceMs);
|
|
8163
|
+
} finally {
|
|
8164
|
+
registry.delete(proc);
|
|
8165
|
+
}
|
|
8121
8166
|
}
|
|
8122
8167
|
async function killAllStdio() {
|
|
8123
8168
|
const procs = [...registry];
|
|
8124
8169
|
if (procs.length === 0) return;
|
|
8125
|
-
await Promise.all(
|
|
8126
|
-
procs.map(async (proc) => {
|
|
8127
|
-
try {
|
|
8128
|
-
await proc.kill("SIGTERM");
|
|
8129
|
-
} catch {
|
|
8130
|
-
}
|
|
8131
|
-
const exited = await Promise.race([
|
|
8132
|
-
proc.wait().then(() => true),
|
|
8133
|
-
new Promise((r) => setTimeout(() => r(false), GRACE_MS))
|
|
8134
|
-
]);
|
|
8135
|
-
if (!exited) {
|
|
8136
|
-
try {
|
|
8137
|
-
await proc.kill("SIGKILL");
|
|
8138
|
-
} catch {
|
|
8139
|
-
}
|
|
8140
|
-
}
|
|
8141
|
-
})
|
|
8142
|
-
);
|
|
8170
|
+
await Promise.all(procs.map((proc) => reapStdio(proc)));
|
|
8143
8171
|
registry.clear();
|
|
8144
8172
|
}
|
|
8145
8173
|
|
|
@@ -8245,16 +8273,8 @@ var PlatformStdioTransport = class {
|
|
|
8245
8273
|
await proc.stdin.close();
|
|
8246
8274
|
} catch {
|
|
8247
8275
|
}
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
await proc.kill("SIGTERM");
|
|
8251
|
-
const exitedAfterTerm = await Promise.race([done, delay(closeTimeoutMs)]);
|
|
8252
|
-
if (!exitedAfterTerm) {
|
|
8253
|
-
await proc.kill("SIGKILL");
|
|
8254
|
-
await done;
|
|
8255
|
-
}
|
|
8256
|
-
}
|
|
8257
|
-
await proc.kill("SIGTERM");
|
|
8276
|
+
await Promise.race([done, delay(grace)]);
|
|
8277
|
+
await reapStdio(proc, closeTimeoutMs);
|
|
8258
8278
|
this.emitClose();
|
|
8259
8279
|
}
|
|
8260
8280
|
async readStdout(pending) {
|
|
@@ -8938,10 +8958,7 @@ function buildConnectionMethods(rpc, discoverResult2, proc) {
|
|
|
8938
8958
|
},
|
|
8939
8959
|
async close() {
|
|
8940
8960
|
rpc.close();
|
|
8941
|
-
|
|
8942
|
-
await proc.kill("SIGTERM");
|
|
8943
|
-
} catch {
|
|
8944
|
-
}
|
|
8961
|
+
await reapStdio(proc);
|
|
8945
8962
|
}
|
|
8946
8963
|
};
|
|
8947
8964
|
}
|
|
@@ -9367,7 +9384,7 @@ function toolDeclaration(tool) {
|
|
|
9367
9384
|
};
|
|
9368
9385
|
}
|
|
9369
9386
|
async function runDescribeTs(platform2, targets, budget) {
|
|
9370
|
-
const { renderDeclarations: renderDeclarations2 } = await Promise.resolve().then(() => (init_dist2(),
|
|
9387
|
+
const { renderDeclarations: renderDeclarations2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports2));
|
|
9371
9388
|
const allTools = [];
|
|
9372
9389
|
for (const target of targets) {
|
|
9373
9390
|
const tools = await target.conn.listTools();
|
|
@@ -9438,6 +9455,39 @@ async function runGrep(platform2, pattern, targets, options) {
|
|
|
9438
9455
|
// src/codemode/run.ts
|
|
9439
9456
|
init_dist2();
|
|
9440
9457
|
init_source();
|
|
9458
|
+
|
|
9459
|
+
// src/codemode/deadline.ts
|
|
9460
|
+
var expiries = /* @__PURE__ */ new WeakMap();
|
|
9461
|
+
var hooked = /* @__PURE__ */ new WeakSet();
|
|
9462
|
+
function hookDeadlines(quickjs) {
|
|
9463
|
+
if (hooked.has(quickjs)) return;
|
|
9464
|
+
hooked.add(quickjs);
|
|
9465
|
+
const create = quickjs.create.bind(quickjs);
|
|
9466
|
+
quickjs.create = (options) => {
|
|
9467
|
+
const expired = options.wasm ? expiries.get(options.wasm) : void 0;
|
|
9468
|
+
const inner = options.interruptHandler;
|
|
9469
|
+
if (!expired || !inner) return create(options);
|
|
9470
|
+
return create({ ...options, interruptHandler: () => expired() || inner() });
|
|
9471
|
+
};
|
|
9472
|
+
}
|
|
9473
|
+
function bindDeadline(wasm, timeoutMs, now = Date.now) {
|
|
9474
|
+
let endsAt = Number.POSITIVE_INFINITY;
|
|
9475
|
+
let tripped = false;
|
|
9476
|
+
expiries.set(wasm, () => {
|
|
9477
|
+
if (!tripped && now() >= endsAt) tripped = true;
|
|
9478
|
+
return tripped;
|
|
9479
|
+
});
|
|
9480
|
+
return {
|
|
9481
|
+
start() {
|
|
9482
|
+
endsAt = now() + timeoutMs;
|
|
9483
|
+
},
|
|
9484
|
+
get tripped() {
|
|
9485
|
+
return tripped;
|
|
9486
|
+
}
|
|
9487
|
+
};
|
|
9488
|
+
}
|
|
9489
|
+
|
|
9490
|
+
// src/codemode/run.ts
|
|
9441
9491
|
async function loadStore(platform2, stateDir2) {
|
|
9442
9492
|
const storePath = `${stateDir2}/codemode-store.json`;
|
|
9443
9493
|
try {
|
|
@@ -9623,9 +9673,23 @@ async function runCode(targets, source, options) {
|
|
|
9623
9673
|
...buildDiscoveryGlobals(allDeclaredTools, namespaces, searchDocs),
|
|
9624
9674
|
...options.allowShell ? [buildShellGlobal(platform2)] : []
|
|
9625
9675
|
];
|
|
9626
|
-
const sandbox = await createSandbox(
|
|
9676
|
+
const { sandbox, deadline } = await createSandbox(
|
|
9677
|
+
platform2,
|
|
9678
|
+
toolImpls,
|
|
9679
|
+
globals,
|
|
9680
|
+
timeoutMs,
|
|
9681
|
+
memoryLimitBytes
|
|
9682
|
+
);
|
|
9627
9683
|
try {
|
|
9628
|
-
|
|
9684
|
+
deadline?.start();
|
|
9685
|
+
const executed = await sandbox.execute(code2, { store });
|
|
9686
|
+
const result = deadline?.tripped && !executed.ok ? {
|
|
9687
|
+
...executed,
|
|
9688
|
+
error: {
|
|
9689
|
+
kind: "timeout",
|
|
9690
|
+
message: `Execution timed out after ${timeoutMs} ms`
|
|
9691
|
+
}
|
|
9692
|
+
} : executed;
|
|
9629
9693
|
if (result.ok) {
|
|
9630
9694
|
const writes = result.storeWrites;
|
|
9631
9695
|
if (Object.keys(writes.set).length > 0 || writes.delete.length > 0) {
|
|
@@ -9671,12 +9735,23 @@ async function createSandbox(platform2, tools, globals, timeoutMs, memoryLimitBy
|
|
|
9671
9735
|
const isKernel2 = platform2.packageDir !== void 0;
|
|
9672
9736
|
if (isKernel2) {
|
|
9673
9737
|
const { InlineCodemodeSandbox: InlineCodemodeSandbox2 } = await Promise.resolve().then(() => (init_portable(), portable_exports));
|
|
9738
|
+
const { QuickJS: QuickJS2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
9739
|
+
hookDeadlines(QuickJS2);
|
|
9674
9740
|
const wasm = await loadWasmKernel(platform2);
|
|
9675
|
-
|
|
9741
|
+
const deadline = bindDeadline(wasm, timeoutMs);
|
|
9742
|
+
const sandbox2 = new InlineCodemodeSandbox2({
|
|
9743
|
+
tools,
|
|
9744
|
+
globals,
|
|
9745
|
+
timeoutMs,
|
|
9746
|
+
wasm,
|
|
9747
|
+
memoryLimitBytes,
|
|
9748
|
+
interruptBudget: Number.POSITIVE_INFINITY
|
|
9749
|
+
});
|
|
9750
|
+
return { sandbox: sandbox2, deadline };
|
|
9676
9751
|
}
|
|
9677
|
-
const { CodemodeSandbox: CodemodeSandbox2, loadQuickJSWasm: loadQuickJSWasm2 } = await Promise.resolve().then(() => (init_dist2(),
|
|
9752
|
+
const { CodemodeSandbox: CodemodeSandbox2, loadQuickJSWasm: loadQuickJSWasm2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports2));
|
|
9678
9753
|
const wasmPath = await resolveWasmPath(platform2);
|
|
9679
|
-
|
|
9754
|
+
const sandbox = new CodemodeSandbox2({
|
|
9680
9755
|
tools,
|
|
9681
9756
|
globals,
|
|
9682
9757
|
timeoutMs,
|
|
@@ -9684,6 +9759,7 @@ async function createSandbox(platform2, tools, globals, timeoutMs, memoryLimitBy
|
|
|
9684
9759
|
wasm: loadQuickJSWasm2(wasmPath),
|
|
9685
9760
|
workerUrl: new URL("./codemode-worker.mjs", import.meta.url)
|
|
9686
9761
|
});
|
|
9762
|
+
return { sandbox };
|
|
9687
9763
|
}
|
|
9688
9764
|
async function resolveWasmPath(platform2) {
|
|
9689
9765
|
const candidates = [
|
|
@@ -12752,6 +12828,11 @@ function concat(chunks) {
|
|
|
12752
12828
|
return out;
|
|
12753
12829
|
}
|
|
12754
12830
|
var KILL_GRACE_MS = 2e3;
|
|
12831
|
+
async function trapShutdown(platform2, handler) {
|
|
12832
|
+
await Promise.all(
|
|
12833
|
+
["SIGINT", "SIGTERM", "SIGHUP"].map((sig) => platform2.onSignal?.(sig, handler))
|
|
12834
|
+
);
|
|
12835
|
+
}
|
|
12755
12836
|
async function killInflight() {
|
|
12756
12837
|
const procs = [...inflightProcs];
|
|
12757
12838
|
if (procs.length === 0) return;
|
|
@@ -12968,8 +13049,7 @@ async function discoverWithSignal(platform2, commands, childEnv, cwd) {
|
|
|
12968
13049
|
earlyAbort.abort();
|
|
12969
13050
|
inflightDone = killInflight();
|
|
12970
13051
|
};
|
|
12971
|
-
platform2
|
|
12972
|
-
platform2.onSignal?.("SIGINT", onShutdown);
|
|
13052
|
+
await trapShutdown(platform2, onShutdown);
|
|
12973
13053
|
for (const cmd of commands) {
|
|
12974
13054
|
try {
|
|
12975
13055
|
const cli = await discoverCli(platform2, cmd.path, cmd.name, childEnv, cwd, earlyAbort.signal);
|
|
@@ -13300,6 +13380,17 @@ async function runWebMcpHttp(platform2, options, getTools, callTool, serverName,
|
|
|
13300
13380
|
const address = serveAddress(platform2, options.host, actualPort);
|
|
13301
13381
|
const listenUrl = address.url;
|
|
13302
13382
|
let tokenFilePath;
|
|
13383
|
+
let shutdownRequested = false;
|
|
13384
|
+
const shutdown = () => {
|
|
13385
|
+
if (shutdownRequested) return;
|
|
13386
|
+
shutdownRequested = true;
|
|
13387
|
+
listener.close();
|
|
13388
|
+
if (tokenFilePath) {
|
|
13389
|
+
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13390
|
+
});
|
|
13391
|
+
}
|
|
13392
|
+
};
|
|
13393
|
+
await trapShutdown(platform2, shutdown);
|
|
13303
13394
|
if (generatedBearer && resolvedBearer) {
|
|
13304
13395
|
tokenFilePath = await publishBearer(
|
|
13305
13396
|
platform2,
|
|
@@ -13308,31 +13399,22 @@ async function runWebMcpHttp(platform2, options, getTools, callTool, serverName,
|
|
|
13308
13399
|
address,
|
|
13309
13400
|
options.json
|
|
13310
13401
|
);
|
|
13402
|
+
if (shutdownRequested && tokenFilePath) {
|
|
13403
|
+
await platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13404
|
+
});
|
|
13405
|
+
}
|
|
13311
13406
|
} else {
|
|
13312
13407
|
if (options.json) {
|
|
13313
13408
|
await platform2.write(1, `${JSON.stringify(address)}
|
|
13314
13409
|
`);
|
|
13315
13410
|
}
|
|
13316
13411
|
}
|
|
13317
|
-
|
|
13412
|
+
if (!shutdownRequested) {
|
|
13413
|
+
await platform2.write(2, `mcpcat serve --webmcp: listening on ${listenUrl}
|
|
13318
13414
|
`);
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
}
|
|
13322
|
-
let shutdownRequested = false;
|
|
13323
|
-
const shutdown = () => {
|
|
13324
|
-
if (shutdownRequested) return;
|
|
13325
|
-
shutdownRequested = true;
|
|
13326
|
-
listener.close();
|
|
13327
|
-
if (tokenFilePath) {
|
|
13328
|
-
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13329
|
-
});
|
|
13415
|
+
if (options.onListening) {
|
|
13416
|
+
await options.onListening(actualPort);
|
|
13330
13417
|
}
|
|
13331
|
-
};
|
|
13332
|
-
if (platform2.onSignal) {
|
|
13333
|
-
platform2.onSignal("SIGINT", shutdown);
|
|
13334
|
-
platform2.onSignal("SIGTERM", shutdown);
|
|
13335
|
-
platform2.onSignal("SIGHUP", shutdown);
|
|
13336
13418
|
}
|
|
13337
13419
|
const handler = async (request) => {
|
|
13338
13420
|
if (request.target !== "/mcp") {
|
|
@@ -13496,6 +13578,19 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
|
|
|
13496
13578
|
const address = serveAddress(platform2, options.host, actualPort);
|
|
13497
13579
|
const listenUrl = address.url;
|
|
13498
13580
|
let tokenFilePath;
|
|
13581
|
+
let shutdownRequested = false;
|
|
13582
|
+
let proxyDone;
|
|
13583
|
+
const shutdown = () => {
|
|
13584
|
+
if (shutdownRequested) return;
|
|
13585
|
+
shutdownRequested = true;
|
|
13586
|
+
listener.close();
|
|
13587
|
+
proxyDone = proxy.shutdown();
|
|
13588
|
+
if (tokenFilePath) {
|
|
13589
|
+
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13590
|
+
});
|
|
13591
|
+
}
|
|
13592
|
+
};
|
|
13593
|
+
await trapShutdown(platform2, shutdown);
|
|
13499
13594
|
if (generatedBearer && resolvedBearer) {
|
|
13500
13595
|
tokenFilePath = await publishBearer(
|
|
13501
13596
|
platform2,
|
|
@@ -13504,32 +13599,22 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
|
|
|
13504
13599
|
address,
|
|
13505
13600
|
options.json
|
|
13506
13601
|
);
|
|
13602
|
+
if (shutdownRequested && tokenFilePath) {
|
|
13603
|
+
await platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13604
|
+
});
|
|
13605
|
+
}
|
|
13507
13606
|
} else {
|
|
13508
13607
|
if (options.json) {
|
|
13509
13608
|
await platform2.write(1, `${JSON.stringify(address)}
|
|
13510
13609
|
`);
|
|
13511
13610
|
}
|
|
13512
13611
|
}
|
|
13513
|
-
|
|
13612
|
+
if (!shutdownRequested) {
|
|
13613
|
+
await platform2.write(2, `mcpcat serve --proxy: listening on ${listenUrl}
|
|
13514
13614
|
`);
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
}
|
|
13518
|
-
let shutdownRequested = false;
|
|
13519
|
-
const shutdown = () => {
|
|
13520
|
-
if (shutdownRequested) return;
|
|
13521
|
-
shutdownRequested = true;
|
|
13522
|
-
listener.close();
|
|
13523
|
-
void proxy.shutdown();
|
|
13524
|
-
if (tokenFilePath) {
|
|
13525
|
-
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13526
|
-
});
|
|
13615
|
+
if (options.onListening) {
|
|
13616
|
+
await options.onListening(actualPort);
|
|
13527
13617
|
}
|
|
13528
|
-
};
|
|
13529
|
-
if (platform2.onSignal) {
|
|
13530
|
-
platform2.onSignal("SIGINT", shutdown);
|
|
13531
|
-
platform2.onSignal("SIGTERM", shutdown);
|
|
13532
|
-
platform2.onSignal("SIGHUP", shutdown);
|
|
13533
13618
|
}
|
|
13534
13619
|
const handler = (request) => handleProxyMcpRequest(
|
|
13535
13620
|
request,
|
|
@@ -13554,6 +13639,7 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
|
|
|
13554
13639
|
} catch {
|
|
13555
13640
|
if (!shutdownRequested) throw new Error("listener closed unexpectedly");
|
|
13556
13641
|
}
|
|
13642
|
+
await proxyDone;
|
|
13557
13643
|
return 0;
|
|
13558
13644
|
}
|
|
13559
13645
|
async function handleProxyMcpRequest(request, proxy, serverOrigins, allowedOrigins, allowedHosts, resolvedBearer) {
|
|
@@ -13673,6 +13759,19 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
|
|
|
13673
13759
|
const address = serveAddress(platform2, options.host, actualPort);
|
|
13674
13760
|
const listenUrl = address.url;
|
|
13675
13761
|
let tokenFilePath;
|
|
13762
|
+
let shutdownRequested = false;
|
|
13763
|
+
let inflightDone;
|
|
13764
|
+
const shutdown = () => {
|
|
13765
|
+
if (shutdownRequested) return;
|
|
13766
|
+
shutdownRequested = true;
|
|
13767
|
+
listener.close();
|
|
13768
|
+
inflightDone = killInflight();
|
|
13769
|
+
if (tokenFilePath) {
|
|
13770
|
+
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13771
|
+
});
|
|
13772
|
+
}
|
|
13773
|
+
};
|
|
13774
|
+
await trapShutdown(platform2, shutdown);
|
|
13676
13775
|
if (generatedBearer && resolvedBearer) {
|
|
13677
13776
|
tokenFilePath = await publishBearer(
|
|
13678
13777
|
platform2,
|
|
@@ -13681,30 +13780,19 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
|
|
|
13681
13780
|
address,
|
|
13682
13781
|
options.json
|
|
13683
13782
|
);
|
|
13783
|
+
if (shutdownRequested && tokenFilePath) {
|
|
13784
|
+
await platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13785
|
+
});
|
|
13786
|
+
}
|
|
13684
13787
|
} else {
|
|
13685
13788
|
if (options.json) {
|
|
13686
13789
|
await platform2.write(1, `${JSON.stringify(address)}
|
|
13687
13790
|
`);
|
|
13688
13791
|
}
|
|
13689
13792
|
}
|
|
13690
|
-
|
|
13793
|
+
if (!shutdownRequested) {
|
|
13794
|
+
await platform2.write(2, `mcpcat serve: listening on ${listenUrl}
|
|
13691
13795
|
`);
|
|
13692
|
-
let shutdownRequested = false;
|
|
13693
|
-
let inflightDone;
|
|
13694
|
-
const shutdown = () => {
|
|
13695
|
-
if (shutdownRequested) return;
|
|
13696
|
-
shutdownRequested = true;
|
|
13697
|
-
listener.close();
|
|
13698
|
-
inflightDone = killInflight();
|
|
13699
|
-
if (tokenFilePath) {
|
|
13700
|
-
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13701
|
-
});
|
|
13702
|
-
}
|
|
13703
|
-
};
|
|
13704
|
-
if (platform2.onSignal) {
|
|
13705
|
-
platform2.onSignal("SIGINT", shutdown);
|
|
13706
|
-
platform2.onSignal("SIGTERM", shutdown);
|
|
13707
|
-
platform2.onSignal("SIGHUP", shutdown);
|
|
13708
13796
|
}
|
|
13709
13797
|
const handler = (request) => handleMcpRequest(
|
|
13710
13798
|
request,
|
|
@@ -16084,8 +16172,10 @@ async function dispatchMultiTarget(platform2, parsed, version) {
|
|
|
16084
16172
|
});
|
|
16085
16173
|
platform2.exit(exitCode);
|
|
16086
16174
|
}
|
|
16087
|
-
|
|
16088
|
-
|
|
16175
|
+
await Promise.all([
|
|
16176
|
+
platform2.onSignal?.("SIGTERM", () => void killTreeAndExit(143)),
|
|
16177
|
+
platform2.onSignal?.("SIGHUP", () => void killTreeAndExit(129))
|
|
16178
|
+
]);
|
|
16089
16179
|
const config = await MergedConfigSource.load(platform2);
|
|
16090
16180
|
if (parsed.verb === "code") {
|
|
16091
16181
|
let source;
|
|
@@ -16446,12 +16536,14 @@ async function runClientVerb(platform2, version, parsed) {
|
|
|
16446
16536
|
});
|
|
16447
16537
|
platform2.exit(exitCode);
|
|
16448
16538
|
}
|
|
16449
|
-
|
|
16450
|
-
|
|
16451
|
-
|
|
16452
|
-
|
|
16453
|
-
|
|
16454
|
-
|
|
16539
|
+
await Promise.all([
|
|
16540
|
+
platform2.onSignal?.("SIGINT", () => {
|
|
16541
|
+
interrupted = true;
|
|
16542
|
+
sigintController.abort();
|
|
16543
|
+
}),
|
|
16544
|
+
platform2.onSignal?.("SIGTERM", () => void killTreeAndExit(143)),
|
|
16545
|
+
platform2.onSignal?.("SIGHUP", () => void killTreeAndExit(129))
|
|
16546
|
+
]);
|
|
16455
16547
|
const showProgress = !parsed.silent && (parsed.verbose || platform2.isatty(2));
|
|
16456
16548
|
const onProgress = (progress, total, message) => {
|
|
16457
16549
|
if (!showProgress) return;
|
|
@@ -16678,6 +16770,15 @@ function nodeSpawn(options) {
|
|
|
16678
16770
|
child.kill(sig);
|
|
16679
16771
|
} catch {
|
|
16680
16772
|
}
|
|
16773
|
+
},
|
|
16774
|
+
async groupAlive() {
|
|
16775
|
+
if (!USE_PROCESS_GROUPS2 || child.pid === void 0) return false;
|
|
16776
|
+
try {
|
|
16777
|
+
process.kill(-child.pid, 0);
|
|
16778
|
+
return true;
|
|
16779
|
+
} catch {
|
|
16780
|
+
return false;
|
|
16781
|
+
}
|
|
16681
16782
|
}
|
|
16682
16783
|
});
|
|
16683
16784
|
}
|
|
@@ -16856,5 +16957,5 @@ try {
|
|
|
16856
16957
|
});
|
|
16857
16958
|
} catch {
|
|
16858
16959
|
}
|
|
16859
|
-
var code = await run(platform, "0.15.
|
|
16960
|
+
var code = await run(platform, "0.15.8", args);
|
|
16860
16961
|
process.exit(code);
|
package/dist/kernel/mcpcat.mjs
CHANGED
|
@@ -1475,6 +1475,16 @@ var init_version = __esm({
|
|
|
1475
1475
|
});
|
|
1476
1476
|
|
|
1477
1477
|
// node_modules/quickjs-wasi/dist/index.js
|
|
1478
|
+
var dist_exports = {};
|
|
1479
|
+
__export(dist_exports, {
|
|
1480
|
+
CompileFlags: () => CompileFlags,
|
|
1481
|
+
EvalFlags: () => EvalFlags,
|
|
1482
|
+
Intrinsics: () => Intrinsics,
|
|
1483
|
+
JSException: () => JSException,
|
|
1484
|
+
JSValueHandle: () => JSValueHandle,
|
|
1485
|
+
MAX_STACK_SIZE: () => MAX_STACK_SIZE,
|
|
1486
|
+
QuickJS: () => QuickJS
|
|
1487
|
+
});
|
|
1478
1488
|
function stringKeyNeedsValuePath(key) {
|
|
1479
1489
|
return key.includes("\0") || LONE_SURROGATE_RE.test(key);
|
|
1480
1490
|
}
|
|
@@ -4986,8 +4996,8 @@ SOURCE: /[\s\S]+/
|
|
|
4986
4996
|
});
|
|
4987
4997
|
|
|
4988
4998
|
// node_modules/@earendil-works/pi-codemode/dist/index.js
|
|
4989
|
-
var
|
|
4990
|
-
__export(
|
|
4999
|
+
var dist_exports2 = {};
|
|
5000
|
+
__export(dist_exports2, {
|
|
4991
5001
|
CODEMODE_OPTIONS_PREFIX: () => CODEMODE_OPTIONS_PREFIX,
|
|
4992
5002
|
CODEMODE_SOURCE_GRAMMAR: () => CODEMODE_SOURCE_GRAMMAR,
|
|
4993
5003
|
CodemodeSandbox: () => CodemodeSandbox,
|
|
@@ -7730,37 +7740,55 @@ var StreamableHttpTransport = class extends TransportEvents {
|
|
|
7730
7740
|
}
|
|
7731
7741
|
};
|
|
7732
7742
|
|
|
7743
|
+
// src/client/reap.ts
|
|
7744
|
+
var POLL_MS = 25;
|
|
7745
|
+
async function gone(proc, exited, ms) {
|
|
7746
|
+
const end = Date.now() + ms;
|
|
7747
|
+
for (; ; ) {
|
|
7748
|
+
if (exited() && !await proc.groupAlive?.()) return true;
|
|
7749
|
+
if (Date.now() >= end) return false;
|
|
7750
|
+
await new Promise((r) => setTimeout(r, POLL_MS));
|
|
7751
|
+
}
|
|
7752
|
+
}
|
|
7753
|
+
async function reap(proc, graceMs) {
|
|
7754
|
+
let exited = false;
|
|
7755
|
+
void proc.wait().then(
|
|
7756
|
+
() => {
|
|
7757
|
+
exited = true;
|
|
7758
|
+
},
|
|
7759
|
+
() => {
|
|
7760
|
+
exited = true;
|
|
7761
|
+
}
|
|
7762
|
+
);
|
|
7763
|
+
try {
|
|
7764
|
+
await proc.kill("SIGTERM");
|
|
7765
|
+
} catch {
|
|
7766
|
+
}
|
|
7767
|
+
if (await gone(proc, () => exited, graceMs)) return;
|
|
7768
|
+
try {
|
|
7769
|
+
await proc.kill("SIGKILL");
|
|
7770
|
+
} catch {
|
|
7771
|
+
}
|
|
7772
|
+
await gone(proc, () => exited, graceMs);
|
|
7773
|
+
}
|
|
7774
|
+
|
|
7733
7775
|
// src/client/stdio-registry.ts
|
|
7734
7776
|
var GRACE_MS = 2e3;
|
|
7735
7777
|
var registry = /* @__PURE__ */ new Set();
|
|
7736
7778
|
function trackStdio(proc) {
|
|
7737
7779
|
registry.add(proc);
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7780
|
+
}
|
|
7781
|
+
async function reapStdio(proc, graceMs = GRACE_MS) {
|
|
7782
|
+
try {
|
|
7783
|
+
await reap(proc, graceMs);
|
|
7784
|
+
} finally {
|
|
7785
|
+
registry.delete(proc);
|
|
7786
|
+
}
|
|
7742
7787
|
}
|
|
7743
7788
|
async function killAllStdio() {
|
|
7744
7789
|
const procs = [...registry];
|
|
7745
7790
|
if (procs.length === 0) return;
|
|
7746
|
-
await Promise.all(
|
|
7747
|
-
procs.map(async (proc) => {
|
|
7748
|
-
try {
|
|
7749
|
-
await proc.kill("SIGTERM");
|
|
7750
|
-
} catch {
|
|
7751
|
-
}
|
|
7752
|
-
const exited = await Promise.race([
|
|
7753
|
-
proc.wait().then(() => true),
|
|
7754
|
-
new Promise((r) => setTimeout(() => r(false), GRACE_MS))
|
|
7755
|
-
]);
|
|
7756
|
-
if (!exited) {
|
|
7757
|
-
try {
|
|
7758
|
-
await proc.kill("SIGKILL");
|
|
7759
|
-
} catch {
|
|
7760
|
-
}
|
|
7761
|
-
}
|
|
7762
|
-
})
|
|
7763
|
-
);
|
|
7791
|
+
await Promise.all(procs.map((proc) => reapStdio(proc)));
|
|
7764
7792
|
registry.clear();
|
|
7765
7793
|
}
|
|
7766
7794
|
|
|
@@ -7866,16 +7894,8 @@ var PlatformStdioTransport = class {
|
|
|
7866
7894
|
await proc.stdin.close();
|
|
7867
7895
|
} catch {
|
|
7868
7896
|
}
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
await proc.kill("SIGTERM");
|
|
7872
|
-
const exitedAfterTerm = await Promise.race([done, delay(closeTimeoutMs)]);
|
|
7873
|
-
if (!exitedAfterTerm) {
|
|
7874
|
-
await proc.kill("SIGKILL");
|
|
7875
|
-
await done;
|
|
7876
|
-
}
|
|
7877
|
-
}
|
|
7878
|
-
await proc.kill("SIGTERM");
|
|
7897
|
+
await Promise.race([done, delay(grace)]);
|
|
7898
|
+
await reapStdio(proc, closeTimeoutMs);
|
|
7879
7899
|
this.emitClose();
|
|
7880
7900
|
}
|
|
7881
7901
|
async readStdout(pending) {
|
|
@@ -8559,10 +8579,7 @@ function buildConnectionMethods(rpc, discoverResult2, proc) {
|
|
|
8559
8579
|
},
|
|
8560
8580
|
async close() {
|
|
8561
8581
|
rpc.close();
|
|
8562
|
-
|
|
8563
|
-
await proc.kill("SIGTERM");
|
|
8564
|
-
} catch {
|
|
8565
|
-
}
|
|
8582
|
+
await reapStdio(proc);
|
|
8566
8583
|
}
|
|
8567
8584
|
};
|
|
8568
8585
|
}
|
|
@@ -8988,7 +9005,7 @@ function toolDeclaration(tool) {
|
|
|
8988
9005
|
};
|
|
8989
9006
|
}
|
|
8990
9007
|
async function runDescribeTs(platform2, targets, budget) {
|
|
8991
|
-
const { renderDeclarations: renderDeclarations2 } = await Promise.resolve().then(() => (init_dist2(),
|
|
9008
|
+
const { renderDeclarations: renderDeclarations2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports2));
|
|
8992
9009
|
const allTools = [];
|
|
8993
9010
|
for (const target of targets) {
|
|
8994
9011
|
const tools = await target.conn.listTools();
|
|
@@ -9059,6 +9076,39 @@ async function runGrep(platform2, pattern, targets, options) {
|
|
|
9059
9076
|
// src/codemode/run.ts
|
|
9060
9077
|
init_dist2();
|
|
9061
9078
|
init_source();
|
|
9079
|
+
|
|
9080
|
+
// src/codemode/deadline.ts
|
|
9081
|
+
var expiries = /* @__PURE__ */ new WeakMap();
|
|
9082
|
+
var hooked = /* @__PURE__ */ new WeakSet();
|
|
9083
|
+
function hookDeadlines(quickjs) {
|
|
9084
|
+
if (hooked.has(quickjs)) return;
|
|
9085
|
+
hooked.add(quickjs);
|
|
9086
|
+
const create = quickjs.create.bind(quickjs);
|
|
9087
|
+
quickjs.create = (options) => {
|
|
9088
|
+
const expired = options.wasm ? expiries.get(options.wasm) : void 0;
|
|
9089
|
+
const inner = options.interruptHandler;
|
|
9090
|
+
if (!expired || !inner) return create(options);
|
|
9091
|
+
return create({ ...options, interruptHandler: () => expired() || inner() });
|
|
9092
|
+
};
|
|
9093
|
+
}
|
|
9094
|
+
function bindDeadline(wasm, timeoutMs, now = Date.now) {
|
|
9095
|
+
let endsAt = Number.POSITIVE_INFINITY;
|
|
9096
|
+
let tripped = false;
|
|
9097
|
+
expiries.set(wasm, () => {
|
|
9098
|
+
if (!tripped && now() >= endsAt) tripped = true;
|
|
9099
|
+
return tripped;
|
|
9100
|
+
});
|
|
9101
|
+
return {
|
|
9102
|
+
start() {
|
|
9103
|
+
endsAt = now() + timeoutMs;
|
|
9104
|
+
},
|
|
9105
|
+
get tripped() {
|
|
9106
|
+
return tripped;
|
|
9107
|
+
}
|
|
9108
|
+
};
|
|
9109
|
+
}
|
|
9110
|
+
|
|
9111
|
+
// src/codemode/run.ts
|
|
9062
9112
|
async function loadStore(platform2, stateDir2) {
|
|
9063
9113
|
const storePath = `${stateDir2}/codemode-store.json`;
|
|
9064
9114
|
try {
|
|
@@ -9244,9 +9294,23 @@ async function runCode(targets, source, options) {
|
|
|
9244
9294
|
...buildDiscoveryGlobals(allDeclaredTools, namespaces, searchDocs),
|
|
9245
9295
|
...options.allowShell ? [buildShellGlobal(platform2)] : []
|
|
9246
9296
|
];
|
|
9247
|
-
const sandbox = await createSandbox(
|
|
9297
|
+
const { sandbox, deadline } = await createSandbox(
|
|
9298
|
+
platform2,
|
|
9299
|
+
toolImpls,
|
|
9300
|
+
globals,
|
|
9301
|
+
timeoutMs,
|
|
9302
|
+
memoryLimitBytes
|
|
9303
|
+
);
|
|
9248
9304
|
try {
|
|
9249
|
-
|
|
9305
|
+
deadline?.start();
|
|
9306
|
+
const executed = await sandbox.execute(code, { store });
|
|
9307
|
+
const result = deadline?.tripped && !executed.ok ? {
|
|
9308
|
+
...executed,
|
|
9309
|
+
error: {
|
|
9310
|
+
kind: "timeout",
|
|
9311
|
+
message: `Execution timed out after ${timeoutMs} ms`
|
|
9312
|
+
}
|
|
9313
|
+
} : executed;
|
|
9250
9314
|
if (result.ok) {
|
|
9251
9315
|
const writes = result.storeWrites;
|
|
9252
9316
|
if (Object.keys(writes.set).length > 0 || writes.delete.length > 0) {
|
|
@@ -9292,12 +9356,23 @@ async function createSandbox(platform2, tools, globals, timeoutMs, memoryLimitBy
|
|
|
9292
9356
|
const isKernel2 = platform2.packageDir !== void 0;
|
|
9293
9357
|
if (isKernel2) {
|
|
9294
9358
|
const { InlineCodemodeSandbox: InlineCodemodeSandbox2 } = await Promise.resolve().then(() => (init_portable(), portable_exports));
|
|
9359
|
+
const { QuickJS: QuickJS2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
9360
|
+
hookDeadlines(QuickJS2);
|
|
9295
9361
|
const wasm = await loadWasmKernel(platform2);
|
|
9296
|
-
|
|
9362
|
+
const deadline = bindDeadline(wasm, timeoutMs);
|
|
9363
|
+
const sandbox2 = new InlineCodemodeSandbox2({
|
|
9364
|
+
tools,
|
|
9365
|
+
globals,
|
|
9366
|
+
timeoutMs,
|
|
9367
|
+
wasm,
|
|
9368
|
+
memoryLimitBytes,
|
|
9369
|
+
interruptBudget: Number.POSITIVE_INFINITY
|
|
9370
|
+
});
|
|
9371
|
+
return { sandbox: sandbox2, deadline };
|
|
9297
9372
|
}
|
|
9298
|
-
const { CodemodeSandbox: CodemodeSandbox2, loadQuickJSWasm: loadQuickJSWasm2 } = await Promise.resolve().then(() => (init_dist2(),
|
|
9373
|
+
const { CodemodeSandbox: CodemodeSandbox2, loadQuickJSWasm: loadQuickJSWasm2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports2));
|
|
9299
9374
|
const wasmPath = await resolveWasmPath(platform2);
|
|
9300
|
-
|
|
9375
|
+
const sandbox = new CodemodeSandbox2({
|
|
9301
9376
|
tools,
|
|
9302
9377
|
globals,
|
|
9303
9378
|
timeoutMs,
|
|
@@ -9305,6 +9380,7 @@ async function createSandbox(platform2, tools, globals, timeoutMs, memoryLimitBy
|
|
|
9305
9380
|
wasm: loadQuickJSWasm2(wasmPath),
|
|
9306
9381
|
workerUrl: new URL("./codemode-worker.mjs", import.meta.url)
|
|
9307
9382
|
});
|
|
9383
|
+
return { sandbox };
|
|
9308
9384
|
}
|
|
9309
9385
|
async function resolveWasmPath(platform2) {
|
|
9310
9386
|
const candidates = [
|
|
@@ -12373,6 +12449,11 @@ function concat(chunks) {
|
|
|
12373
12449
|
return out;
|
|
12374
12450
|
}
|
|
12375
12451
|
var KILL_GRACE_MS = 2e3;
|
|
12452
|
+
async function trapShutdown(platform2, handler) {
|
|
12453
|
+
await Promise.all(
|
|
12454
|
+
["SIGINT", "SIGTERM", "SIGHUP"].map((sig) => platform2.onSignal?.(sig, handler))
|
|
12455
|
+
);
|
|
12456
|
+
}
|
|
12376
12457
|
async function killInflight() {
|
|
12377
12458
|
const procs = [...inflightProcs];
|
|
12378
12459
|
if (procs.length === 0) return;
|
|
@@ -12589,8 +12670,7 @@ async function discoverWithSignal(platform2, commands, childEnv, cwd) {
|
|
|
12589
12670
|
earlyAbort.abort();
|
|
12590
12671
|
inflightDone = killInflight();
|
|
12591
12672
|
};
|
|
12592
|
-
platform2
|
|
12593
|
-
platform2.onSignal?.("SIGINT", onShutdown);
|
|
12673
|
+
await trapShutdown(platform2, onShutdown);
|
|
12594
12674
|
for (const cmd of commands) {
|
|
12595
12675
|
try {
|
|
12596
12676
|
const cli = await discoverCli(platform2, cmd.path, cmd.name, childEnv, cwd, earlyAbort.signal);
|
|
@@ -12921,6 +13001,17 @@ async function runWebMcpHttp(platform2, options, getTools, callTool, serverName,
|
|
|
12921
13001
|
const address = serveAddress(platform2, options.host, actualPort);
|
|
12922
13002
|
const listenUrl = address.url;
|
|
12923
13003
|
let tokenFilePath;
|
|
13004
|
+
let shutdownRequested = false;
|
|
13005
|
+
const shutdown = () => {
|
|
13006
|
+
if (shutdownRequested) return;
|
|
13007
|
+
shutdownRequested = true;
|
|
13008
|
+
listener.close();
|
|
13009
|
+
if (tokenFilePath) {
|
|
13010
|
+
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13011
|
+
});
|
|
13012
|
+
}
|
|
13013
|
+
};
|
|
13014
|
+
await trapShutdown(platform2, shutdown);
|
|
12924
13015
|
if (generatedBearer && resolvedBearer) {
|
|
12925
13016
|
tokenFilePath = await publishBearer(
|
|
12926
13017
|
platform2,
|
|
@@ -12929,31 +13020,22 @@ async function runWebMcpHttp(platform2, options, getTools, callTool, serverName,
|
|
|
12929
13020
|
address,
|
|
12930
13021
|
options.json
|
|
12931
13022
|
);
|
|
13023
|
+
if (shutdownRequested && tokenFilePath) {
|
|
13024
|
+
await platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13025
|
+
});
|
|
13026
|
+
}
|
|
12932
13027
|
} else {
|
|
12933
13028
|
if (options.json) {
|
|
12934
13029
|
await platform2.write(1, `${JSON.stringify(address)}
|
|
12935
13030
|
`);
|
|
12936
13031
|
}
|
|
12937
13032
|
}
|
|
12938
|
-
|
|
13033
|
+
if (!shutdownRequested) {
|
|
13034
|
+
await platform2.write(2, `mcpcat serve --webmcp: listening on ${listenUrl}
|
|
12939
13035
|
`);
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
}
|
|
12943
|
-
let shutdownRequested = false;
|
|
12944
|
-
const shutdown = () => {
|
|
12945
|
-
if (shutdownRequested) return;
|
|
12946
|
-
shutdownRequested = true;
|
|
12947
|
-
listener.close();
|
|
12948
|
-
if (tokenFilePath) {
|
|
12949
|
-
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
12950
|
-
});
|
|
13036
|
+
if (options.onListening) {
|
|
13037
|
+
await options.onListening(actualPort);
|
|
12951
13038
|
}
|
|
12952
|
-
};
|
|
12953
|
-
if (platform2.onSignal) {
|
|
12954
|
-
platform2.onSignal("SIGINT", shutdown);
|
|
12955
|
-
platform2.onSignal("SIGTERM", shutdown);
|
|
12956
|
-
platform2.onSignal("SIGHUP", shutdown);
|
|
12957
13039
|
}
|
|
12958
13040
|
const handler = async (request) => {
|
|
12959
13041
|
if (request.target !== "/mcp") {
|
|
@@ -13117,6 +13199,19 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
|
|
|
13117
13199
|
const address = serveAddress(platform2, options.host, actualPort);
|
|
13118
13200
|
const listenUrl = address.url;
|
|
13119
13201
|
let tokenFilePath;
|
|
13202
|
+
let shutdownRequested = false;
|
|
13203
|
+
let proxyDone;
|
|
13204
|
+
const shutdown = () => {
|
|
13205
|
+
if (shutdownRequested) return;
|
|
13206
|
+
shutdownRequested = true;
|
|
13207
|
+
listener.close();
|
|
13208
|
+
proxyDone = proxy.shutdown();
|
|
13209
|
+
if (tokenFilePath) {
|
|
13210
|
+
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13211
|
+
});
|
|
13212
|
+
}
|
|
13213
|
+
};
|
|
13214
|
+
await trapShutdown(platform2, shutdown);
|
|
13120
13215
|
if (generatedBearer && resolvedBearer) {
|
|
13121
13216
|
tokenFilePath = await publishBearer(
|
|
13122
13217
|
platform2,
|
|
@@ -13125,32 +13220,22 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
|
|
|
13125
13220
|
address,
|
|
13126
13221
|
options.json
|
|
13127
13222
|
);
|
|
13223
|
+
if (shutdownRequested && tokenFilePath) {
|
|
13224
|
+
await platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13225
|
+
});
|
|
13226
|
+
}
|
|
13128
13227
|
} else {
|
|
13129
13228
|
if (options.json) {
|
|
13130
13229
|
await platform2.write(1, `${JSON.stringify(address)}
|
|
13131
13230
|
`);
|
|
13132
13231
|
}
|
|
13133
13232
|
}
|
|
13134
|
-
|
|
13233
|
+
if (!shutdownRequested) {
|
|
13234
|
+
await platform2.write(2, `mcpcat serve --proxy: listening on ${listenUrl}
|
|
13135
13235
|
`);
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
}
|
|
13139
|
-
let shutdownRequested = false;
|
|
13140
|
-
const shutdown = () => {
|
|
13141
|
-
if (shutdownRequested) return;
|
|
13142
|
-
shutdownRequested = true;
|
|
13143
|
-
listener.close();
|
|
13144
|
-
void proxy.shutdown();
|
|
13145
|
-
if (tokenFilePath) {
|
|
13146
|
-
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13147
|
-
});
|
|
13236
|
+
if (options.onListening) {
|
|
13237
|
+
await options.onListening(actualPort);
|
|
13148
13238
|
}
|
|
13149
|
-
};
|
|
13150
|
-
if (platform2.onSignal) {
|
|
13151
|
-
platform2.onSignal("SIGINT", shutdown);
|
|
13152
|
-
platform2.onSignal("SIGTERM", shutdown);
|
|
13153
|
-
platform2.onSignal("SIGHUP", shutdown);
|
|
13154
13239
|
}
|
|
13155
13240
|
const handler = (request) => handleProxyMcpRequest(
|
|
13156
13241
|
request,
|
|
@@ -13175,6 +13260,7 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
|
|
|
13175
13260
|
} catch {
|
|
13176
13261
|
if (!shutdownRequested) throw new Error("listener closed unexpectedly");
|
|
13177
13262
|
}
|
|
13263
|
+
await proxyDone;
|
|
13178
13264
|
return 0;
|
|
13179
13265
|
}
|
|
13180
13266
|
async function handleProxyMcpRequest(request, proxy, serverOrigins, allowedOrigins, allowedHosts, resolvedBearer) {
|
|
@@ -13294,6 +13380,19 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
|
|
|
13294
13380
|
const address = serveAddress(platform2, options.host, actualPort);
|
|
13295
13381
|
const listenUrl = address.url;
|
|
13296
13382
|
let tokenFilePath;
|
|
13383
|
+
let shutdownRequested = false;
|
|
13384
|
+
let inflightDone;
|
|
13385
|
+
const shutdown = () => {
|
|
13386
|
+
if (shutdownRequested) return;
|
|
13387
|
+
shutdownRequested = true;
|
|
13388
|
+
listener.close();
|
|
13389
|
+
inflightDone = killInflight();
|
|
13390
|
+
if (tokenFilePath) {
|
|
13391
|
+
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13392
|
+
});
|
|
13393
|
+
}
|
|
13394
|
+
};
|
|
13395
|
+
await trapShutdown(platform2, shutdown);
|
|
13297
13396
|
if (generatedBearer && resolvedBearer) {
|
|
13298
13397
|
tokenFilePath = await publishBearer(
|
|
13299
13398
|
platform2,
|
|
@@ -13302,30 +13401,19 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
|
|
|
13302
13401
|
address,
|
|
13303
13402
|
options.json
|
|
13304
13403
|
);
|
|
13404
|
+
if (shutdownRequested && tokenFilePath) {
|
|
13405
|
+
await platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13406
|
+
});
|
|
13407
|
+
}
|
|
13305
13408
|
} else {
|
|
13306
13409
|
if (options.json) {
|
|
13307
13410
|
await platform2.write(1, `${JSON.stringify(address)}
|
|
13308
13411
|
`);
|
|
13309
13412
|
}
|
|
13310
13413
|
}
|
|
13311
|
-
|
|
13414
|
+
if (!shutdownRequested) {
|
|
13415
|
+
await platform2.write(2, `mcpcat serve: listening on ${listenUrl}
|
|
13312
13416
|
`);
|
|
13313
|
-
let shutdownRequested = false;
|
|
13314
|
-
let inflightDone;
|
|
13315
|
-
const shutdown = () => {
|
|
13316
|
-
if (shutdownRequested) return;
|
|
13317
|
-
shutdownRequested = true;
|
|
13318
|
-
listener.close();
|
|
13319
|
-
inflightDone = killInflight();
|
|
13320
|
-
if (tokenFilePath) {
|
|
13321
|
-
platform2.fs.unlink?.(tokenFilePath).catch(() => {
|
|
13322
|
-
});
|
|
13323
|
-
}
|
|
13324
|
-
};
|
|
13325
|
-
if (platform2.onSignal) {
|
|
13326
|
-
platform2.onSignal("SIGINT", shutdown);
|
|
13327
|
-
platform2.onSignal("SIGTERM", shutdown);
|
|
13328
|
-
platform2.onSignal("SIGHUP", shutdown);
|
|
13329
13417
|
}
|
|
13330
13418
|
const handler = (request) => handleMcpRequest(
|
|
13331
13419
|
request,
|
|
@@ -15705,8 +15793,10 @@ async function dispatchMultiTarget(platform2, parsed, version) {
|
|
|
15705
15793
|
});
|
|
15706
15794
|
platform2.exit(exitCode);
|
|
15707
15795
|
}
|
|
15708
|
-
|
|
15709
|
-
|
|
15796
|
+
await Promise.all([
|
|
15797
|
+
platform2.onSignal?.("SIGTERM", () => void killTreeAndExit(143)),
|
|
15798
|
+
platform2.onSignal?.("SIGHUP", () => void killTreeAndExit(129))
|
|
15799
|
+
]);
|
|
15710
15800
|
const config = await MergedConfigSource.load(platform2);
|
|
15711
15801
|
if (parsed.verb === "code") {
|
|
15712
15802
|
let source;
|
|
@@ -16067,12 +16157,14 @@ async function runClientVerb(platform2, version, parsed) {
|
|
|
16067
16157
|
});
|
|
16068
16158
|
platform2.exit(exitCode);
|
|
16069
16159
|
}
|
|
16070
|
-
|
|
16071
|
-
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
|
|
16075
|
-
|
|
16160
|
+
await Promise.all([
|
|
16161
|
+
platform2.onSignal?.("SIGINT", () => {
|
|
16162
|
+
interrupted = true;
|
|
16163
|
+
sigintController.abort();
|
|
16164
|
+
}),
|
|
16165
|
+
platform2.onSignal?.("SIGTERM", () => void killTreeAndExit(143)),
|
|
16166
|
+
platform2.onSignal?.("SIGHUP", () => void killTreeAndExit(129))
|
|
16167
|
+
]);
|
|
16076
16168
|
const showProgress = !parsed.silent && (parsed.verbose || platform2.isatty(2));
|
|
16077
16169
|
const onProgress = (progress, total, message) => {
|
|
16078
16170
|
if (!showProgress) return;
|
|
@@ -16320,6 +16412,15 @@ async function kernelSpawn(ctx, options) {
|
|
|
16320
16412
|
await ctx.kill(childPid, signal);
|
|
16321
16413
|
} catch {
|
|
16322
16414
|
}
|
|
16415
|
+
},
|
|
16416
|
+
async groupAlive() {
|
|
16417
|
+
if (!useGroupKill) return false;
|
|
16418
|
+
try {
|
|
16419
|
+
await ctx.kill(-childPid, "SIGCONT");
|
|
16420
|
+
return true;
|
|
16421
|
+
} catch {
|
|
16422
|
+
return false;
|
|
16423
|
+
}
|
|
16323
16424
|
}
|
|
16324
16425
|
};
|
|
16325
16426
|
}
|
|
@@ -16555,8 +16656,8 @@ function createKernelPlatform(ctx, options) {
|
|
|
16555
16656
|
exit(code) {
|
|
16556
16657
|
ctx.exit(code);
|
|
16557
16658
|
},
|
|
16558
|
-
onSignal(signal, handler) {
|
|
16559
|
-
ctx.signals.on(signal, handler);
|
|
16659
|
+
async onSignal(signal, handler) {
|
|
16660
|
+
await ctx.signals.on(signal, handler);
|
|
16560
16661
|
},
|
|
16561
16662
|
async seal(request) {
|
|
16562
16663
|
return kernelSeal(ctx, request);
|
|
@@ -16577,7 +16678,7 @@ async function main(ctx) {
|
|
|
16577
16678
|
packageDir: "/node_modules/@ai-ecoverse/mcpcat"
|
|
16578
16679
|
});
|
|
16579
16680
|
const args = ctx.argv.slice(1);
|
|
16580
|
-
return run(platform2, "0.15.
|
|
16681
|
+
return run(platform2, "0.15.8", args);
|
|
16581
16682
|
}
|
|
16582
16683
|
export {
|
|
16583
16684
|
main as default
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/mcpcat",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.8",
|
|
4
4
|
"description": "A curl for the Model Context Protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -56,8 +56,9 @@
|
|
|
56
56
|
"trust:dry": "npx fledgling sync --dry-run -y --skip-publish"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@ai-ecoverse/slicc-
|
|
60
|
-
"@ai-ecoverse/slicc-
|
|
59
|
+
"@ai-ecoverse/slicc-bios": "1.1.2",
|
|
60
|
+
"@ai-ecoverse/slicc-kernel": "1.94.4",
|
|
61
|
+
"@ai-ecoverse/slicc-shared-web": "1.20.0",
|
|
61
62
|
"@biomejs/biome": "2.5.15",
|
|
62
63
|
"@earendil-works/pi-codemode": "1.2.0",
|
|
63
64
|
"@earendil-works/pi-mcp": "1.2.0",
|