@moor-sh/mcp 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/index.ts +37 -3
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -364,15 +364,49 @@ server.registerTool(
|
|
|
364
364
|
"moor_exec",
|
|
365
365
|
{
|
|
366
366
|
title: "Execute Command",
|
|
367
|
-
description:
|
|
367
|
+
description:
|
|
368
|
+
"Run a shell command inside a project's running container. Bounded by a per-call timeout (default 10 min, max 1 h). For jobs that may exceed an hour, wait for the async exec tools to ship.",
|
|
368
369
|
inputSchema: z.object({
|
|
369
370
|
project: z.string().describe("Project name or ID"),
|
|
370
371
|
command: z.string().describe("Shell command to execute"),
|
|
372
|
+
timeout_ms: z
|
|
373
|
+
.number()
|
|
374
|
+
.int()
|
|
375
|
+
.min(1000)
|
|
376
|
+
.max(3_600_000)
|
|
377
|
+
.optional()
|
|
378
|
+
.describe(
|
|
379
|
+
"Max time in milliseconds before the exec is aborted. Default 600000 (10 min). Max 3600000 (1 h).",
|
|
380
|
+
),
|
|
371
381
|
}),
|
|
372
382
|
},
|
|
373
|
-
async ({ project, command }) => {
|
|
383
|
+
async ({ project, command, timeout_ms }) => {
|
|
374
384
|
const p = await resolveProject(project);
|
|
375
|
-
const
|
|
385
|
+
const body: Record<string, unknown> = { command };
|
|
386
|
+
if (timeout_ms !== undefined) body.timeout_ms = timeout_ms;
|
|
387
|
+
const res = await apiPost(`/api/projects/${p.id}/exec`, body);
|
|
388
|
+
// The API returns 504 with a structured timeout body when the exec hit
|
|
389
|
+
// timeout_ms. Surface the kill outcome in the tool error so the agent can
|
|
390
|
+
// tell "the process was actually stopped" from "we just stopped waiting."
|
|
391
|
+
if (res.status === 504) {
|
|
392
|
+
const t = (await res.json()) as {
|
|
393
|
+
timeout_ms: number;
|
|
394
|
+
killed: boolean;
|
|
395
|
+
killed_pid: string | null;
|
|
396
|
+
live_remaining: number;
|
|
397
|
+
message: string;
|
|
398
|
+
};
|
|
399
|
+
let detail: string;
|
|
400
|
+
if (t.killed) {
|
|
401
|
+
detail = `Process tree terminated (container pid ${t.killed_pid}).`;
|
|
402
|
+
} else if (t.killed_pid !== null) {
|
|
403
|
+
detail = `Kill attempted on container pid ${t.killed_pid} but ${t.live_remaining} descendant process(es) still running inside the container.`;
|
|
404
|
+
} else {
|
|
405
|
+
detail =
|
|
406
|
+
"Process kill could not locate the running process — it may still be running inside the container.";
|
|
407
|
+
}
|
|
408
|
+
throw new Error(`Exec timed out after ${t.timeout_ms}ms. ${detail}`);
|
|
409
|
+
}
|
|
376
410
|
if (!res.ok) throw new Error(`Failed: ${await res.text()}`);
|
|
377
411
|
const result = (await res.json()) as {
|
|
378
412
|
exitCode: number;
|