Commit eb3511d
chore(deps): bump rmcp from 2.2.0 to 3.2.0 and port the OAuth transport
Supersedes the red Dependabot PR #5877. rmcp 3.2 reshaped
`transport::auth`; this ports our client and the in-process OAuth mock
to the new contract without changing any product guarantee.
What changed in rmcp, and what we adapted to:
1. `AuthorizationManager::discover_metadata()` is now
`resolve_metadata()`, returning `AuthorizationMetadataResolution
{ metadata, source }`. The discovery order (RFC 9728 protected
resource metadata, then RFC 8414 / OIDC, then legacy synthesized
endpoints) and the legacy fallback are unchanged, so the two call
sites just take `.metadata`.
2. `OAuthState::start_authorization(scopes, redirect_uri, client_name)`
is now a single `AuthorizationRequest` builder. It also introduces a
client-identity priority order (pre-registered client ID, then a
Client ID Metadata Document, then Dynamic Client Registration); we
supply neither of the first two, so we still land on DCR exactly as
before. Empty scopes now mean "let the SDK select from the
WWW-Authenticate challenge / PRM / AS metadata" rather than "request
none" — strictly better, and our explicit scopes still win.
3. Discovery now validates the `issuer` in the fetched authorization
server metadata against the discovery URL (RFC 8414 / OIDC) and
fails with `AuthError::AuthorizationServerMismatch` instead of
silently accepting it. Our in-process mock answered *every*
`/.well-known/oauth-authorization-server*` path with one document
whose `issuer` is the origin root, including rmcp's first candidate
`/.well-known/oauth-authorization-server/mcp`, whose issuer must be
`<origin>/mcp`. The mock now answers only the canonical path, which
is what a real authorization server at the origin root does. That is
a conformance fix to a test double, not a product behavior change:
every assertion in the eight tests is untouched.
4. `AuthError` split the refresh outcomes: `TokenRefreshFailed` is now
the retryable case and the new `TokenRefreshRejected` carries a
definitive `invalid_grant`; separately, `refresh_token()` returns
`AuthError::AuthorizationRequired` where 2.2 returned
`TokenRefreshFailed("No refresh token available")`. The
`invalid_grant` text still reaches us intact, so the dead-grant
guarantees hold unchanged, but "OAuth authorization required" — a
credential with no usable grant left — was classified as a plain
transport failure on every surface. `error_text_looks_auth_required`
now matches rmcp's full phrase, so that case flips the server to
`auth required` and offers the login tool like every other
unrecoverable credential.
Not adapted because nothing depended on it: `StoredCredentials` gained
an `issuer` field and `initialize_from_store` now discards tokens when
the authorization server changes; `CredentialStore` gained an optional
`acquire_refresh_guard`; the RFC 8707 `resource` parameter on refreshes
now prefers the discovered PRM resource indicator and falls back to the
base URL, which is what 2.2 always sent. We keep our own credential
store, so rmcp's in-memory default is untouched by any of these.
Verified locally:
cargo fmt clean
cargo check -p codewhale-tui clean
RUST_MIN_STACK=16777216 cargo test -p codewhale-tui --lib -- mcp::
230 passed; 0 failed; 1 ignored (was 222 passed; 8 failed)
RUST_MIN_STACK=16777216 cargo test -p codewhale-tui --lib
11717 passed; 0 failed; 13 ignored
Two earlier full-suite runs each tripped one different pre-existing
parallel-execution flake in a module this change does not touch
(`model_inventory::...ollama_default_prefers_live_local_tags...`, then
`remote_control::...distinct_recovery_turn_ids`); both pass alone and
the run above is clean.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0188XYyJaw9Mh9uSrqQBoqhm
Signed-off-by: CodeWhale Bot <bot@codewhale.net>1 parent 41fecf8 commit eb3511d
4 files changed
Lines changed: 45 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
65 | | - | |
| 65 | + | |
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
14 | 16 | | |
15 | 17 | | |
16 | 18 | | |
| |||
76 | 78 | | |
77 | 79 | | |
78 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
79 | 89 | | |
80 | 90 | | |
81 | 91 | | |
| |||
611 | 621 | | |
612 | 622 | | |
613 | 623 | | |
614 | | - | |
615 | | - | |
616 | | - | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
617 | 627 | | |
618 | 628 | | |
619 | 629 | | |
| |||
1344 | 1354 | | |
1345 | 1355 | | |
1346 | 1356 | | |
1347 | | - | |
| 1357 | + | |
| 1358 | + | |
| 1359 | + | |
| 1360 | + | |
| 1361 | + | |
1348 | 1362 | | |
1349 | 1363 | | |
1350 | 1364 | | |
1351 | 1365 | | |
1352 | 1366 | | |
1353 | 1367 | | |
1354 | | - | |
| 1368 | + | |
1355 | 1369 | | |
1356 | 1370 | | |
1357 | 1371 | | |
| |||
1677 | 1691 | | |
1678 | 1692 | | |
1679 | 1693 | | |
| 1694 | + | |
| 1695 | + | |
| 1696 | + | |
| 1697 | + | |
| 1698 | + | |
| 1699 | + | |
| 1700 | + | |
| 1701 | + | |
| 1702 | + | |
1680 | 1703 | | |
1681 | 1704 | | |
1682 | 1705 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5986 | 5986 | | |
5987 | 5987 | | |
5988 | 5988 | | |
5989 | | - | |
5990 | | - | |
5991 | | - | |
| 5989 | + | |
| 5990 | + | |
| 5991 | + | |
| 5992 | + | |
| 5993 | + | |
| 5994 | + | |
| 5995 | + | |
| 5996 | + | |
| 5997 | + | |
| 5998 | + | |
5992 | 5999 | | |
5993 | 6000 | | |
5994 | 6001 | | |
| |||
0 commit comments