mcp-ssh has 7 tools with consistent naming (verb_noun pattern) and comprehensive descriptions. All tools have input schemas with type definitions and parameter descriptions. However, several critical issues limit the score: (1) Output schemas are not explicitly documented, responses are inferred from code but not formally declared in tool definitions. (2) Error handling is minimal, no error categorization, recovery guidance, or actionable error messages. (3) No per-parameter constraints (enums, min/max, patterns) in schemas despite handling sensitive inputs like commands. (4) No pagination or result-limit documentation for list_hosts. (5) Security concerns: commands are executed directly from user input without sanitization guidance, and sensitive paths (local_path, remote_path) lack format validation. (6) The descriptions are good (100-150 chars on average), but lack dependency hints and prerequisites (e.g., 'Must configure hosts in hosts.json first'). Tools like ssh_execute and ssh_execute_batch operate on high-risk operations (remote command execution) without idempotency guidance or dry-run options.
List all configured SSH hosts and their connection status. Returns a list of hosts with name, hostname, port, username, connection state, and any command restrictions. Call this first to discover available hosts.
Disconnect from a specific SSH host. Args: host: Name of the configured SSH host. Returns: Dict confirming disconnection.
Download a file from a remote SSH host via SFTP. Args: host: Name of the configured SSH host. remote_path: Path to the file on the remote host. local_path: Local destination path. Returns: Dict with success status, paths, and byte count.
Execute a shell command on a remote SSH host. Args: host: Name of the configured SSH host (from list_hosts). command: The shell command to execute on the remote host. Returns: Dict with stdout, stderr, exit_code, duration_ms, and timing info.
Execute multiple commands sequentially on a remote SSH host. Args: host: Name of the configured SSH host. commands: List of shell commands to execute in order. stop_on_error: If True (default), stop executing after the first command that fails (non-zero exit code or exception). Returns: Dict with results list and overall success boolean.
Output schemas not formally documented. Code returns dicts with fields like 'exit_code', 'stdout', 'stderr', 'duration_ms', 'connectivity', but the tool definitions do not declare structured return types. LLMs cannot reliably parse responses or plan downstream operations.
No input validation or constraint declarations in schemas. 'command' parameter in ssh_execute accepts any string with no length limits, regex patterns, or sanitization hints. Risk of command injection, buffer overflow, or accidental destructive commands. Schemas lack enums, min/max, or format restrictions.
Error handling is absent. Code catches exceptions generically (e.g., 'Command execution failed on host') but does not categorize errors as retryable, user-fixable, or fatal. No recovery guidance. LLMs cannot determine whether to retry, ask the user, or abandon the operation.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 53 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 44 | - | v1 |
Check connectivity and status for a specific SSH host. Args: host: Name of the configured SSH host. Returns: Dict with connection state, host details, and connectivity test result.
Upload a local file to a remote SSH host via SFTP. Args: host: Name of the configured SSH host. local_path: Path to the local file to upload. remote_path: Destination path on the remote host. Returns: Dict with success status, paths, and byte count.
Destructive operations (ssh_execute with rm/delete commands, ssh_disconnect) lack confirmation or dry-run support. Agents can trigger irreversible file deletion or connection loss without safeguards. No idempotency markers.
Path parameters (local_path, remote_path) lack format validation or path traversal safeguards. Descriptions do not specify allowed directory ranges or constraints. ssh_upload and ssh_download could be exploited via '../../../etc/passwd' style traversal attacks.
Missing pagination and result-limit documentation. list_hosts has no documented limit, offset, or cursor parameters. If many hosts are configured, the response could grow unbounded, wasting tokens and degrading LLM reasoning.
Descriptions lack dependency hints and prerequisites. E.g., ssh_execute does not note 'hosts must be pre-configured in hosts.json and available via list_hosts()'. No guidance on when to call list_hosts first. Descriptions should state prerequisites explicitly.
Audit logging is server-side only. No tool-level error reporting or structured error responses. When an operation fails, the LLM receives a generic exception message without context for recovery. Audit events are thread-safe but not exposed to the protocol.