How to Start a New Process Using Desktop Commander MCP: A Complete Guide

Desktop Commander MCP launches external commands through its process-tool layer, returning a process ID you can use to monitor output, send input, or terminate the session.

Starting a new process with Desktop Commander MCP involves a validated pipeline that ensures security while providing flexible shell execution. This guide explains the exact mechanism used in the wonderwhy-er/DesktopCommanderMCP repository, from the initial tool call through process spawning and state detection.

Entry Point and Schema Validation

The execution begins when a client invokes the start_process tool defined in src/tools/improved-process-tools.ts. Before any command reaches the operating system, the payload undergoes strict validation against StartProcessArgsSchema located in src/tools/schemas.ts.

This schema ensures the request contains:

  • A command string (required)
  • Optional timeout in milliseconds
  • Optional shell override
  • Boolean flags for timing metadata

All arguments are type-checked using Zod, preventing malformed requests from proceeding to the execution phase.

Authorization and Command Validation

Security enforcement happens in src/command-manager.ts through the commandManager.validateCommand method. This function compares the requested command against allow-lists and deny-lists defined in the user configuration.

If a command matches blocked patterns or falls outside permitted scopes, the tool returns an error before spawning any process. This layer protects against unauthorized execution while maintaining flexibility for approved workflows.

Shell Selection and Configuration

When the caller does not explicitly specify a shell, Desktop Commander MCP resolves the appropriate interpreter through configManager.getConfig() in src/config-manager.ts. The system employs platform-specific fallbacks:

  • Windows: Uses COMSPEC environment variable
  • Unix/Linux: Uses SHELL environment variable or defaults to /bin/sh

You can override this behavior by passing a specific shell path in the shell parameter, forcing execution through Bash, Zsh, or any other installed interpreter.

Process Spawning and State Detection

Actual execution occurs in src/terminal-manager.ts via terminalManager.executeCommand, which wraps Node.js child_process.spawn. This approach captures the initial output immediately while maintaining a buffer for streaming data.

After the first chunk of output arrives, the system runs analyzeProcessState from src/utils/process-detection.ts to determine if the process:

  • Is waiting for interactive input
  • Has completed immediately
  • Continues running in the background

The tool returns a ServerResult containing the PID, shell used, initial output, and optional timing statistics.

Practical Implementation Examples

Basic Command Execution

Execute a simple command with automatic shell detection and a timeout:

await startProcess({
  command: "ls -la /tmp",
  timeout_ms: 5000
});

This uses the default shell from your configuration with a 5-second execution limit.

Custom Shell Configuration

Force a specific interpreter and request timing metadata:

await startProcess({
  command: "echo $PATH",
  shell: "/bin/bash",
  verbose_timing: true
});

The verbose_timing flag includes execution duration statistics in the response.

Local Node.js Sessions

Launch a virtual Node.js environment that runs directly on the MCP server:

await startProcess({
  command: "node:local",
  timeout_ms: 30000
});

This special sentinel creates a virtual PID for server-side JavaScript execution rather than spawning a system process.

Interacting with Running Processes

Once start_process returns a PID, you can manage the lifecycle through three additional tools defined in src/tools/improved-process-tools.ts:

  • read_process_output: Retrieves buffered stdout/stderr from a running process
  • interact_with_process: Sends input to processes waiting for interactive data
  • force_terminate: Kills a process immediately regardless of state

This architecture separates process initiation from ongoing interaction, allowing you to start long-running servers or REPLs and communicate with them across multiple tool calls.

Summary

  • Desktop Commander MCP validates all process requests through StartProcessArgsSchema before execution
  • Authorization occurs via commandManager.validateCommand against configurable allow-lists
  • Shell selection defaults to platform standards but accepts explicit overrides
  • terminalManager.executeCommand spawns processes using Node.js child_process.spawn
  • The system analyzes process state immediately after spawning to detect interactive vs. batch modes
  • Returned PIDs enable ongoing interaction through read, write, and terminate operations

Frequently Asked Questions

What permissions are required to start a process?

Desktop Commander MCP checks commands against validation rules defined in src/command-manager.ts. The server must have operating system permissions to spawn child processes, and specific commands may be blocked by the deny-list configuration even if the OS permits them.

How does Desktop Commander MCP handle process timeouts?

The timeout_ms parameter passed to startProcess sets a hard limit on execution duration. If the process exceeds this limit, the system terminates it automatically. This prevents runaway commands from consuming server resources indefinitely.

Can I use a custom shell other than the system default?

Yes. While the system defaults to COMSPEC on Windows or SHELL//bin/sh on Unix, you can specify any executable path in the shell parameter. This allows execution through Bash, PowerShell, Zsh, or specialized interpreters installed on the host system.

How do I capture output from a long-running process?

Use the PID returned by start_process to call read_process_output periodically. The terminalManager in src/terminal-manager.ts maintains an internal buffer that captures stdout and stderr streams, allowing you to retrieve output even after the initial tool call completes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →