ssh_key_load
Load an SSH private key into the running agent for authentication. Use after listing keys to load an unloaded key.
Instructions
Load an SSH private key into the running agent. Ensures the agent is running first. Use this after ssh_key_list shows a key that is not loaded.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| keyPath | Yes | Path to the SSH private key to load (e.g. ~/.ssh/id_ed25519) |
Implementation Reference
- src/tools.ts:223-233 (registration)Registration of the ssh_key_load tool with its schema (keyPath param) and handler that delegates to the loadKey function.
server.tool( "ssh_key_load", "Load an SSH private key into the running agent. Ensures the agent is running first. Use this after ssh_key_list shows a key that is not loaded.", { keyPath: z.string().describe("Path to the SSH private key to load (e.g. ~/.ssh/id_ed25519)"), }, async ({ keyPath }) => { const result = loadKey(keyPath); return { content: [{ type: "text", text: result.message }], isError: result.status === "error" }; }, ); - src/env.ts:268-295 (handler)Core handler for loading an SSH key: ensures the agent is running, resolves the key path, calls ssh-add, and returns a structured result with descriptive error messages for missing keys, passphrase-protected keys, and permission issues.
export function loadKey(keyPath: string): { status: "ok" | "error"; message: string } { // Ensure agent is running first const agent = ensureAgent(); if (!agent.reachable) { return { status: "error", message: agent.message }; } // Resolve ~ to home directory const resolved = keyPath.startsWith("~") ? join(homedir(), keyPath.slice(1)) : keyPath; if (!existsSync(resolved)) { return { status: "error", message: `Key not found: ${resolved}` }; } const { stdout, ok } = runArgs("ssh-add", [resolved]); if (ok) { return { status: "ok", message: `Key loaded: ${resolved}` }; } if (stdout.includes("passphrase") || stdout.includes("incorrect") || stdout.includes("bad permissions")) { if (stdout.includes("UNPROTECTED PRIVATE KEY")) { return { status: "error", message: `Key ${resolved} has too-open permissions. Fix: chmod 600 ${resolved}` }; } return { status: "error", message: `Key ${resolved} requires a passphrase. Add it manually: ssh-add ${resolved}` }; } return { status: "error", message: `Failed to load key: ${stdout}` }; } - src/env.ts:16-24 (helper)Type interface for the agent status result, used by ensureAgent() which is called by loadKey to verify the agent is reachable before loading a key.
export interface AgentResult { running: boolean; reachable: boolean; socket?: string; keys: string[]; started: boolean; env?: { SSH_AUTH_SOCK?: string; SSH_AGENT_PID?: string }; message: string; } - src/env.ts:111-161 (helper)Helper that ensures ssh-agent is running (used by loadKey before attempting to add a key). Probes existing agent, falls back to Windows OpenSSH agent, or starts a new agent scoped to the MCP server process.
export function ensureAgent(): AgentResult { const sock = process.env.SSH_AUTH_SOCK; if (sock) { const result = probeAgent(sock, "ssh-agent"); if (result) return result; } // On Windows, try the OpenSSH agent service (uses named pipe, not SSH_AUTH_SOCK) if (!sock && process.platform === "win32") { const result = probeAgent("\\\\.\\pipe\\openssh-ssh-agent", "Windows OpenSSH agent"); if (result) return result; } // Try to start a new agent (Unix) const { stdout, ok } = runArgs("ssh-agent", ["-s"]); if (ok) { const sockMatch = stdout.match(/SSH_AUTH_SOCK=([^;]+)/); const pidMatch = stdout.match(/SSH_AGENT_PID=([^;]+)/); if (sockMatch) { process.env.SSH_AUTH_SOCK = sockMatch[1]; if (pidMatch) { process.env.SSH_AGENT_PID = pidMatch[1]; startedAgentPid = Number.parseInt(pidMatch[1], 10); } return { running: true, reachable: true, socket: sockMatch[1], keys: [], started: true, env: { SSH_AUTH_SOCK: sockMatch[1], SSH_AGENT_PID: pidMatch?.[1] }, message: "Started new ssh-agent scoped to the ssh-mcp server process. " + "Your shell's environment is NOT modified — this agent is only visible " + "to this MCP server and will terminate when the server exits. " + "No keys loaded yet — use ssh_key_load to add one.", }; } } return { running: false, reachable: false, keys: [], started: false, message: process.platform === "win32" ? "Windows OpenSSH agent not running. Start it: Get-Service ssh-agent | Set-Service -StartupType Automatic; Start-Service ssh-agent" : 'Could not start ssh-agent. Run manually: eval "$(ssh-agent -s)"', }; }