task_exec_sequence
Execute multiple SSH commands sequentially on a single remote server to automate server management tasks.
Instructions
Exécute plusieurs commandes SSH en séquence sur le même serveur.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| alias | Yes | Alias du serveur cible. | |
| commands | Yes | Liste des commandes à exécuter en séquence (minimum 1). | |
| continueOnError | No | Continuer même si une commande échoue. | |
| rappel | No | Définit un rappel en secondes. |
Implementation Reference
- server.js:599-614 (handler)The primary handler function registered for the 'task_exec_sequence' MCP tool. It queues a job of type 'ssh_sequence', logs it to history, initiates execution via the SSH module, waits for completion (with adjusted timeout), and returns the results or background initiation message.async (params) => { const job = queue.addJob({ type: 'ssh_sequence', ...params, status: 'pending' }); history.logTask(job); ssh.executeCommandSequence(job.id); const finalJob = await waitForJobCompletion(job.id, config.syncTimeout * params.commands.length); if (finalJob) { return { content: [{ type: "text", text: `Résultat séquence (tâche ${finalJob.id}):\n${JSON.stringify(finalJob, null, 2)}` }] }; } else { return { content: [{ type: "text", text: `Séquence de commandes ${job.id} initiée en arrière-plan.` }] }; } }
- server.js:585-597 (schema)Zod input schema validating the tool parameters: server alias, array of commands (simple strings or detailed objects with timeout and continueOnError), global continueOnError flag, and optional reminder seconds.inputSchema: z.object({ alias: z.string().describe("Alias du serveur cible."), commands: z.array(z.union([ z.string(), z.object({ command: z.string(), timeout: z.number().optional(), continueOnError: z.boolean().optional() }) ])).min(1).describe("Liste des commandes à exécuter en séquence (minimum 1)."), continueOnError: z.boolean().optional().default(false).describe("Continuer même si une commande échoue."), rappel: z.number().optional().describe("Définit un rappel en secondes.") })
- server.js:580-615 (registration)MCP server registration of the 'task_exec_sequence' tool, specifying title, description, input schema, and the inline handler function.server.registerTool( "task_exec_sequence", { title: "Exécuter une séquence de commandes (SSH)", description: "Exécute plusieurs commandes SSH en séquence sur le même serveur.", inputSchema: z.object({ alias: z.string().describe("Alias du serveur cible."), commands: z.array(z.union([ z.string(), z.object({ command: z.string(), timeout: z.number().optional(), continueOnError: z.boolean().optional() }) ])).min(1).describe("Liste des commandes à exécuter en séquence (minimum 1)."), continueOnError: z.boolean().optional().default(false).describe("Continuer même si une commande échoue."), rappel: z.number().optional().describe("Définit un rappel en secondes.") }) }, async (params) => { const job = queue.addJob({ type: 'ssh_sequence', ...params, status: 'pending' }); history.logTask(job); ssh.executeCommandSequence(job.id); const finalJob = await waitForJobCompletion(job.id, config.syncTimeout * params.commands.length); if (finalJob) { return { content: [{ type: "text", text: `Résultat séquence (tâche ${finalJob.id}):\n${JSON.stringify(finalJob, null, 2)}` }] }; } else { return { content: [{ type: "text", text: `Séquence de commandes ${job.id} initiée en arrière-plan.` }] }; } } );
- ssh.js:302-361 (helper)Supporting function that implements the sequential SSH command execution logic. Acquires a pooled connection, iterates over commands with per-command timeout/error handling, collects step results, and updates job status accordingly. Called by the tool handler.async function executeCommandSequence(jobId) { const job = queue.getJob(jobId); if (!job) return queue.log('error', `Tâche introuvable: ${jobId}`); const results = []; let connection = null; try { const serverConfig = await serverManager.getServer(job.alias); queue.updateJobStatus(jobId, 'running'); // Obtenir une connexion du pool connection = await sshPool.getConnection(job.alias, serverConfig); // Exécuter chaque commande en séquence for (let i = 0; i < job.commands.length; i++) { const cmd = job.commands[i]; const stepJob = { ...job, cmd: typeof cmd === 'string' ? cmd : cmd.command, timeout: cmd.timeout || job.timeout, continueOnError: cmd.continueOnError || job.continueOnError }; try { queue.log('info', `Exécution étape ${i+1}/${job.commands.length}: ${stepJob.cmd}`); const result = await executeWithPooledConnection(connection, stepJob, `${jobId}_step_${i}`); results.push({ step: i + 1, command: stepJob.cmd, success: true, ...result }); } catch (err) { results.push({ step: i + 1, command: stepJob.cmd, success: false, error: err.message }); if (!stepJob.continueOnError) { throw new Error(`Échec à l'étape ${i+1}: ${err.message}`); } } } queue.updateJobStatus(jobId, 'completed', { results }); } catch (err) { queue.updateJobStatus(jobId, 'failed', { error: err.message, results }); } finally { if (connection) { sshPool.releaseConnection(connection.id); } } }