Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 The instruction to "re-register the client" isn't actionable as written: the SDK only performs dynamic client registration when
TokenStorage.get_client_info()returns nothing, so a persisted registration is reused as-is and there is no API to force re-registration. Suggest rewording to tell affected users to clear the stored client registration (and tokens) from theirTokenStorageso the next flow registers afresh with the slash-less redirect URI.Extended reasoning...
What the note says vs. what the SDK does. The new paragraph tells users whose registration "is persisted in
TokenStorage" to "re-register the client so the stored value matches what the SDK now transmits." However,OAuthClientProvideronly performs dynamic client registration when no registration is already persisted: insrc/mcp/client/auth/oauth2.py,_initialize()loadsclient_infofromstorage.get_client_info()(line 484), and Step 4 of the 401 flow only registers underif not self.context.client_info:(line 596). There is no SDK API to force re-registration while a registration remains in storage, so a reader following the note literally has no way to act on it.The code path that makes the mismatch real. After PR #2925,
OAuthClientMetadataserializes a path-lessredirect_urisentry without the trailing slash, and the client sendsclient_metadata.redirect_uris[0]verbatim in the/authorizerequest and the token exchange (oauth2.py lines 340 and 399). Meanwhile the authorization server still holds the old slash-suffixed registration created by a previous SDK release, and RFC 6749 §3.1.2.3 mandates exact string comparison — so the flow fails. The note correctly identifies the problem; only the remedy is unclear.Step-by-step example. (1) A user on the previous SDK registers with
redirect_uris=['http://localhost:8080']; the metadata serialized ashttp://localhost:8080/, and the AS stored that. The resultingOAuthClientInformationFullis persisted viaTokenStorage.set_client_info(). (2) The user upgrades and tokens later expire/are cleared, triggering a fresh authorization. (3)_initialize()loads the oldclient_infofrom storage, so the registration step is skipped, but theredirect_uriquery parameter now goes out ashttp://localhost:8080(no slash). (4) The AS exact-matches against its storedhttp://localhost:8080/and rejects the request. (5) The user reads the migration note and tries to "re-register" — but as long asget_client_info()keeps returning the old registration, the SDK never re-registers, so the failure persists.Secondary wording issue. The phrase "so the stored value matches what the SDK now transmits" conflates two stores: the
OAuthClientInformationFullpersisted in the user'sTokenStorage(which gates whether DCR runs at all) and the registration held by the authorization server (which is what the RFC 6749 exact-match comparison actually runs against). Re-registration fixes the AS-side record; clearingTokenStorageis what causes re-registration to happen.Suggested fix. Reword the final clause to something like: "…clear the stored client registration from your
TokenStorage(soget_client_info()returnsNone) and let the client perform a fresh registration with the new redirect URI — or update the registration at the authorization server out of band." This is a docs-only clarity improvement to a docs-only PR whose entire content is this paragraph; the statement isn't wrong, just not actionable, hence nit severity. All four verifiers independently confirmed the underlying SDK behavior and agreed on this characterization.