fix(mcp): replace global _oauth_port with per-provider closures - #44685
fix(mcp): replace global _oauth_port with per-provider closures#44685HrushiYadav wants to merge 1 commit into
Conversation
|
Code Review — Clean ✅ Reviewed the diff (3 files, +85/-19 lines). Findings:
LGTM — eliminates a subtle concurrency bug in multi-provider OAuth flows. |
f33846b to
d8403df
Compare
|
Friendly ping -- this fixes the global _oauth_port race condition with per-provider closures. Any feedback? |
- Add `port` kwarg to `_redirect_handler` and `_wait_for_callback`, falling back to the module-level global for backward compatibility. - In `build_oauth_auth` and `MCPOAuthManager._build_provider`, create closures that capture the resolved port so each provider uses its own callback port instead of reading the last-writer-wins global. - Add regression test verifying two back-to-back providers capture independent ports in their redirect handler closures. Closes #44588
d8403df to
bd88c16
Compare
|
Rebased on latest main. Thanks @liuhao1024 for the review earlier. Ready whenever a maintainer can take a look. |
|
Thanks for isolating the per-provider callback state. Problems
Suggested changes
Current main still assigns the global at Automated hermes-sweeper review. |
Duplicate of #5345 (earliest open PR taking the same per-provider-closure approach to the |
|
Resolved on main via PR #65622, which merged the same closure-factory approach (salvaged from #44872; #5345 by @caseyg was the earliest submission — all credited in the PR body). Thanks for the contribution @HrushiYadav! |
Summary
_oauth_portis a module-level global that gets overwritten each timebuild_oauth_auth()orMCPOAuthManager._build_provider()is called. When multiple MCP servers need OAuth, the last call wins and earlier providers read the wrong port from the global, causing their callback servers to bind the wrong port or cross-pollute each other's flows.Changes
portkeyword argument to_redirect_handlerand_wait_for_callback. Both fall back to the module-level global whenportis not provided, preserving backward compatibility.build_oauth_authandMCPOAuthManager._build_provider, capture the resolved port in closures (scoped_redirect,scoped_callback) so each provider carries its own port instead of reading the shared global._oauth_portglobal is still set by_configure_callback_portfor any external consumers, but the two primary construction paths no longer depend on it.TestOAuthPortIsolation) that builds two providers back-to-back and verifies each closure passes the correct port to_redirect_handler.Test plan
test_concurrent_providers_use_different_portspassestest_mcp_oauth.pytests pass (13 passed, 1 skipped on Windows)TestRedirectHandlerSshHint) pass with the newportkwargCloses #44588