Upgrade rmcp to 3.2 and drop the audit suppression - #51
Conversation
RUSTSEC-2026-0189 covers DNS rebinding in rmcp Streamable HTTP server
transport. It never applied here, since the workspace enables only
transport-io and tempyr-mcp serves over rmcp::transport::stdio, and that
reasoning was recorded in .cargo/audit.toml rather than carried silently.
Moving off the affected version retires the entry outright, so cargo audit
passes with no ignore list.
The intermediate 1.8 release is not usable. Under it, a server-to-client
roots/list round trip leaves two readers on the process stdin, and strace
shows them splitting single JSON-RPC lines between them:
read(0, {\jsonrpc\:\2.0\,, 8192) = 17
read(0, \method\:, 8192) = 9
write(1, ...-32700 Parse error...)
test_mcp_relative_project_root_arg_uses_client_roots_when_server_cwd_is_wrong
failed about 40% of runs there against 0/20 on 1.3. Relocating the request
into ServerHandler::on_initialized made it worse, so the extra reader is not
a product of the call site. 3.2 fixes it: 0/25 on that test with the original
call site unchanged.
Three API changes come with the move. peer_info() now returns owned data, so
the capability test cannot borrow out of a closure. The tool_handler macro
defaults its router to the static Self::tool_router(), which would leave the
instance field unread under -D warnings, so name the field explicitly. Roots
is deprecated by SEP-2577 and rmcp marks list_roots and the ListRootsResult
fields accordingly; the allow sits on the whole function with the reasoning,
since the replacement is unsettled and the capability check already gates it.
fmt, clippy -D warnings, test --workspace --locked over four runs, and audit
all pass.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Essentials Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
💤 Files with no reviewable changes (1)
Included review availability: 3 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour. 📝 WalkthroughWalkthroughThe workspace upgrades RMCP from 1.3 to 3.2. The MCP handler updates deprecated Roots API usage, simplifies capability detection, and explicitly binds the tool router. ChangesRMCP upgrade
Estimated code review effort: 1 (Trivial) | ~5 minutes Merge Risk: ⚪ Minimal · up to This updates RMCP and its handler integration while retaining Roots capability behavior and explicit tool routing. No current merge-blocking risk remains. Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 1 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
Why
RUSTSEC-2026-0189is DNS rebinding in rmcp's Streamable HTTP server transport. It never applied here — the workspace enables onlytransport-ioandtempyr-mcpserves overrmcp::transport::stdio— and that reasoning was recorded in.cargo/audit.tomlrather than carried silently. Moving off the affected version retires the entry outright:cargo auditnow passes with no ignore list, and the file is deleted.Why not 1.8
I tried the minimum bump first and it is not shippable. Under rmcp 1.8, a server→client
roots/listround trip leaves two readers on the process stdin, which split single JSON-RPC lines between them. Fromstrace -f -e trace=read,writeon a failing run:test_mcp_relative_project_root_arg_uses_client_roots_when_server_cwd_is_wrongfailed ~40% of runs on 1.8 versus 0/20 on 1.3.Things I ruled out along the way, so nobody repeats them: the test harness discarding buffered bytes via
BufReader::into_inner()(still failed with a 1-byte buffer); client write timing (a 250 ms delay made it worse); fragmented writes (reproduced cleanly outside the harness, 6/6 pass); and the call site itself — relocating the request intoServerHandler::on_initializedmade it worse, which is what showed the extra reader is not something this repository creates.3.2 fixes it. 0/25 on that test, with the original call site left exactly as it was — so this PR does not touch
lib.rsat all.API changes that came with it
peer_info()returns owned data, so the capability test can no longer borrow out of the closure (is_some_and).#[tool_handler]now defaults its router to the staticSelf::tool_router(), which would leave the instance field unread under-D warnings. Named explicitly as#[tool_handler(router = self.tool_router)]to keep the pre-upgrade behaviour.list_roots,ListRootsResult::roots, andRoot::uriaccordingly. Theallowsits on the whole function with the reasoning: the replacement is unsettled, and the capability check already prevents sending to a client that does not advertise it. When SEP-2577 lands a replacement this is the one place to revisit.Verification
Diff is 4 files:
Cargo.toml,Cargo.lock, 11 lines ofhandler.rs, and the deleted suppression.🤖 Generated with Claude Code
https://claude.ai/code/session_01EwBDuaQS537MdX3GUtmhqj
Summary by CodeRabbit