Skip to main content
Glama

task_exec_interactive

Execute SSH commands with interactive prompt handling for yes/no, password, and custom responses in remote server management.

Instructions

Exécute une commande SSH avec gestion des prompts interactifs (yes/no, passwords, etc.).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
aliasYesAlias du serveur cible.
cmdYesLa commande à exécuter.
interactiveNoMode interactif.
autoRespondNoRépondre automatiquement aux prompts standards.
responsesNoRéponses personnalisées aux prompts (clé: pattern, valeur: réponse).
timeoutNoTimeout personnalisé en secondes. Défaut 2 minutes.
rappelNoDéfinit un rappel en secondes.

Implementation Reference

  • server.js:545-578 (registration)
    Registration of the 'task_exec_interactive' tool, including input schema and the top-level handler that queues the job and awaits completion.
    server.registerTool( "task_exec_interactive", { title: "Exécuter une commande interactive (SSH)", description: "Exécute une commande SSH avec gestion des prompts interactifs (yes/no, passwords, etc.).", inputSchema: z.object({ alias: z.string().describe("Alias du serveur cible."), cmd: z.string().describe("La commande à exécuter."), interactive: z.boolean().optional().default(true).describe("Mode interactif."), autoRespond: z.boolean().optional().default(true).describe("Répondre automatiquement aux prompts standards."), responses: z.record(z.string()).optional().describe("Réponses personnalisées aux prompts (clé: pattern, valeur: réponse)."), timeout: z.number().optional().describe("Timeout personnalisé en secondes. Défaut 2 minutes."), rappel: z.number().optional().describe("Définit un rappel en secondes.") }) }, async (params) => { const job = queue.addJob({ type: 'ssh', ...params, status: 'pending', interactive: params.interactive, autoRespond: params.autoRespond }); history.logTask(job); ssh.executeCommand(job.id); const finalJob = await waitForJobCompletion(job.id, params.timeout || config.syncTimeout); if (finalJob) { return { content: [{ type: "text", text: `Résultat commande interactive (tâche ${finalJob.id}):\n${finalJob.output || JSON.stringify(finalJob, null, 2)}` }] }; } else { return { content: [{ type: "text", text: `Tâche interactive ${job.id} initiée en arrière-plan.` }] }; } } );
  • ssh.js:179-298 (handler)
    Core handler for interactive SSH execution: opens a shell, executes the command, detects and auto-responds to prompts using custom or default responses, and terminates on END_MARKER.
    async function executeWithNewConnection(serverConfig, job, jobId) { return new Promise((resolve, reject) => { const conn = new Client(); conn.on('ready', () => { conn.shell((err, stream) => { if (err) { conn.end(); return reject(err); } let output = ''; const responses = job.responses || {}; const END_MARKER = `GEMINI_TASK_COMPLETE_MARKER_${job.id}`; let responseSent = false; const cleanupAndResolve = (status = 'completed') => { clearTimeout(jobTimeout); output = output.replace(END_MARKER, '').trim(); const result = { output, exitCode: 0 }; queue.updateJobStatus(jobId, status, result); try { stream.end(); conn.end(); } catch(e) {/* ignore */} resolve(result); }; const jobTimeout = setTimeout(() => { cleanupAndResolve('failed'); }, (job.timeout ? job.timeout * 1000 : config.interactiveCommandTimeout)); stream.on('close', () => { if (!output.includes(END_MARKER)) { cleanupAndResolve('failed'); } }); stream.on('data', (data) => { const chunk = data.toString(); output += chunk; if (output.includes(END_MARKER)) { cleanupAndResolve(); return; } if (!responseSent && job.autoRespond) { const lowerChunk = chunk.toLowerCase(); let responseToSend = null; // Chercher une réponse personnalisée for (const [pattern, response] of Object.entries(responses)) { if (lowerChunk.includes(pattern.toLowerCase())) { responseToSend = response; queue.log('info', `Réponse interactive: ${pattern} -> ${response}`); break; } } // Sinon, chercher une réponse par défaut if (!responseToSend) { for (const [pattern, response] of Object.entries(INTERACTIVE_RESPONSES)) { if (response && lowerChunk.includes(pattern.toLowerCase())) { responseToSend = response; queue.log('info', `Réponse auto: ${pattern} -> ${response}`); break; } } } // Si une réponse a été trouvée, l'envoyer if (responseToSend) { stream.write(responseToSend + '\n'); responseSent = true; // Envoyer le marqueur de fin juste après setTimeout(() => stream.write(`echo "${END_MARKER}"; exit\n`), 100); } } }); stream.stderr.on('data', (data) => { output += `[STDERR] ${data.toString()}`; }); // Envoyer uniquement la commande initiale stream.write(job.cmd + '\n'); }); }); conn.on('error', (err) => { reject(err); }); const connectConfig = { host: serverConfig.host, port: 22, username: serverConfig.user, readyTimeout: 20000 }; (async () => { if (serverConfig.keyPath) { try { connectConfig.privateKey = await fs.readFile(serverConfig.keyPath); } catch (err) { reject(new Error(`Impossible de lire la clé SSH: ${err.message}`)); return; } } else if (serverConfig.password) { connectConfig.password = serverConfig.password; } else { reject(new Error("Aucune méthode d'authentification configurée")); return; } conn.connect(connectConfig); })(); }); }
  • ssh.js:39-55 (helper)
    Helper function to detect if command output contains an interactive prompt requiring user input/response.
    function detectInteractivePrompt(output) { const lastLine = output.split('\n').pop().toLowerCase(); for (const [pattern, response] of Object.entries(INTERACTIVE_RESPONSES)) { if (lastLine.includes(pattern.toLowerCase())) { return { pattern, response, needsInput: true }; } } // Vérifier les patterns qui attendent une entrée if (lastLine.endsWith(':') || lastLine.endsWith('?') || lastLine.includes('[y/n]') || lastLine.includes('(yes/no)')) { return { pattern: 'generic', response: null, needsInput: true }; } return { needsInput: false }; }
  • ssh.js:27-36 (helper)
    Constant object defining default automatic responses for common interactive prompts in SSH sessions.
    const INTERACTIVE_RESPONSES = { // Patterns courants et leurs réponses 'continue connecting': 'yes', 'Are you sure': 'yes', 'password:': null, // Sera géré séparément 'Password:': null, 'Do you want to continue': 'y', 'Overwrite': 'y', 'Save': 'y' };
  • Zod input schema defining parameters for the task_exec_interactive tool, including support for custom responses and timeouts.
    inputSchema: z.object({ alias: z.string().describe("Alias du serveur cible."), cmd: z.string().describe("La commande à exécuter."), interactive: z.boolean().optional().default(true).describe("Mode interactif."), autoRespond: z.boolean().optional().default(true).describe("Répondre automatiquement aux prompts standards."), responses: z.record(z.string()).optional().describe("Réponses personnalisées aux prompts (clé: pattern, valeur: réponse)."), timeout: z.number().optional().describe("Timeout personnalisé en secondes. Défaut 2 minutes."), rappel: z.number().optional().describe("Définit un rappel en secondes.")

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/fkom13/mcp-sftp-orchestrator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server