From d5f5b3178640db9de934e0a4751171a68d98398b Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Mon, 31 Mar 2025 22:28:10 +1100 Subject: [PATCH] Added a wait for the token exchange --- src/client.ts | 5 ++++- src/lib/mcp-auth-config.ts | 6 +++++- src/lib/node-oauth-client-provider.ts | 7 +++++++ src/proxy.ts | 5 ++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/client.ts b/src/client.ts index 7cf4db0..5b908c3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -44,7 +44,10 @@ async function runClient(serverUrl: string, callbackPort: number, clean: boolean // If auth was completed by another instance, just log that we'll use the auth from disk if (skipBrowserAuth) { - log('Authentication was completed by another instance - will use tokens from disk') + log('Authentication was completed by another instance - will use tokens from disk...') + // TODO: remove, the callback is happening before the tokens are exchanged + // so we're slightly too early + await new Promise((res) => setTimeout(res, 1_000)) } // Create the client diff --git a/src/lib/mcp-auth-config.ts b/src/lib/mcp-auth-config.ts index 7782096..fce4219 100644 --- a/src/lib/mcp-auth-config.ts +++ b/src/lib/mcp-auth-config.ts @@ -169,11 +169,15 @@ export async function readJsonFile( const filePath = getConfigFilePath(serverUrlHash, filename) const content = await fs.readFile(filePath, 'utf-8') - return await schema.parseAsync(JSON.parse(content)) + const result = await schema.parseAsync(JSON.parse(content)) + // console.log({ filename: result }) + return result } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') { + // console.log(`File ${filename} does not exist`) return undefined } + log(`Error reading ${filename}:`, error) return undefined } } diff --git a/src/lib/node-oauth-client-provider.ts b/src/lib/node-oauth-client-provider.ts index f8203fc..c02ce97 100644 --- a/src/lib/node-oauth-client-provider.ts +++ b/src/lib/node-oauth-client-provider.ts @@ -59,6 +59,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @returns The client information or undefined */ async clientInformation(): Promise { + // log('Reading client info') return readJsonFile(this.serverUrlHash, 'client_info.json', OAuthClientInformationSchema, this.options.clean) } @@ -67,6 +68,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @param clientInformation The client information to save */ async saveClientInformation(clientInformation: OAuthClientInformationFull): Promise { + // log('Saving client info') await writeJsonFile(this.serverUrlHash, 'client_info.json', clientInformation) } @@ -75,6 +77,8 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @returns The OAuth tokens or undefined */ async tokens(): Promise { + // log('Reading tokens') + // console.log(new Error().stack) return readJsonFile(this.serverUrlHash, 'tokens.json', OAuthTokensSchema, this.options.clean) } @@ -83,6 +87,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @param tokens The tokens to save */ async saveTokens(tokens: OAuthTokens): Promise { + // log('Saving tokens') await writeJsonFile(this.serverUrlHash, 'tokens.json', tokens) } @@ -105,6 +110,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @param codeVerifier The code verifier to save */ async saveCodeVerifier(codeVerifier: string): Promise { + // log('Saving code verifier') await writeTextFile(this.serverUrlHash, 'code_verifier.txt', codeVerifier) } @@ -113,6 +119,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider { * @returns The code verifier */ async codeVerifier(): Promise { + // log('Reading code verifier') return await readTextFile(this.serverUrlHash, 'code_verifier.txt', 'No code verifier saved for session', this.options.clean) } } diff --git a/src/proxy.ts b/src/proxy.ts index cbaaf5d..4c8d75c 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -38,10 +38,13 @@ async function runProxy(serverUrl: string, callbackPort: number, clean: boolean clientName: 'MCP CLI Proxy', clean, }) - + // If auth was completed by another instance, just log that we'll use the auth from disk if (skipBrowserAuth) { log('Authentication was completed by another instance - will use tokens from disk') + // TODO: remove, the callback is happening before the tokens are exchanged + // so we're slightly too early + await new Promise((res) => setTimeout(res, 1_000)) } // Create the STDIO transport for local connections