deepset-ai / deepset-ai/haystack-core-integrations
mcp: Implement Automatic OAuth Discovery via 401 Detection
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 203
- Forks
- 332
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 80
Description
Scope
Implement automatic OAuth discovery when MCP servers return 401 Unauthorized responses, following the MCP spec's discovery mechanisms. This enables zero-configuration OAuth for compliant servers.
Haystack MCP Integration Details
401 Detection Points:
StreamableHttpClient.connect(): Catch 401 during initial connection/session establishmentStreamableHttpClient.call_tool(): Catch 401 during tool invocations- Both should trigger the same discovery and OAuth flow
Discovery Flow:
- Parse
WWW-Authenticate: Bearer ...header to extract metadata hints - Try
WWW-Authenticateheaderresource_metadataparameter first - Fallback to
/.well-known/oauth-protected-resource{path}(with path insertion per RFC 9728) - Fallback to
/.well-known/oauth-protected-resource(root) - Extract
authorization_serverslist from resource metadata - Fetch authorization server metadata from
/.well-known/oauth-authorization-server - Extract
authorization_endpoint,token_endpoint,registration_endpoint, etc. - Validate S256 PKCE support (required by MCP spec)
Dynamic Client Registration (DCR):
- Check for
registration_endpointin AS metadata - POST to register client and obtain
client_id(andclient_secretif confidential) - Fallback to requiring user-provided
client_idif DCR not supported - This enables truly zero-config OAuth for servers that support it
Auto-Population of OAuthConfig:
- Create
OAuthConfiginstance from discovered metadata - Fill in
authorization_endpoint,token_endpointfrom metadata - If DCR succeeds, populate
client_idandclient_secret - Store discovered config for reuse (avoid repeated discovery)
Retry Logic:
- After obtaining token, retry the original request that triggered 401
- Cache token in
server_info.headers["Authorization"]for subsequent requests - Handle token expiration and refresh (if refresh token available)
Integration with Existing Code:
- Discovery should be non-invasive - existing code should work without OAuth
- If
OAuthConfigis provided, use it (still perform discovery for endpoints if not specified) - Discovery should happen lazily (only on 401) to avoid unnecessary requests
- Consider caching discovered metadata to avoid repeated discovery
Error Handling:
- If discovery fails, provide clear error messages
- If DCR fails, fallback to requiring user-provided credentials
- If OAuth flow fails, propagate meaningful errors
Requirements
- Catch 401 Unauthorized responses in
StreamableHttpClient.connect()andcall_tool() - Parse
WWW-Authenticate: Bearer ...header to extract metadata hints - Implement automatic resource metadata discovery:
- Try
WWW-Authenticateheaderresource_metadataparameter first - Fallback to
/.well-known/oauth-protected-resource{path}(with path insertion) - Fallback to
/.well-known/oauth-protected-resource(root)
- Try
- Implement automatic authorization server metadata discovery:
- Fetch
/.well-known/oauth-authorization-serverfrom discovered issuer - Extract
authorization_endpoint,token_endpoint,code_challenge_methods_supported - Validate S256 PKCE support (required by MCP spec)
- Fetch
- (Optional) Implement Dynamic Client Registration (RFC 7591):
- Check for
registration_endpointin AS metadata - POST to register client and obtain
client_id(andclient_secretif confidential) - Fallback to requiring user-provided
client_idif DCR not supported
- Check for
- Auto-populate
OAuthConfigfrom discovered metadata - Trigger appropriate OAuth flow (Authorization Code or Client Credentials) based on discovery
- Retry original request after obtaining token
- Cache discovered metadata and tokens to avoid repeated discovery
- Handle errors gracefully with clear messages
- Add comprehensive tests for discovery flow
- Add tests for 401 handling and retry logic
- Add tests for DCR (if implemented)
References
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with StreamableHttpClient.connect() and call_tool(), tracing how 401 responses and OAuthConfig are currently handled. Review the MCP discovery, RFC 9728, RFC 8414, and RFC 7591 references, then add focused tests for metadata discovery, retry behavior, caching, and errors. Done means both entry points share lazy discovery and can retry authenticated requests without breaking existing OAuth configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, authentication
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100