How to Manage Long-Running Processes with Desktop Commander MCP: Timeout Configuration and Process Control
Desktop Commander MCP manages long-running processes through a configurable timeout system that spawns child processes with a default 30-second limit, automatically terminating executions that exceed their allocated time and reporting exitReason: 'timeout'.
Managing long-running processes safely is critical for any desktop automation tool. In the wonderwhy-er/DesktopCommanderMCP repository, the terminal manager implements robust process control through Node.js child process spawning combined with explicit timeout boundaries. This article examines the source code implementation to show how you can manage long-running processes with Desktop Commander MCP while preventing system hangs and resource exhaustion.
Core Timeout Architecture in Terminal Manager
The src/terminal-manager.ts file contains the primary execution logic that governs how shell commands are spawned and monitored. The architecture centers on a default safety boundary that can be overridden per command.
Default Timeout Constants
At line 172 of src/terminal-manager.ts, the system defines a hard default:
const DEFAULT_COMMAND_TIMEOUT = 30_000; // 30 seconds
This constant ensures that no runaway process hangs the Model Context Protocol (MCP) interface indefinitely. When users invoke the executeCommand method (starting around line 177), they can pass a custom timeoutMs parameter to override this default for specific operations.
Process Spawning and Signal Handling
The actual process creation occurs at line 256, where the spawn function launches the executable:
const childProcess = spawn(spawnConfig.executable, spawnConfig.args, spawnOptions);
Immediately after spawning, the system installs a timer that compares elapsed time against the configured timeoutMs value. If the process exceeds this limit, the manager invokes childProcess.kill() to force termination. This mechanism protects the host from resource exhaustion when executing unpredictable third-party commands.
Exit Reason Classification
The manager tracks why a process ended through the exitReason variable (lines 288-419). When the timeout fires before the process exits naturally, the code explicitly sets:
let exitReason: TimingInfo['exitReason'] = 'timeout';
// ...
exitReason = 'timeout';
This classification allows upstream tools to distinguish between successful completions, errors, and timeout kills, enabling appropriate retry logic or user notifications.
Virtual Node.js Session Timeouts
Beyond standard shell commands, Desktop Commander MCP supports isolated Node.js execution environments through src/tools/improved-process-tools.ts.
Session-Based Timeout Storage
Each virtual Node session maintains its own timeout_ms value, defaulting to 30 seconds. The session map stores this configuration alongside the child process reference, ensuring that long-running scripts respect the same safety boundaries as shell commands.
Per-Execution Timeout Overrides
At line 421, the improved process tools calculate the effective timeout using nullish coalescing:
const effectiveTimeout = timeout_ms ?? session.timeout_ms;
This pattern allows individual executeNodeCode calls to specify urgent timeouts (e.g., 5 seconds) while falling back to the session default for standard operations. When the timer elapses, the system forces exitReason = 'timeout' (line 431) and terminates the Node process, mirroring the terminal manager behavior.
Implementing Custom Timeouts in Practice
You can leverage these timeout mechanisms through several API surfaces depending on your integration point.
Shell Commands with Custom Limits
Override the default 30-second limit when executing terminal commands:
import { terminalManager } from './terminal-manager';
const result = await terminalManager.executeCommand(
'python long_job.py',
10_000, // 10 second timeout
undefined,
false
);
if (result.exitReason === 'timeout') {
console.error('Process killed due to timeout');
}
Virtual Node.js Execution
For sandboxed JavaScript execution with strict time limits:
import { executeNodeCode } from './tools/improved-process-tools';
const code = `
// Simulate intensive computation
while (true) {}
`;
const execResult = await executeNodeCode(code, 5_000); // 5 second limit
// execResult.status.exitReason will be 'timeout' if loop never ends
UI-Level Process Integration
When triggering processes from the user interface layer in src/ui/file-preview/src/panel-actions.ts, forward the timeout parameter through the tool interface:
await options.callTool?.('start_process', {
command: 'ffmpeg -i input.mp4 -c:v libx264 output.mp4',
timeout_ms: 60_000, // 1 minute for video processing
origin: 'ui'
});
Summary
- Default Safety: All commands execute with a 30-second timeout unless overridden via the
timeoutMsparameter insrc/terminal-manager.ts. - Forced Termination: Processes exceeding their limit receive a kill signal and report
exitReason: 'timeout'in the result object. - Dual Architecture: Both shell commands (
terminal-manager.ts) and virtual Node sessions (improved-process-tools.ts) implement identical timeout protection. - Flexible Configuration: Per-command timeouts support long-running operations like video encoding while maintaining system responsiveness.
Frequently Asked Questions
What is the default timeout for commands in Desktop Commander MCP?
The default timeout is 30 seconds (30,000 milliseconds), defined as DEFAULT_COMMAND_TIMEOUT in src/terminal-manager.ts at line 172. This value applies to all shell commands and virtual Node.js sessions unless explicitly overridden by the caller.
How does Desktop Commander MCP handle processes that exceed the timeout limit?
When a process exceeds its allocated timeoutMs, the system calls childProcess.kill() to force immediate termination. The result object returned to the caller contains exitReason: 'timeout', allowing your application logic to detect hangs and respond appropriately, such as prompting the user or retrying with modified parameters.
Can I configure different timeouts for different types of processes?
Yes. The executeCommand method accepts a timeoutMs parameter that overrides the default for individual shell commands. Similarly, executeNodeCode in the improved process tools accepts a timeout_ms argument that takes precedence over the session default. This allows CPU-intensive tasks to run for minutes while keeping quick queries bounded to seconds.
What is the difference between terminal command timeouts and virtual Node session timeouts?
Terminal commands in src/terminal-manager.ts spawn system shells (bash, PowerShell, etc.) and use a simple timer-based kill mechanism. Virtual Node sessions in src/tools/improved-process-tools.ts maintain persistent execution contexts with per-session default timeouts, but both systems report exitReason: 'timeout' and force process termination when limits are exceeded.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →