Skip to content

[rmcp-client] Test MCP OAuth concurrency and recovery#30089

Open
stevenlee-oai wants to merge 1 commit into
dev/stevenlee/mcp-oauth-stack-5-codex-refreshfrom
dev/stevenlee/mcp-oauth-stack-8-transport-tests
Open

[rmcp-client] Test MCP OAuth concurrency and recovery#30089
stevenlee-oai wants to merge 1 commit into
dev/stevenlee/mcp-oauth-stack-5-codex-refreshfrom
dev/stevenlee/mcp-oauth-stack-8-transport-tests

Conversation

@stevenlee-oai

@stevenlee-oai stevenlee-oai commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

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:

  1. openai/codex#30292 — shared File/Secrets store locking
  2. openai/codex#30293 — authoritative serialized refresh
  3. openai/codex#30294 — Codex-owned transport refresh and one-shot 401 recovery
  4. openai/codex#30295 — login/logout transaction serialization
  5. openai/codex#30296 — diagnostic-only Auto store drift reporting

This is part 5 of a five-PR stack that prevents concurrent MCP OAuth refreshes from replaying a rotating refresh token or overwriting newer credentials. This layer is test-only.

Review and merge as one stack. The five PRs are an atomic merge unit split only for reviewability. Production behavior lives in parts 1–4; this PR centralizes the regression matrix so the same large fixtures and scenarios are not repeated across intermediate diffs.

Review order

  1. openai/codex#29017 — refresh ownership, authoritative reread, and lifecycle-local store pinning
  2. openai/codex#29019 — serialize login and logout with refresh
  3. openai/codex#29021 — lock aggregate stores and observe Auto resolution drift
  4. openai/codex#29018 — route all OAuth recovery through Codex
  5. openai/codex#30089 — consolidated concurrency and transport regression tests (this PR)

Why

The final ownership boundary spans cross-process storage, public operations, and RMCP-internal traffic. These tests exercise the complete stack once, through the real Streamable HTTP adapter where applicable, without obscuring the production layers with repeated fixtures.

What is covered

  • Auto source selection and lifecycle pinning.
  • Diagnostic resolution history: Auto-to-Auto drift, explicit mode/backend baseline resets, persistence across calls, and failure remaining non-authoritative.
  • Authoritative reread, winner adoption, latest-refresh-token use, and proactive refresh guard-band behavior.
  • Keyring read/write failure without File fallback.
  • Provider timeout: release the lock, leave durable state unchanged, and permit a later serialized retry.
  • Caller cancellation: allow the owned refresh and persistence transaction to finish.
  • Refresh-vs-login and refresh-vs-logout ordering, synchronized on the real credential-lock WouldBlock branch.
  • File and Secrets save, load, and delete contention, synchronized on the real aggregate-store WouldBlock branch.
  • Cross-process File-mode startup refresh, including proof that the second child actually observes credential-lock contention and exactly one provider refresh occurs.
  • Transaction-level delayed same-client and cross-client 401 handling issuing exactly one provider refresh.
  • Initialization/public-operation recovery without RMCP-owned refresh.
  • RMCP-owned Response POST, SSE GET/reconnect, and session DELETE recovery.
  • Persistence failure returning the original error, restoring previous request-only credentials, avoiding File fallback, and making no hidden retry.

Decisions encoded by these tests

  • Codex is the only refresh owner; RMCP never receives a reusable refresh token during ordinary traffic.
  • Public Request/Notification recovery stays in outer RmcpClient; RMCP-owned Response/Error, GET/reconnect, and DELETE recover in the wrapper.
  • Each rejected token causes at most one serialized provider refresh, and later users adopt the winner.
  • Provider timeout releases the lock and permits a later retry.
  • Failed persistence has no automatic retry and does not make an unpersisted token request-authoritative.
  • The resolution sidecar is diagnostic only and can never change OAuth success or backend selection.
  • Auto is lifecycle-local and never hot-switches within one client.
  • openai/codex#28647 and its branch remain untouched.

Review focus

This PR should contain tests only. Review whether each race synchronizes on the behavior it claims to exercise, whether adapter-level scenarios assert the bearer token used after recovery, and whether provider refresh counts rule out duplicate rotation.

Validation

  • just test -p codex-rmcp-client: 113 passed, 8 skipped.
  • As local negative controls, temporarily bypassing the aggregate store lock made the File contention test fail, and temporarily bypassing the credential lock made the cross-process startup test fail because the second child never emitted the real contention marker. Those bypasses were restored and are not part of this PR.

@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from aa94ede to d6434ec Compare June 25, 2026 18:07
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from 6161cf2 to ce7b286 Compare June 25, 2026 18:07
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from d6434ec to 64f9f77 Compare June 25, 2026 18:13
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from ce7b286 to 72603dd Compare June 25, 2026 18:13
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from 64f9f77 to 6bf5882 Compare June 25, 2026 18:45
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from 72603dd to 61abba3 Compare June 25, 2026 18:45
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from 6bf5882 to 7b4f748 Compare June 25, 2026 19:09
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from 61abba3 to f947f83 Compare June 25, 2026 19:09
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from 7b4f748 to dd9a13b Compare June 25, 2026 21:11
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from f947f83 to 2e9465b Compare June 25, 2026 21:11
@stevenlee-oai stevenlee-oai changed the title [rmcp-client] Cover OAuth transport recovery end to end [rmcp-client] Test MCP OAuth concurrency and recovery Jun 25, 2026
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from dd9a13b to 0b3dcef Compare June 25, 2026 21:16
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from 2e9465b to 6741493 Compare June 25, 2026 21:29
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from dd9a13b to 52e1548 Compare June 25, 2026 21:29
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from 52e1548 to 6bb89cb Compare June 26, 2026 05:51
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from 6741493 to b296b36 Compare June 26, 2026 05:51
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from 6bb89cb to 6705ef7 Compare June 26, 2026 06:10
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from b296b36 to 5d03b4e Compare June 26, 2026 06:10
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from 6705ef7 to 44d29b6 Compare June 26, 2026 06:33
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from 5d03b4e to e864f5c Compare June 26, 2026 06:33
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-5-codex-refresh branch from 44d29b6 to 2e6a3e1 Compare June 26, 2026 07:39
@stevenlee-oai stevenlee-oai force-pushed the dev/stevenlee/mcp-oauth-stack-8-transport-tests branch from e864f5c to 8d833da Compare June 26, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant