How the Desktop Commander MCP Feature Flag System Enables and Disables Experimental Functionality
Desktop Commander MCP uses a singleton FeatureFlagManager that fetches remote JSON configuration, caches it locally for 30 minutes, and exposes a get() method to enable or disable experimental functionality at runtime.
Desktop Commander MCP implements a lightweight yet robust feature flag system to control experimental functionality without redeploying the application. According to the source code in wonderwhy-er/DesktopCommanderMCP, this system uses a singleton manager pattern that loads cached flags immediately on startup while refreshing configuration asynchronously from a remote endpoint. This architecture ensures the UI remains responsive while allowing maintainers to toggle features globally or target specific user segments.
Core Architecture and Initialization
Singleton Manager Pattern
The feature flag system centers on src/utils/feature-flags.ts, which exports a single featureFlagManager instance imported wherever a component needs to evaluate experimental functionality. This singleton maintains an in-memory cache and coordinates all network operations and disk persistence.
The manager defaults to fetching configuration from https://desktopcommander.app/flags/v2/production.json, but operators can override this by setting the DC_FLAG_URL environment variable to point to staging or development endpoints.
Startup Initialization Flow
During application bootstrap in src/index.ts, the system initializes the manager via await featureFlagManager.initialize();. The initialize() method first invokes loadFromCache() to restore previously saved values from feature-flags.json in the config directory, ensuring immediate availability of last-known states. It then triggers fetchFlags() in the background to retrieve fresh configuration without blocking the startup sequence.
Caching Strategy and Refresh Mechanisms
Local Cache and TTL
Fetched flags persist locally as feature-flags.json. According to lines 61-66 in src/utils/feature-flags.ts, the system enforces a 30-minute cache validity period (cacheMaxAge), after which the manager automatically refreshes data from the remote source.
Manual Refresh
Developers and administrators can force an immediate update by calling await featureFlagManager.refresh(), which re-executes the network fetch and updates the local cache. This is particularly useful in testing scenarios or when debugging feature rollouts.
Runtime Flag Evaluation
Synchronous Flag Checks
Components query flag states using featureFlagManager.get(name, defaultValue), which returns the cached boolean or object if present, otherwise the supplied default (typically false). This synchronous API prevents UI blocking while providing immediate answers for feature gates.
Example usage for a new UI panel:
import { featureFlagManager } from './utils/feature-flags.js';
if (featureFlagManager.get('new_panel_enabled', false)) {
showNewPanel();
}
Asynchronous Fresh Flag Waiting
Experiments requiring the latest remote data before rendering can await featureFlagManager.waitForFreshFlags(). According to lines 120-134 in src/utils/feature-flags.ts, this method returns a Promise that resolves when the background fetch completes, or after a 5-second safety timeout to prevent startup hangs.
Example for A/B testing:
await featureFlagManager.waitForFreshFlags();
const experiment = featureFlagManager.get('experiments', {});
const variant = experiment.myFeature?.variant;
if (variant === 'beta') {
enableBetaFeature();
}
Production Usage Examples
The feature flag system governs several experimental subsystems throughout the codebase.
Welcome Page Onboarding
The onboarding controller in src/utils/welcome-onboarding.ts checks welcome_page_enabled and welcome_page_excluded_clients (lines 20-69) to determine whether to display the welcome UI.
A/B Testing Framework
The testing module in src/utils/ab-test.ts reads the experiments flag object (lines 2-5) to assign variants to users.
Telemetry and Survey Controls
src/utils/usageTracker.ts queries user_surveys (lines 224-225) to enable or suppress telemetry prompts, and checks onboarding_injection (lines 434-435) to decide whether to insert onboarding hints into tool results.
Summary
- The FeatureFlagManager singleton in
src/utils/feature-flags.tsprovides centralized flag management with a simpleget()interface. - Configuration fetches from
desktopcommander.app/flags/v2/production.json(or viaDC_FLAG_URLoverride) with 30-minute automatic cache refreshing. - Flags load from local cache immediately on startup via
initialize(), then refresh asynchronously to keep the UI responsive. - Use
get(name, default)for synchronous checks andwaitForFreshFlags()for experiments requiring the freshest remote data. - Manual refresh available via
refresh()for testing or administrative overrides.
Frequently Asked Questions
How does the feature flag system handle offline scenarios?
Desktop Commander MCP stores the last successfully fetched configuration in feature-flags.json within the local config directory. During initialization, loadFromCache() restores these values immediately, ensuring experimental features retain their last known states even when the remote endpoint is unreachable. The system attempts background refreshes automatically when connectivity returns.
Can I use a custom feature flag endpoint instead of the production URL?
Yes. Set the DC_FLAG_URL environment variable to point to your own JSON endpoint before starting the application. The fetchFlags() method in src/utils/feature-flags.ts prioritizes this variable over the default https://desktopcommander.app/flags/v2/production.json, allowing seamless testing of experimental flag sets in staging environments.
What happens if the remote flag server is slow or unresponsive?
The waitForFreshFlags() method includes a 5-second safety timeout that prevents startup hangs if the remote server fails to respond. Synchronous get() calls always return the cached value or the provided default immediately, ensuring the application remains functional regardless of network latency or server outages.
How do I implement a new experimental feature flag in the codebase?
First, add your flag to the remote JSON configuration served at the endpoint. Then import the singleton in your module: import { featureFlagManager } from './utils/feature-flags.js'. Use featureFlagManager.get('your_flag_name', false) to branch logic safely, defaulting to false to keep the feature disabled until explicitly enabled in the remote configuration.
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 →