Skip to content

Migrate workspace from rmcp 1.7.0 → 2.1.0 #184

Description

@jmagar

Summary

Bump the workspace off rmcp = "1.7" to 2.1. This is a 1.7 → 1.8 → 2.0 → 2.1 span, so we inherit the 1.8 schema/auth hardening, the 2.0 breaking rename batch (MCP 2025-11-25 model alignment, #927), and the 2.1 meta helpers.

Good news: we hand-roll all our ServerHandler/ClientHandler impls — zero #[tool]/#[tool_router]/#[prompt_router]/#[tool_handler] usage — so the entire macro-migration surface is a non-issue. Damage is concentrated in labby (server handlers + mcp/logging) and labby-gateway (upstream/pool/relay.rs). labby-auth is behavioral-only.

Bad news: CI + just + release all run RUSTFLAGS: -D warnings and cargo clippy -- -D warnings, so every SEP-2577 deprecation is a hard build failure, not a friendly warning. The ~121 LoggingLevel references block the merge.

  • Current: rmcp 1.7.0 (workspace-pinned "1.7"), audited @ 97244c0
  • Target: rmcp 2.1.0 (2026-07-02)

Cargo bump

# Cargo.toml [workspace.dependencies]
rmcp = { version = "2.1", features = [
  "server", "client", "auth", "schemars", "elicitation",
  "transport-io", "transport-child-process",
  "transport-streamable-http-server", "transport-streamable-http-client-reqwest",
  # "macros",  # unused — safe to drop, shaves build time
] }

All enabled feature flags still exist in 2.1. Regenerate Cargo.lock.


A. Hard compile errors (won't build regardless of lints)

  • A1 — Content removed → ContentBlock. rmcp::model::Content no longer exists (was Annotated<RawContent>; 2.x flattened to a ContentBlock enum), no compat alias. ~34 Content::text(...) calls + 5 imports across 8 files. Mechanical Content::textContentBlock::text, but eyeball each import line.
    • labby-gateway/src/upstream/pool/relay.rs, .../tools_call.rs
    • labby/src/mcp/result_format.rs, .../call_tool.rs, .../upstream.rs, .../upstream/tests.rs
  • A2 — Elicitation type renames (#927): CreateElicitationRequestParamsElicitRequestParams, CreateElicitationResultElicitResult. Method name create_elicitation is unchanged; only param/result types change. We already use the plural variant names (FormElicitationParams), which match 2.x. Sites: labby-gateway/.../relay.rs (ClientHandler::create_elicitation impl), labby/src/mcp/elicitation.rs (peer call).
  • A3 — Enum variant renames: ServerRequest::CreateElicitationRequestElicitRequest; ClientResult::CreateElicitationResultElicitResult; ServerNotification::ElicitationCompletionNotificationElicitationCompleteNotification. (relay.rs)
  • A4 — ⚠️ Local name clash: labby/src/mcp/elicitation.rs defines its own pub(crate) enum ElicitResult { Confirmed, Declined, Cancelled, NotSupported, Failed } (12 refs across 2 files). rmcp 2.x now owns rmcp::model::ElicitResult. Rename ours (e.g. ConfirmOutcome) to kill the shadow.

B. Deprecations → CI failures under -D warnings (SEP-2577)

Deprecated ≠ removed. As a gateway we legitimately must keep proxying logging/sampling/roots for our upstreams while the SDK still supports them. Recommended: scoped #![allow(deprecated)] islands, not a full rip-out.

  • B1 — LoggingLevel (whole enum deprecated). 121 hits / 11 files. Our entire mcp/logging.rs severity model is built on it. → #![allow(deprecated)] island (or migrate to an internal severity enum, later).
  • B2 — LoggingMessageNotificationParam / LoggingMessageNotification (4 hits, mcp/logging.rs).
  • B3 — .enable_logging() server-capability buildermcp/server.rs:138.
  • B4 — create_message (peer) + CreateMessage* — sampling proxy in relay.rs (5 hits).
  • B5 — list_roots (peer) + ListRootsResult/Root — roots proxy in relay.rs.
  • B6 — PrimitiveSchemaPrimitiveSchemaDefinition (deprecated alias, 4 hits in elicitation.rs + relay.rs). One-word swap — just rename, don't allow.

C. Behavioral / non-compile (test + eyeball — no compiler safety net)

  • 1.8 tool-schema stripping/validation (#856 remove unnecessary inputSchema fields, #860 strip+validate in/out schema). We re-expose upstream schemas via lab:search/lab:execute; emitted inputSchema shape can change. Adjacent to the old MAX_SCHEMA_BYTES truncation issue. Re-run + re-accept insta snapshots; diff advertised gateway tool schemas before/after.
  • 1.8 tool errors for invalid arguments (#894) — error surface for bad args changed; check tests asserting old behavior.
  • 1.8 → 2.1 protocol-version negotiation (#855, #930) + 2025-11-25 support — verify gateway↔upstream handshake. (Note: ProtocolVersion::V1 in acp/runtime.rs is Agent Client Protocol, not rmcp — leave it.)
  • Auth stack (labby-auth upstream-oauth-rmcp) — 1.8: OAuth issuer validation (#896), DCR application_type (#883), metadata-discovery ordering (#887); 2.0: block resource spoofing (#937) + metadata SSRF (#935); 2.1: preserve refresh_token when omitted (#949) + block redirect header leaks (#936). Mostly free hardening, but issuer validation + discovery ordering can change which OAuth upstreams authenticate — smoke-test the real ones.
  • #[non_exhaustive] + new TaskStatusNotification / ClientHandler::on_task_status — default impl, non-breaking; only bites an exhaustive match on ServerNotification/ClientNotification without a _ arm (we don't appear to). Optionally implement on_task_status to surface upstream task progress.
  • Verify relocated helpers on first compile: AnnotateAble, RawResource, Annotated (used in handlers_resources.rs) — 2.x model restructure may have moved these.

D. Free wins to adopt while we're in here (new in 2.1)

  • SEP-414 trace context (traceparent/tracestate/baggage on _meta) — thread a trace ID through gateway hops; would make the bimodal catalog flapping (simultaneous lab:search/lab:execute drops) actually traceable end-to-end.
  • SEP-2575 meta helpers — read clientInfo / clientCapabilities / protocolVersion / logLevel off per-request _meta; tailor-made for stateless/multiplexed dispatch.
  • 1.8 custom HTTP client for OAuth (#908) + preserve configured reqwest client (#917) — let labby-auth reuse one tuned client across the upstream OAuth stack.

Suggested execution order

  1. Cargo bump + Cargo.lock regen (expect a wall of errors — fine).
  2. A1 ContentContentBlock (unblocks most of the tree).
  3. A2/A3/A4 elicitation renames + rename local ElicitResult; B6 PrimitiveSchema in the same files.
  4. B1–B5 #![allow(deprecated)] islands on logging.rs, server.rs, relay.rs.
  5. cargo build green → C snapshot re-accept + auth/upstream smoke tests.
  6. Optional D in a follow-up PR.

Files touched (~20)

labby-gateway/src/upstream/pool/relay.rs        A2 A3 B4 B5 B6  (worst offender)
labby-gateway/src/upstream/pool/tools_call.rs   A1
labby/src/mcp/elicitation.rs                    A2 A4 B6
labby/src/mcp/call_tool.rs                      A1
labby/src/mcp/result_format.rs                  A1 B1
labby/src/mcp/upstream.rs, upstream/tests.rs    A1
labby/src/mcp/logging.rs                        B1 B2  (allow-island)
labby/src/mcp/server.rs                         B3     (allow-island)
labby/src/mcp/resource_proxy.rs                 B1
labby/src/mcp/in_process_peer.rs                B1
labby/src/mcp/handlers_resources.rs             B1 + verify AnnotateAble/RawResource
labby/src/mcp/handlers_tools/tests.rs           B1
labby/src/cli/serve.rs                          B1

References

Audited against 97244c0 (workspace v0.30.0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions