Skip to content

test(mcp): make OAuth browser launch injectable across platforms - #3979

Open
aheritier wants to merge 2 commits into
mainfrom
test/3976-injectable-browser-opener
Open

test(mcp): make OAuth browser launch injectable across platforms#3979
aheritier wants to merge 2 commits into
mainfrom
test/3976-injectable-browser-opener

Conversation

@aheritier

Copy link
Copy Markdown
Collaborator

Fixes #3976

Stacked on #3881 — this branch is based on fix/3879-dcr-scope-propagation because the two target tests exist only there (not yet on main). Once #3881 merges the diff here narrows to just this commit.


Two browser-fixture tests (TestHandleManagedOAuthFlow_DCRSuccess_EndToEndScopeEquality, TestHandleEnable_OAuthDCR_ChallengePRMScopeFallback) were skipped on Windows: they used POSIX PATH shims (#!/bin/sh scripts shadowing open/xdg-open) that cannot intercept rundll32.

Introduces a BrowserOpener seam in pkg/tools/mcp/oauthflow — an atomic.Pointer[BrowserOpener] (defaulting to browser.Open) plus SetBrowserOpenerForTesting, mirroring the pre-existing SetHTTPClientForTesting idiom in the same file. RequestAuthorizationCode calls through the seam; production behavior is unchanged.

Both test packages replace their PATH-shim helpers with a channel-based stub via oauthflow.SetBrowserOpenerForTesting. The Windows t.Skip is removed; both tests now run on all platforms.

Testing: go test -v -run 'TestHandleManagedOAuthFlow_DCRSuccess_EndToEndScopeEquality|TestHandleEnable_OAuthDCR_ChallengePRMScopeFallback' ./pkg/tools/mcp/... ./pkg/tools/builtin/mcpcatalog/... — both PASS.

aheritier and others added 2 commits August 13, 2026 18:13
Carry explicitly configured or provider-advertised scopes through
DCR-based remote MCP OAuth so registration, authorization, and stored
token bookkeeping stay consistent. Adds quote-aware, multi-challenge-
continuing WWW-Authenticate parsing, normalizes configured scopes the
same way on both the DCR-selection and preflight-coverage sides to
avoid a reauth loop, and exercises every resolveClientCredentials
branch (explicit client, prompt fallback, successful DCR) with
end-to-end scope equality across the registration body, authorize URL,
and RequestedScopes.

Also covers the Docker MCP Catalog's on-demand toolset
(pkg/tools/builtin/mcpcatalog), which always constructs its inner
mcp.Toolset with a nil *latest.RemoteOAuthConfig: a new httptest
fixture drives enable_remote_mcp_server through a real, unstubbed
Start() and proves that same nil-config product path reaches a
successful dynamic client registration carrying the challenge/PRM
scope fallback, and then the authorize URL and stored token's
RequestedScopes bookkeeping, without panicking.

Windows test fixture coverage: setupFakeBrowserOpener and
setupFakeCatalogBrowserOpener shim only the open/xdg-open binaries via
a #!/bin/sh script on PATH, but pkg/browser launches rundll32 on
Windows instead, so the shim never intercepts it -- the real launcher
runs, no URL is captured, and the polling read times out while holding
interactiveOAuthMu, wedging later interactive-OAuth tests in the same
run. Skip both helpers on Windows before any mutex-touching setup, and
fix their comments, which falsely claimed the shim was host-independent.
Add a BrowserOpener seam to pkg/tools/mcp/oauthflow so tests can swap
the system browser launcher for a channel-based stub without relying on
POSIX PATH shims (open/xdg-open scripts) that can't intercept rundll32
on Windows.

- oauthflow: add BrowserOpener type + atomic.Pointer var (default
  browser.Open) + SetBrowserOpenerForTesting (mirrors the existing
  SetHTTPClientForTesting idiom in the same file); route
  RequestAuthorizationCode through the seam.
- oauth_test: replace setupFakeBrowserOpener / requireCapturedAuthorizeURL
  (PATH shim + Windows skip) with fakeBrowserOpener / requireCapturedAuthorizeURL
  backed by a buffered channel; add oauthflow import; drop os/filepath/runtime.
- mcpcatalog_test: same channel-based treatment for the duplicate catalog
  helpers; update stale comment; drop path/filepath and runtime imports.

TestHandleManagedOAuthFlow_DCRSuccess_EndToEndScopeEquality and
TestHandleEnable_OAuthDCR_ChallengePRMScopeFallback now run on all
platforms without skipping.

Fixes #3976
@aheritier
aheritier marked this pull request as ready for review August 13, 2026 17:50
@aheritier
aheritier requested a review from a team as a code owner August 13, 2026 17:50
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.

test(mcp): make OAuth browser launch injectable across platforms

1 participant