@moor-sh/mcp 0.10.0 → 0.11.0
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 +41 -0
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -660,6 +660,47 @@ server.registerTool(
|
|
|
660
660
|
},
|
|
661
661
|
);
|
|
662
662
|
|
|
663
|
+
server.registerTool(
|
|
664
|
+
"moor_project_stats",
|
|
665
|
+
{
|
|
666
|
+
title: "Project Container Stats (live)",
|
|
667
|
+
description:
|
|
668
|
+
"Live container stats for one project: CPU percent, memory (excluding page cache, same accounting as `docker stats`), network and block I/O totals, PID count. Single Docker stats snapshot — CPU uses the cpu_stats/precpu_stats delta the daemon already includes. Stopped or never-started projects return running=false with zeroed counters (no 404).",
|
|
669
|
+
inputSchema: z.object({
|
|
670
|
+
project: z.string().describe("Project name or ID"),
|
|
671
|
+
}),
|
|
672
|
+
},
|
|
673
|
+
async ({ project }) => {
|
|
674
|
+
const p = await resolveProject(project);
|
|
675
|
+
const res = await apiGet(`/api/projects/${p.id}/container-stats`);
|
|
676
|
+
if (!res.ok) throw new Error(`Failed: ${res.status} ${await res.text()}`);
|
|
677
|
+
const s = (await res.json()) as {
|
|
678
|
+
running: boolean;
|
|
679
|
+
cpu_percent: number;
|
|
680
|
+
memory_bytes: number;
|
|
681
|
+
memory_limit_bytes: number;
|
|
682
|
+
memory_percent: number;
|
|
683
|
+
network_rx_bytes: number;
|
|
684
|
+
network_tx_bytes: number;
|
|
685
|
+
block_read_bytes: number;
|
|
686
|
+
block_write_bytes: number;
|
|
687
|
+
pids: number;
|
|
688
|
+
};
|
|
689
|
+
if (!s.running) {
|
|
690
|
+
return {
|
|
691
|
+
content: [{ type: "text", text: `${p.name}: not running (zeroed counters returned).` }],
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
const memLimit = s.memory_limit_bytes > 0 ? formatBytes(s.memory_limit_bytes) : "unlimited";
|
|
695
|
+
const lines = [
|
|
696
|
+
`${p.name}: CPU ${s.cpu_percent}% | Memory ${formatBytes(s.memory_bytes)} / ${memLimit} (${s.memory_percent}%) | PIDs ${s.pids}`,
|
|
697
|
+
`Network: rx ${formatBytes(s.network_rx_bytes)} / tx ${formatBytes(s.network_tx_bytes)}`,
|
|
698
|
+
`Block I/O: read ${formatBytes(s.block_read_bytes)} / write ${formatBytes(s.block_write_bytes)}`,
|
|
699
|
+
];
|
|
700
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
701
|
+
},
|
|
702
|
+
);
|
|
703
|
+
|
|
663
704
|
function formatBytes(bytes: number): string {
|
|
664
705
|
if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
|
|
665
706
|
const units = ["B", "KB", "MB", "GB", "TB"];
|