An MCP server that enables SSH connections to Linux servers for command execution, file operations, and system information retrieval.
The SSH MCP server has three tools with clear action-verb naming (test_*, get_*, execute_*) and reasonable descriptions. However, several critical gaps reduce the score: (1) Parameters lack strict type enforcement and validation in schemas, hostname is string but no format constraint; port is integer but no min/max bounds. (2) The execute_command tool accepts a destructive 'confirm' boolean parameter, which is a pattern anti-pattern, it should use a dedicated confirmation flow instead of a boolean flag. (3) Output schemas are not formally documented, responses are free-form strings rather than structured objects. (4) Error handling is present but generic; many errors return formatted strings without actionable recovery guidance. (5) Security: credentials (SSH_PASSWORD, SSH_KEY_FILE) are injected via environment variables, which is correct, but the tool parameters include optional password and key_file, accepting secrets as parameters is a violation of pattern:secret-injection. (6) The server returns markdown-formatted text instead of structured JSON, forcing LLMs to parse unstructured output. Average parameter descriptions are ~100 chars, which is reasonable, but several lack context (e.g., 'confirm' parameter description is minimal and doesn't explain the destructive-operation workflow).
Execute a command on a Linux server.
Get comprehensive system information from a Linux server.
Test SSH connection to a Linux server.
Credentials accepted as tool parameters violate secret injection pattern. 'password' and 'key_file' parameters in test_ssh_connection and execute_command should NOT be exposed to the LLM layer, credentials must be injected server-side only.
execute_command uses a 'confirm' boolean parameter to gate destructive operations. This is a dangerous pattern, an LLM can easily omit the parameter or set it to false. Per pattern:confirmation-request, destructive operations should require a dedicated multi-step workflow (attempt → warning with destructive indicators → user confirmation → re-invoke with confirmation token), not a binary flag.
Output schemas are not documented. All three tools return free-form strings (plain text or markdown) instead of structured JSON with typed fields. LLMs must parse unstructured text to extract results, increasing error rates and token waste. Per pattern:response-shaper, tools should return objects with well-defined fields (e.g., {status: string, message: string, data: object}).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 56 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 56 | - | v1 |
Parameter validation constraints are missing from schemas. 'hostname' has no format constraint, 'port' has no min/max bounds (should be 1-65535), 'command' in execute_command is unbounded. Per pattern:constrained-input, numeric and string parameters must declare ranges, enums, or patterns to prevent invalid LLM inputs.
Error responses are not actionable. Errors return formatted strings like '❌ Authentication failed' but do not guide the LLM on next steps. Per pattern:recovery-guide, errors should suggest corrective actions (e.g., 'Authentication failed. Check SSH_USER and SSH_PASSWORD environment variables, or pass username/password parameters.').
Parameter descriptions lack context on mutually exclusive relationships. For example, in test_ssh_connection, 'username', 'password', and 'key_file' should document that authentication requires either (username + password) OR (username + key_file), and these cannot be mixed. Per pattern:tool-description, parameter descriptions must state dependencies.