@aaarc/handfree-ssh-mcp 1.0.6 → 1.0.9
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 +14 -10
- package/build/config/server.js +8 -6
- package/build/services/ssh-connection-manager.js +579 -191
- package/build/tools/download.js +15 -2
- package/build/tools/execute-command.js +1 -0
- package/build/tools/help.js +63 -27
- package/build/tools/transfer.js +13 -6
- package/build/tools/upload.js +13 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,9 +116,9 @@ The AI can now execute commands on your servers. All within your defined securit
|
|
|
116
116
|
| `execute-command` | Run SSH command (with optional `stream` for real-time output) |
|
|
117
117
|
| `show-whitelist` | Show active command policy + SFTP policy + output-log path for a server |
|
|
118
118
|
| `close-connection` | Close a cached SSH connection for a server |
|
|
119
|
-
| `upload` | Upload local file to a remote server (CRLF-fix for shell scripts, skip-if-identical) |
|
|
120
|
-
| `download` | Download remote file to local disk |
|
|
121
|
-
| `transfer` | Unified upload / download / server-to-server relay (`mode`: `upload` / `download` / `relay`, optional `recursive`,
|
|
119
|
+
| `upload` | Upload local file to a remote server (CRLF-fix for shell scripts, skip-if-identical, optional `reuseConnection`, `vvv`, `fast`) |
|
|
120
|
+
| `download` | Download remote file to local disk (optional `reuseConnection`, `vvv`, `fast`) |
|
|
121
|
+
| `transfer` | Unified upload / download / server-to-server relay (`mode`: `upload` / `download` / `relay`, optional `recursive`, `skipIfIdentical`, `reuseConnection`, `vvv`, `fast`) |
|
|
122
122
|
| `list-servers` | List configured (enabled) servers. Lean by default; `verbose:true` adds cached system status, `refresh:true` re-collects it (implies verbose). |
|
|
123
123
|
| `help` | Self-describing help text for the MCP client |
|
|
124
124
|
|
|
@@ -298,16 +298,18 @@ Rules (enforced at config load — bad configs fail fast):
|
|
|
298
298
|
- **Cached clients stay open while reused.** With the default `reuseConnection: true`, `execute-command` does not close the SSH client after each command. If a cached client must be opened first, SSH setup, jump, SOCKS, and channel-open waits are bounded by the call's `timeout`. The cached client is closed on explicit disconnect/server shutdown, config hot-reload for changed connection fields, underlying SSH close/error cleanup, or reconnect after a connection-shaped command failure.
|
|
299
299
|
- **Manual cached-client close.** Use `close-connection { connectionName: "name" }` to drop a cached SSH client on demand. If the named server is a jump host, cached targets that jump through it are closed too.
|
|
300
300
|
- **Auto-reconnect on `execute-command`.** Every command runs inside a retry loop (default 3 attempts: 1 initial + 2 retries) with exponential backoff. If the underlying error matches a connection-shaped pattern (`econnreset`, `epipe`, `socket`, `closed`, `channel`, `end of stream`, or a `SSH_CONNECTION_FAILED` ToolError), the manager closes the dead client, reconnects, and retries the command. Non-connection errors (permission denied, validation, command-not-found) are returned immediately without retry.
|
|
301
|
-
- **Optional fresh command connections.** `execute-command`
|
|
301
|
+
- **Optional fresh command/SFTP connections.** `execute-command`, `upload`, `download`, and `transfer` reuse cached SSH clients by default (`reuseConnection: true`). If a call times out or you suspect the cached `ssh2.Client` is stale while native `ssh` works, retry with `reuseConnection: false`; that one operation opens a fresh SSH connection and closes it afterwards. SFTP still opens a new SFTP channel/session per operation.
|
|
302
302
|
- **Optional SSH debug output.** Set `vvv: true` on `execute-command` to append bounded SSH/channel debug output to the result or error. For full ssh2 handshake logs, combine it with `reuseConnection: false`; an already-open cached client cannot retroactively emit handshake debug.
|
|
303
|
-
- **SFTP
|
|
303
|
+
- **Optional SFTP debug output.** Set `vvv: true` on `upload`, `download`, or `transfer` to append bounded SSH/SFTP debug where the result is textual. Recursive `transfer` success keeps its structured `{ summary, files }` JSON response, so recursive debug is surfaced on errors rather than appended to successful summaries.
|
|
304
|
+
- **SFTP transfers do NOT auto-retry.** `upload` / `download` / `transfer` lazy-connect via the same acquisition path and close stale cached clients on connection-shaped SFTP/channel errors, but a mid-transfer disconnect surfaces as a single failure — re-issue the call manually, preferably with `reuseConnection: false` if you suspect the cached SSH client.
|
|
304
305
|
- **No background keepalive or health probe.** Dead connections are only discovered on the next tool call. If you idle for hours through a NATed network, expect the first call after the gap to fail-then-reconnect on its own (you'll see one retry in the logs).
|
|
305
306
|
|
|
306
307
|
### Upload behaviors
|
|
307
308
|
|
|
308
|
-
- **CRLF auto-fix for shell scripts.** When uploading a `.sh`, `.bash`, or `.zsh` file, any `\r\n` line endings are automatically converted to `\n` before the bytes are sent. The response notes when this happens and how many line endings were rewritten. The local file on disk is left untouched.
|
|
309
|
-
- **Skip-if-identical (default on).** Before transferring, `upload` checks whether the remote file already matches the local payload. Files ≤ 256 MiB are compared byte-for-byte; larger files are compared via MD5 (using `md5sum` on the remote host). **Shell scripts (`.sh` / `.bash` / `.zsh`) are compared in a line-ending-agnostic way — both sides are LF-normalized before the comparison, so a CRLF-only diff is treated as identical and the upload is still skipped.** If they match, the upload is skipped and the response says so. Pass `skipIfIdentical: false` to force a re-upload. Recursive `transfer` (`mode: upload`, `recursive: true`) applies the same check per file.
|
|
310
|
-
- **
|
|
309
|
+
- **CRLF auto-fix for shell scripts.** When uploading a `.sh`, `.bash`, or `.zsh` file, any `\r\n` line endings are automatically converted to `\n` before the bytes are sent. The response notes when this happens and how many line endings were rewritten. The local file on disk is left untouched.
|
|
310
|
+
- **Skip-if-identical (default on).** Before transferring, `upload` checks whether the remote file already matches the local payload. Files ≤ 256 MiB are compared byte-for-byte; larger files are compared via MD5 (using `md5sum` on the remote host). **Shell scripts (`.sh` / `.bash` / `.zsh`) are compared in a line-ending-agnostic way — both sides are LF-normalized before the comparison, so a CRLF-only diff is treated as identical and the upload is still skipped.** If they match, the upload is skipped and the response says so. Pass `skipIfIdentical: false` to force a re-upload. Recursive `transfer` (`mode: upload`, `recursive: true`) applies the same check per file.
|
|
311
|
+
- **Fast single-file SFTP (default off).** Set `fast: true` on `upload`, `download`, or `transfer` upload/download mode to use ssh2 `fastPut` / `fastGet` for host-to-remote or remote-to-host single-file throughput. Optional `sftpConcurrency` and `chunkSize` are passed to ssh2 only when `fast: true`; omitted values use ssh2 defaults. This is not multi-file concurrency: recursive directory transfer remains sequential, and relay mode keeps its remote-A → MCP host → remote-B streaming pipe path. If a shell-script upload needs CRLF-to-LF conversion, it falls back to the normal safe upload path.
|
|
312
|
+
- **Relay skip-if-identical (default on).** `transfer mode=relay` does the same check between two remote servers: matching size on both sides plus matching `md5sum` skips the transfer. If `md5sum` is missing on either server, the check falls back to a normal transfer.
|
|
311
313
|
|
|
312
314
|
### `execute-command` output capping & full logs
|
|
313
315
|
|
|
@@ -375,8 +377,10 @@ Example with selective servers:
|
|
|
375
377
|
### Nice to Have
|
|
376
378
|
- [x] **Command history / output archive**: full stdout/stderr of every `execute-command` is persisted under `<outputLogDir>/<server>/<user>/*.log`
|
|
377
379
|
- [x] **Multi-command execution**: Execute multiple commands in sequence with `&&` or `;` safely (fixed: `2>/dev/null` now allowed)
|
|
378
|
-
- [x] **Connection auto-recovery**: `execute-command` retries with exponential backoff and forced reconnect on connection-shaped errors
|
|
379
|
-
- [
|
|
380
|
+
- [x] **Connection auto-recovery**: `execute-command` retries with exponential backoff and forced reconnect on connection-shaped errors
|
|
381
|
+
- [x] **SFTP connection reuse controls**: `upload` / `download` / `transfer` support `reuseConnection`, `vvv`, and explicit fresh one-shot SSH clients
|
|
382
|
+
- [x] **Fast single-file SFTP**: optional ssh2 `fastPut` / `fastGet` via `fast`, `sftpConcurrency`, and `chunkSize`
|
|
383
|
+
- [ ] **SFTP retry parity**: extend the retry-with-reconnect loop to `upload` / `download` / `transfer`
|
|
380
384
|
- [ ] **TCP keepalive**: pass `keepaliveInterval` / `keepaliveCountMax` to `ssh2.Client` so half-open connections are detected without waiting for the next command
|
|
381
385
|
- [ ] **Server health check**: optional periodic ping to detect drops proactively
|
|
382
386
|
|
package/build/config/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const SERVER_CONFIG = {
|
|
2
2
|
name: "ssh-mcp-server",
|
|
3
|
-
version: "1.0.
|
|
3
|
+
version: "1.0.9",
|
|
4
4
|
};
|
|
5
5
|
export const SERVER_INSTRUCTIONS = `This server provides SSH access to servers loaded from OpenSSH config (~/.ssh/config by default) and optional YAML config/policy overlays.
|
|
6
6
|
|
|
@@ -11,10 +11,12 @@ Recommended workflow:
|
|
|
11
11
|
4. Use stream=false for short commands that should finish quickly, such as pwd, ls, cat, head, tail, git status, or docker ps.
|
|
12
12
|
5. Use stream=true for commands that may take longer or where incremental output is useful.
|
|
13
13
|
6. execute-command reuses SSH connections by default. If an execute-command call times out, retry the next command with reuseConnection=false to bypass a potentially stale cached SSH connection.
|
|
14
|
-
7.
|
|
15
|
-
8.
|
|
16
|
-
9.
|
|
17
|
-
10.
|
|
14
|
+
7. SFTP tools also reuse SSH connections by default. If upload/download/transfer times out or reports a connection-shaped SFTP/channel error, retry with reuseConnection=false; the fresh SSH connection closes after that transfer.
|
|
15
|
+
8. Use close-connection to close a cached SSH connection for a server before retrying with a clean reused connection. Closing a jump host also closes cached targets that jump through it.
|
|
16
|
+
9. For SSH/channel diagnostics, add vvv=true. Use it with reuseConnection=false when you need fresh handshake/debug output.
|
|
17
|
+
10. Use upload and download for single-file SFTP transfers. Use transfer for recursive directory transfers or cross-server relay.
|
|
18
|
+
11. For large host-to-remote or remote-to-host single-file SFTP transfers, fast=true enables ssh2 fastPut/fastGet with optional sftpConcurrency and chunkSize. It is off by default and does not add multi-file concurrency; relay keeps the streaming pipe path.
|
|
19
|
+
12. Call help or help { tool: "<name>" } for detailed per-tool parameter docs and examples.
|
|
18
20
|
|
|
19
21
|
Server targeting:
|
|
20
22
|
- When only one server is enabled, connectionName can be omitted and the server is auto-selected.
|
|
@@ -24,5 +26,5 @@ Behavior notes:
|
|
|
24
26
|
- A tool may automatically establish the SSH connection on first use.
|
|
25
27
|
- Command execution uses blacklist mode by default, with a built-in dangerous-command blacklist. Servers can opt into whitelist mode through YAML. If a command is rejected, inspect the command policy rather than retrying the same command repeatedly.
|
|
26
28
|
- Some commands return no output on success; this is normal.
|
|
27
|
-
- File transfer tools use SFTP and can fail if the remote path is missing or permissions are insufficient.
|
|
29
|
+
- File transfer tools use SFTP and can fail if the remote path is missing or permissions are insufficient. They open a new SFTP channel per operation; they reuse the underlying SSH client unless reuseConnection=false is set.
|
|
28
30
|
- OpenSSH/YAML config changes are hot-reloaded without restarting the server. Connection-field changes close the old client so the next tool call reconnects with fresh settings.`;
|