Skip to main content
Glama

exec_in_pod

Execute commands directly in Kubernetes pods or containers without shell interpretation for secure cluster management and debugging.

Instructions

Execute a command in a Kubernetes pod or container and return the output. Command must be an array of strings where the first element is the executable and remaining elements are arguments. This executes directly without shell interpretation for security.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesName of the pod to execute the command in
namespaceNoKubernetes namespacedefault
commandYesCommand to execute as an array of strings (e.g. ["ls", "-la", "/app"]). First element is the executable, remaining are arguments. Shell operators like pipes, redirects, or command chaining are not supported - use explicit array format for security.
containerNoContainer name (required when pod has multiple containers)
timeoutNoTimeout for command - 60000 milliseconds if not specified
contextNoKubeconfig Context to use for the command (optional - defaults to null)

Implementation Reference

  • The main handler function that executes the command in the specified Kubernetes pod using the Kubernetes Exec API, captures stdout/stderr with streams, handles timeouts, and returns the output or throws errors.
    export async function execInPod( k8sManager: KubernetesManager, input: { name: string; namespace?: string; command: string[]; container?: string; timeout?: number; context?: string; } ): Promise<{ content: { type: string; text: string }[] }> { const namespace = input.namespace || "default"; // Validate command is an array (defense in depth - schema should enforce this) if (!Array.isArray(input.command)) { throw new McpError( ErrorCode.InvalidParams, "Command must be an array of strings (e.g. [\"ls\", \"-la\"]). String commands are not supported for security reasons." ); } if (input.command.length === 0) { throw new McpError( ErrorCode.InvalidParams, "Command array cannot be empty" ); } // Validate all elements are strings for (let i = 0; i < input.command.length; i++) { if (typeof input.command[i] !== "string") { throw new McpError( ErrorCode.InvalidParams, `Command array element at index ${i} must be a string` ); } } const commandArr = input.command; // Prepare buffers to capture stdout and stderr let stdout = ""; let stderr = ""; // Use Node.js Writable streams to collect output const stdoutStream = new Writable({ write(chunk, _encoding, callback) { stdout += chunk.toString(); callback(); } }); const stderrStream = new Writable({ write(chunk, _encoding, callback) { stderr += chunk.toString(); callback(); } }); // Add a dummy stdin stream const stdinStream = new Writable({ write(_chunk, _encoding, callback) { callback(); } }); try { // Set context if provided if (input.context) { k8sManager.setCurrentContext(input.context); } // Use the Kubernetes client-node Exec API for native exec const kc = k8sManager.getKubeConfig(); const exec = new k8s.Exec(kc); // Add a timeout to avoid hanging forever if exec never returns await new Promise<void>((resolve, reject) => { let finished = false; const timeoutMs = input.timeout || 60000; const timeout = setTimeout(() => { if (!finished) { finished = true; reject( new McpError( ErrorCode.InternalError, "Exec operation timed out (possible networking, RBAC, or cluster issue)" ) ); } }, timeoutMs); console.log("[exec_in_pod] Calling exec.exec with params:", { namespace, pod: input.name, container: input.container ?? "", commandArr, stdoutStreamType: typeof stdoutStream, stderrStreamType: typeof stderrStream, }); exec.exec( namespace, input.name, input.container ?? "", commandArr, stdoutStream as any, stderrStream as any, stdinStream as any, // use dummy stdin true, // set tty to true (status: any) => { console.log("[exec_in_pod] exec.exec callback called. Status:", status); if (finished) return; finished = true; clearTimeout(timeout); // Always resolve; handle errors based on stderr or thrown errors resolve(); } ).catch((err: any) => { console.log("[exec_in_pod] exec.exec threw error:", err); if (!finished) { finished = true; clearTimeout(timeout); reject( new McpError( ErrorCode.InternalError, `Exec threw error: ${err?.message || err}` ) ); } }); }); // Return the collected stdout as the result // If there is stderr output or no output at all, treat as error if (stderr || (!stdout && !stderr)) { throw new McpError( ErrorCode.InternalError, `Failed to execute command in pod: ${stderr || "No output"}` ); } return { content: [ { type: "text", text: stdout, }, ], }; } catch (error: any) { // Collect error message and stderr output if available let message = error.message || "Unknown error"; if (stderr) { message += "\n" + stderr; } throw new McpError( ErrorCode.InternalError, `Failed to execute command in pod: ${message}` ); } }
  • Input schema for the exec_in_pod tool defining parameters: pod name (required), namespace, command as string array (required), optional container, timeout, and context.
    export const execInPodSchema = { name: "exec_in_pod", description: "Execute a command in a Kubernetes pod or container and return the output. Command must be an array of strings where the first element is the executable and remaining elements are arguments. This executes directly without shell interpretation for security.", annotations: { destructiveHint: true, }, inputSchema: { type: "object", properties: { name: { type: "string", description: "Name of the pod to execute the command in", }, namespace: namespaceParameter, command: { type: "array", items: { type: "string" }, description: "Command to execute as an array of strings (e.g. [\"ls\", \"-la\", \"/app\"]). First element is the executable, remaining are arguments. Shell operators like pipes, redirects, or command chaining are not supported - use explicit array format for security.", }, container: { type: "string", description: "Container name (required when pod has multiple containers)", }, timeout: { type: "number", description: "Timeout for command - 60000 milliseconds if not specified", }, context: contextParameter, }, required: ["name", "command"], }, };
  • src/index.ts:519-531 (registration)
    Registration and dispatch of the exec_in_pod handler in the main CallToolRequestHandler switch statement.
    case "exec_in_pod": { return await execInPod( k8sManager, input as { name: string; namespace?: string; command: string[]; container?: string; timeout?: number; context?: string; } ); }
  • src/index.ts:131-131 (registration)
    Inclusion of execInPodSchema in the allTools array used for listing available tools.
    execInPodSchema,

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/Flux159/mcp-server-kubernetes'

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