swarm repositories / source
aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 640056e099669f9dbfd8cefaa1870742fe890dbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# 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 algebra
- `ra-mcp-engine`: resilient rust-analyzer transport + supervisor
- `adequate-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:

```bash
cargo run -p adequate-rust-mcp
```

To launch the disposable worker directly:

```bash
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`, or `summary`
- `render`: `porcelain` (default line-oriented text) or `json`
- default responses are model-friendly porcelain text in `content`
- `render=json` exposes the structured payload and schema for programmatic consumers
- empty `definition`/`references`/`hover` results 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 crate` diagnostics 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 status `0`
- `workspace_root`: resolved workspace root path
- `steps`: 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_path` accepts absolute paths, `file://` URIs, and relative paths (resolved against workspace root)
- position indices accept numeric strings and integer-like floats
- `0` indices are normalized to `1` for one-indexed fields
- alias spellings are accepted for common fields (`filePath`, `lineNumber`, `character`, `newName`, etc.)
- `advanced_lsp_request.method` accepts snake_case, camelCase, kebab-case, and full LSP method paths
- `diagnostics.mode` accepts `compact` (default), `full` (aliases: `raw`, `verbose`), or `summary`
- `diagnostics.render` accepts `porcelain` (default; aliases: `text`, `plain`, `plain_text`) or `json` (alias: `structured`)
- `diagnostics.max_items` and `diagnostics.max_message_chars` accept numeric strings and integer-like floats
- `diagnostics` and `clippy_diagnostics` accept either a single file (`file_path`) or many files (`file_paths`/`files`/`paths`)
- `clippy_diagnostics` accepts the same render controls as `diagnostics`
- multi-file diagnostics preserve requested file order and return one fused diagnostics list
- `render=json` compact 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]` in `Cargo.toml` is the canonical policy (`all` + `pedantic` with explicit carve-outs)
- `./check.py` runs `cargo clippy` without inline lint flags, so commit-gate behavior is sourced from `Cargo.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:

```toml
[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_count` with low restart count: semantic/query misuse or LSP-level request issues
- high `avg_latency_ms`/`max_latency_ms` in one method: method-specific hot spot in large workspaces
- non-zero `consecutive_failures` while state is `recovering`: 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_root`
- `request_id`
- `tool_name` and optional `lsp_method`
- `path_hint` (best-effort normalized path extraction)
- `latency_ms`, `replay_attempts`
- `outcome` (`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_count` per path

## QA Checklist

For a lean live MCP smoke pass against this repo, run:

```bash
python3 qa_checklist.py
```

The literal step list lives in `docs/qa-checklist.md`.