diff --git a/packages/opencode/src/mcp/index.ts b/packages/opencode/src/mcp/index.ts index 66843aedc1..a0a3297755 100644 --- a/packages/opencode/src/mcp/index.ts +++ b/packages/opencode/src/mcp/index.ts @@ -795,6 +795,11 @@ export namespace MCP { // The SDK has already added the state parameter to the authorization URL // We just need to open the browser log.info("opening browser for oauth", { mcpName, url: authorizationUrl, state: oauthState }) + + // Register the callback BEFORE opening the browser to avoid race condition + // when the IdP has an active SSO session and redirects immediately + const callbackPromise = McpOAuthCallback.waitForCallback(oauthState) + try { const subprocess = await open(authorizationUrl) // The open package spawns a detached process and returns immediately. @@ -822,8 +827,8 @@ export namespace MCP { Bus.publish(BrowserOpenFailed, { mcpName, url: authorizationUrl }) } - // Wait for callback using the OAuth state parameter - const code = await McpOAuthCallback.waitForCallback(oauthState) + // Wait for callback using the already-registered promise + const code = await callbackPromise // Validate and clear the state const storedState = await McpAuth.getOAuthState(mcpName)