refactor: unwrap McpOAuthCallback namespace + self-reexport (#22943)

This commit is contained in:
Kit Langton
2026-04-17 00:00:46 +00:00
committed by GitHub
parent bae80af1b4
commit 4e27804160
+25 -25
View File
@@ -56,25 +56,24 @@ interface PendingAuth {
timeout: ReturnType<typeof setTimeout> timeout: ReturnType<typeof setTimeout>
} }
export namespace McpOAuthCallback { let server: ReturnType<typeof createServer> | undefined
let server: ReturnType<typeof createServer> | undefined const pendingAuths = new Map<string, PendingAuth>()
const pendingAuths = new Map<string, PendingAuth>() // Reverse index: mcpName → oauthState, so cancelPending(mcpName) can
// Reverse index: mcpName → oauthState, so cancelPending(mcpName) can // find the right entry in pendingAuths (which is keyed by oauthState).
// find the right entry in pendingAuths (which is keyed by oauthState). const mcpNameToState = new Map<string, string>()
const mcpNameToState = new Map<string, string>()
const CALLBACK_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes const CALLBACK_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes
function cleanupStateIndex(oauthState: string) { function cleanupStateIndex(oauthState: string) {
for (const [name, state] of mcpNameToState) { for (const [name, state] of mcpNameToState) {
if (state === oauthState) { if (state === oauthState) {
mcpNameToState.delete(name) mcpNameToState.delete(name)
break break
} }
} }
} }
function handleRequest(req: import("http").IncomingMessage, res: import("http").ServerResponse) { function handleRequest(req: import("http").IncomingMessage, res: import("http").ServerResponse) {
const url = new URL(req.url || "/", `http://localhost:${currentPort}`) const url = new URL(req.url || "/", `http://localhost:${currentPort}`)
if (url.pathname !== currentPath) { if (url.pathname !== currentPath) {
@@ -137,9 +136,9 @@ export namespace McpOAuthCallback {
res.writeHead(200, { "Content-Type": "text/html" }) res.writeHead(200, { "Content-Type": "text/html" })
res.end(HTML_SUCCESS) res.end(HTML_SUCCESS)
} }
export async function ensureRunning(redirectUri?: string): Promise<void> { export async function ensureRunning(redirectUri?: string): Promise<void> {
// Parse the redirect URI to get port and path (uses defaults if not provided) // Parse the redirect URI to get port and path (uses defaults if not provided)
const { port, path } = parseRedirectUri(redirectUri) const { port, path } = parseRedirectUri(redirectUri)
@@ -168,9 +167,9 @@ export namespace McpOAuthCallback {
}) })
server!.on("error", reject) server!.on("error", reject)
}) })
} }
export function waitForCallback(oauthState: string, mcpName?: string): Promise<string> { export function waitForCallback(oauthState: string, mcpName?: string): Promise<string> {
if (mcpName) mcpNameToState.set(mcpName, oauthState) if (mcpName) mcpNameToState.set(mcpName, oauthState)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
@@ -183,9 +182,9 @@ export namespace McpOAuthCallback {
pendingAuths.set(oauthState, { resolve, reject, timeout }) pendingAuths.set(oauthState, { resolve, reject, timeout })
}) })
} }
export function cancelPending(mcpName: string): void { export function cancelPending(mcpName: string): void {
// Look up the oauthState for this mcpName via the reverse index // Look up the oauthState for this mcpName via the reverse index
const oauthState = mcpNameToState.get(mcpName) const oauthState = mcpNameToState.get(mcpName)
const key = oauthState ?? mcpName const key = oauthState ?? mcpName
@@ -196,9 +195,9 @@ export namespace McpOAuthCallback {
mcpNameToState.delete(mcpName) mcpNameToState.delete(mcpName)
pending.reject(new Error("Authorization cancelled")) pending.reject(new Error("Authorization cancelled"))
} }
} }
export async function isPortInUse(port: number = OAUTH_CALLBACK_PORT): Promise<boolean> { export async function isPortInUse(port: number = OAUTH_CALLBACK_PORT): Promise<boolean> {
return new Promise((resolve) => { return new Promise((resolve) => {
const socket = createConnection(port, "127.0.0.1") const socket = createConnection(port, "127.0.0.1")
socket.on("connect", () => { socket.on("connect", () => {
@@ -209,9 +208,9 @@ export namespace McpOAuthCallback {
resolve(false) resolve(false)
}) })
}) })
} }
export async function stop(): Promise<void> { export async function stop(): Promise<void> {
if (server) { if (server) {
await new Promise<void>((resolve) => server!.close(() => resolve())) await new Promise<void>((resolve) => server!.close(() => resolve()))
server = undefined server = undefined
@@ -224,9 +223,10 @@ export namespace McpOAuthCallback {
} }
pendingAuths.clear() pendingAuths.clear()
mcpNameToState.clear() mcpNameToState.clear()
}
export function isRunning(): boolean {
return server !== undefined
}
} }
export function isRunning(): boolean {
return server !== undefined
}
export * as McpOAuthCallback from "./oauth-callback"