@@ -2056,6 +2056,90 @@ describe('connectToMcpServer with OAuth', () => {
20562056 capturedTransport . _requestInit ?. headers ?. [ 'Authorization' ] ;
20572057 expect ( authHeader ) . toBe ( 'Bearer test-access-token-from-discovery' ) ;
20582058 } ) ;
2059+
2060+ it ( 'should use discoverOAuthFromWWWAuthenticate when it succeeds and skip discoverOAuthConfig' , async ( ) => {
2061+ const serverUrl = 'http://test-server.com/mcp' ;
2062+ const authUrl = 'http://auth.example.com/auth' ;
2063+ const tokenUrl = 'http://auth.example.com/token' ;
2064+ const wwwAuthHeader = `Bearer realm="test", resource_metadata="http://test-server.com/.well-known/oauth-protected-resource"` ;
2065+
2066+ vi . mocked ( mockedClient . connect ) . mockRejectedValueOnce (
2067+ new StreamableHTTPError (
2068+ 401 ,
2069+ `Unauthorized\nwww-authenticate: ${ wwwAuthHeader } ` ,
2070+ ) ,
2071+ ) ;
2072+
2073+ vi . mocked ( OAuthUtils . discoverOAuthFromWWWAuthenticate ) . mockResolvedValue ( {
2074+ authorizationUrl : authUrl ,
2075+ tokenUrl,
2076+ scopes : [ 'read' ] ,
2077+ } ) ;
2078+
2079+ vi . mocked ( mockedClient . connect ) . mockResolvedValueOnce ( undefined ) ;
2080+
2081+ const client = await connectToMcpServer (
2082+ '0.0.1' ,
2083+ 'test-server' ,
2084+ { httpUrl : serverUrl , oauth : { enabled : true } } ,
2085+ false ,
2086+ workspaceContext ,
2087+ EMPTY_CONFIG ,
2088+ ) ;
2089+
2090+ expect ( client ) . toBe ( mockedClient ) ;
2091+ expect ( OAuthUtils . discoverOAuthFromWWWAuthenticate ) . toHaveBeenCalledWith (
2092+ wwwAuthHeader ,
2093+ serverUrl ,
2094+ ) ;
2095+ expect ( OAuthUtils . discoverOAuthConfig ) . not . toHaveBeenCalled ( ) ;
2096+ expect ( mockAuthProvider . authenticate ) . toHaveBeenCalledOnce ( ) ;
2097+ } ) ;
2098+
2099+ it ( 'should fall back to extractBaseUrl + discoverOAuthConfig when discoverOAuthFromWWWAuthenticate returns null' , async ( ) => {
2100+ const serverUrl = 'http://test-server.com/mcp' ;
2101+ const baseUrl = 'http://test-server.com' ;
2102+ const authUrl = 'http://auth.example.com/auth' ;
2103+ const tokenUrl = 'http://auth.example.com/token' ;
2104+ const wwwAuthHeader = `Bearer realm="test"` ;
2105+
2106+ vi . mocked ( mockedClient . connect ) . mockRejectedValueOnce (
2107+ new StreamableHTTPError (
2108+ 401 ,
2109+ `Unauthorized\nwww-authenticate: ${ wwwAuthHeader } ` ,
2110+ ) ,
2111+ ) ;
2112+
2113+ vi . mocked ( OAuthUtils . discoverOAuthFromWWWAuthenticate ) . mockResolvedValue (
2114+ null ,
2115+ ) ;
2116+ vi . mocked ( OAuthUtils . extractBaseUrl ) . mockReturnValue ( baseUrl ) ;
2117+ vi . mocked ( OAuthUtils . discoverOAuthConfig ) . mockResolvedValue ( {
2118+ authorizationUrl : authUrl ,
2119+ tokenUrl,
2120+ scopes : [ 'read' ] ,
2121+ } ) ;
2122+
2123+ vi . mocked ( mockedClient . connect ) . mockResolvedValueOnce ( undefined ) ;
2124+
2125+ const client = await connectToMcpServer (
2126+ '0.0.1' ,
2127+ 'test-server' ,
2128+ { httpUrl : serverUrl , oauth : { enabled : true } } ,
2129+ false ,
2130+ workspaceContext ,
2131+ EMPTY_CONFIG ,
2132+ ) ;
2133+
2134+ expect ( client ) . toBe ( mockedClient ) ;
2135+ expect ( OAuthUtils . discoverOAuthFromWWWAuthenticate ) . toHaveBeenCalledWith (
2136+ wwwAuthHeader ,
2137+ serverUrl ,
2138+ ) ;
2139+ expect ( OAuthUtils . extractBaseUrl ) . toHaveBeenCalledWith ( serverUrl ) ;
2140+ expect ( OAuthUtils . discoverOAuthConfig ) . toHaveBeenCalledWith ( baseUrl ) ;
2141+ expect ( mockAuthProvider . authenticate ) . toHaveBeenCalledOnce ( ) ;
2142+ } ) ;
20592143} ) ;
20602144
20612145describe ( 'connectToMcpServer - HTTP→SSE fallback' , ( ) => {
0 commit comments