-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
Describe the bug
When using OAuth with MCP servers that employ separate authorization servers (like AWS Cognito, Auth0, Okta) via RFC 9728 Protected Resource Metadata, the SDK fails during token exchange with an "Invalid api path" error. The root cause is that resourceMetadataUrl is not extracted from the WWW-Authenticate header during the initial connection attempt, causing finishAuth() to use undefined for the resource metadata URL. This makes the SDK fall back to incorrectly using the MCP server URL as the authorization server URL, resulting in token requests being sent to the wrong endpoint.
To Reproduce
Steps to reproduce the behavior:
-
Set up an MCP server that uses a separate authorization server (e.g., AWS Cognito) and returns a 401 response with a WWW-Authenticate header containing
resource_metadataparameter:WWW-Authenticate: Bearer realm="mcp", resource_metadata="https://example.com/.well-known/oauth-protected-resource" -
Create an OAuth client provider and attempt to connect:
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client'; const transport = new StreamableHTTPClientTransport( new URL('https://bedrock-agentcore.us-east-1.amazonaws.com/'), { authProvider: myOAuthProvider } ); await transport.start(); // Triggers auth flow
-
After user authorization, call
finishAuth()with the authorization code:await transport.finishAuth(authorizationCode);
-
Observe the error: Token exchange fails with "Invalid api path" because the SDK constructs the wrong token endpoint URL (e.g.,
https://bedrock-agentcore.us-east-1.amazonaws.com/tokeninstead of the Cognito token endpoint).
Expected behavior
The SDK should:
- Extract the
resource_metadataURL from the WWW-Authenticate header during the initial 401 response - Store this URL in
_resourceMetadataUrlbefore starting the auth flow - Use the stored
_resourceMetadataUrlwhenfinishAuth()is called - Correctly discover the authorization server's OpenID configuration from the resource metadata
- Use the correct token endpoint (e.g., Cognito's token endpoint) for token exchange
- Successfully complete the OAuth flow
Logs
Error during token exchange:
Error: Invalid api path
at token exchange
POST https://bedrock-agentcore.us-east-1.amazonaws.com/token
(should be: https://cognito-idp.us-east-1.amazonaws.com/oauth2/token)
Additional context
- This bug affects both
StreamableHTTPClientTransportandSSEClientTransport - The issue occurs because
_resourceMetadataUrlis only extracted in thesend()method, which is called AFTER the initial connection is established - The initial 401 that triggers the auth flow happens during
transport.start(), but the resource metadata URL extraction was missing at this point - When
finishAuth()is later called,_resourceMetadataUrlis stillundefined, causing the SDK to fall back to using the MCP server URL as the authorization server URL (line 12247 in the SDK) - This affects all MCP servers using:
- Separate authorization servers (AWS Cognito, Auth0, Okta, etc.)
- RFC 9728 Protected Resource Metadata
- OAuth 2.0 with
resource_metadataparameter in WWW-Authenticate headers
Workarounds
Until fixed, users can:
- Use a proxy that handles OAuth and presents the same domain for both MCP and OAuth endpoints
- Configure the MCP server to use the same domain for both the MCP endpoint and OAuth endpoints
- Pin to SDK version 1.20.0 (though this may have other limitations)
Files Affected
packages/client/src/client/streamableHttp.ts-_startOrAuthSse()methodpackages/client/src/client/sse.ts-_startOrAuth()method