[rmcp-client] Serialize MCP OAuth refresh ownership - #29017
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1328e80255
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
1328e80 to
251a6b8
Compare
69a7bec to
fc09471
Compare
80b1dd7 to
01f7bc5
Compare
bf747a3 to
7d11960
Compare
7d11960 to
61a6e45
Compare
09c6d6f to
a727719
Compare
3202970 to
4f9dc56
Compare
4f9dc56 to
4d4b956
Compare
|
|
||
| #[expect( | ||
| clippy::await_holding_invalid_type, | ||
| reason = "AuthorizationManager async access must be serialized through its mutex" |
There was a problem hiding this comment.
This makes sense, but holding a synchronous mutex across an await boundary is a recipe for deadlocks. Can we avoid this?
| // than serving an unpersisted token whose eventual loss would be difficult to correlate | ||
| // with this transaction. A later refresh may require reauthorization if the provider | ||
| // already consumed the previous token; that is the accepted fail-closed behavior. | ||
| // TODO: If persistence failures are common in practice, add an explicit bounded retry or |
There was a problem hiding this comment.
I think we should assume that transient storage issues will happen in the field, doesn't need to be in this PR but could this be addressed in this stack?
| authorization_manager.set_credential_store(store); | ||
| // TODO(stevenlee): RMCP's `initialize_from_store` updates the credential store and client ID | ||
| // but not its private `current_scopes`. Credential adoption can therefore leave scope-upgrade | ||
| // state stale until RMCP exposes an adoption API that synchronizes both. |
There was a problem hiding this comment.
This seems like it might invite bugs -- what would we need to do to fix it?
Codex Thread 019edd6d-6f14-74e2-853c-345d1803d4a6
Important
This PR belongs to the superseded MCP OAuth stack. Please review and merge the replacement stack beginning with openai/codex#30292. This PR remains available only as historical/reference context.
Replacement review order:
This is part 1 of a five-PR stack that prevents concurrent MCP OAuth refreshes from replaying a rotating refresh token or overwriting newer credentials.
Review order
Autoresolution driftWhy
OAuth providers may rotate the refresh token on every refresh. The provider request, authoritative credential reread, in-memory update, and durable write therefore have to behave as one serialized transaction. Otherwise two Codex processes can both consume token A, or a slower writer can overwrite the newer token B and force reauthentication.
Autoalso currently chooses between keyring and File independently on each operation. That fallback is useful when a client starts, but switching stores during one refresh lifecycle can replay an older token from the other store. This layer resolves the source once for theRmcpClientlifecycle and then reads and writes only that source.What changes
Autoonce at client construction using the existing keyring-first/File-fallback policy, and retain that concrete source across transport retries and session rebuilds.compute_store_key(server_name, url).Decisions encoded by this stack
Review focus
Review the credential identity, lifecycle source pin, authoritative reread, cancellation boundary, persist-before-authority policy, and provider-timeout policy. Part 4 completes the ownership switch by withholding refresh capability from RMCP and routing all transport paths through Codex.
Non-goals
Autobackend selection.Validation
just test -p codex-rmcp-client: 90 passed, 2 skipped.