MCP Telemetry Collection and Data Pseudonymization: How DesktopCommanderMCP Protects User Privacy

DesktopCommanderMCP implements privacy-first telemetry that pseudonymizes every event using a randomly generated UUID, ensuring no personally identifiable information links usage data to individual users while maintaining transparent opt-out controls.

DesktopCommanderMCP is an open-source MCP (Model Context Protocol) server that handles file system operations and command execution. Understanding its approach to MCP telemetry collection and data pseudonymization reveals how the project balances product analytics with strict privacy protections. The implementation uses a proxy-based architecture, opaque identifiers, and explicit user consent mechanisms to ensure data minimization.

Core Telemetry Architecture

The Telemetry Proxy Pattern

Rather than connecting directly to analytics backends, DesktopCommanderMCP routes all events through a lightweight proxy. In [src/utils/capture.ts](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/capture.ts), the primary endpoint https://telemetry.desktopcommander.app/mp/collect handles ingestion, while a fallback URL ensures redundancy. This proxy strips request-origin metadata before forwarding to BigQuery, preventing the analytics store from receiving raw client IP addresses or direct connection details.

Client Identifier and Pseudonymization

The pseudonymization layer centers on a randomly generated UUID stored as clientId in the user's configuration. Defined in the ServerConfig interface in [src/config-manager.ts](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config-manager.ts) (line 16), this identifier persists across sessions but never correlates to email addresses, usernames, or OS-level identifiers. The UUID lives in the standard config directory (~/.config/desktop-commander/config.json by default), ensuring that every telemetry event remains anonymous.

Opt-Out Controls via telemetryEnabled

User agency is enforced through the telemetryEnabled boolean flag, located in the same ServerConfig interface at line 13 of [src/config-manager.ts](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config-manager.ts). Defaulting to enabled for first-run experience, this setting is respected by every telemetry call through the isTelemetryDisabledValue helper (lines 43-45), which normalizes string values like "false" or "FALSE" to boolean equivalents.

Graceful Fallback Mechanisms

The system implements silent failure principles to prevent telemetry from impacting core functionality. If the primary proxy fails, the code automatically retries TELEMETRY_PROXY_FALLBACK_URL, and all network calls are wrapped in try/catch blocks. Guard clauses in [src/utils/capture.ts](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/capture.ts) (lines 106-115) ensure that disabled telemetry returns early without throwing errors.

Data Pseudonymization Implementation

The clientId UUID Strategy

Every telemetry payload includes four core fields: event (string name), clientId (UUID), version (application version), and timestamp. The clientId is the sole identification mechanism—an opaque string generated during initial configuration that contains no encoded personal data. This approach ensures that event streams cannot be reverse-engineered to reveal user identities while still allowing aggregate analysis of usage patterns.

Transmission Security

Events transmit over HTTPS to the proxy endpoint, where TLS encryption protects data in transit. The proxy architecture adds a sanitization layer between the DesktopCommanderMCP client and the analytics warehouse, ensuring that backend storage never receives direct client fingerprints or network metadata.

Absence of Personal Data

The telemetry system explicitly excludes personal identifiers. When [track-installation.js](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/track-installation.js) captures installation events, it only records the clientId, operating system type, and timestamp—never capturing home directory paths, environment variables containing usernames, or machine hostnames.

Telemetry Lifecycle in Practice

The capture() Function Implementation

The capture() function in src/utils/capture.ts (lines 92-110) serves as the central emission point. It constructs payloads by merging the event name with configuration values retrieved through configManager.getValue():

// src/utils/capture.ts – simplified flow
export async function capture(eventName: string, payload: any) {
  const telemetryEnabled = await configManager.getValue('telemetryEnabled');
  if (isTelemetryDisabledValue(telemetryEnabled)) return;   // respect opt-out

  const clientId = await configManager.getValue('clientId');
  const body = {
    event: eventName,
    clientId,
    version: VERSION,
    timestamp: Date.now(),
    ...payload,
  };
  
  try {
    await fetch(TELEMETRY_PROXY_URL, { 
      method: 'POST', 
      body: JSON.stringify(body),
      headers: { 'Content-Type': 'application/json' }
    });
  } catch (e) {
    // Fail silently; retry with fallback URL if implemented
  }
}

Installation Tracking Example

Real-world usage appears in [track-installation.js](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/track-installation.js), which builds an installation payload and calls capture('install', payload). This demonstrates how the system records adoption metrics without exposing sensitive system information.

Managing Telemetry Preferences

Programmatic Opt-Out

Users can disable telemetry without editing configuration files manually. The configManager.updateConfig() method provides a clean API for toggling the telemetryEnabled flag:

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

async function disableTelemetry() {
  await configManager.updateConfig({ telemetryEnabled: false });
  console.log('Telemetry disabled successfully');
}

disableTelemetry();

When set to false, all subsequent capture() calls return at the guard clause, guaranteeing zero network traffic to analytics endpoints.

Checking Current Settings

Verify your current telemetry status and pseudonymized ID using the configuration manager:

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

async function checkTelemetryStatus() {
  const enabled = await configManager.getValue('telemetryEnabled');
  const clientId = await configManager.getValue('clientId');
  
  console.log(`Telemetry enabled: ${enabled}`);
  console.log(`Pseudonymous client ID: ${clientId}`);
}

checkTelemetryStatus();

Code Examples for Developers

Sending Custom Events

Extend the telemetry system for custom monitoring while maintaining the same privacy protections:

import { capture } from './src/utils/capture.js';

async function reportCustomAction(action: string, details: Record<string, any>) {
  await capture('custom_action', { action, ...details });
}

// Usage
await reportCustomAction('batch_rename', { fileCount: 150 });

Reading the Pseudonymized Client ID

Access the anonymous identifier for debugging or correlation purposes:

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

async function getClientId() {
  const id = await configManager.getValue('clientId');
  console.log('Your pseudonymous client ID:', id);
  // Example output: 550e8400-e29b-41d4-a716-446655440000
}

getClientId();

Summary

  • Proxy Architecture: DesktopCommanderMCP routes telemetry through https://telemetry.desktopcommander.app/mp/collect via the capture() function in src/utils/capture.ts, adding a privacy layer between clients and analytics storage.
  • Pseudonymization: The clientId UUID in src/config-manager.ts provides the only identification, containing no personal data and persisting in ~/.config/desktop-commander/config.json.
  • Opt-Out Control: The telemetryEnabled flag in ServerConfig allows immediate cessation of data collection, respected by guard clauses in every telemetry call.
  • Silent Operation: All telemetry failures are caught and ignored, with fallback URL support ensuring that network issues never block core functionality.
  • Transparency: Installation tracking in track-installation.js demonstrates real-world usage limited to system type and timestamp, excluding sensitive path or identity information.

Frequently Asked Questions

What data does DesktopCommanderMCP collect through its telemetry system?

DesktopCommanderMCP collects event data including the action type (e.g., "install"), a pseudonymized clientId UUID, application version, operating system type, and timestamp. As implemented in src/utils/capture.ts, the system explicitly excludes file paths, usernames, environment variables, and other personally identifiable information from every payload.

How does the pseudonymization mechanism protect my identity?

The system generates a random UUID stored as clientId in your configuration file during first run. This identifier, defined in src/config-manager.ts, contains no encoded personal information and never links to your email, username, or hardware identifiers. When combined with the proxy architecture that strips request metadata, this ensures that telemetry events cannot be traced back to individual users.

Can I completely disable telemetry collection?

Yes. Set telemetryEnabled to false using the configuration API, which updates your config.json file. The isTelemetryDisabledValue helper in src/config-manager.ts ensures that once disabled, the capture() function returns immediately without emitting network requests, guaranteeing zero data transmission to the proxy endpoints.

Where is my configuration and client ID stored?

The clientId and telemetryEnabled settings persist in a JSON configuration file located at ~/.config/desktop-commander/config.json by default, as defined in src/config.ts. This standard directory location keeps sensitive configuration separate from application code while remaining accessible for user inspection or modification.

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 →