How Desktop Commander MCP Telemetry Collection Works: Privacy-First Implementation

Desktop Commander MCP collects anonymous usage telemetry through an opt-in system that automatically sanitizes all sensitive data—including file paths, user identifiers, and error stack traces—before transmission to a secure endpoint.

The wonderwhy-er/DesktopCommanderMCP repository implements a privacy-preserving telemetry collection system designed to gather usage insights without compromising user security. This TypeScript-based MCP server uses a multi-stage pipeline to capture, sanitize, and transmit event data, ensuring that no personally identifiable information ever leaves the local environment. Understanding how this telemetry collection mechanism operates helps developers audit the data flow and configure the system according to their privacy requirements.

How Telemetry Collection Works

The telemetry collection system in Desktop Commander MCP follows a seven-step pipeline that begins with user consent and ends with secure transmission. Each stage is designed to minimize data exposure while maintaining diagnostic utility.

Opt-in Configuration

Telemetry collection is controlled by the boolean configuration field telemetryEnabled, defined in src/config-field-definitions.ts (lines 26-30), which defaults to true. Users can disable telemetry at runtime by setting the environment variable DESKTOP_COMMANDER_DISABLE_TELEMETRY to any of the following values: 1, true, yes, or on. This dual-layer control ensures that system administrators can enforce telemetry policies without modifying configuration files.

Event Capture API

Throughout the codebase, developers invoke await capture('event_name', { … }) or await captureRemote('event_name', { … }) to record actions. The capture() function, implemented in src/utils/capture.ts (lines 82-87), first checks the execution context—specifically filtering out calls originating from widget UI contexts, which are silently ignored. Valid events proceed to the telemetry pipeline for processing.

Building Standard Event Properties

The buildEventProperties() function in src/utils/capture.ts (lines 28-41) constructs a base payload containing non-personal metadata:

  • timestamp: ISO 8601 formatted date
  • platform: Operating system identifier from os.platform()
  • container metadata: Detection flags including isContainer, containerType, orchestrator, and sanitized versions of containerName and containerImage
  • runtime source: Classification as smithery-runtime, npx-runtime, or direct-runtime
  • isDXT flag: Boolean indicating whether installed via DXT
  • app_version: Current Desktop Commander version
  • client context: client_name and client_version strings
  • saw_onboarding_page: User onboarding completion flag

Data Sanitization Pipeline

Before merging caller-provided properties, the system performs aggressive sanitization in src/utils/capture.ts (lines 57-69). The process deep-copies all properties and applies these filters:

  • Error sanitization: Strips stack traces from any error object, retaining only the message and optional code fields
  • Path removal: Deletes any keys resembling file paths (path, filePath, directory, etc.), replacing values with [PATH] placeholders, except for fileExtension which is preserved
  • Identity stripping: For remote telemetry, removes identity keys including deviceId, userId, and email

Payload Transmission

The sendToTelemetryProxy() function in src/utils/capture.ts (lines 25-33) assembles the final JSON payload and POSTs it to https://telemetry.desktopcommander.app/mp/collect. If the primary endpoint fails, the system implements a single retry against a Cloud Run fallback URL. All network errors are silently caught to ensure that telemetry failures never interrupt core application functionality.

Opt-out Handling

When users disable telemetry via configManager.setValue('telemetryEnabled', false), the code in src/config-manager.ts (lines 44-66) emits a single server_telemetry_opt_out event before persisting the new configuration value. This allows the development team to measure opt-out rates accurately while respecting the user's decision to cease further data collection.

What Data Is Captured by Desktop Commander MCP

The final telemetry payload contains only generic, non-identifying information. The system explicitly excludes file contents, absolute paths, user emails, device IDs, and personally identifiable data. A typical transmitted event appears as follows:

{
  "client_id": "<generated-uuid>",
  "timestamp_micros": 1720971234567890,
  "events": [
    {
      "name": "event_name",
      "params": {
        "timestamp": "2024-07-13T12:34:56.789Z",
        "platform": "darwin",
        "isContainer": "false",
        "containerType": "none",
        "orchestrator": "none",
        "containerName": "none",
        "containerImage": "none",
        "runtimeSource": "direct-runtime",
        "isDXT": "false",
        "app_version": "1.2.3",
        "client_name": "desktop-commander-cli",
        "client_version": "1.2.3",
        "saw_onboarding_page": true
      }
    }
  ]
}

All potentially sensitive keys are replaced with placeholders or removed entirely before transmission.

Implementing Telemetry in Your Code

The following examples demonstrate how to properly instrument code using the Desktop Commander MCP telemetry collection utilities:

import { capture, captureRemote } from './utils/capture.js';

// Simple telemetry event for tool execution
await capture('tool_executed', {
  tool_name: 'edit',
  file_extension: 'ts',
  user_action: 'replace',
  // File paths are automatically filtered out
  filePath: '/home/user/sensitive/path'  // Will be replaced with [PATH]
});

// Remote-device telemetry with identity stripping
await captureRemote('remote_tool_call', {
  tool_name: 'search',
  query: 'TODO comments',
  userId: '12345'   // Automatically removed before transmission
});

To disable telemetry collection programmatically:

import { configManager } from './config-manager.js';

// Emit opt-out event and disable future collection
await configManager.setValue('telemetryEnabled', false);

Or disable via environment variable for a single execution:

DESKTOP_COMMANDER_DISABLE_TELEMETRY=1 npx desktop-commander-mcp

Summary

  • Desktop Commander MCP implements telemetry collection through a privacy-first pipeline defined in src/utils/capture.ts that defaults to enabled but supports both configuration-based and environment-based opt-out.
  • All sensitive data—including file paths, error stack traces, and user identifiers—is automatically sanitized or removed before transmission, ensuring no PII leaves the system.
  • Two capture functions exist: capture() for local operations and captureRemote() for remote devices, with the latter applying additional identity stripping.
  • Transmission occurs via POST request to https://telemetry.desktopcommander.app/mp/collect with automatic retry logic and silent failure handling.
  • Opt-out events are tracked via server_telemetry_opt_out in src/config-manager.ts to measure privacy preference trends without violating user consent.

Frequently Asked Questions

Does Desktop Commander MCP collect personal data or file contents?

No. According to the source code in src/utils/capture.ts, the telemetry collection system explicitly removes any keys resembling file paths (replacing them with [PATH] placeholders), strips error stack traces, and filters out identity fields like userId and email. The system only captures generic metadata such as platform type, container environment, and runtime source.

How can I completely disable telemetry collection?

You have two methods to disable telemetry collection. First, set the environment variable DESKTOP_COMMANDER_DISABLE_TELEMETRY to 1, true, yes, or on before starting the application. Alternatively, programmatically call configManager.setValue('telemetryEnabled', false) from src/config-manager.ts, which will emit a final opt-out event and persist the disabled state.

What happens if the telemetry endpoint is unreachable?

The sendToTelemetryProxy() function in src/utils/capture.ts implements graceful degradation. If the primary endpoint at telemetry.desktopcommander.app fails, the system attempts one retry against a Cloud Run fallback URL. All network errors are silently caught and ignored, ensuring that telemetry transmission failures never impact core MCP functionality or user experience.

What is the difference between capture() and captureRemote()?

The capture() function handles standard local telemetry events while filtering out widget UI contexts. The captureRemote() function, also defined in src/utils/capture.ts, adds a remote: "true" flag to the payload and applies additional sanitization specifically designed for remote device scenarios, ensuring that any identity markers from remote environments are thoroughly stripped before transmission.

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 →