Skip to content

rmcp 3.3: typed custom responses and strict Origin validation - #3

Merged
jmagar merged 30 commits into
mainfrom
codex/rmcp-3.3-labby-compat
Sep 13, 2026
Merged

jmagar merged 30 commits into
mainfrom
codex/rmcp-3.3-labby-compat

Conversation

@jmagar

@jmagar jmagar commented Sep 13, 2026

Copy link
Copy Markdown

Scope

Minimal Labby compatibility patch on stock rmcp 3.3.0 (3e636cab26c013eca5131103c03d20237f12c4df). The PR targets an unchanged release-baseline branch so the diff is only the patch, not the upstream release history. It does not update the fork's main branch, submit anything to modelcontextprotocol/rust-sdk, or deploy Labby.

  • Preserve raw response envelopes through stdio, workers, HTTP JSON/SSE, Unix sockets, and OAuth wrappers; expose generic typed custom-request APIs without changing global core-result classification.
  • Preserve normal response correlation, errors, timeouts, cancellation, and tool-header discovery through authenticated transports.
  • Enforce MCP HTTP Origin rejection with 403 for malformed/non-UTF8/duplicate values; reject non-origin URI components and compare normalized effective ports without arbitrary-port wildcarding.
  • Preserve legacy meta-only CallToolResult behavior. The upstream classifier proposal is intentionally not included.

Labby adopts stock SDK credential refresh guards separately, with distinct operation/persistence locks and exact-generation persistence/invalidation fencing. No SDK source is vendored into Labby.

Validation

Independent review found no remaining P1/P2/P3 issues in this patch after corrections.

  • rmcp library: 496 passed.
  • Result-wire compatibility: 12 passed, including legacy meta-only results.
  • Typed/raw custom requests: 8 passed, including OAuth HTTP round-trip and header discovery.
  • Custom headers: 27 passed, including 11 Origin cases.
  • Labby-equivalent feature matrix, all-target Clippy with -D warnings: passed.
  • SDK formatting and diff checks: passed.
  • Labby integration: expanded real HTTP Origin, protocol mismatch, unknown method, two-request cancellation isolation, and CI routing: 5 passed.
  • Labby auth: 586 unit + 14 integration tests passed, including cross-upstream one-exchange coalescing and delayed-exchange credential replacement; all-target Clippy passed.

The custom-request suite was explicitly run without the SDK local feature; an all-features invocation alone skips that target. Live vendor hosts and full specification compliance are not claimed by these checks.

nickcoai and others added 28 commits August 24, 2026 22:43
…1186)

* fix: allow concurrent streamable http requests

* fix: keep streamable http recovery responsive

Keep cancellation and replies available while old session POSTs finish.
Bound the wait for old POSTs and the replacement initialization handshake.
Do not retry interrupted POSTs because the server may have processed them.

Add regressions for recovery, queued cancellation, control timeouts, and
server replies needed by active requests.

* fix: preserve response and cancellation ordering

* refactor: clarify streamable http control flow

* fix: match stream responses against pending request ids

Match responses against all pending requests before removing a stream
registration. Keep distinct numeric and string ids separate while preserving
the existing fallback for servers that stringify numeric ids.

Add a mixed-id regression and keep a separate registration owner alive in
the abandoned-cancellation test.

* feat: make streamable http control timeouts configurable
…odelcontextprotocol#1211)

* fix(transport): fall back after HTTP discover rejection

* fix(transport): limit legacy fallback to sessionless probes

* style: apply nightly rustfmt import ordering
* feat: add request-state key rotation

* docs: streamline request-state codec documentation

* fix: harden request-state fallback verification

* refactor: refine request-state keyring API

* docs: make request-state rotation guidance self-contained

* docs: streamline request-state keyring rustdocs

* test: streamline request-state keyring coverage

* docs: restore request-state key rotation doctest

* chore: remove manual changelog entry
…lcontextprotocol#1230)

Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.85.13 to 2.86.7.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](taiki-e/install-action@82cd3e7...b6ff580)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-version: 2.86.7
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…elcontextprotocol#1232)

* feat(auth): coordinate refreshes through credential stores

Add an optional owned guard covering credential reload, refresh, and save.
Keep credential-store failures distinct from reauthorization, including
reactive refresh after an HTTP 401.

Existing stores retain their default uncoordinated behavior. Cover guard
ordering, concurrent rotation, storage failures, and client identity checks.

* docs(auth): clarify refresh guard coordination
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…ontextprotocol#1229)

Updates the requirements on [process-wrap](https://github.com/watchexec/process-wrap) to permit the latest version.
- [Changelog](https://github.com/watchexec/process-wrap/blob/main/CHANGELOG.md)
- [Commits](watchexec/process-wrap@v9.0.0...v10.0.0)

---
updated-dependencies:
- dependency-name: process-wrap
  dependency-version: 10.0.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…xtprotocol#1238)

Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 7.6.0 to 10.0.1.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](astral-sh/setup-uv@37802ad...20cfd1b)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 10.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ontextprotocol#1234)

* feat(auth): request ID-JAGs with enterprise refresh tokens

* feat(auth): exchange ID-JAGs for MCP access tokens

Redeem ID-JAGs at the approved resource authorization server and return
its bearer token, lifetime, and effective granted scopes. Preserve scope
narrowing and redacted diagnostics, and reuse the default HTTP adapter.

Support independently configured client authentication at both servers.
Document the exchange profile and test redirects and staged failures.

Partially addresses modelcontextprotocol#531.

* test(conformance): cover EMA refresh-token exchange
…col#1236)

* fix(auth): unify refresh checks and error handling

Claude-Session: https://claude.ai/code/session_011pHFfoTygeG84mCDXzCcmw

* test(auth): add live authorization-server checks

Claude-Session: https://claude.ai/code/session_011pHFfoTygeG84mCDXzCcmw
)

* fix: resolve clippy warnings across workspace

* ci: also run clippy on rmcp with all features except local

--all-features enables the local feature, which cfg-gates out
tower.rs and most of the test suite, so the existing clippy step
never actually lints them.
…contextprotocol#1250)

Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.86.7 to 2.87.6.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](taiki-e/install-action@b6ff580...7b8d471)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-version: 2.87.6
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1a51d4b5a03bb97576af186c813af67e9137ba7c to d43b6c087ac471e2ea7b8af622ff15f05c0c365b.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](crate-ci/typos@1a51d4b...d43b6c0)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: d43b6c087ac471e2ea7b8af622ff15f05c0c365b
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…nic (modelcontextprotocol#1231)

* fix(sse): saturate exponential reconnect backoff

ExponentialBackoff::retry computed the reconnect multiplier with
2u32.pow(current_times). With max_times unset, current_times can reach
the bit width, panicking in debug builds and wrapping to a zero delay in
release builds for long-lived SSE clients. Use saturating_pow and
Duration::saturating_mul so the delay stays monotonic and panic-free.

* fix(sse): cap exponential reconnect backoff at a bounded max delay

Saturating the multiplier alone can still yield decades-long sleeps once
current_times reaches the bit width, pinning the stream in
tokio::time::sleep without reconnecting or terminating. Add an optional
max_delay (default 30s) that clamps the computed delay, keeping the
backoff monotonic and panic-free while guaranteeing the client retries.

* fix(sse): default max_delay to None to preserve unbounded backoff

Per maintainer feedback, leave ExponentialBackoff::default() unbounded so
the fix stays a pure overflow bug-fix. The saturating multiplier removes
the debug panic / release wrap from modelcontextprotocol#1198, while max_delay stays opt-in
for callers that want a bounded reconnect delay.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@jmagar
jmagar force-pushed the codex/rmcp-3.3-labby-compat branch from 4655184 to 2faf762 Compare September 13, 2026 17:55
@jmagar
jmagar merged commit f2639b9 into main Sep 13, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants