@zswarm/mcp 0.1.7 → 0.1.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/README.md +3 -1
- package/dist/mcp-server.js +104 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -41,7 +41,9 @@ the Zellij environment. Give the interpreter an absolute path and set
|
|
|
41
41
|
`ZSWARM_SESSION`. Forward `ZELLIJ_PANE_ID` (or set `ZSWARM_FROM`) so send
|
|
42
42
|
labels `[zswarm from=…]` with the sending pane instead of `swarm`.
|
|
43
43
|
`ZSWARM_SSH` or `ZSWARM_SERVE` routes the same tool at a remote crew.
|
|
44
|
-
|
|
44
|
+
`ZSWARM_SERVE` may be `host:port` or `ssh://user@host?servePort=9419` (MCP reuses
|
|
45
|
+
a healthy owned tunnel until stdin EOF, then cancels in-flight work and reaps
|
|
46
|
+
the SSH child). Details: the [zswarm README](../../README.md).
|
|
45
47
|
|
|
46
48
|
## License
|
|
47
49
|
|
package/dist/mcp-server.js
CHANGED
|
@@ -3,9 +3,58 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
-
import { dispatchZswarm, mcpInputSchema, MCP_TOOL_DESCRIPTION, } from "@zswarm/core";
|
|
6
|
+
import { createServeTunnelManager, dispatchZswarm, mcpInputSchema, MCP_TOOL_DESCRIPTION, } from "@zswarm/core";
|
|
7
7
|
const { version } = createRequire(import.meta.url)("../package.json");
|
|
8
|
+
const SHUTDOWN_BOUND_MS = 5_000;
|
|
9
|
+
const serveTunnels = createServeTunnelManager({ persistIdle: true });
|
|
10
|
+
const requestAborts = new Set();
|
|
11
|
+
let inflight = 0;
|
|
12
|
+
let shuttingDown = false;
|
|
13
|
+
let shutdownPromise;
|
|
8
14
|
const server = new Server({ name: "zswarm", version }, { capabilities: { tools: {} } });
|
|
15
|
+
const transport = new StdioServerTransport();
|
|
16
|
+
function sleep(ms) {
|
|
17
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
|
+
}
|
|
19
|
+
async function shutdown() {
|
|
20
|
+
if (shutdownPromise)
|
|
21
|
+
return shutdownPromise;
|
|
22
|
+
shuttingDown = true;
|
|
23
|
+
shutdownPromise = (async () => {
|
|
24
|
+
for (const ac of requestAborts)
|
|
25
|
+
ac.abort();
|
|
26
|
+
const bound = Date.now() + SHUTDOWN_BOUND_MS;
|
|
27
|
+
while (inflight > 0 && Date.now() < bound) {
|
|
28
|
+
await sleep(15);
|
|
29
|
+
}
|
|
30
|
+
await Promise.race([
|
|
31
|
+
serveTunnels.closeAll(),
|
|
32
|
+
sleep(2_000),
|
|
33
|
+
]);
|
|
34
|
+
await Promise.race([
|
|
35
|
+
server.close().catch(() => undefined),
|
|
36
|
+
sleep(500),
|
|
37
|
+
]);
|
|
38
|
+
try {
|
|
39
|
+
await Promise.race([transport.close(), sleep(500)]);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
/* already closed */
|
|
43
|
+
}
|
|
44
|
+
})();
|
|
45
|
+
await shutdownPromise;
|
|
46
|
+
}
|
|
47
|
+
function requestShutdown(exitAfter) {
|
|
48
|
+
const force = setTimeout(() => {
|
|
49
|
+
if (exitAfter)
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}, SHUTDOWN_BOUND_MS);
|
|
52
|
+
void shutdown().finally(() => {
|
|
53
|
+
clearTimeout(force);
|
|
54
|
+
if (exitAfter)
|
|
55
|
+
process.exit(0);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
9
58
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
10
59
|
tools: [
|
|
11
60
|
{
|
|
@@ -32,13 +81,59 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
32
81
|
isError: true,
|
|
33
82
|
};
|
|
34
83
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
84
|
+
if (shuttingDown) {
|
|
85
|
+
return {
|
|
86
|
+
content: [
|
|
87
|
+
{
|
|
88
|
+
type: "text",
|
|
89
|
+
text: JSON.stringify({
|
|
90
|
+
ok: false,
|
|
91
|
+
error: { code: "cancelled", message: "serve tunnel manager is closed" },
|
|
92
|
+
}),
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
isError: true,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const ac = new AbortController();
|
|
99
|
+
const onExtraAbort = () => ac.abort();
|
|
100
|
+
extra.signal?.addEventListener("abort", onExtraAbort, { once: true });
|
|
101
|
+
requestAborts.add(ac);
|
|
102
|
+
inflight += 1;
|
|
103
|
+
try {
|
|
104
|
+
const result = await dispatchZswarm(args, undefined, {
|
|
105
|
+
signal: ac.signal,
|
|
106
|
+
serveTunnels,
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
content: [
|
|
110
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
111
|
+
],
|
|
112
|
+
isError: !result.ok,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
extra.signal?.removeEventListener("abort", onExtraAbort);
|
|
117
|
+
requestAborts.delete(ac);
|
|
118
|
+
inflight -= 1;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
transport.onclose = () => {
|
|
122
|
+
requestShutdown(true);
|
|
123
|
+
};
|
|
124
|
+
transport.onerror = () => {
|
|
125
|
+
requestShutdown(true);
|
|
126
|
+
};
|
|
127
|
+
process.stdin.on("end", () => {
|
|
128
|
+
requestShutdown(true);
|
|
129
|
+
});
|
|
130
|
+
process.stdin.on("close", () => {
|
|
131
|
+
requestShutdown(true);
|
|
132
|
+
});
|
|
133
|
+
process.once("SIGINT", () => {
|
|
134
|
+
requestShutdown(true);
|
|
135
|
+
});
|
|
136
|
+
process.once("SIGTERM", () => {
|
|
137
|
+
requestShutdown(true);
|
|
42
138
|
});
|
|
43
|
-
const transport = new StdioServerTransport();
|
|
44
139
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zswarm/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "zSwarm MCP server — Zellij pane coordination",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
11
|
-
"@zswarm/core": "0.1.
|
|
11
|
+
"@zswarm/core": "0.1.8"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@types/node": "22.14.1",
|