How Desktop Commander Telemetry Works: Data Collection and Privacy Controls
Desktop Commander MCP captures anonymous usage metrics through a fire-and-forget telemetry layer that POSTs sanitized JSON payloads to a proxy endpoint, with opt-out controls available via both configuration files and environment variables.
Desktop Commander MCP (Model Context Protocol) records tool interactions and system context through a privacy-focused telemetry system designed to never block user operations. Understanding Desktop Commander telemetry collection helps users and administrators configure appropriate privacy settings while maintaining visibility into how the tool aggregates usage statistics across filesystem, terminal, and editing operations.
Telemetry Architecture and Entry Points
The telemetry flow originates from three primary entry points in the codebase:
capture(event, props?)– General-purpose function located insrc/utils/capture.tsthat records custom events from any tool implementation.captureRemote(event, props?)– Variant that forcesremote:trueand strips identity fields (deviceId,email) for calls originating from remote devices.usageTracker.trackSuccess(toolName)andtrackFailure(toolName)– High-level wrappers insrc/utils/usageTracker.tsautomatically called from tool wrappers to record invocation outcomes.
All paths ultimately delegate through capture() → buildEventProperties() → sendToTelemetryProxy().
Data Payload Structure and Automatic Properties
When buildEventProperties() executes (lines 13-84 in src/utils/capture.ts), it constructs a JSON payload containing automatically detected system metadata and user-supplied properties.
Automatically collected fields include:
timestamp– ISO-8601 string fromnew Date().toISOString().platform– Operating system identifier (win32,darwin,linux) viaos.platform().- Container detection –
isContainer,containerType(e.g.,docker,kubernetes),orchestrator,containerName, andcontainerImage(sanitized to remove long hashes). runtimeSource– Heuristic classification assmithery-runtime,npx-runtime, ordirect-runtime.isDXT– Boolean indicating presence of theMCP_DXTenvironment variable.app_version– Version imported fromsrc/version.ts.- Client context –
client_nameandclient_versionfromcurrentClientorcurrentRemoteClientinsrc/server.ts. saw_onboarding_page– Config flag indicating onboarding completion.remote– Flag indicating remote device invocation viacurrentCallIsRemote.
User-supplied properties passed to capture() are deep-cloned and subject to sanitization before transmission.
Data Sanitization and Privacy Protection
Before any payload leaves the process, Desktop Commander applies aggressive sanitization to prevent leakage of sensitive information:
- Path stripping – The sanitizer removes any property keys containing
path,filePath, ordirectory, ensuring filesystem locations never exit the local machine. - Error cleaning –
sanitizeErrorstrips stack traces and path information from error objects. - Identity separation –
captureRemote()explicitly removesdeviceId,email, anduserIdfields, leaving only the anonymousclient_id.
All network operations use a 3-second timeout, and failures are silently ignored to guarantee telemetry never blocks tool execution.
Transmission Pipeline and Kill Switches
The sendToTelemetryProxy() function (lines 25-44 in src/utils/capture.ts) manages the actual network transmission:
- Kill-switch verification – Checks
DESKTOP_COMMANDER_DISABLE_TELEMETRYenvironment variable andtelemetryEnabledconfig value viaisTelemetryDisabledByEnvandisTelemetryDisabledValue. - Payload construction – Creates minimal JSON with
client_id(a per-machine UUID fromconfigManager.getOrCreateClientId()),timestamp_micros, and event parameters. - Dual endpoint strategy – Attempts primary endpoint
https://telemetry.desktopcommander.app/mp/collect, falling back tohttps://dc-telemetry-proxy-83847352264.europe-west1.run.app/mp/collecton failure. - Fire-and-forget – Asynchronous POST with timeout; errors are caught and discarded.
The client_id is the only persistent identifier, stored in ~/.config/desktop-commander/config.json and created lazily on first telemetry use.
Usage Statistics and Feedback Prompts
src/utils/usageTracker.ts maintains aggregated counters in the user config under the usageStats key:
- Category counters –
filesystemOperations,terminalOperations,editOperations,searchOperations,configOperations,processOperations. - Outcome tracking –
totalToolCalls,successfulCalls,failedCalls, and per-tool frequency counts (toolCounts). - Session metrics –
firstUsed,lastUsed, andtotalSessions(session resets after 30 minutes inactivity). - Feedback state –
feedbackAttemptsandlastFeedbackPromptDate.
The shouldPromptForFeedback() and shouldPromptForErrorFeedback() methods use these statistics to determine when to request user surveys.
Practical Code Examples
Recording a Custom Event
import { capture } from './utils/capture.js';
await capture('tool_call', {
tool: 'read_file',
filePath: '/Users/alice/project/README.md', // sanitized and removed
sizeBytes: 3421,
});
Note: The filePath property is automatically stripped before transmission.
Automatic Tool Tracking
import { usageTracker } from './utils/usageTracker.js';
await usageTracker.trackSuccess('read_file');
// Increments filesystemOperations, successfulCalls,
// toolCounts['read_file'], and session counters
Disabling Telemetry in CI
export DESKTOP_COMMANDER_DISABLE_TELEMETRY=1
npm test # All capture() calls become no-ops
Checking Feedback Eligibility
if (await usageTracker.shouldPromptForFeedback()) {
const { message } = await usageTracker.getFeedbackPromptMessage();
// Present survey to user
}
Summary
- Desktop Commander telemetry operates through
src/utils/capture.ts, which builds sanitized payloads and POSTs them to BigQuery-backed endpoints. - Automatic data collection includes OS platform, container status, runtime source, client version, and session timing—never file paths or personal identifiers.
- Privacy controls include the
telemetryEnabledconfig flag and theDESKTOP_COMMANDER_DISABLE_TELEMETRYenvironment kill-switch. - Usage aggregation in
src/utils/usageTracker.tstracks tool categories and success rates to inform development priorities and user feedback timing. - All transmissions use a fire-and-forget model with 3-second timeouts to ensure zero impact on tool performance.
Frequently Asked Questions
What data does Desktop Commander telemetry capture?
Desktop Commander captures anonymous system metadata including OS platform, container detection flags, runtime source identification (smithery-runtime, npx-runtime, or direct-runtime), client version, and aggregated tool usage statistics. According to the src/utils/capture.ts source code, all file paths and potential identifiers are stripped before transmission, leaving only operational metrics and a per-machine UUID.
How do I completely disable Desktop Commander telemetry?
Set the environment variable DESKTOP_COMMANDER_DISABLE_TELEMETRY=1, true, yes, or on before starting the process. Alternatively, edit ~/.config/desktop-commander/config.json and set telemetryEnabled to false. The environment variable functions as a kill-switch that prevents telemetry initialization even before config loading, making it ideal for CI environments and containers.
Where is the telemetry data sent?
The system attempts to POST JSON payloads to https://telemetry.desktopcommander.app/mp/collect, falling back to https://dc-telemetry-proxy-83847352264.europe-west1.run.app/mp/collect if the primary endpoint fails. Both endpoints receive sanitized, anonymous data ultimately stored in BigQuery for analysis of tool usage patterns and error rates.
Why does Desktop Commander need a client ID?
The client_id is a randomly generated UUID created once per machine via configManager.getOrCreateClientId() and stored locally in the config file. This identifier allows the telemetry system to aggregate sessions and usage patterns without collecting personal information, enabling accurate statistics about unique active users while maintaining complete anonymity.
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 →