Recently Written · git

sshp-ai

Agent skill + read-only MCP server for parallel SSH fleet checks with bahamas10/sshp

git clone https://github.com/equwal/sshp-ai

Log | Files | Refs


README.md (3470 bytes)

1 # sshp-ai
2 
3 A parallel SSH runner for AI coding agents: run one command on many hosts at once and get per-host output and exit codes.
4 
5 sshp-ai wraps [sshp](https://github.com/bahamas10/sshp) by Dave Eddy (bahamas10), a fast parallel SSH executor written in C. It adds two things:
6 
7 - **`skills/sshp/SKILL.md`**: an agent skill that teaches when and how to use sshp: `-n` dry runs before risky commands, `BatchMode` and timeouts so nothing hangs, output grouping, and per-host exit codes. It works in the skills folders of Claude Code, Codex, Copilot CLI and Antigravity.
8 - **`sshp_mcp.py`**: a stdio MCP server (Python 3 stdlib only) with two tools:
9   - `sshp_run(command, hosts?, max_jobs?, timeout?, user?, dry_run?)` returns JSON with each host's output and exit code.
10   - `sshp_hosts()` lists the allowlisted hosts and whether writes are enabled.
11 
12 sshp-ai does not include sshp's code. Install sshp yourself.
13 
14 ## Safety model
15 
16 The operator sets the limits in a config file. The model cannot change them.
17 
18 - **Host allowlist.** Only hosts in the hosts file can be targeted.
19 - **Conservative default.** Out of the box, a command must start with an allowed verb (`uptime`, `df`, `systemctl status`, `journalctl`, `docker ps`, ...) and must not contain shell metacharacters (`; | & > < $ \` ( )`). Write-like forms such as `find -delete`, `systemctl restart` or `date -s` are refused.
20 - **`"allow_write": true` makes it a general-purpose runner.** Set it in the config to run any command (restarts, installs, edits). Only the operator can set it. The host allowlist still applies.
21 - ssh runs with `BatchMode=yes` and `ConnectTimeout=10`, so a prompt fails fast. The whole run has a timeout (default 60 s, max 600 s).
22 
23 ## Install
24 
25 1. Build and install sshp (see its README). It must be on `PATH`, or set `"sshp"` in the config.
26 2. Copy the skill into your agent's skills folder:
27 
28    ```sh
29    for d in ~/.claude/skills ~/.codex/skills ~/.copilot/skills ~/.gemini/skills ~/.gemini/antigravity/skills; do
30      mkdir -p "$d" && cp -r skills/sshp "$d/"
31    done
32    ```
33 
34 3. Create the hosts file and (optionally) the config:
35 
36    ```sh
37    mkdir -p ~/.config/sshp-ai
38    printf 'web1.example.com\nroot@db1.example.com\n' > ~/.config/sshp-ai/hosts
39    ```
40 
41    `~/.config/sshp-ai/config.json` (all keys optional):
42 
43    ```json
44    {
45      "hosts_file": "~/.config/sshp-ai/hosts",
46      "allow_write": false,
47      "sshp": "sshp",
48      "ssh_options": ["BatchMode=yes", "ConnectTimeout=10"]
49    }
50    ```
51 
52    Set `SSHP_AI_CONFIG` to use another config path.
53 
54 4. Register the MCP server, for example in Claude Code:
55 
56    ```sh
57    claude mcp add -s user sshp -- python3 /path/to/sshp_mcp.py
58    ```
59 
60    Other clients take the same command (`python3 /path/to/sshp_mcp.py`) in their MCP config.
61 
62 ## Example result
63 
64 ```json
65 {
66  "sshp_exit_code": 1,
67  "dry_run": false,
68  "hosts": {
69   "web1.example.com": {"output": " 10:00:01 up 3 days, load average: 0.10", "exit_code": 0},
70   "db1.example.com": {"output": "ssh: connect to host db1.example.com port 22: Connection refused", "exit_code": 255}
71  },
72  "sshp_stderr": ""
73 }
74 ```
75 
76 sshp merges each host's stdout and stderr into one stream, so `output` holds both.
77 
78 ## Tests
79 
80 ```sh
81 python3 -m unittest -v test_sshp_mcp
82 ```
83 
84 The policy tests run anywhere. The integration tests need `sshp` on `PATH` and a POSIX system; a mock `ssh` script plays the remote hosts, so no network is used.
85 
86 ## License
87 
88 MIT, the same license as sshp. sshp is Copyright 2021 Dave Eddy.