ssh_exec_interactive
Execute interactive commands on remote SSH servers with automated prompt responses for sudo passwords and confirmations, featuring safety confirmations for destructive operations.
Instructions
Ejecuta un comando interactivo en el servidor remoto con PTY. Permite responder automáticamente a prompts (ej: sudo password, confirmaciones yes/no). Si el comando es destructivo requiere confirm: true
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | Comando a ejecutar en el servidor remoto | |
| responses | No | Lista de respuestas automáticas a prompts. Cada entrada tiene un regex que detecta el prompt y la respuesta a enviar | |
| timeout | No | Timeout global en milisegundos (default: 30000) | |
| confirm | No | Confirmar ejecución de comandos peligrosos. Requerido cuando el comando es detectado como destructivo |
Implementation Reference
- src/index.ts:444-535 (handler)The `handleExecInteractive` method implements the logic for executing interactive commands over SSH using a PTY, handling automatic responses to prompts and timeouts.
private async handleExecInteractive(args: any): Promise<CallToolResult> { this.requireConnection(); const command = args.command as string; const responses = (args.responses || []) as PromptResponse[]; const timeout = (args.timeout as number) || SSHMCPServer.EXEC_TIMEOUT; const confirm = args.confirm as boolean | undefined; const check = isDangerousCommand(command); if (check.dangerous && !confirm) { return { content: [ { type: "text", text: [ `ADVERTENCIA: Comando potencialmente destructivo detectado.`, `Comando: ${command}`, `Razón: ${check.reason}`, ``, `Para ejecutar este comando, reenvía con confirm: true.`, ].join("\n"), }, ], }; } // Compilar regex de prompts const compiledResponses = responses.map((r) => ({ regex: new RegExp(r.prompt), answer: r.answer, sensitive: r.sensitive || false, })); const auditResponses = responses .map((r) => (r.sensitive ? `${r.prompt}:[REDACTED]` : `${r.prompt}:${r.answer}`)) .join(", "); return new Promise<CallToolResult>((resolve, reject) => { this.sshClient!.exec(command, { pty: true }, (err, stream) => { if (err) { this.audit("ssh_exec_interactive", `${command} responses=[${auditResponses}]`, "error"); reject(new Error(`Error ejecutando comando interactivo: ${err.message}`)); return; } let output = ""; let settled = false; let settleTimer: ReturnType<typeof setTimeout> | null = null; let globalTimer: ReturnType<typeof setTimeout> | null = null; const cleanup = () => { if (settleTimer) clearTimeout(settleTimer); if (globalTimer) clearTimeout(globalTimer); }; const finish = () => { if (settled) return; settled = true; cleanup(); this.audit("ssh_exec_interactive", `${command} responses=[${auditResponses}]`, "ok"); const cleanOutput = stripAnsi(output) || "(sin salida)"; this.recordOperation("ssh_exec_interactive", { command, responses: responses.length }, cleanOutput, false); resolve({ content: [{ type: "text", text: cleanOutput }], }); }; const resetSettle = () => { if (settleTimer) clearTimeout(settleTimer); settleTimer = setTimeout(finish, SSHMCPServer.SETTLE_TIMEOUT); }; globalTimer = setTimeout(() => { if (!settled) { settled = true; if (settleTimer) clearTimeout(settleTimer); stream.destroy(); this.audit("ssh_exec_interactive", `${command} (timeout)`, "ok"); resolve({ content: [ { type: "text", text: stripAnsi(output) + "\n[timeout: comando excedió el tiempo límite]", }, ], }); } }, timeout); stream.on("data", (data: Buffer) => { const chunk = data.toString(); output += chunk; - src/tools.ts:143-164 (schema)Definition of the `ssh_exec_interactive` tool, including its name, description, and input schema.
{ name: "ssh_exec_interactive", description: "Ejecuta un comando interactivo en el servidor remoto con PTY. Permite responder automáticamente a prompts (ej: sudo password, confirmaciones yes/no). Si el comando es destructivo requiere confirm: true", inputSchema: { type: "object", properties: { command: { type: "string", description: "Comando a ejecutar en el servidor remoto", }, responses: { type: "array", description: "Lista de respuestas automáticas a prompts. Cada entrada tiene un regex que detecta el prompt y la respuesta a enviar", items: { type: "object", properties: { prompt: { type: "string", description: "Regex para detectar el prompt (ej: '[Pp]assword[:\\s]')", }, - src/index.ts:77-78 (registration)Registration of the `ssh_exec_interactive` tool in the main request handler switch block.
case "ssh_exec_interactive": return await this.handleExecInteractive(args);