@hheei/ssh-exec-mcp 0.1.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/LICENSE +21 -0
- package/README.md +162 -0
- package/bin/ssh-exec-mcp.js +37 -0
- package/examples/pi-agent.mcp.json +10 -0
- package/package.json +35 -0
- package/plugins/ssh-exec/.codex-plugin/plugin.json +35 -0
- package/plugins/ssh-exec/.mcp.json +11 -0
- package/plugins/ssh-exec/assets/icon.svg +34 -0
- package/plugins/ssh-exec/scripts/output-tail-sink.test.ts +69 -0
- package/plugins/ssh-exec/scripts/output-tail-sink.ts +182 -0
- package/plugins/ssh-exec/scripts/session-manager.ts +525 -0
- package/plugins/ssh-exec/scripts/ssh-exec-mcp.test.ts +206 -0
- package/plugins/ssh-exec/scripts/ssh-exec-mcp.ts +368 -0
- package/plugins/ssh-exec/scripts/ssh-exec.test.ts +364 -0
- package/plugins/ssh-exec/scripts/ssh-exec.ts +336 -0
- package/plugins/ssh-exec/scripts/ssh-mount.ts +27 -0
- package/ssh-exec-mcp.ts +43 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SessionManager, type ProcessRunner, type SshMountResult } from "./session-manager";
|
|
2
|
+
import { validateHost } from "./ssh-exec";
|
|
3
|
+
|
|
4
|
+
export interface SshMountArgs {
|
|
5
|
+
host: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function validateSshMountArgs(value: unknown): SshMountArgs {
|
|
9
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10
|
+
throw new Error("ssh_mount arguments must be an object");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const record = value as Record<string, unknown>;
|
|
14
|
+
if (typeof record.host !== "string" || record.host.trim() === "") {
|
|
15
|
+
throw new Error("ssh_mount.host must be a non-empty string");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return { host: validateHost(record.host) };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function executeSshMount(
|
|
22
|
+
manager: SessionManager,
|
|
23
|
+
args: SshMountArgs,
|
|
24
|
+
runner: ProcessRunner,
|
|
25
|
+
): Promise<SshMountResult> {
|
|
26
|
+
return await manager.ensureMounted(validateHost(args.host), runner);
|
|
27
|
+
}
|
package/ssh-exec-mcp.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createMcpServer,
|
|
5
|
+
runCleanupSshProcess,
|
|
6
|
+
runStdio,
|
|
7
|
+
} from "./plugins/ssh-exec/scripts/ssh-exec-mcp";
|
|
8
|
+
|
|
9
|
+
const server = createMcpServer();
|
|
10
|
+
const runner = (args: string[], timeoutMs?: number) =>
|
|
11
|
+
runCleanupSshProcess(server.manager.sshBin, args, timeoutMs, server.manager.sensitiveValues());
|
|
12
|
+
|
|
13
|
+
let cleanupPromise: Promise<void> | undefined;
|
|
14
|
+
|
|
15
|
+
async function cleanup(budgetMs = 1_500): Promise<void> {
|
|
16
|
+
cleanupPromise ??= Promise.race([
|
|
17
|
+
server.manager.closeAll(runner, Math.min(1_000, budgetMs)),
|
|
18
|
+
new Promise<void>((resolve) => setTimeout(resolve, budgetMs)),
|
|
19
|
+
]).catch(() => undefined);
|
|
20
|
+
await cleanupPromise;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
process.once("beforeExit", () => {
|
|
24
|
+
void cleanup();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
process.on("SIGINT", () => {
|
|
28
|
+
void cleanup().finally(() => process.exit(130));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
process.on("SIGTERM", () => {
|
|
32
|
+
void cleanup().finally(() => process.exit(143));
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
runStdio(server)
|
|
36
|
+
.then(async () => {
|
|
37
|
+
await cleanup();
|
|
38
|
+
process.exit(0);
|
|
39
|
+
})
|
|
40
|
+
.catch((error) => {
|
|
41
|
+
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
});
|