oauthPort.ts
services/mcp/oauthPort.ts
79
Lines
2325
Bytes
2
Exports
2
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with integrations, mcp. It contains 79 lines, 2 detected imports, and 2 detected exports.
Important relationships
Detected exports
buildRedirectUrifindAvailablePort
Keywords
porttestserverredirectrangeoauthredirect_port_fallbackrandomresolverejectcreateserver
Detected imports
http../../utils/platform.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
/**
* OAuth redirect port helpers — extracted from auth.ts to break the
* auth.ts ↔ xaaIdpLogin.ts circular dependency.
*/
import { createServer } from 'http'
import { getPlatform } from '../../utils/platform.js'
// Windows dynamic port range 49152-65535 is reserved
const REDIRECT_PORT_RANGE =
getPlatform() === 'windows'
? { min: 39152, max: 49151 }
: { min: 49152, max: 65535 }
const REDIRECT_PORT_FALLBACK = 3118
/**
* Builds a redirect URI on localhost with the given port and a fixed `/callback` path.
*
* RFC 8252 Section 7.3 (OAuth for Native Apps): loopback redirect URIs match any
* port as long as the path matches.
*/
export function buildRedirectUri(
port: number = REDIRECT_PORT_FALLBACK,
): string {
return `http://localhost:${port}/callback`
}
function getMcpOAuthCallbackPort(): number | undefined {
const port = parseInt(process.env.MCP_OAUTH_CALLBACK_PORT || '', 10)
return port > 0 ? port : undefined
}
/**
* Finds an available port in the specified range for OAuth redirect
* Uses random selection for better security
*/
export async function findAvailablePort(): Promise<number> {
// First, try the configured port if specified
const configuredPort = getMcpOAuthCallbackPort()
if (configuredPort) {
return configuredPort
}
const { min, max } = REDIRECT_PORT_RANGE
const range = max - min + 1
const maxAttempts = Math.min(range, 100) // Don't try forever
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const port = min + Math.floor(Math.random() * range)
try {
await new Promise<void>((resolve, reject) => {
const testServer = createServer()
testServer.once('error', reject)
testServer.listen(port, () => {
testServer.close(() => resolve())
})
})
return port
} catch {
// Port in use, try another random port
continue
}
}
// If random selection failed, try the fallback port
try {
await new Promise<void>((resolve, reject) => {
const testServer = createServer()
testServer.once('error', reject)
testServer.listen(REDIRECT_PORT_FALLBACK, () => {
testServer.close(() => resolve())
})
})
return REDIRECT_PORT_FALLBACK
} catch {
throw new Error(`No available ports for OAuth redirect`)
}
}