diff --git a/src/lib/coordination.ts b/src/lib/coordination.ts index 8b729f8..8cf86d0 100644 --- a/src/lib/coordination.ts +++ b/src/lib/coordination.ts @@ -4,7 +4,7 @@ import { Server } from 'http' import express from 'express' import { AddressInfo } from 'net' import { unlinkSync } from 'fs' -import { log, debugLog, DEBUG, setupOAuthCallbackServerWithLongPoll } from './utils' +import { log, debugLog, setupOAuthCallbackServerWithLongPoll } from './utils' export type AuthCoordinator = { initializeAuth: () => Promise<{ server: Server; waitForAuthCode: () => Promise; skipBrowserAuth: boolean }> @@ -18,10 +18,10 @@ export type AuthCoordinator = { export async function isPidRunning(pid: number): Promise { try { process.kill(pid, 0) // Doesn't kill the process, just checks if it exists - if (DEBUG) debugLog(`Process ${pid} is running`) + debugLog(`Process ${pid} is running`) return true } catch (err) { - if (DEBUG) debugLog(`Process ${pid} is not running`, err) + debugLog(`Process ${pid} is not running`, err) return false } } @@ -32,30 +32,29 @@ export async function isPidRunning(pid: number): Promise { * @returns True if the lockfile is valid, false otherwise */ export async function isLockValid(lockData: LockfileData): Promise { - if (DEBUG) debugLog('Checking if lockfile is valid', lockData) + debugLog('Checking if lockfile is valid', lockData) // Check if the lockfile is too old (over 30 minutes) const MAX_LOCK_AGE = 30 * 60 * 1000 // 30 minutes if (Date.now() - lockData.timestamp > MAX_LOCK_AGE) { log('Lockfile is too old') - if (DEBUG) - debugLog('Lockfile is too old', { - age: Date.now() - lockData.timestamp, - maxAge: MAX_LOCK_AGE, - }) + debugLog('Lockfile is too old', { + age: Date.now() - lockData.timestamp, + maxAge: MAX_LOCK_AGE, + }) return false } // Check if the process is still running if (!(await isPidRunning(lockData.pid))) { log('Process from lockfile is not running') - if (DEBUG) debugLog('Process from lockfile is not running', { pid: lockData.pid }) + debugLog('Process from lockfile is not running', { pid: lockData.pid }) return false } // Check if the endpoint is accessible try { - if (DEBUG) debugLog('Checking if endpoint is accessible', { port: lockData.port }) + debugLog('Checking if endpoint is accessible', { port: lockData.port }) const controller = new AbortController() const timeout = setTimeout(() => controller.abort(), 1000) @@ -67,11 +66,11 @@ export async function isLockValid(lockData: LockfileData): Promise { clearTimeout(timeout) const isValid = response.status === 200 || response.status === 202 - if (DEBUG) debugLog(`Endpoint check result: ${isValid ? 'valid' : 'invalid'}`, { status: response.status }) + debugLog(`Endpoint check result: ${isValid ? 'valid' : 'invalid'}`, { status: response.status }) return isValid } catch (error) { log(`Error connecting to auth server: ${(error as Error).message}`) - if (DEBUG) debugLog('Error connecting to auth server', error) + debugLog('Error connecting to auth server', error) return false } } @@ -90,11 +89,11 @@ export async function waitForAuthentication(port: number): Promise { attempts++ const url = `http://127.0.0.1:${port}/wait-for-auth` log(`Querying: ${url}`) - if (DEBUG) debugLog(`Poll attempt ${attempts}`) + debugLog(`Poll attempt ${attempts}`) try { const response = await fetch(url) - if (DEBUG) debugLog(`Poll response status: ${response.status}`) + debugLog(`Poll response status: ${response.status}`) if (response.status === 200) { // Auth completed, but we don't return the code anymore @@ -103,21 +102,21 @@ export async function waitForAuthentication(port: number): Promise { } else if (response.status === 202) { // Continue polling log(`Authentication still in progress`) - if (DEBUG) debugLog(`Will retry in 1s`) + debugLog(`Will retry in 1s`) await new Promise((resolve) => setTimeout(resolve, 1000)) } else { log(`Unexpected response status: ${response.status}`) return false } } catch (fetchError) { - if (DEBUG) debugLog(`Fetch error during poll`, fetchError) + debugLog(`Fetch error during poll`, fetchError) // If we can't connect, we'll try again after a delay await new Promise((resolve) => setTimeout(resolve, 2000)) } } } catch (error) { log(`Error waiting for authentication: ${(error as Error).message}`) - if (DEBUG) debugLog(`Error waiting for authentication`, error) + debugLog(`Error waiting for authentication`, error) return false } } @@ -136,16 +135,16 @@ export function createLazyAuthCoordinator(serverUrlHash: string, callbackPort: n initializeAuth: async () => { // If auth has already been initialized, return the existing state if (authState) { - if (DEBUG) debugLog('Auth already initialized, reusing existing state') + debugLog('Auth already initialized, reusing existing state') return authState } log('Initializing auth coordination on-demand') - if (DEBUG) debugLog('Initializing auth coordination on-demand', { serverUrlHash, callbackPort }) + debugLog('Initializing auth coordination on-demand', { serverUrlHash, callbackPort }) // Initialize auth using the existing coordinateAuth logic authState = await coordinateAuth(serverUrlHash, callbackPort, events) - if (DEBUG) debugLog('Auth coordination completed', { skipBrowserAuth: authState.skipBrowserAuth }) + debugLog('Auth coordination completed', { skipBrowserAuth: authState.skipBrowserAuth }) return authState }, } @@ -163,17 +162,15 @@ export async function coordinateAuth( callbackPort: number, events: EventEmitter, ): Promise<{ server: Server; waitForAuthCode: () => Promise; skipBrowserAuth: boolean }> { - if (DEBUG) debugLog('Coordinating authentication', { serverUrlHash, callbackPort }) + debugLog('Coordinating authentication', { serverUrlHash, callbackPort }) // Check for a lockfile (disabled on Windows for the time being) const lockData = process.platform === 'win32' ? null : await checkLockfile(serverUrlHash) - if (DEBUG) { - if (process.platform === 'win32') { - debugLog('Skipping lockfile check on Windows') - } else { - debugLog('Lockfile check result', { found: !!lockData, lockData }) - } + if (process.platform === 'win32') { + debugLog('Skipping lockfile check on Windows') + } else { + debugLog('Lockfile check result', { found: !!lockData, lockData }) } // If there's a valid lockfile, try to use the existing auth process @@ -182,7 +179,7 @@ export async function coordinateAuth( try { // Try to wait for the authentication to complete - if (DEBUG) debugLog('Waiting for authentication from other instance') + debugLog('Waiting for authentication from other instance') const authCompleted = await waitForAuthentication(lockData.port) if (authCompleted) { @@ -191,7 +188,7 @@ export async function coordinateAuth( // Setup a dummy server - the client will use tokens directly from disk const dummyServer = express().listen(0) // Listen on any available port const dummyPort = (dummyServer.address() as AddressInfo).port - if (DEBUG) debugLog('Started dummy server', { port: dummyPort }) + debugLog('Started dummy server', { port: dummyPort }) // This shouldn't actually be called in normal operation, but provide it for API compatibility const dummyWaitForAuthCode = () => { @@ -210,11 +207,11 @@ export async function coordinateAuth( } } catch (error) { log(`Error waiting for authentication: ${error}`) - if (DEBUG) debugLog('Error waiting for authentication', error) + debugLog('Error waiting for authentication', error) } // If we get here, the other process didn't complete auth successfully - if (DEBUG) debugLog('Other instance did not complete auth successfully, deleting lockfile') + debugLog('Other instance did not complete auth successfully, deleting lockfile') await deleteLockfile(serverUrlHash) } else if (lockData) { // Invalid lockfile, delete it @@ -223,7 +220,7 @@ export async function coordinateAuth( } // Create our own lockfile - if (DEBUG) debugLog('Setting up OAuth callback server', { port: callbackPort }) + debugLog('Setting up OAuth callback server', { port: callbackPort }) const { server, waitForAuthCode, authCompletedPromise } = setupOAuthCallbackServerWithLongPoll({ port: callbackPort, path: '/oauth/callback', @@ -233,7 +230,7 @@ export async function coordinateAuth( // Get the actual port the server is running on const address = server.address() as AddressInfo const actualPort = address.port - if (DEBUG) debugLog('OAuth callback server running', { port: actualPort }) + debugLog('OAuth callback server running', { port: actualPort }) log(`Creating lockfile for server ${serverUrlHash} with process ${process.pid} on port ${actualPort}`) await createLockfile(serverUrlHash, process.pid, actualPort) @@ -245,7 +242,7 @@ export async function coordinateAuth( await deleteLockfile(serverUrlHash) } catch (error) { log(`Error cleaning up lockfile: ${error}`) - if (DEBUG) debugLog('Error cleaning up lockfile', error) + debugLog('Error cleaning up lockfile', error) } } @@ -254,19 +251,19 @@ export async function coordinateAuth( // Synchronous version for 'exit' event since we can't use async here const configPath = getConfigFilePath(serverUrlHash, 'lock.json') unlinkSync(configPath) - if (DEBUG) console.error(`[DEBUG] Removed lockfile on exit: ${configPath}`) + debugLog(`Removed lockfile on exit: ${configPath}`) } catch (error) { - if (DEBUG) console.error(`[DEBUG] Error removing lockfile on exit:`, error) + debugLog(`Error removing lockfile on exit:`, error) } }) // Also handle SIGINT separately process.once('SIGINT', async () => { - if (DEBUG) debugLog('Received SIGINT signal, cleaning up') + debugLog('Received SIGINT signal, cleaning up') await cleanupHandler() }) - if (DEBUG) debugLog('Auth coordination complete, returning primary instance handlers') + debugLog('Auth coordination complete, returning primary instance handlers') return { server, waitForAuthCode, diff --git a/src/lib/node-oauth-client-provider.ts b/src/lib/node-oauth-client-provider.ts index 7ecb908..c97cec3 100644 --- a/src/lib/node-oauth-client-provider.ts +++ b/src/lib/node-oauth-client-provider.ts @@ -9,7 +9,7 @@ import { import type { OAuthProviderOptions, StaticOAuthClientMetadata } from './types' import { readJsonFile, writeJsonFile, readTextFile, writeTextFile, deleteConfigFile } from './mcp-auth-config' import { StaticOAuthClientInformationFull } from './types' -import { getServerUrlHash, log, debugLog, DEBUG, MCP_REMOTE_VERSION } from './utils' +import { getServerUrlHash, log, debugLog, MCP_REMOTE_VERSION } from './utils' import { sanitizeUrl } from 'strict-url-sanitise' import { randomUUID } from 'node:crypto' @@ -73,9 +73,9 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @returns The client information or undefined */ async clientInformation(): Promise { - if (DEBUG) debugLog('Reading client info') + debugLog('Reading client info') if (this.staticOAuthClientInfo) { - if (DEBUG) debugLog('Returning static client info') + debugLog('Returning static client info') return this.staticOAuthClientInfo } const clientInfo = await readJsonFile( @@ -83,7 +83,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { 'client_info.json', OAuthClientInformationFullSchema, ) - if (DEBUG) debugLog('Client info result:', clientInfo ? 'Found' : 'Not found') + debugLog('Client info result:', clientInfo ? 'Found' : 'Not found') return clientInfo } @@ -92,7 +92,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @param clientInformation The client information to save */ async saveClientInformation(clientInformation: OAuthClientInformationFull): Promise { - if (DEBUG) debugLog('Saving client info', { client_id: clientInformation.client_id }) + debugLog('Saving client info', { client_id: clientInformation.client_id }) await writeJsonFile(this.serverUrlHash, 'client_info.json', clientInformation) } @@ -101,67 +101,61 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @returns The OAuth tokens or undefined */ async tokens(): Promise { - if (DEBUG) { - debugLog('Reading OAuth tokens') - debugLog('Token request stack trace:', new Error().stack) - } + debugLog('Reading OAuth tokens') + debugLog('Token request stack trace:', new Error().stack) const tokens = await readJsonFile(this.serverUrlHash, 'tokens.json', OAuthTokensSchema) - if (DEBUG) { - if (tokens) { - const timeLeft = tokens.expires_in || 0 - - // Alert if expires_in is invalid - if (typeof tokens.expires_in !== 'number' || tokens.expires_in < 0) { - debugLog('⚠️ WARNING: Invalid expires_in detected while reading tokens ⚠️', { - expiresIn: tokens.expires_in, - tokenObject: JSON.stringify(tokens), - stack: new Error('Invalid expires_in value').stack, - }) - } - - debugLog('Token result:', { - found: true, - hasAccessToken: !!tokens.access_token, - hasRefreshToken: !!tokens.refresh_token, - expiresIn: `${timeLeft} seconds`, - isExpired: timeLeft <= 0, - expiresInValue: tokens.expires_in, - }) - } else { - debugLog('Token result: Not found') - } - } - - return tokens - } - - /** - * Saves OAuth tokens - * @param tokens The tokens to save - */ - async saveTokens(tokens: OAuthTokens): Promise { - if (DEBUG) { + if (tokens) { const timeLeft = tokens.expires_in || 0 // Alert if expires_in is invalid if (typeof tokens.expires_in !== 'number' || tokens.expires_in < 0) { - debugLog('⚠️ WARNING: Invalid expires_in detected in tokens ⚠️', { + debugLog('⚠️ WARNING: Invalid expires_in detected while reading tokens ⚠️', { expiresIn: tokens.expires_in, tokenObject: JSON.stringify(tokens), stack: new Error('Invalid expires_in value').stack, }) } - debugLog('Saving tokens', { + debugLog('Token result:', { + found: true, hasAccessToken: !!tokens.access_token, hasRefreshToken: !!tokens.refresh_token, expiresIn: `${timeLeft} seconds`, + isExpired: timeLeft <= 0, expiresInValue: tokens.expires_in, }) + } else { + debugLog('Token result: Not found') } + return tokens + } + + /** + * Saves OAuth tokens + * @param tokens The tokens to save + */ + async saveTokens(tokens: OAuthTokens): Promise { + const timeLeft = tokens.expires_in || 0 + + // Alert if expires_in is invalid + if (typeof tokens.expires_in !== 'number' || tokens.expires_in < 0) { + debugLog('⚠️ WARNING: Invalid expires_in detected in tokens ⚠️', { + expiresIn: tokens.expires_in, + tokenObject: JSON.stringify(tokens), + stack: new Error('Invalid expires_in value').stack, + }) + } + + debugLog('Saving tokens', { + hasAccessToken: !!tokens.access_token, + hasRefreshToken: !!tokens.refresh_token, + expiresIn: `${timeLeft} seconds`, + expiresInValue: tokens.expires_in, + }) + await writeJsonFile(this.serverUrlHash, 'tokens.json', tokens) } @@ -176,14 +170,14 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { log(`\nPlease authorize this client by visiting:\n${authorizationUrl.toString()}\n`) - if (DEBUG) debugLog('Redirecting to authorization URL', authorizationUrl.toString()) + debugLog('Redirecting to authorization URL', authorizationUrl.toString()) try { await open(sanitizeUrl(authorizationUrl.toString())) log('Browser opened automatically.') } catch (error) { log('Could not open browser automatically. Please copy and paste the URL above into your browser.') - if (DEBUG) debugLog('Failed to open browser', error) + debugLog('Failed to open browser', error) } } @@ -192,7 +186,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @param codeVerifier The code verifier to save */ async saveCodeVerifier(codeVerifier: string): Promise { - if (DEBUG) debugLog('Saving code verifier') + debugLog('Saving code verifier') await writeTextFile(this.serverUrlHash, 'code_verifier.txt', codeVerifier) } @@ -201,9 +195,9 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @returns The code verifier */ async codeVerifier(): Promise { - if (DEBUG) debugLog('Reading code verifier') + debugLog('Reading code verifier') const verifier = await readTextFile(this.serverUrlHash, 'code_verifier.txt', 'No code verifier saved for session') - if (DEBUG) debugLog('Code verifier found:', !!verifier) + debugLog('Code verifier found:', !!verifier) return verifier } @@ -212,7 +206,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @param scope The scope of credentials to invalidate */ async invalidateCredentials(scope: 'all' | 'client' | 'tokens' | 'verifier'): Promise { - if (DEBUG) debugLog(`Invalidating credentials: ${scope}`) + debugLog(`Invalidating credentials: ${scope}`) switch (scope) { case 'all': @@ -221,22 +215,22 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { deleteConfigFile(this.serverUrlHash, 'tokens.json'), deleteConfigFile(this.serverUrlHash, 'code_verifier.txt'), ]) - if (DEBUG) debugLog('All credentials invalidated') + debugLog('All credentials invalidated') break case 'client': await deleteConfigFile(this.serverUrlHash, 'client_info.json') - if (DEBUG) debugLog('Client information invalidated') + debugLog('Client information invalidated') break case 'tokens': await deleteConfigFile(this.serverUrlHash, 'tokens.json') - if (DEBUG) debugLog('OAuth tokens invalidated') + debugLog('OAuth tokens invalidated') break case 'verifier': await deleteConfigFile(this.serverUrlHash, 'code_verifier.txt') - if (DEBUG) debugLog('Code verifier invalidated') + debugLog('Code verifier invalidated') break default: diff --git a/src/lib/utils.test.ts b/src/lib/utils.test.ts index 7e819a1..6045143 100644 --- a/src/lib/utils.test.ts +++ b/src/lib/utils.test.ts @@ -1,3 +1,8 @@ import { describe, it, expect } from 'vitest' // All sanitizeUrl tests have been moved to the strict-url-sanitise package +describe('sample test', () => { + it('Adds numbers', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 5aa4c84..2c86d85 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -75,9 +75,7 @@ export function log(str: string, ...rest: unknown[]) { console.error(`[${pid}] ${str}`, ...rest) // If debug mode is on, also log to debug file - if (DEBUG && global.currentServerUrlHash) { - debugLog(str, ...rest) - } + debugLog(str, ...rest) } /** @@ -93,22 +91,18 @@ export function mcpProxy({ transportToClient, transportToServer }: { transportTo const message = _message as any log('[Local→Remote]', message.method || message.id) - if (DEBUG) { - debugLog('Local → Remote message', { - method: message.method, - id: message.id, - params: message.params ? JSON.stringify(message.params).substring(0, 500) : undefined, - }) - } + debugLog('Local → Remote message', { + method: message.method, + id: message.id, + params: message.params ? JSON.stringify(message.params).substring(0, 500) : undefined, + }) if (message.method === 'initialize') { const { clientInfo } = message.params if (clientInfo) clientInfo.name = `${clientInfo.name} (via mcp-remote ${MCP_REMOTE_VERSION})` log(JSON.stringify(message, null, 2)) - if (DEBUG) { - debugLog('Initialize message with modified client info', { clientInfo }) - } + debugLog('Initialize message with modified client info', { clientInfo }) } transportToServer.send(message).catch(onServerError) @@ -119,14 +113,12 @@ export function mcpProxy({ transportToClient, transportToServer }: { transportTo const message = _message as any log('[Remote→Local]', message.method || message.id) - if (DEBUG) { - debugLog('Remote → Local message', { - method: message.method, - id: message.id, - result: message.result ? 'result-present' : undefined, - error: message.error, - }) - } + debugLog('Remote → Local message', { + method: message.method, + id: message.id, + result: message.result ? 'result-present' : undefined, + error: message.error, + }) transportToClient.send(message).catch(onClientError) } @@ -137,7 +129,7 @@ export function mcpProxy({ transportToClient, transportToServer }: { transportTo } transportToClientClosed = true - if (DEBUG) debugLog('Local transport closed, closing remote transport') + debugLog('Local transport closed, closing remote transport') transportToServer.close().catch(onServerError) } @@ -146,7 +138,7 @@ export function mcpProxy({ transportToClient, transportToServer }: { transportTo return } transportToServerClosed = true - if (DEBUG) debugLog('Remote transport closed, closing local transport') + debugLog('Remote transport closed, closing local transport') transportToClient.close().catch(onClientError) } @@ -155,12 +147,12 @@ export function mcpProxy({ transportToClient, transportToServer }: { transportTo function onClientError(error: Error) { log('Error from local client:', error) - if (DEBUG) debugLog('Error from local client', { stack: error.stack }) + debugLog('Error from local client', { stack: error.stack }) } function onServerError(error: Error) { log('Error from remote server:', error) - if (DEBUG) debugLog('Error from remote server', { stack: error.stack }) + debugLog('Error from remote server', { stack: error.stack }) } } @@ -231,20 +223,20 @@ export async function connectToRemoteServer( }) try { - if (DEBUG) debugLog('Attempting to connect to remote server', { sseTransport }) + debugLog('Attempting to connect to remote server', { sseTransport }) if (client) { - if (DEBUG) debugLog('Connecting client to transport') + debugLog('Connecting client to transport') await client.connect(transport) } else { - if (DEBUG) debugLog('Starting transport directly') + debugLog('Starting transport directly') await transport.start() if (!sseTransport) { // Extremely hacky, but we didn't actually send a request when calling transport.start() above, so we don't // know if we're even talking to an HTTP server. But if we forced that now we'd get an error later saying that // the client is already connected. So let's just create a one-off client to make a single request and figure // out if we're actually talking to an HTTP server or not. - if (DEBUG) debugLog('Creating test transport for HTTP-only connection test') + debugLog('Creating test transport for HTTP-only connection test') const testTransport = new StreamableHTTPClientTransport(url, { authProvider, requestInit: { headers } }) const testClient = new Client({ name: 'mcp-remote-fallback-test', version: '0.0.0' }, { capabilities: {} }) await testClient.connect(testTransport) @@ -289,16 +281,14 @@ export async function connectToRemoteServer( ) } else if (error instanceof UnauthorizedError || (error instanceof Error && error.message.includes('Unauthorized'))) { log('Authentication required. Initializing auth...') - if (DEBUG) { - debugLog('Authentication error detected', { - errorCode: error instanceof OAuthError ? error.errorCode : undefined, - errorMessage: error.message, - stack: error.stack, - }) - } + debugLog('Authentication error detected', { + errorCode: error instanceof OAuthError ? error.errorCode : undefined, + errorMessage: error.message, + stack: error.stack, + }) // Initialize authentication on-demand - if (DEBUG) debugLog('Calling authInitializer to start auth flow') + debugLog('Calling authInitializer to start auth flow') const { waitForAuthCode, skipBrowserAuth } = await authInitializer() if (skipBrowserAuth) { @@ -308,49 +298,46 @@ export async function connectToRemoteServer( } // Wait for the authorization code from the callback - if (DEBUG) debugLog('Waiting for auth code from callback server') + debugLog('Waiting for auth code from callback server') const code = await waitForAuthCode() - if (DEBUG) debugLog('Received auth code from callback server') + debugLog('Received auth code from callback server') try { log('Completing authorization...') await transport.finishAuth(code) - if (DEBUG) debugLog('Authorization completed successfully') + debugLog('Authorization completed successfully') if (recursionReasons.has(REASON_AUTH_NEEDED)) { const errorMessage = `Already attempted reconnection for reason: ${REASON_AUTH_NEEDED}. Giving up.` log(errorMessage) - if (DEBUG) - debugLog('Already attempted auth reconnection, giving up', { - recursionReasons: Array.from(recursionReasons), - }) + debugLog('Already attempted auth reconnection, giving up', { + recursionReasons: Array.from(recursionReasons), + }) throw new Error(errorMessage) } // Track this reason for recursion recursionReasons.add(REASON_AUTH_NEEDED) log(`Recursively reconnecting for reason: ${REASON_AUTH_NEEDED}`) - if (DEBUG) debugLog('Recursively reconnecting after auth', { recursionReasons: Array.from(recursionReasons) }) + debugLog('Recursively reconnecting after auth', { recursionReasons: Array.from(recursionReasons) }) // Recursively call connectToRemoteServer with the updated recursion tracking return connectToRemoteServer(client, serverUrl, authProvider, headers, authInitializer, transportStrategy, recursionReasons) } catch (authError: any) { log('Authorization error:', authError) - if (DEBUG) - debugLog('Authorization error during finishAuth', { - errorMessage: authError.message, - stack: authError.stack, - }) + debugLog('Authorization error during finishAuth', { + errorMessage: authError.message, + stack: authError.stack, + }) throw authError } } else { log('Connection error:', error) - if (DEBUG) - debugLog('Connection error', { - errorMessage: error.message, - stack: error.stack, - transportType: transport.constructor.name, - }) + debugLog('Connection error', { + errorMessage: error.message, + stack: error.stack, + transportType: transport.constructor.name, + }) throw error } } @@ -635,9 +622,7 @@ export async function parseCommandLineArgs(args: string[], usage: string) { // Set server hash globally for debug logging global.currentServerUrlHash = serverUrlHash - if (DEBUG) { - debugLog(`Starting mcp-remote with server URL: ${serverUrl}`) - } + debugLog(`Starting mcp-remote with server URL: ${serverUrl}`) const defaultPort = calculateDefaultPort(serverUrlHash)