How to Troubleshoot DesktopCommanderMCP Startup Issues: A Complete Diagnostic Guide

DesktopCommanderMCP startup failures typically stem from malformed config.json files, port conflicts, incompatible logging modes with MCP clients like Cline, or Docker environment issues, all of which can be diagnosed by analyzing startup logs and validating configuration through the get_config tool.

DesktopCommanderMCP is a Node-based MCP server developed in the wonderwhy-er/DesktopCommanderMCP repository that enables Claude Desktop and other MCP-compatible clients to execute shell commands and manage processes. When the server fails to initialize, it usually occurs during the bootstrap sequence defined in src/version.ts or while spawning child processes. Understanding how to troubleshoot DesktopCommanderMCP startup issues requires examining the initialization chain, from configuration parsing to the hybrid logging system documented in CLINE_NOTIFICATION_PROBLEM.md.

Common DesktopCommanderMCP Startup Failure Categories

Missing or Corrupt Configuration Files

The server reads config.json immediately upon startup via the initialization logic in src/version.ts. If this file contains JSON syntax errors or lacks required keys like allowedDirectories or defaultShell, the server logs a fatal error and exits.

Symptoms include immediate termination or fallback to insecure defaults. To diagnose, run:

get_config({})

Or inspect the file directly:

cat config.json

Port and Process Conflicts

DesktopCommanderMCP spawns child processes for tools such as start_process. If another instance occupies the same IPC pipe or OS ports, the spawn fails with "Unable to bind" errors.

Before restarting, check for stranded sessions and processes:

list_sessions({})
list_processes({})

Kill any conflicting instances:

kill_process({ pid: 12345 })

Logging Method Incompatibility with MCP Clients

The server transmits logs via JSON-RPC notifications/message by default, which Cline displays as UI pop-ups while Claude Desktop renders them in log panes. This behavior is documented in CLINE_NOTIFICATION_PROBLEM.md.

The server automatically detects the client from request.params?.clientInfo?.name and adjusts output accordingly:

// From CLINE_NOTIFICATION_PROBLEM.md
if (clientInfo.name === 'claude-desktop') {
  this.logConfig.useNotifications = true;
} else if (clientInfo.name?.includes('cline')) {
  this.logConfig.useNotifications = false; // use stderr
}

If you experience notification floods in Cline, force stderr output by setting useNotifications to false in the logging section of config.json.

Startup-Time Script Exceptions

The server executes build scripts including scripts/build-mcpb.cjs and scripts/build-ui-runtime.cjs during initialization. Errors in these modules produce "Uncaught Exception" stack traces before any tool calls execute.

These messages are captured in the startup log buffer explained in CUSTOM_STDIO_EXPLANATION.md, which guarantees ordered replay of all log lines regardless of transmission method.

Docker Environment Issues

For containerized deployments, the install-docker.sh script pulls mcp/desktop-commander:latest and mounts host directories. Startup fails if the Docker daemon is inactive or mount paths are invalid.

Verify the installation status:

bash <(curl -fsSL https://raw.githubusercontent.com/wonderwhy-er/DesktopCommanderMCP/refs/heads/main/install-docker.sh) --status

Check container logs:

docker logs $(docker ps -q -f ancestor=mcp/desktop-commander)

Version Mismatch Between Client and Server

The server version defined in src/version.ts must align with the MCP schema expected by the client. Legacy clients may reject newer tool IDs, resulting in "unknown tool" errors after startup.

Compare versions by querying:

get_config({}).then(cfg => {
  console.log('Server version:', cfg.serverVersion);
  console.log('Client:', cfg.clientInfo?.name);
});

Step-by-Step Workflow to Troubleshoot DesktopCommanderMCP Startup Issues

  1. Capture the complete startup log

    Retrieve buffered logs using:

    get_recent_tool_calls({})

    This replays the ordered log buffer described in CUSTOM_STDIO_EXPLANATION.md, showing both notifications/message and stderr output.

  2. Identify the MCP client

    Determine if the server is auto-configuring for Cline or Claude Desktop:

    get_config({}).then(cfg => console.log(cfg.clientInfo));

    If clientInfo.name contains cline, the server disables notifications per the hybrid logging implementation in CLINE_NOTIFICATION_PROBLEM.md.

  3. Validate configuration integrity

    Ensure allowedDirectories is a non-empty array and defaultShell points to a valid executable:

    {
      "allowedDirectories": ["/home/user/projects"],
      "defaultShell": "/bin/bash",
      "logging": {
        "enabled": true,
        "useNotifications": false,
        "level": "warning"
      }
    }
  4. Terminate orphaned processes

    Remove conflicting instances before restarting:

    list_processes | grep desktop-commander | awk '{print $1}' | xargs -r kill -9
  5. Reset Docker installations

    If using Docker, verify the daemon and reset the environment:

    docker info
    bash <(curl -fsSL https://raw.githubusercontent.com/wonderwhy-er/DesktopCommanderMCP/refs/heads/main/install-docker.sh) --reset
  6. Reinstall the server

    Remove and reinstall to resolve version conflicts:

    npx @wonderwhy-er/desktop-commander@latest remove
    npx @wonderwhy-er/desktop-commander@latest setup

How to Repair Configuration Files Causing DesktopCommanderMCP Startup Failures

When config.json is malformed, the server cannot reach the initialization state required for tool execution. The get_config({}) tool exposes the currently loaded configuration, allowing you to verify that allowedDirectories restricts access appropriately. Note that empty arrays allow all directories, creating security risks.

For noisy logs in Cline, add a logging block to force stderr-only output:

{
  "logging": {
    "enabled": true,
    "useNotifications": false,
    "level": "warning"
  }
}

This configuration aligns with the client detection logic in src/version.ts and prevents UI notification floods while preserving diagnostic output in the server logs.

Summary

  • Configuration errors in config.json are the most common cause of immediate startup termination; use get_config({}) to verify JSON validity and required keys like allowedDirectories and defaultShell.
  • Process conflicts resolve by running list_processes({}) and kill_process({ pid }) before restarting the server, or checking list_sessions({}) for stranded sessions.
  • Logging incompatibility with Cline is automatically mitigated when clientInfo.name contains "cline", or manually via the logging configuration block in config.json.
  • Docker issues require verifying daemon status with docker info, checking logs with docker logs, and using the install-docker.sh --reset flag for clean reinstallation.
  • Version mismatches between the server (src/version.ts) and legacy clients trigger "unknown tool" errors; reinstall via npx @wonderwhy-er/desktop-commander@latest setup to synchronize versions.

Frequently Asked Questions

Why does DesktopCommanderMCP exit immediately after starting?

Immediate exits indicate fatal errors during configuration parsing in src/version.ts. Check config.json for syntax errors or missing allowedDirectories and defaultShell keys. Run get_config({}) to see the loaded configuration, or inspect the startup log buffer via get_recent_tool_calls({}) to identify the exact parsing failure.

How do I stop Cline from showing constant notification pop-ups?

Cline displays JSON-RPC notifications/message as UI alerts, unlike Claude Desktop which logs them quietly. The server detects Cline via clientInfo.name and automatically switches to stderr logging. To force this behavior manually, set "useNotifications": false in the logging section of config.json as documented in CLINE_NOTIFICATION_PROBLEM.md.

What should I do when I see "Process already running" errors?

This error occurs when a previous DesktopCommanderMCP instance occupies the IPC pipe or required ports. Use list_processes({}) to identify stranded processes, then terminate them with kill_process({ pid: <number> }) before attempting to restart the server.

Ensure the Docker daemon is running with docker info, then verify the container image exists using docker images. Check specific error messages with docker logs. If the container fails to mount host directories or exits immediately, run the installer with the --reset flag: bash <(curl ...) --reset to clear corrupted states and pull fresh images.

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 →