diff --git a/packages/opencode/src/mcp/oauth-callback.ts b/packages/opencode/src/mcp/oauth-callback.ts index e132cbf02b61..6b88f802a10b 100644 --- a/packages/opencode/src/mcp/oauth-callback.ts +++ b/packages/opencode/src/mcp/oauth-callback.ts @@ -71,6 +71,13 @@ function cleanupStateIndex(oauthState: string) { } } +function stopIfIdle() { + if (pendingAuths.size > 0 || !server) return + + server.close() + server = undefined +} + function handleRequest(req: import("http").IncomingMessage, res: import("http").ServerResponse) { const url = new URL(req.url || "/", `http://localhost:${currentPort}`) @@ -104,6 +111,7 @@ function handleRequest(req: import("http").IncomingMessage, res: import("http"). } res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }) res.end(HTML_ERROR(errorMsg)) + stopIfIdle() return } @@ -130,6 +138,7 @@ function handleRequest(req: import("http").IncomingMessage, res: import("http"). res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }) res.end(HTML_SUCCESS) + stopIfIdle() } export async function ensureRunning(redirectUri?: string): Promise { @@ -168,6 +177,7 @@ export function waitForCallback(oauthState: string, mcpName?: string): Promise { expect(McpOAuthCallback.isRunning()).toBe(true) }) + test("stops after the callback completes", async () => { + const redirectUri = "http://127.0.0.1:18003/custom/callback" + await McpOAuthCallback.ensureRunning(redirectUri) + const callback = McpOAuthCallback.waitForCallback("success") + + const response = await fetch(`${redirectUri}?code=code&state=success`) + + expect(response.status).toBe(200) + expect(await callback).toBe("code") + expect(McpOAuthCallback.isRunning()).toBe(false) + }) + test("escapes provider error markup in callback HTML", async () => { const redirectUri = "http://127.0.0.1:18001/custom/callback" await McpOAuthCallback.ensureRunning(redirectUri)