fix(mcp): stop idle OAuth callback server (#32245)

This commit is contained in:
Aiden Cline
2026-06-14 22:36:21 -04:00
committed by GitHub
parent 98d66e9a8b
commit 5d0f86606a
2 changed files with 23 additions and 0 deletions
@@ -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<void> {
@@ -168,6 +177,7 @@ export function waitForCallback(oauthState: string, mcpName?: string): Promise<s
pendingAuths.delete(oauthState)
if (mcpName) mcpNameToState.delete(mcpName)
reject(new Error("OAuth callback timeout - authorization took too long"))
stopIfIdle()
}
}, CALLBACK_TIMEOUT_MS)
@@ -185,6 +195,7 @@ export function cancelPending(mcpName: string): void {
pendingAuths.delete(key)
mcpNameToState.delete(mcpName)
pending.reject(new Error("Authorization cancelled"))
stopIfIdle()
}
}
@@ -32,6 +32,18 @@ describe("McpOAuthCallback.ensureRunning", () => {
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)