execute_docker_command
Run Docker commands through natural language or direct input to manage containers, images, and system operations.
Instructions
Execute Docker commands using natural language or direct commands
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | Natural language command or direct Docker command to execute |
Implementation Reference
- src/index.ts:1158-1195 (registration)Registration of the 'execute_docker_command' MCP tool, including schema and inline handler function.server.registerTool( "execute_docker_command", { title: "Execute Docker Command", description: "Execute Docker commands using natural language or direct commands", inputSchema: { command: z.string().describe("Natural language command or direct Docker command to execute") } }, async ({ command }) => { try { // Parse natural language to Docker command const dockerCommand = parseDockerCommand(command); // Execute the Docker command const result = await executeDockerCommand(dockerCommand); return { content: [ { type: "text", text: `Executed: ${dockerCommand}\n\nOutput:\n${result.stdout}${result.stderr ? `\nErrors:\n${result.stderr}` : ""}` } ] }; } catch (error) { return { content: [ { type: "text", text: `Error executing Docker command: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } } );
- src/index.ts:1167-1195 (handler)Handler function for execute_docker_command tool: parses input with parseDockerCommand, executes via executeDockerCommand, and formats response.async ({ command }) => { try { // Parse natural language to Docker command const dockerCommand = parseDockerCommand(command); // Execute the Docker command const result = await executeDockerCommand(dockerCommand); return { content: [ { type: "text", text: `Executed: ${dockerCommand}\n\nOutput:\n${result.stdout}${result.stderr ? `\nErrors:\n${result.stderr}` : ""}` } ] }; } catch (error) { return { content: [ { type: "text", text: `Error executing Docker command: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } } );
- src/index.ts:1160-1165 (schema)Input schema definition for the execute_docker_command tool using Zod.{ title: "Execute Docker Command", description: "Execute Docker commands using natural language or direct commands", inputSchema: { command: z.string().describe("Natural language command or direct Docker command to execute") }
- src/index.ts:383-390 (helper)Core helper function executeDockerCommand that runs shell commands using Node's child_process.exec (promisified). Used by the tool handler and throughout the codebase.async function executeDockerCommand(command: string): Promise<{ stdout: string; stderr: string }> { try { const result = await execAsync(command); return result; } catch (error: any) { throw new Error(`Docker command failed: ${error.message}`); } }
- src/index.ts:393-723 (helper)parseDockerCommand helper: Converts natural language descriptions (e.g., 'list running containers') to exact Docker CLI commands via regex pattern matching.function parseDockerCommand(naturalLanguage: string): string { const input = naturalLanguage.toLowerCase().trim(); // === CONTAINER OPERATIONS === // List containers with various formats if (input.match(/(list|show|display|get)\s+(all\s+)?(containers?|running|stopped)/)) { if (input.includes("all") || input.includes("stopped")) { return "docker ps -a"; } if (input.includes("running")) { return "docker ps"; } return "docker ps -a"; } if (input.match(/(what|which)\s+containers?\s+are\s+(running|active)/)) { return "docker ps"; } // Container lifecycle operations if (input.match(/(start|run|launch)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(start|run|launch)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker start ${match[2]}`; } } if (input.match(/(stop|halt|kill)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(stop|halt|kill)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { const action = match[1] === "kill" ? "kill" : "stop"; return `docker ${action} ${match[3]}`; } } if (input.match(/(restart|reboot)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(restart|reboot)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker restart ${match[3]}`; } } if (input.match(/(remove|delete|rm)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(remove|delete|rm)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker rm ${match[3]}`; } } // Container inspection and logs if (input.match(/(inspect|examine|details?)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(inspect|examine|details?)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker inspect ${match[3]}`; } } if (input.match(/(logs?|output)\s+(from\s+)?(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(logs?|output)\s+(?:from\s+)?(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { const follow = input.includes("follow") || input.includes("tail") ? " -f" : ""; const lines = input.match(/(\d+)\s+lines?/) ? ` --tail ${input.match(/(\d+)\s+lines?/)![1]}` : ""; return `docker logs${follow}${lines} ${match[2]}`; } } if (input.match(/(exec|execute|run)\s+(in|into)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(exec|execute|run)\s+(?:in|into)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { const command = input.includes("bash") ? "bash" : input.includes("sh") ? "sh" : "bash"; return `docker exec -it ${match[2]} ${command}`; } } // === IMAGE OPERATIONS === // List images if (input.match(/(list|show|display|get)\s+(all\s+)?(images?|repos?|repositories)/)) { if (input.includes("dangling")) { return "docker images -f dangling=true"; } return "docker images"; } // Pull images if (input.match(/(pull|download|fetch)\s+(image\s+)?([a-zA-Z0-9/_.-]+)(:([a-zA-Z0-9._-]+))?/)) { const match = input.match(/(pull|download|fetch)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)(?::([a-zA-Z0-9._-]+))?/); if (match) { const image = match[2]; const tag = match[3] || (input.includes("latest") ? "latest" : ""); return `docker pull ${image}${tag ? `:${tag}` : ""}`; } } // Push images if (input.match(/(push|upload)\s+(image\s+)?([a-zA-Z0-9/_.-]+)(:([a-zA-Z0-9._-]+))?/)) { const match = input.match(/(push|upload)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)(?::([a-zA-Z0-9._-]+))?/); if (match) { const image = match[2]; const tag = match[3] || ""; return `docker push ${image}${tag ? `:${tag}` : ""}`; } } // Build images if (input.match(/(build|create)\s+(image\s+)?([a-zA-Z0-9/_.-]+)/)) { const match = input.match(/(build|create)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)/); if (match) { const dockerfile = input.includes("dockerfile") ? ` -f ${input.match(/dockerfile[:\s]+([^\s]+)/)?.[1] || "Dockerfile"}` : ""; const context = input.match(/(?:from|in)\s+([^\s]+)/) ? ` ${input.match(/(?:from|in)\s+([^\s]+)/)![1]}` : " ."; return `docker build${dockerfile} -t ${match[3]}${context}`; } } // Remove images if (input.match(/(remove|delete|rm)\s+(image\s+)?([a-zA-Z0-9/_.-]+)/)) { const match = input.match(/(remove|delete|rm)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)/); if (match) { const force = input.includes("force") ? " -f" : ""; return `docker rmi${force} ${match[3]}`; } } // Tag images if (input.match(/(tag|label)\s+(image\s+)?([a-zA-Z0-9/_.-]+)\s+(as\s+)?([a-zA-Z0-9/_.-]+)/)) { const match = input.match(/(tag|label)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)\s+(?:as\s+)?([a-zA-Z0-9/_.-]+)/); if (match) { return `docker tag ${match[2]} ${match[3]}`; } } // === VOLUME OPERATIONS === if (input.match(/(list|show|display)\s+(all\s+)?(volumes?|storage)/)) { if (input.includes("dangling")) { return "docker volume ls -f dangling=true"; } return "docker volume ls"; } if (input.match(/(create|make)\s+(volume\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(create|make)\s+(?:volume\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker volume create ${match[2]}`; } } if (input.match(/(remove|delete)\s+(volume\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(remove|delete)\s+(?:volume\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker volume rm ${match[3]}`; } } if (input.match(/(inspect|examine)\s+(volume\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(inspect|examine)\s+(?:volume\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker volume inspect ${match[3]}`; } } // === NETWORK OPERATIONS === if (input.match(/(list|show|display)\s+(all\s+)?(networks?|networking)/)) { return "docker network ls"; } if (input.match(/(create|make)\s+(network\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(create|make)\s+(?:network\s+)?([a-zA-Z0-9_-]+)/); if (match) { const driver = input.includes("bridge") ? " --driver bridge" : input.includes("overlay") ? " --driver overlay" : ""; return `docker network create${driver} ${match[2]}`; } } if (input.match(/(remove|delete)\s+(network\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(remove|delete)\s+(?:network\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker network rm ${match[3]}`; } } if (input.match(/(connect|attach)\s+([a-zA-Z0-9_-]+)\s+(to\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(connect|attach)\s+([a-zA-Z0-9_-]+)\s+(?:to\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker network connect ${match[3]} ${match[2]}`; } } if (input.match(/(disconnect|detach)\s+([a-zA-Z0-9_-]+)\s+(from\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(disconnect|detach)\s+([a-zA-Z0-9_-]+)\s+(?:from\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker network disconnect ${match[4]} ${match[2]}`; } } // === SYSTEM OPERATIONS === if (input.match(/(system\s+)?(info|information|details)/)) { return "docker system info"; } if (input.match(/(version|ver)/)) { return "docker --version && docker-compose --version"; } if (input.match(/(stats|statistics|status|monitor)/)) { const noStream = !input.includes("follow") && !input.includes("continuous"); return `docker stats${noStream ? " --no-stream" : ""}`; } if (input.match(/(disk\s+usage|space|storage\s+usage)/)) { const verbose = input.includes("verbose") || input.includes("detailed") ? " -v" : ""; return `docker system df${verbose}`; } if (input.match(/(clean\s*up?|prune|cleanup)/)) { if (input.includes("all") || input.includes("everything")) { return "docker system prune -a -f"; } if (input.includes("volumes")) { return "docker system prune --volumes -f"; } return "docker system prune -f"; } // === DOCKER COMPOSE OPERATIONS === if (input.match(/(compose\s+)?(up|start|launch)/)) { const detached = !input.includes("foreground") && !input.includes("attached"); const build = input.includes("build") || input.includes("rebuild"); const service = input.match(/service\s+([a-zA-Z0-9_-]+)/) ? ` ${input.match(/service\s+([a-zA-Z0-9_-]+)/)![1]}` : ""; return `docker-compose up${detached ? " -d" : ""}${build ? " --build" : ""}${service}`; } if (input.match(/(compose\s+)?(down|stop|halt)/)) { const volumes = input.includes("volumes") || input.includes("data") ? " --volumes" : ""; const images = input.includes("images") ? " --rmi all" : ""; return `docker-compose down${volumes}${images}`; } if (input.match(/(compose\s+)?(logs|output)/)) { const follow = input.includes("follow") || input.includes("tail") ? " -f" : ""; const service = input.match(/(?:from\s+|service\s+)([a-zA-Z0-9_-]+)/) ? ` ${input.match(/(?:from\s+|service\s+)([a-zA-Z0-9_-]+)/)![1]}` : ""; return `docker-compose logs${follow}${service}`; } if (input.match(/(compose\s+)?(ps|status|services)/)) { return "docker-compose ps"; } if (input.match(/(compose\s+)?(restart|reboot)/)) { const service = input.match(/service\s+([a-zA-Z0-9_-]+)/) ? ` ${input.match(/service\s+([a-zA-Z0-9_-]+)/)![1]}` : ""; return `docker-compose restart${service}`; } if (input.match(/(compose\s+)?(build|rebuild)/)) { const service = input.match(/service\s+([a-zA-Z0-9_-]+)/) ? ` ${input.match(/service\s+([a-zA-Z0-9_-]+)/)![1]}` : ""; const noCache = input.includes("fresh") || input.includes("clean") ? " --no-cache" : ""; return `docker-compose build${noCache}${service}`; } // === ADVANCED OPERATIONS === // Search Docker Hub if (input.match(/(search|find)\s+(for\s+)?([a-zA-Z0-9/_.-]+)/)) { const match = input.match(/(search|find)\s+(?:for\s+)?([a-zA-Z0-9/_.-]+)/); if (match) { return `docker search ${match[2]}`; } } // Copy files if (input.match(/(copy|cp)\s+([^\s]+)\s+(from|to)\s+([a-zA-Z0-9_-]+)/)) { const match = input.match(/(copy|cp)\s+([^\s]+)\s+(from|to)\s+([a-zA-Z0-9_-]+)/); if (match) { const [, , path, direction, container] = match; if (direction === "from") { return `docker cp ${container}:${path} .`; } else { return `docker cp ${path} ${container}:/tmp/`; } } } // Port mapping info if (input.match(/(port|ports)\s+(of\s+|for\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(port|ports)\s+(?:of\s+|for\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker port ${match[2]}`; } } // Process list in container if (input.match(/(processes?|ps|top)\s+(in|inside)\s+([a-zA-Z0-9_-]+)/)) { const match = input.match(/(processes?|ps|top)\s+(?:in|inside)\s+([a-zA-Z0-9_-]+)/); if (match) { return `docker top ${match[3]}`; } } // === REGISTRY OPERATIONS === if (input.match(/login\s+(to\s+)?([a-zA-Z0-9._-]+)?/)) { const match = input.match(/login\s+(?:to\s+)?([a-zA-Z0-9._-]+)?/); const registry = match?.[1] || ""; return `docker login${registry ? ` ${registry}` : ""}`; } if (input.match(/logout\s+(from\s+)?([a-zA-Z0-9._-]+)?/)) { const match = input.match(/logout\s+(?:from\s+)?([a-zA-Z0-9._-]+)?/); const registry = match?.[1] || ""; return `docker logout${registry ? ` ${registry}` : ""}`; } // === FALLBACK === // If no pattern matches but it starts with docker, pass through if (input.startsWith("docker")) { return input; } // General help if (input.match(/(help|usage|commands)/)) { return "docker --help"; } // Default to treating as direct docker command return `docker ${input}`; }