Skip to main content
Glama
MrGNSS

Desktop Commander MCP

execute_command

Execute terminal commands with timeout control, allowing commands to run in background if they exceed the timeout duration.

Instructions

Execute a terminal command with timeout. Command will continue running in background if it doesn't complete within timeout.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
commandYes
timeout_msNo

Implementation Reference

  • The primary handler function for the 'execute_command' MCP tool. It validates input arguments using the schema, checks if the command is allowed, executes the command via the terminal manager with optional timeout, and returns a formatted response including PID and initial output.
    export async function executeCommand(args: unknown) {
      const parsed = ExecuteCommandArgsSchema.safeParse(args);
      if (!parsed.success) {
        throw new Error(`Invalid arguments for execute_command: ${parsed.error}`);
      }
    
      if (!commandManager.validateCommand(parsed.data.command)) {
        throw new Error(`Command not allowed: ${parsed.data.command}`);
      }
    
      const result = await terminalManager.executeCommand(
        parsed.data.command,
        parsed.data.timeout_ms
      );
    
      return {
        content: [{
          type: "text",
          text: `Command started with PID ${result.pid}\nInitial output:\n${result.output}${
            result.isBlocked ? '\nCommand is still running. Use read_output to get more output.' : ''
          }`
        }],
      };
    }
  • Zod schema defining the input parameters for the execute_command tool: required 'command' string and optional 'timeout_ms' number.
    export const ExecuteCommandArgsSchema = z.object({
      command: z.string(),
      timeout_ms: z.number().optional(),
    });
  • src/server.ts:61-65 (registration)
    Tool registration in the MCP server's ListTools response, specifying name, description, and input schema for execute_command.
      name: "execute_command",
      description:
        "Execute a terminal command with timeout. Command will continue running in background if it doesn't complete within timeout.",
      inputSchema: zodToJsonSchema(ExecuteCommandArgsSchema),
    },
  • src/server.ts:216-219 (registration)
    Dispatch logic in the MCP server's CallToolRequest handler that routes 'execute_command' calls to the executeCommand function after parsing arguments.
    case "execute_command": {
      const parsed = ExecuteCommandArgsSchema.parse(args);
      return executeCommand(parsed);
    }
  • Low-level helper in TerminalManager that spawns the shell process for the command, handles stdout/stderr streaming, timeout blocking, and exit handling. Called by the main handler.
    async executeCommand(command: string, timeoutMs: number = DEFAULT_COMMAND_TIMEOUT): Promise<CommandExecutionResult> {
      const process = spawn(command, [], { shell: true });
      let output = '';
      
      // Ensure process.pid is defined before proceeding
      if (!process.pid) {
        throw new Error('Failed to get process ID');
      }
      
      const session: TerminalSession = {
        pid: process.pid,
        process,
        lastOutput: '',
        isBlocked: false,
        startTime: new Date()
      };
      
      this.sessions.set(process.pid, session);
    
      return new Promise((resolve) => {
        process.stdout.on('data', (data) => {
          const text = data.toString();
          output += text;
          session.lastOutput += text;
        });
    
        process.stderr.on('data', (data) => {
          const text = data.toString();
          output += text;
          session.lastOutput += text;
        });
    
        setTimeout(() => {
          session.isBlocked = true;
          resolve({
            pid: process.pid!,
            output,
            isBlocked: true
          });
        }, timeoutMs);
    
        process.on('exit', (code) => {
          if (process.pid) {
            // Store completed session before removing active session
            this.completedSessions.set(process.pid, {
              pid: process.pid,
              output: output + session.lastOutput, // Combine all output
              exitCode: code,
              startTime: session.startTime,
              endTime: new Date()
            });
            
            // Keep only last 100 completed sessions
            if (this.completedSessions.size > 100) {
              const oldestKey = Array.from(this.completedSessions.keys())[0];
              this.completedSessions.delete(oldestKey);
            }
            
            this.sessions.delete(process.pid);
          }
          resolve({
            pid: process.pid!,
            output,
            isBlocked: false
          });
        });
      });
    }

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/MrGNSS/ClaudeDesktopCommander'

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