@@ -292,25 +292,24 @@ export async function discoverOAuthProtectedResourceMetadata(
292292 return OAuthProtectedResourceMetadataSchema . parse ( await response . json ( ) ) ;
293293}
294294
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- */
301295/**
302296 * Helper function to handle fetch with CORS retry logic
303297 */
304298async function fetchWithCorsRetry (
305299 url : URL ,
306- headers : Record < string , string > ,
307- ) : Promise < Response > {
300+ headers ? : Record < string , string > ,
301+ ) : Promise < Response | undefined > {
308302 try {
309303 return await fetch ( url , { headers } ) ;
310304 } catch ( error ) {
311- // CORS errors come back as TypeError, retry without headers
312305 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+ }
314313 }
315314 throw error ;
316315 }
@@ -334,7 +333,7 @@ function buildWellKnownPath(pathname: string): string {
334333async function tryMetadataDiscovery (
335334 url : URL ,
336335 protocolVersion : string ,
337- ) : Promise < Response > {
336+ ) : Promise < Response | undefined > {
338337 const headers = {
339338 "MCP-Protocol-Version" : protocolVersion
340339 } ;
@@ -344,10 +343,16 @@ async function tryMetadataDiscovery(
344343/**
345344 * Determines if fallback to root discovery should be attempted
346345 */
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 !== '/' ;
349348}
350349
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+ */
351356export async function discoverOAuthMetadata (
352357 authorizationServerUrl : string | URL ,
353358 opts ?: { protocolVersion ?: string } ,
@@ -362,18 +367,10 @@ export async function discoverOAuthMetadata(
362367
363368 // If path-aware discovery fails with 404, try fallback to root discovery
364369 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 ) {
377374 return undefined ;
378375 }
379376
0 commit comments