Added a wait for the token exchange

This commit is contained in:
Glen Maddern 2025-03-31 22:28:10 +11:00
parent 9fbba0509c
commit d5f5b31786
4 changed files with 20 additions and 3 deletions

View file

@ -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 auth was completed by another instance, just log that we'll use the auth from disk
if (skipBrowserAuth) { 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 // Create the client

View file

@ -169,11 +169,15 @@ export async function readJsonFile<T>(
const filePath = getConfigFilePath(serverUrlHash, filename) const filePath = getConfigFilePath(serverUrlHash, filename)
const content = await fs.readFile(filePath, 'utf-8') 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) { } catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') { if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
// console.log(`File ${filename} does not exist`)
return undefined return undefined
} }
log(`Error reading ${filename}:`, error)
return undefined return undefined
} }
} }

View file

@ -59,6 +59,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
* @returns The client information or undefined * @returns The client information or undefined
*/ */
async clientInformation(): Promise<OAuthClientInformation | undefined> { async clientInformation(): Promise<OAuthClientInformation | undefined> {
// log('Reading client info')
return readJsonFile<OAuthClientInformation>(this.serverUrlHash, 'client_info.json', OAuthClientInformationSchema, this.options.clean) return readJsonFile<OAuthClientInformation>(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 * @param clientInformation The client information to save
*/ */
async saveClientInformation(clientInformation: OAuthClientInformationFull): Promise<void> { async saveClientInformation(clientInformation: OAuthClientInformationFull): Promise<void> {
// log('Saving client info')
await writeJsonFile(this.serverUrlHash, 'client_info.json', clientInformation) await writeJsonFile(this.serverUrlHash, 'client_info.json', clientInformation)
} }
@ -75,6 +77,8 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
* @returns The OAuth tokens or undefined * @returns The OAuth tokens or undefined
*/ */
async tokens(): Promise<OAuthTokens | undefined> { async tokens(): Promise<OAuthTokens | undefined> {
// log('Reading tokens')
// console.log(new Error().stack)
return readJsonFile<OAuthTokens>(this.serverUrlHash, 'tokens.json', OAuthTokensSchema, this.options.clean) return readJsonFile<OAuthTokens>(this.serverUrlHash, 'tokens.json', OAuthTokensSchema, this.options.clean)
} }
@ -83,6 +87,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
* @param tokens The tokens to save * @param tokens The tokens to save
*/ */
async saveTokens(tokens: OAuthTokens): Promise<void> { async saveTokens(tokens: OAuthTokens): Promise<void> {
// log('Saving tokens')
await writeJsonFile(this.serverUrlHash, 'tokens.json', tokens) await writeJsonFile(this.serverUrlHash, 'tokens.json', tokens)
} }
@ -105,6 +110,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
* @param codeVerifier The code verifier to save * @param codeVerifier The code verifier to save
*/ */
async saveCodeVerifier(codeVerifier: string): Promise<void> { async saveCodeVerifier(codeVerifier: string): Promise<void> {
// log('Saving code verifier')
await writeTextFile(this.serverUrlHash, 'code_verifier.txt', codeVerifier) await writeTextFile(this.serverUrlHash, 'code_verifier.txt', codeVerifier)
} }
@ -113,6 +119,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
* @returns The code verifier * @returns The code verifier
*/ */
async codeVerifier(): Promise<string> { async codeVerifier(): Promise<string> {
// log('Reading code verifier')
return await readTextFile(this.serverUrlHash, 'code_verifier.txt', 'No code verifier saved for session', this.options.clean) return await readTextFile(this.serverUrlHash, 'code_verifier.txt', 'No code verifier saved for session', this.options.clean)
} }
} }

View file

@ -38,10 +38,13 @@ async function runProxy(serverUrl: string, callbackPort: number, clean: boolean
clientName: 'MCP CLI Proxy', clientName: 'MCP CLI Proxy',
clean, clean,
}) })
// If auth was completed by another instance, just log that we'll use the auth from disk // If auth was completed by another instance, just log that we'll use the auth from disk
if (skipBrowserAuth) { 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 STDIO transport for local connections // Create the STDIO transport for local connections