v0.9.14: converge on the MCP 2026-07-28 spec — rmcp ClientLifecycleMode negotiation, per-server opt-in, server echoes requested protocolVersion
- Dominant language
- Rust
- Stars
- 41k
- Forks
- 3.6k
- Avg merge
- 13h 59m
- Merged PRs (30d)
- 299
Description
## Why this matters
Codewhale was pinned to the original MCP revision (2024-11-05) in three places and the client never read the `protocolVersion` a server returns. Current servers negotiate 2026-07-28; we could not participate.
## Verified state
- Original pin sites: `crates/mcp/src/lib.rs:1039`, `crates/tui/src/mcp_server.rs:317`, `crates/tui/src/mcp.rs:1834`.
- **First half landed from a parallel lane (2026-09-16, uncommitted at filing):** advertise **2025-06-18**, negotiate over `MCP_SUPPORTED_PROTOCOL_VERSIONS = [2025-06-18, 2025-03-26, 2024-11-05]` — server echoes the client's revision when supported (latest otherwise), stdio client accepts the set instead of exact-match, streamable HTTP sends the required `MCP-Protocol-Version` header post-initialize. Verified: `codewhale-mcp` 79/79, `codewhale-tui --lib mcp` 425/425, fmt clean.
- **rmcp 3.2.0 is already a dependency** of crates/tui (`Cargo.toml:76`, features `auth, client`) — the hand-rolled client in `crates/tui/src/mcp.rs` coexists with it. The remaining work is convergence, not adoption.
- `~/.codewhale/mcp.json` today: 2 servers, both stdio, no HTTP/SSE servers configured. The legacy HTTP+SSE transport (`mcp.rs:1510` region) has no local dependents — keep it reachable or gate it explicitly, never silently drop.
- reqwest: workspace on 0.13.1 while Cargo.lock still carries 0.12.28 (see #6151); grokbuild quarantines rmcp in a dedicated crate (`refs/grokbuild/crates/codegen/xai-grok-mcp`) — mirror that isolation only if the lock graph demands it.
## Remaining work (second half)
Per `refs/codex/codex-rs/rmcp-client` — do not hand-roll negotiation:
1. Copy the model of `rmcp-client/src/protocol_mode.rs`: `McpProtocolMode` (Legacy | V20260728) defaulting to Legacy, mapping to rmcp's `ClientLifecycleMode`; Auto performs the 2026-07-28 probe with 2025-06-18 fallback. Reference tests: `rmcp-client/tests/mcp_2026_discovery.rs`, `mcp_2026_stdio.rs`.
2. Default every server to Legacy; modern is opt-in per server; stdio opts in via an env marker exactly as the codex reference does. Keep that property.
3. Replace the hand-rolled client in `crates/tui/src/mcp.rs` with rmcp, isolated in its own crate. Expect a large deletion.
4. Keep the legacy HTTP+SSE transport reachable (or explicitly gated with a report of what uses it).
## Order and gates
Implementation first, prove it runs against a real MCP server, then tests. Land in slices, one commit each. Final gate: `npm test && npm run check:web` with real pass/fail counts in the commit message; failures reported with output.
## Related
- #6142 (reconcile the two MCP client stacks — this lands its direction)
- #6131 (one negotiated protocol adapter across legacy and current servers)
Contributor guide
Research direction
Start with crates/tui/src/mcp.rs and crates/tui/Cargo.toml, then read refs/codex/codex-rs/rmcp-client/protocol_mode.rs and its mcp_2026_discovery.rs and mcp_2026_stdio.rs tests. Verify how the legacy HTTP+SSE region is used before isolating the rmcp client. Done means per-server Legacy defaults, the documented modern opt-in and negotiation behavior, a reachable legacy transport, real-server verification, and passing npm test && npm run check:web.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, networking
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100