Skip to content

chore(deps): upgrade rmcp to 3.5 - #3897

Merged
ScriptedAlchemy merged 3 commits into
masterfrom
chore/deps-rmcp-3.5
Oct 14, 2026
Merged

ScriptedAlchemy merged 3 commits into
masterfrom
chore/deps-rmcp-3.5

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

What changed

rmcp moves from 3.4.0 to 3.5.1 in both consumers (crates/tracedecay and crates/tracedecay-mcp, normal and dev requirements). No other manifest depends on rmcp.

Since #3886, MCP sessions run on our own loop (crates/tracedecay-mcp/src/server/session.rs), which copied rmcp 3.4's server request policy. rmcp now supplies only the wire model types and the client used in tests. This PR ports the 3.5 policy changes onto that loop.

Protocol version constants

rmcp 3.5.0 (#1105) sets ProtocolVersion::LATEST to 2026-07-28. That revision replaced the initialize handshake with per-request _meta. The new LATEST_WITH_INITIALIZE is 2025-11-25. Four call sites meant "newest handshake revision" and now use LATEST_WITH_INITIALIZE:

  • initialize_result default for an initialize that names no version.
  • negotiate_protocol_version, both the known_up_to ceiling and the fallback. A supported handshake revision is echoed. 2026-07-28 or an unknown revision gets 2025-11-25, the same answer rmcp 3.5's negotiate_protocol_version gives.
  • attach_stateless_request_context. Stamping LATEST would add resultType, ttlMs and cacheScope to every stateless result, and strict 2025-11-25 hosts reject those fields.

Pre-initialize lifecycle

rmcp 3.5 changed what its server does before a lifecycle is chosen (service/server.rs). Session::open now follows it:

  • A non-initialize request with missing or malformed _meta gets an invalid-params error, and the session stays open. Before, the session closed.
  • A request whose inline _meta names an unsupported version gets UNSUPPORTED_PROTOCOL_VERSION, and the session stays open.
  • server/discover with complete _meta is answered, and the session stays in Opening. Before, the probe committed the session to the inline lifecycle, so a later initialize opened a session that refused every request without _meta. rmcp 3.5's ClientLifecycleMode::Auto probes server/discover first and falls back to initialize.
  • Any other request with complete _meta selects the inline lifecycle, as before.

The handler side needs no change. rmcp 3.5 fills ttlMs/cacheScope for 2026-07-28 results (#1308), and stamp_2026_07_28_result already does that here.

Tests

New or changed in crates/tracedecay-mcp/tests/server_rmcp.rs:

  • rmcp_3_5_clients_open_a_session_on_either_lifecycle. A default rmcp 3.5 client (initialize naming 2026-07-28) negotiates 2025-11-25. An Auto client discovers 2026-07-28. Both then list tools.
  • a_discover_probe_leaves_the_session_open_for_initialize. Raw frames: server/discover, then initialize at 2025-06-18, then tools/list without _meta gets the legacy {"tools": []} shape.
  • refused_inline_openers_leave_the_session_open_for_initialize replaces an_inline_opener_without_full_request_context_is_refused_and_closed. A partial _meta opener and an unsupported-version opener are refused, then initialize succeeds on the same connection.
  • initialize_naming_a_per_request_revision_negotiates_the_newest_handshake_revision now expects LATEST_WITH_INITIALIZE. Against 3.5 with the old code it passed for the wrong reason, because LATEST itself became 2026-07-28.

The branch's earlier tests remain. rmcp_wire_matrix_matches_raw_dispatch_initialize_tools_and_resources and rmcp_initialize_echoes_a_supported_handshake_revision cover the rmcp wire against raw dispatch. The stateless test asserts the 2026-07-28 fields are absent. mcp_suite test_initialize_negotiates_legacy_and_unknown_client_versions covers 2025-11-25 and 2026-07-28.

Fail-before evidence: the new test file was run against the merge commit 296648bf77, which has the 3.5 lock and none of the port. //crates/tracedecay-mcp:server_rmcp failed 4 of 11. The 4 failures were the four tests above. The discover test failed with request _meta is missing ... on the tools/list after initialize.

Lock command

relock.sh with default arguments merged origin/master and ran cargo +1.99.0 update -w, pnpm install and gen_builds.py. The lock was already consistent, so no regeneration commit was needed. The lock diff against master is the single rmcp 3.4.0 -> 3.5.1 entry.

Gates (head 3133aee038)

  • bazel build --config=clippy //crates/tracedecay-mcp/...: Build completed successfully
  • bazel build --config=clippy //crates/tracedecay/...: Build completed successfully
  • bazel build //:rustfmt_check: Build completed successfully
  • //crates/tracedecay-mcp:unit_test: 461 passed; 0 failed
  • //crates/tracedecay-mcp:server_rmcp: 11 passed; 0 failed
  • //crates/tracedecay-mcp:server_protocol: 5 passed; 0 failed
  • //crates/tracedecay:unit_test --test_arg=mcp::server::rmcp::tests: 10 passed; 0 failed
  • //crates/tracedecay:mcp_suite (full): 661 passed; 0 failed
  • cargo +1.99.0 metadata --locked: ok
  • bazel run //scripts:bazel/gen_builds.py -- --check: all 60 generated BUILD.bazel files are current

rmcp 3.5 moves ProtocolVersion::LATEST to 2026-07-28, a revision with no
initialize handshake. Initialize negotiation and the stateless request
context stay on LATEST_WITH_INITIALIZE (2025-11-25): a supported handshake
revision is echoed, a handshake-less or unknown one negotiates down.

The wire tests now pin what the default rmcp client requests (LATEST), the
downgrade, the echo of a supported revision on both the rmcp and raw paths,
and that stateless results omit the 2026-07-28 result fields.
@changeset-bot

changeset-bot Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3133aee

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@ScriptedAlchemy
ScriptedAlchemy marked this pull request as draft October 14, 2026 10:03
auto-merge was automatically disabled October 14, 2026 10:03

Pull request was converted to draft

# Conflicts:
#	crates/tracedecay-mcp/src/server/protocol.rs
#	crates/tracedecay-mcp/src/server/rmcp.rs
#	crates/tracedecay/Cargo.toml
#	crates/tracedecay/src/mcp/server/rmcp.rs
rmcp 3.5 sets ProtocolVersion::LATEST to 2026-07-28, which has no
initialize handshake. Initialize negotiation, its default answer and the
stateless request context use LATEST_WITH_INITIALIZE, so a default 3.5
client that asks for 2026-07-28 over initialize gets 2025-11-25.

Before a lifecycle is chosen, the session now answers a request with
missing context or an unsupported inline version and stays open, and
answers a server/discover probe without choosing the inline lifecycle.
A client that probes first can still fall back to initialize.
@ScriptedAlchemy
ScriptedAlchemy marked this pull request as ready for review October 14, 2026 19:12
@ScriptedAlchemy
ScriptedAlchemy merged commit 1e46202 into master Oct 14, 2026
5 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant