ssh_config_lookup
Resolve the effective SSH configuration for any host. Displays hostname, user, port, identity files, proxy settings, and all options from ~/.ssh/config.
Instructions
Resolve the effective SSH configuration for a host. Shows hostname, user, port, identity files, proxy settings, and all other options from ~/.ssh/config. Use this to understand how SSH will connect to a host.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | SSH hostname or IP address |
Implementation Reference
- src/tools.ts:241-257 (handler)The handler function for the 'ssh_config_lookup' tool. Calls configLookup(host) and formats the result into a human-readable output showing hostname, user, port, identity files, proxy settings.
async ({ host }) => { const result = configLookup(host); if ("error" in result) { return { content: [{ type: "text", text: result.error }], isError: true }; } const lines: string[] = [`SSH config for "${host}":`, ""]; lines.push(` Hostname: ${result.hostname}`); lines.push(` User: ${result.user}`); lines.push(` Port: ${result.port}`); if (result.identityFile.length > 0) { lines.push(` Identity files: ${result.identityFile.join(", ")}`); } if (result.proxyJump) lines.push(` ProxyJump: ${result.proxyJump}`); if (result.proxyCommand) lines.push(` ProxyCommand: ${result.proxyCommand}`); return { content: [{ type: "text", text: lines.join("\n") }] }; }, - src/tools.ts:235-258 (registration)Registration of the 'ssh_config_lookup' tool on the MCP server using server.tool(), with description and schema (host: HostSchema).
server.tool( "ssh_config_lookup", "Resolve the effective SSH configuration for a host. Shows hostname, user, port, identity files, proxy settings, and all other options from ~/.ssh/config. Use this to understand how SSH will connect to a host.", { host: HostSchema, }, async ({ host }) => { const result = configLookup(host); if ("error" in result) { return { content: [{ type: "text", text: result.error }], isError: true }; } const lines: string[] = [`SSH config for "${host}":`, ""]; lines.push(` Hostname: ${result.hostname}`); lines.push(` User: ${result.user}`); lines.push(` Port: ${result.port}`); if (result.identityFile.length > 0) { lines.push(` Identity files: ${result.identityFile.join(", ")}`); } if (result.proxyJump) lines.push(` ProxyJump: ${result.proxyJump}`); if (result.proxyCommand) lines.push(` ProxyCommand: ${result.proxyCommand}`); return { content: [{ type: "text", text: lines.join("\n") }] }; }, ); - src/env.ts:297-305 (schema)The ConfigLookupResult interface that defines the shape of the data returned by configLookup, used by the tool handler to format output.
export interface ConfigLookupResult { hostname: string; user: string; port: string; identityFile: string[]; proxyJump?: string; proxyCommand?: string; all: Record<string, string>; raw: string; - src/env.ts:308-330 (helper)The configLookup function that executes 'ssh -G <host>' and parses the output via parseSshConfigOutput, returning the effective SSH configuration.
export function configLookup(host: string): ConfigLookupResult | { error: string } { if (!isValidHostname(host)) { return { error: `Invalid hostname: "${host}"` }; } const { stdout, ok } = runArgs("ssh", ["-G", host]); if (!ok) { return { error: `Failed to resolve SSH config for ${host}: ${stdout}` }; } const { all, identityFiles } = parseSshConfigOutput(stdout); return { hostname: all.hostname || host, user: all.user || "", port: all.port || "22", identityFile: identityFiles, proxyJump: all.proxyjump && all.proxyjump !== "none" ? all.proxyjump : undefined, proxyCommand: all.proxycommand && all.proxycommand !== "none" ? all.proxycommand : undefined, all, raw: stdout, }; } - src/ssh-config.ts:9-30 (helper)The parseSshConfigOutput helper that parses the raw 'ssh -G' stdout into a key-value map and extracts identity files.
export function parseSshConfigOutput(stdout: string): { all: Record<string, string>; identityFiles: string[]; } { const all: Record<string, string> = {}; const identityFiles: string[] = []; for (const line of stdout.split("\n")) { const spaceIdx = line.indexOf(" "); if (spaceIdx > 0) { const key = line.substring(0, spaceIdx); const value = line.substring(spaceIdx + 1); if (key === "identityfile") { identityFiles.push(value); } else { all[key] = value; } } } return { all, identityFiles }; }