ssh_test
Test SSH connectivity before running operations. Reports success or failure with timing and actionable error details for quick troubleshooting.
Instructions
Quick connectivity test to an SSH host. Reports success/failure with timing and actionable error details. Lighter and faster than ssh_diagnose — use this for a quick check before running operations.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | SSH hostname or IP address | |
| port | No | SSH port (default: 22) |
Implementation Reference
- src/tools.ts:279-290 (registration)Registration of the 'ssh_test' tool on the MCP server with its schema (HostSchema, PortSchema) and description, delegating to testConnection().
server.tool( "ssh_test", "Quick connectivity test to an SSH host. Reports success/failure with timing and actionable error details. Lighter and faster than ssh_diagnose — use this for a quick check before running operations.", { host: HostSchema, port: PortSchema, }, async ({ host, port }) => { const result = testConnection(host, port || 22); return { content: [{ type: "text", text: result.message }], isError: result.status === "error" }; }, ); - src/env.ts:419-477 (handler)The actual handler function 'testConnection' that executes the SSH connectivity test logic: validates hostname, runs ssh with ConnectTimeout/BatchMode/StrictHostKeyChecking=no, checks stdout for success/failure patterns, and returns status with actionable error messages.
export function testConnection(host: string, port = 22): { status: "ok" | "warning" | "error"; message: string } { if (!isValidHostname(host)) { return { status: "error", message: `Invalid hostname: "${host}"` }; } const start = Date.now(); // StrictHostKeyChecking=no on a read-only "echo SSH_OK" probe. No passwords or // private-key material transit -- BatchMode=yes suppresses password prompts and ssh // never sends private keys over the wire. But the SSH client WILL attempt pubkey auth // against the (possibly-MitM'd) endpoint, so the public-key fingerprints of any // identities loaded in the agent are observable to whatever answers on this port. // For real connections, hostVerifier in resolveConfig (src/ssh.ts) enforces // known_hosts matching and prevents this exposure. const { ok, stdout } = runArgs("ssh", [ "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-p", String(port), host, "echo", "SSH_OK", ]); const elapsed = Date.now() - start; if (ok && stdout.includes("SSH_OK")) { return { status: "ok", message: `Connected to ${host}:${port} in ${elapsed}ms` }; } if (stdout.includes("Permission denied")) { return { status: "error", message: `Authentication failed to ${host}:${port} (${elapsed}ms). Key not authorized. Check: ssh-add -l, verify correct username, verify key is in remote authorized_keys.`, }; } if (stdout.includes("Connection refused")) { return { status: "error", message: `Connection refused at ${host}:${port}. SSH server not running or port blocked.`, }; } if (stdout.includes("timed out")) { return { status: "error", message: `Connection timed out to ${host}:${port}. Host down or firewall blocking.` }; } if (stdout.includes("Host key verification failed")) { return { status: "error", message: `Host key mismatch for ${host}. Instance was likely recreated. Fix with ssh_known_hosts_fix.`, }; } if (stdout.includes("Could not resolve")) { return { status: "error", message: `Could not resolve "${host}". Check DNS, /etc/hosts, or SSH config.` }; } return { status: "error", message: `Connection failed to ${host}:${port}: ${stdout}` }; } - src/tools.ts:9-10 (schema)The HostSchema and PortSchema used as input schema for ssh_test (and other tools).
const HostSchema = z.string().describe("SSH hostname or IP address"); const PortSchema = z.number().int().min(1).max(65535).optional().describe("SSH port (default: 22)");