ssh_connect
Establish a secure SSH connection to a remote server. Provide the server ID from the list of servers, and optionally set a connection timeout.
Instructions
Connect to an SSH server
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| serverId | Yes | Server ID from ssh_list_servers | |
| timeout | No | Connection timeout in milliseconds (optional) |
Implementation Reference
- src/index.ts:62-79 (registration)Tool registration: 'ssh_connect' is registered in the ListToolsRequestSchema handler with name, description, and inputSchema (requires serverId, optional timeout).
{ name: 'ssh_connect', description: 'Connect to an SSH server', inputSchema: { type: 'object', properties: { serverId: { type: 'string', description: 'Server ID from ssh_list_servers', }, timeout: { type: 'number', description: 'Connection timeout in milliseconds (optional)', }, }, required: ['serverId'], }, }, - src/index.ts:312-347 (handler)Tool handler: The 'ssh_connect' case in CallToolRequestSchema. It looks up the server config by serverId, calls sshManager.connect(serverConfig), and returns the connectionId on success or an error on failure.
case 'ssh_connect': { const serverId = args.serverId as string; const serverConfig = config.servers.find(s => s.id === serverId); if (!serverConfig) { return { content: [ { type: 'text', text: JSON.stringify({ error: `Server ${serverId} not found` }, null, 2), }, ], isError: true, }; } try { const connectionId = await sshManager.connect(serverConfig); return { content: [ { type: 'text', text: JSON.stringify({ connectionId, status: 'connected' }, null, 2), }, ], }; } catch (err: unknown) { return { content: [ { type: 'text', text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }, null, 2), }, ], isError: true, }; } } - src/types.ts:31-39 (schema)Type definition: SSHConnection interface used by the connect method to store connection state (id, serverId, client, timestamps, isBusy, serverConfig).
export interface SSHConnection { id: string; serverId: string; client: Client; connectedAt: Date; lastActivity: Date; isBusy: boolean; serverConfig?: ServerConfig; // For auto-reconnect } - src/ssh-manager.ts:48-139 (helper)Helper: SSHManager.connect() method - the actual SSH connection logic using ssh2 Client. Handles max connections check, timeout, auth methods (agent/key/password), keepalive, and stores the connection.
/** * Connect to an SSH server. * @param serverConfig - The server configuration containing connection details * @returns A promise that resolves to the connection ID * @throws Error if max connections limit is reached or connection fails */ async connect(serverConfig: ServerConfig): Promise<string> { // Check max connections limit if (this.connections.size >= this.maxConnections) { throw new Error(`Max connections limit reached (${this.maxConnections})`); } const connectionId = uuidv4(); const client = new Client(); return new Promise((resolve, reject) => { const timeoutMs = serverConfig.connectTimeout || 30000; let isResolved = false; const timeout = setTimeout(() => { if (!isResolved) { client.end(); // Clean up resources on timeout reject(new Error('Connection timeout')); } }, timeoutMs); client.on('ready', () => { clearTimeout(timeout); isResolved = true; const connection: SSHConnection = { id: connectionId, serverId: serverConfig.id, client, connectedAt: new Date(), lastActivity: new Date(), isBusy: false, serverConfig: { ...serverConfig }, // Store for auto-reconnect }; this.connections.set(connectionId, connection); this.lastConnectionId = connectionId; resolve(connectionId); }); client.on('error', (err) => { clearTimeout(timeout); if (!isResolved) { reject(err); } }); // Handle connection end/close const handleConnectionClose = () => { if (this.logCommands) { console.error(`[SSH] Connection ${connectionId} closed`); } this.connections.delete(connectionId); if (this.lastConnectionId === connectionId) { const remaining = Array.from(this.connections.keys()); this.lastConnectionId = remaining.length > 0 ? remaining[remaining.length - 1] : null; } }; client.on('end', handleConnectionClose); client.on('close', handleConnectionClose); // Build connect options const connectOptions: ConnectConfig = { host: serverConfig.host, port: serverConfig.port, username: serverConfig.username, }; // Auth method if (serverConfig.authMethod === 'agent') { connectOptions.agent = this.getAgentPath(); connectOptions.agentForward = true; } else if (serverConfig.authMethod === 'key' && serverConfig.privateKeyPath) { const keyPath = expandUser(serverConfig.privateKeyPath); connectOptions.privateKey = fs.readFileSync(keyPath); } else if (serverConfig.authMethod === 'password' && serverConfig.password) { connectOptions.password = serverConfig.password; } if (serverConfig.keepaliveInterval !== undefined) { connectOptions.keepaliveInterval = serverConfig.keepaliveInterval; } else if (this.keepaliveInterval > 0) { connectOptions.keepaliveInterval = this.keepaliveInterval; } client.connect(connectOptions); }); } - src/types.ts:4-15 (schema)Type definition: ServerConfig interface defines the structure needed for ssh_connect's serverId lookup, including host, port, username, authMethod, privateKeyPath, etc.
export interface ServerConfig { id: string; name: string; host: string; port: number; username: string; authMethod: 'agent' | 'key' | 'password'; privateKeyPath?: string; password?: string; connectTimeout?: number; keepaliveInterval?: number; }