@@ -292,25 +292,24 @@ export async function discoverOAuthProtectedResourceMetadata(
292
292
return OAuthProtectedResourceMetadataSchema . parse ( await response . json ( ) ) ;
293
293
}
294
294
295
- /**
296
- * Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata.
297
- *
298
- * If the server returns a 404 for the well-known endpoint, this function will
299
- * return `undefined`. Any other errors will be thrown as exceptions.
300
- */
301
295
/**
302
296
* Helper function to handle fetch with CORS retry logic
303
297
*/
304
298
async function fetchWithCorsRetry (
305
299
url : URL ,
306
- headers : Record < string , string > ,
307
- ) : Promise < Response > {
300
+ headers ? : Record < string , string > ,
301
+ ) : Promise < Response | undefined > {
308
302
try {
309
303
return await fetch ( url , { headers } ) ;
310
304
} catch ( error ) {
311
- // CORS errors come back as TypeError, retry without headers
312
305
if ( error instanceof TypeError ) {
313
- return await fetch ( url ) ;
306
+ if ( headers ) {
307
+ // CORS errors come back as TypeError, retry without headers
308
+ return fetchWithCorsRetry ( url )
309
+ } else {
310
+ // We're getting CORS errors on retry too, return undefined
311
+ return undefined
312
+ }
314
313
}
315
314
throw error ;
316
315
}
@@ -334,7 +333,7 @@ function buildWellKnownPath(pathname: string): string {
334
333
async function tryMetadataDiscovery (
335
334
url : URL ,
336
335
protocolVersion : string ,
337
- ) : Promise < Response > {
336
+ ) : Promise < Response | undefined > {
338
337
const headers = {
339
338
"MCP-Protocol-Version" : protocolVersion
340
339
} ;
@@ -344,10 +343,16 @@ async function tryMetadataDiscovery(
344
343
/**
345
344
* Determines if fallback to root discovery should be attempted
346
345
*/
347
- function shouldAttemptFallback ( response : Response , pathname : string ) : boolean {
348
- return response . status === 404 && pathname !== '/' ;
346
+ function shouldAttemptFallback ( response : Response | undefined , pathname : string ) : boolean {
347
+ return ! response || response . status === 404 && pathname !== '/' ;
349
348
}
350
349
350
+ /**
351
+ * Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata.
352
+ *
353
+ * If the server returns a 404 for the well-known endpoint, this function will
354
+ * return `undefined`. Any other errors will be thrown as exceptions.
355
+ */
351
356
export async function discoverOAuthMetadata (
352
357
authorizationServerUrl : string | URL ,
353
358
opts ?: { protocolVersion ?: string } ,
@@ -362,18 +367,10 @@ export async function discoverOAuthMetadata(
362
367
363
368
// If path-aware discovery fails with 404, try fallback to root discovery
364
369
if ( shouldAttemptFallback ( response , issuer . pathname ) ) {
365
- try {
366
- const rootUrl = new URL ( "/.well-known/oauth-authorization-server" , issuer ) ;
367
- response = await tryMetadataDiscovery ( rootUrl , protocolVersion ) ;
368
-
369
- if ( response . status === 404 ) {
370
- return undefined ;
371
- }
372
- } catch {
373
- // If fallback fails, return undefined
374
- return undefined ;
375
- }
376
- } else if ( response . status === 404 ) {
370
+ const rootUrl = new URL ( "/.well-known/oauth-authorization-server" , issuer ) ;
371
+ response = await tryMetadataDiscovery ( rootUrl , protocolVersion ) ;
372
+ }
373
+ if ( ! response || response . status === 404 ) {
377
374
return undefined ;
378
375
}
379
376
0 commit comments