Feature flags are essential for modern software development, but they create a hidden technical debt crisis:
- ๐ดโโ ๏ธ Dead flags remain in production code for months/years
- ๐ Branching complexity makes code harder to understand and maintain
- ๐ Bug risk from outdated conditional logic
- ๐ Performance overhead from unnecessary runtime checks
- ๐ค Developer frustration navigating flag-polluted codebases
The reality: Most feature flags should be temporary, but manual cleanup is time-consuming and error-prone.
A Model Context Protocol (MCP) server that uses Polyglot Piranha to automatically clean up feature flags in your codebase. Transform feature flag calls into their final values based on flag states defined in flags.json.
๐ฏ Vision: Connect to live feature flag systems (LaunchDarkly, Split.io, custom experimentation MCP) to automatically identify and safely remove stable flags from your codebase.
Before (Feature Flag Hell):
if isFeatureEnabled("beta_ui") {
renderBetaUI()
} else {
renderOldUI()
}
if client.GetString("new_checkout") == "true" {
processNewCheckout()
} else {
processLegacyCheckout()
}After (Clean, Maintainable Code):
if true {
renderBetaUI()
} else {
renderOldUI()
}
if false {
processNewCheckout()
} else {
processLegacyCheckout()
}Next step: Let your compiler/optimizer remove the dead branches entirely!
-
Install dependencies:
pip install fastmcp polyglot-piranha
-
Configure in Cursor: Add to
~/.cursor/mcp.json:{ "mcpServers": { "mcp-piranha": { "command": "python3", "args": ["-m", "mcp-piranha"], "cwd": "/path/to/your/project", "env": { "PYTHONPATH": "/path/to/your/project" } } } } -
Create
flags.jsonin your project:{ "functions": [ "isFeatureEnabled", "client.GetString", "isEnabled", "getFlag", "is_feature_enabled" ], "flags": { "beta_ui": { "value": true, "description": "Enables the new beta user interface", "replace_with": true }, "new_checkout": { "value": false, "description": "New payment processing flow", "replace_with": false } } }
Loads and parses feature flags from flags.json in your project directory.
Parameters:
working_directory(optional): Directory to search forflags.json
Returns:
flags: List of flag namesflag_details: Detailed flag informationglobal_patterns: Function patterns for detectionsource_file: Path to the loadedflags.json
Transforms code by replacing feature flag calls with their final values.
Parameters:
code: Source code to transformlanguage: Programming language (go, java, python, etc.)flag_name(optional): Specific flag to clean uprules(optional): Custom Piranha rulesedges(optional): Custom rule edges
Returns:
transformed_code: The transformed codemessage: Status message
JSON format for defining feature flags and detection patterns:
{
"functions": ["function1", "function2", "function3"],
"flags": {
"flag_name": {
"value": true,
"description": "Flag description",
"replace_with": true
}
}
}Functions Array:
- Array of function names to detect
- Examples:
"isFeatureEnabled","client.GetString","isEnabled" - Supports any function that takes the flag name as a string parameter
Flags Object:
- Object with flag names as keys
- Each flag contains:
value: Current state (true/false)description: Human-readable descriptionreplace_with: What to replace with when cleaning up
{
"functions": [
"isFeatureEnabled",
"client.GetString",
"isEnabled",
"getFlag",
"is_feature_enabled",
"get_flag",
"flag_manager.is_feature_enabled",
"config.getBoolean",
"settings.isEnabled"
],
"flags": {
"beta_ui": {
"value": true,
"description": "Enables the new beta user interface with modern design elements",
"replace_with": true
},
"new_checkout_flow": {
"value": false,
"description": "New payment processing flow with improved UX",
"replace_with": false
},
"feature_flag": {
"value": true,
"description": "Generic feature flag for testing purposes",
"replace_with": true
},
"legacy_auth": {
"value": false,
"description": "Legacy authentication system (deprecated)",
"replace_with": false
},
"debug_mode": {
"value": true,
"description": "Enables debug logging and additional error information",
"replace_with": true
}
}
}- Pattern Detection: Uses global function patterns to find feature flag calls
- Flexible Matching: Supports various function signatures:
isFeatureEnabled("flag_name")isFeatureEnabled("flag_name", arg2)isFeatureEnabled(arg1, "flag_name")isFeatureEnabled(arg1, "flag_name", arg3)
- Rule Generation: Creates Piranha rules for each function pattern
- Code Transformation: Replaces flag calls with their final values
Run tests in the tests/ directory:
python3 tests/test_multilayered.pymcp-piranha/
โโโ src/
โ โโโ __init__.py
โ โโโ server.py # Main MCP server
โโโ tests/
โ โโโ test_multilayered.py
โ โโโ test_*.py # Additional test files
โโโ __main__.py # Entry point
โโโ flags.json # Feature flag definitions
โโโ motivation.png # The problem we're solving
โโโ README.md
- Go -
isFeatureEnabled(),client.GetString(), custom patterns - Java -
config.getBoolean(),featureManager.isEnabled() - Python -
is_feature_enabled(),get_flag() - JavaScript/TypeScript - Various flag checking patterns
- C# - Config-based flag patterns
- And more - Extensible via Polyglot Piranha's rule system
Before: Navigating nested flag conditions
if is_feature_enabled("new_dashboard"):
if is_feature_enabled("advanced_analytics"):
render_advanced_dashboard()
else:
render_basic_new_dashboard()
else:
render_legacy_dashboard()After: Clear, linear logic
if true:
if true:
render_advanced_dashboard()
else:
render_basic_new_dashboard()
else:
render_legacy_dashboard()- โ Runtime flag evaluation (database/API calls)
- โ Compile-time constants (zero runtime overhead)
- ๐ Dead code elimination by compilers/bundlers
graph LR
A[Feature Flag System<br/>LaunchDarkly/Split.io] --> B[Safety Analysis<br/>Rollout % / Stability]
B --> C[MCP Piranha<br/>Code Transformation]
C --> D[Clean Codebase<br/>Zero Technical Debt]
Coming Soon:
- ๐ Live flag system integration - Connect directly to LaunchDarkly, Split.io, Unleash
- ๐ก๏ธ Safety analysis - Only remove flags with 95%+ rollout and 30+ day stability
- ๐ Automated workflows - CI/CD integration with approval processes
- ๐ Impact analysis - Preview changes before applying
- ๐ฏ Bulk operations - Clean entire codebases safely
- "No transformations applied": Check that
flags.jsonexists and contains the flag - "Connection closed": Restart Claude Code or the MCP server
- "Invalid tree-sitter query": Ensure function patterns are valid identifiers
"Feature flags are a powerful tool, but without proper cleanup, they become technical debt that compounds over time. This project automates the tedious but critical task of flag removal, keeping codebases clean and maintainable."
The goal: Make feature flag cleanup so easy and safe that it becomes a standard part of every development workflow.
