Roadmap
Current version: v1.1.0
Completed
catenary-mcp (v0.6.x) — MCP Bridge ✓
LSP tools exposed via MCP. Feature complete.
Development History
Phase 1: Configuration Logic
- Add
configanddirsdependencies - Define
Configstruct (usingserde) - Implement config loading from
XDG_CONFIG_HOMEor--configflag
Phase 2: Lazy Architecture
- Create
ClientManagerstruct - Move
spawnandinitializelogic frommain.rsintoClientManager::get_or_spawn - Update
LspBridgeHandlerto useClientManager
Phase 3: Cleanup & Optimization
- Update
document_cleanup_taskto communicate withClientManager - Implement server shutdown logic when no documents are open for that language
Phase 4: Context Awareness (“Smart Wait”)
- Progress Tracking: Monitor LSP
$/progressnotifications to detect “Indexing” states - Smart Blocking: Block/Queue requests while the server is initializing or indexing
- Internal Retry: Retry internally if a server returns
nullshortly after spawn - Status Tool: Add
statustool to report server states
Phase 4.5: Observability & CD
- Session Monitoring: Add
catenary listandcatenary monitorcommands - Event Broadcasting: Broadcast tool calls, results, and raw MCP messages
- CI/CD: Add GitHub Actions for automated testing, release builds, and crates.io publishing
Phase 5: High-Level Tools (“Catenary Intelligence”)
- Auto-Fix: Add
apply_quickfixtool (chainscodeAction+workspaceEditapplication) - Codebase Map: Add
codebase_mapto generate a high-level semantic tree of the project (synthesized from file walk +documentSymbol) - Relative Path Support: Resolve relative paths in tool arguments against the current working directory
Phase 6: Multi-Workspace Support ✓
Single Catenary instance multiplexing across multiple workspace roots.
- Accept multiple
--rootpaths - Pass all roots as
workspace_foldersto each LSP server - Multi-root search across roots
- Multi-root
codebase_map(walks all roots, prefixes entries in multi-root mode) -
add_root()plumbing (appends root, sendsdidChangeWorkspaceFolders) - Expose
add_rootmid-session via MCProots/list
Phase 6.5: Hardening ✓
- Remove
apply_workspace_edit—rename,apply_quickfix, andformattingreturn proposed edits only; MCP client applies them (see LSP Fault Model) - Error attribution — prefix all LSP-originated errors with server
language:
[rust] request timed out - Pass
initializationOptionsfrom config to LSP server -
search— unified search tool replacingfind_symbol
Phase 7: Complete Agent Toolkit ✓
Full toolset to replace CLI built-in tools.
File I/O:
-
read_file— Read file contents + return diagnostics -
write_file— Write file + return diagnostics -
edit_file— Edit file + return diagnostics -
list_directory— List directory contents
Shell Execution:
-
runtool with allowlist enforcement -
allowed = ["*"]opt-in for unrestricted shell - Dynamic language detection — language-specific commands activate when matching files exist in the workspace
- Tool description updates dynamically to show current allowlist
- Emit
tools/list_changedwhen allowlist changes (e.g., workspace added) - Error messages on denied commands include the current allowlist
Security:
- Path validation against workspace roots (read and write)
- Symlink traversal protection (
canonicalize()+ root check) - Config file self-modification protection (
.catenary.toml,~/.config/catenary/config.toml) - Direct command execution (no shell injection)
- Output size limits (100KB per stream) and timeout enforcement
Phase 8: Reliability & Polish ✓
- Eager server startup — detect workspace languages at startup and spawn configured servers immediately (on-demand for undetected languages)
- Always-on readiness wait — all LSP tools wait for server readiness
automatically (removed
smart_waitconfig toggle andwait_for_reanalysisparameter) -
workspace/configurationsupport — respond to server configuration requests with empty defaults instead ofMethodNotFound - Search rework —
searchreturns LSP workspace symbols plus a ripgrep file heatmap (match count + line range per file), replacing the previous fallback chain - Diagnostic resilience — explicit warnings when an LSP server is dead or unresponsive instead of silently returning empty results
-
deniedsubcommands — block specific command+subcommand pairs in theruntool (e.g.,"git grep"), takes priority over allowlist including["*"]
CLI Integration Research ✓
Validated approach: use existing CLI tools (Claude Code, Gemini CLI) with built-in tools disabled, replaced by catenary-mcp.
Findings
Why not a custom CLI? Subscription plans ($20/month Pro tier) are tied to official CLI tools. A custom CLI requires pay-per-token API access — wrong billing model for individual developers.
Validated configurations:
- Gemini CLI:
tools.coreallowlist (blocklist doesn’t work) - Claude Code:
permissions.deny+ must blockTaskto prevent sub-agent escape
See CLI Integration for full details.
Known Vulnerabilities
See LSP Fault Model and Adversarial Testing for full details.
Symlink traversal.Resolved in Phase 7. File I/O tools usecanonicalize()+ workspace root validation.list_directoryusessymlink_metadata()to avoid following symlinks.- Unbounded LSP data. Diagnostic caches grow without limit. Hover responses, symbol trees, and workspace edit previews have no size caps. A malicious or buggy LSP server can cause unbounded memory growth.
Resolved in Phase 6.5.apply_workspace_edittrusts LSP URIs.apply_workspace_editremoved. All edit tools now return proposed edits as text; the MCP client applies them.
Low Priority
- Batch Operations: Query hover/definition/references for multiple positions in a single call
- References with Context: Include surrounding lines (e.g.,
-C 3) in reference results - Multi-file Diagnostics: Check diagnostics across multiple files in one call
Abandoned
catenary-cli — Custom Agent Runtime
Originally planned to build a custom CLI to control the model agent loop. Abandoned because subscription plans are tied to official CLI tools.
See Archive: CLI Design for the original design.