From 47f320c9ab200ff595a4ae65f6b235785c199753 Mon Sep 17 00:00:00 2001 From: WUKUNTAI-0211 Date: Tue, 9 Jun 2026 17:54:11 +0800 Subject: [PATCH] fix(mcp): fail clearly when OAuth callback port is in use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, when the OAuth callback port (19876 by default) was already in use, ensureRunning silently returned. The OAuth flow then opened a browser and waited for a callback that would never reach this opencode instance — surfacing as a misleading "Invalid or expired state parameter - potential CSRF attack" error. Now ensureRunning throws with a clear message telling the user to set oauth.callbackPort (or oauth.redirectUri) on the MCP server entry. Both fields already exist in the schema; this just stops the silent fallback from masking the real cause. --- packages/opencode/src/mcp/oauth-callback.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/mcp/oauth-callback.ts b/packages/opencode/src/mcp/oauth-callback.ts index 8d3161849ae3..b51f3871466e 100644 --- a/packages/opencode/src/mcp/oauth-callback.ts +++ b/packages/opencode/src/mcp/oauth-callback.ts @@ -144,7 +144,13 @@ export async function ensureRunning(redirectUri?: string): Promise { const running = await isPortInUse(port) if (running) { - return + // Cannot reuse: the other listener may not be opencode, and OAuth + // callbacks landing there surface as a misleading CSRF error. + throw new Error( + `OAuth callback port ${port} is already in use. ` + + `Set "oauth.callbackPort" (or "oauth.redirectUri") on the MCP server ` + + `entry in your opencode config to use a different port.`, + ) } currentPort = port