Skip to content

fix: recover stale dynamic OAuth client registrations - #305

Open
piyushmor wants to merge 7 commits into
geelen:mainfrom
piyushmor:fix/stale-dynamic-oauth-clients
Open

fix: recover stale dynamic OAuth client registrations#305
piyushmor wants to merge 7 commits into
geelen:mainfrom
piyushmor:fix/stale-dynamic-oauth-clients

Conversation

@piyushmor

@piyushmor piyushmor commented Jul 27, 2026

Copy link
Copy Markdown

Summary

Make dynamic OAuth authorization resilient when several local MCP clients or proxy processes start at once. The proxy recovers the affected server automatically without deleting unrelated credentials or requiring a restart.

  • Detect stale or unregistered dynamic client_id responses (for example, unknown client_id), clear only that server’s dynamic registration/tokens/transaction, re-register once, and retry.
  • Persist a state-bound PKCE transaction (state, verifier, creation time); only its matching callback may exchange a code. Stale or expired callbacks are rejected.
  • Fence late token exchanges by authorization state, so a timed-out old exchange cannot overwrite a newer transaction’s tokens.
  • Coordinate concurrent processes with lease IDs, atomic lock claims, lease-specific completion records, and a fail-closed local mutation guard. Stale lease reclamation, replacement-listener startup, and callback-port handoff are serialized safely.
  • Let secondary clients consume a successful owner completion even after the owner has released its callback listener.
  • Return retryable -32001 while authorization is in progress. Recovery failures clean up the active round so a later request can start a fresh flow; failures no longer permanently poison the proxy.
  • Use one shared 30-second deadline for the callback wait and token exchange.
  • Preserve static-client and redirect-URI/configuration errors; no broad auth-cache deletion and no unbounded retry loop.
  • Include the generated dist/ bundle so Git-archive installations contain runnable package artifacts.

Validation

  • corepack pnpm test:unit — 157 tests
  • corepack pnpm check
  • corepack pnpm build
  • Package lifecycle validation for Git-archive installation
  • Regression coverage for simultaneous initialization, stale-reclaim races, completion-after-release, callback-port handoff, and fragmented/delayed mutation-guard traffic.

Expected behaviour

When consent is needed, one browser authorization window opens per MCP server. Other clients receive a retryable pending response and can retry after authorization completes. Subsequent client starts reuse the persisted authorization without another login.

@piyushmor

Copy link
Copy Markdown
Author

fixes #299

@piyushmor

Copy link
Copy Markdown
Author

@geelen please help me with this PR. would really make my local setup very stable.

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.

2 participants