adequate-rust-mcp
Industrial-grade, self-healing MCP server for rust-analyzer.
Dependency Note
This workspace currently consumes libmcp from the public swarm Git surface:
https://git.swarm.moe/libmcp.git
Cargo will fetch that dependency automatically on first build.
Crates
ra-mcp-domain: strict domain types and lifecycle algebrara-mcp-engine: resilient rust-analyzer transport + supervisoradequate-rust-mcp: MCP stdio server exposing analysis tools
Guarantees
- automatic recovery from broken pipes and dead workers
- bounded request/startup deadlines
- typed boundaries for lifecycle, faults, and source positions
- fault-injection integration tests for restart behavior
Runtime Modes
- default (
adequate-rust-mcp): stable host process (Codex-facing stdio endpoint) - worker (
adequate-rust-mcp --worker): actual MCP tool server process
The host supervises worker generations, drains pending requests with explicit JSON-RPC errors on worker loss, and automatically respawns.
Quick Start
From the workspace root:
cargo run -p adequate-rust-mcp
To launch the disposable worker directly:
cargo run -p adequate-rust-mcp -- --worker
Live Reload
Host mode watches the worker binary path for updates. On Unix it self-reexecs into
the new binary and restores live session state before spawning the next worker generation;
on other platforms it falls back to worker-only restart. It replays initialize and
reconstructs notifications/initialized if needed so replacement workers come up fully live.
In-flight requests are replayed across host/worker restarts with bounded at-least-once semantics,
so transient rollout and recovery churn is hidden from clients by default.
Environment knobs:
ADEQUATE_MCP_WORKER_BINARY: worker binary path to execute/watch (default: current executable)ADEQUATE_MCP_HOST_RELOAD_DEBOUNCE_MS: file-change debounce before reload (default:250)ADEQUATE_MCP_HOST_RESPAWN_FLOOR_MS: initial respawn backoff floor (default:100)ADEQUATE_MCP_HOST_RESPAWN_CEILING_MS: respawn backoff ceiling (default:3000)ADEQUATE_MCP_HOST_QUEUE_CAPACITY: max queued inbound frames while recovering (default:512)ADEQUATE_MCP_HOST_MAX_REPLAY_ATTEMPTS: replay budget per in-flight request before surfacing an error (default:8)
Tool Surface
In addition to typed core tools (hover, definition, references, rename_symbol,
diagnostics, clippy_diagnostics, fix_everything, health_snapshot, telemetry_snapshot), the server exposes
advanced_lsp_request for
editing-heavy and advanced rust-analyzer capabilities:
- completions
- completion/resolve
- code actions + resolve
- code lens + resolve
- prepare rename
- rename
- execute command
- formatting (document/range/on-type)
- symbols + workspace symbol resolve
- document links + resolve
- colors + color presentation
- linked editing range, inline value, moniker
- document/workspace diagnostics
- selection/folding/inlay hints + inlay resolve
- semantic tokens (full/range/full-delta), call hierarchy, type hierarchy
hover, definition, references, health_snapshot, and telemetry_snapshot
also default to line-oriented porcelain text with render=json opt-in.
diagnostics and clippy_diagnostics split detail from presentation:
mode:compact(default),full, orsummaryrender:porcelain(default line-oriented text) orjson- default responses are model-friendly porcelain text in
content render=jsonexposes the structured payload and schema for programmatic consumers- empty
definition/references/hoverresults may include an indexing note during early rust-analyzer warm-up when the empty result could be a false negative - transient early-startup
unlinked-file/not part of any cratediagnostics are retried during the same warm-up window before surfacing to clients
One-Stop Autofix
fix_everything is the do-the-obvious thing button for agent loops.
It runs, in order:
- workspace formatter command (default:
cargo fmt --all) - workspace clippy fix command (default:
cargo clippy --fix --workspace --all-targets --all-features --allow-dirty --allow-staged)
The output is structured and model-friendly:
success: whether all steps exited with status0workspace_root: resolved workspace root pathsteps: per-step command argv, exit code, and bounded stdout/stderr excerpts
Input Normalization
User-facing tool inputs are intentionally permissive and normalized at the boundary:
file_pathaccepts absolute paths,file://URIs, and relative paths (resolved against workspace root)- position indices accept numeric strings and integer-like floats
0indices are normalized to1for one-indexed fields- alias spellings are accepted for common fields (
filePath,lineNumber,character,newName, etc.) advanced_lsp_request.methodaccepts snake_case, camelCase, kebab-case, and full LSP method pathsdiagnostics.modeacceptscompact(default),full(aliases:raw,verbose), orsummarydiagnostics.renderacceptsporcelain(default; aliases:text,plain,plain_text) orjson(alias:structured)diagnostics.max_itemsanddiagnostics.max_message_charsaccept numeric strings and integer-like floatsdiagnosticsandclippy_diagnosticsaccept either a single file (file_path) or many files (file_paths/files/paths)clippy_diagnosticsaccepts the same render controls asdiagnostics- multi-file diagnostics preserve requested file order and return one fused diagnostics list
render=jsoncompact diagnostics use descriptive field names (severity,file_path,start_line, etc.) and descriptive counters (error_count,total_count, ...)
Clippy Gate Integration
clippy_diagnostics runs cargo clippy and filters results to the requested file.
Strictness lives in workspace lint configuration:
[workspace.lints.clippy]inCargo.tomlis the canonical policy (all+pedanticwith explicit carve-outs)./check.pyrunscargo clippywithout inline lint flags, so commit-gate behavior is sourced fromCargo.toml
The MCP worker executes:
cargo clippy --workspace --all-targets --all-features --message-format=json
To override command shape (for example, alternate target selection), configure:
[workspace.metadata.adequate-rust-mcp]
format_command = ["cargo", "fmt", "--all"]
clippy_command = [
"cargo",
"clippy",
"--workspace",
"--all-targets",
"--all-features",
"--message-format=json",
]
fix_command = [
"cargo",
"clippy",
"--fix",
"--workspace",
"--all-targets",
"--all-features",
"--allow-dirty",
"--allow-staged",
]
Telemetry
Use telemetry_snapshot as first-line triage when the system slows down or starts flapping.
It reports:
- lifecycle state + generation
- uptime
- consecutive failures and restart count
- total request counters (success, response error, transport fault, retries)
- per-method counters and latency aggregates (
last,avg,max) - last observed method-level error text
- latest restart-triggering fault
Useful choke signatures:
- rising
transport_fault_count+restart_count: rust-analyzer process instability or I/O link failure - rising
response_error_countwith low restart count: semantic/query misuse or LSP-level request issues - high
avg_latency_ms/max_latency_msin one method: method-specific hot spot in large workspaces - non-zero
consecutive_failureswhile state isrecovering: active degradation loop
Host JSONL Telemetry (XDG State)
The host process also emits append-only JSONL telemetry for path-level heat/error analysis.
- default path:
$XDG_STATE_HOME/adequate-rust-mcp/telemetry.jsonl - fallback path:
$HOME/.local/state/adequate-rust-mcp/telemetry.jsonl - snapshot cadence:
ADEQUATE_MCP_TELEMETRY_SNAPSHOT_EVERY(default:100)
Each tool call writes a tool_call event with:
repo_rootrequest_idtool_nameand optionallsp_methodpath_hint(best-effort normalized path extraction)latency_ms,replay_attemptsoutcome(ok/error)- optional
error_code,error_kind,error_message
Every N calls, and once on shutdown, the host writes hot_paths_snapshot with:
hottest_paths(highest request volume)slowest_paths(highest average latency)error_countper path
QA Checklist
For a lean live MCP smoke pass against this repo, run:
python3 qa_checklist.py
The literal step list lives in docs/qa-checklist.md.