Skip to content

Conversation

@nypdmax
Copy link

@nypdmax nypdmax commented Feb 6, 2026

Motivation and Context

This PR adds multi-protocol authentication support to the MCP Python SDK, centered around unified authorization
server discovery
so clients can discover, select, and apply one of multiple supported auth protocols consistently.

Key capabilities:

  • Unified auth protocol discovery via /.well-known/authorization_servers plus RFC 9728 PRM fallback.
    • Allows servers to advertise multiple protocols (e.g. oauth2, api_key) with optional default protocol and
      preferences.
    • Allows clients to select an injected protocol instance based on server hints and preferences, with safe fallbacks.
  • Extensible protocol metadata (MCP extension fields) to represent protocol endpoints/capabilities consistently.
  • DPoP support (RFC 9449):
    • Client-side proof generation and header injection (opt-in).
    • Server-side proof verification integrated into verification flow (opt-in).
  • Streamable HTTP server maintainability: refactors request handling to reduce complexity while preserving behavior.
  • Examples support: adds a small FastMCP compatibility wrapper used by examples and updates multiprotocol examples.
  • Documentation updates covering protocol discovery and multiprotocol usage.

How Has This Been Tested?

  • Unit/integration tests:

    • PYTEST_DISABLE_PLUGIN_AUTOLOAD="" uv run --frozen pytest
  • Lint / typecheck:

    • uv run --frozen ruff format --check .
    • uv run --frozen ruff check .
    • uv run --frozen pyright
  • E2E examples (manual OAuth flow):

    • ./examples/clients/simple-auth-multiprotocol-client/run_multiprotocol_test.sh
    • ./examples/clients/simple-auth-multiprotocol-client/run_dpop_test.sh
    • ./examples/clients/simple-auth-multiprotocol-client/run_oauth2_test.sh

Spec compliance notes (additive extensions)

This PR keeps MCP Authorization (2025-06-18) OAuth behavior intact (RFC 9728 PRM + RFC 8414 metadata + RFC 8707
resource indicators). It also adds optional extensions to support multi-protocol auth and stronger token binding:

  • Multi-protocol selection (extension):

    • Optional /.well-known/authorization_servers endpoint (best-effort; client falls back if missing).
    • Optional PRM extension fields: mcp_auth_protocols, mcp_default_auth_protocol, mcp_auth_protocol_preferences.
    • Optional WWW-Authenticate: Bearer ... hint params: auth_protocols, default_protocol, protocol_preferences
      (ignored by spec-only clients).
  • DPoP (RFC 9449) (optional extension): adds opt-in DPoP proof generation/verification; standard Bearer flow remains
    supported when disabled.

Interoperability: spec-only servers/clients can ignore these extensions and continue using the standard OAuth discovery
and Bearer token flow.

Breaking Changes

None expected. Changes are additive and aim to preserve existing behavior and public APIs.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Suggested review order (commit-by-commit):

  1. Streamable HTTP server refactor
  2. Auth server token handling + verifiers (and tests)
  3. Multi-protocol client/provider behavior + test coverage
  4. DPoP client/server pieces + tests
  5. FastMCP wrapper + updated examples
  6. Documentation updates

resolves #2024

…ig for examples/clients

- Add examples/clients/simple-auth-multiprotocol-client (API Key + mTLS placeholder)
- Pyright: include examples/clients; executionEnvironments + extraPaths for client packages
- Fixes import resolution for mcp_simple_auth_multiprotocol_client.main in __main__.py
…rotocol integration test script

- APIKeyVerifier: optional scopes param for AccessToken (satisfy required_scopes)
- simple-auth-multiprotocol: build_multiprotocol_backend(api_key_scopes=[mcp_scope])
- scripts/run_phase2_multiprotocol_integration_test.sh: api_key (default), oauth (AS+RS+simple-auth-client), mutual_tls (placeholder)
…erator and storage

- Add DPoPKeyPair for ES256/RS256 key generation with configurable RSA key size
- Add DPoPProofGeneratorImpl for generating DPoP proof JWTs per RFC 9449
- Add InMemoryDPoPStorage for key pair persistence
- Add compute_jwk_thumbprint for RFC 7638 JWK Thumbprint calculation
- Include comprehensive unit tests (12 test cases)
Add DPoPProofVerifier for validating DPoP proof JWTs per RFC 9449 Section 4.3,
including replay protection, claim validation, and JWK thumbprint verification.
Add DPoP support to OAuth2Protocol implementing DPoPEnabledProtocol,
inject DPoP proofs via MultiProtocolAuthProvider, and verify DPoP-bound
tokens in OAuthTokenVerifier.
Add --dpop-enabled CLI flag and integrate DPoPProofVerifier with
MultiProtocolAuthBackend for end-to-end DPoP verification.
- Add scripts/run_phase4_dpop_integration_test.sh for automated DPoP tests
- Update test_oauth2_protocol: expect OAuthFlowError when http_client is None
- Update simple-auth-multiprotocol-client: OAuth+DPoP support, InMemoryStorage
- Update simple-auth-multiprotocol: DPoP logging, oauth2 protocol_version 2.0
- Add _oauth_401_flow.py: oauth_401_flow_generator, oauth_403_flow_generator
- Refactor OAuthClientProvider.async_auth_flow to drive shared generators
- Refactor MultiProtocolAuthProvider 401 handling to use shared OAuth flow
- Fix OAuth2Protocol.authenticate to use fresh client when called outside flow
- Fix OAuthTokenVerifier: use scope for HTTP method (HTTPConnection compat)
Prefer only locally injected protocol instances when selecting the auth protocol, and ensure the final response corresponds to the original request (avoid leaking discovery responses).
Add regression tests ensuring 401 handling falls back when the server default protocol isn't injected, and that discovery responses are never returned as the business request response.
Make api_key and mutual_tls runs non-interactive with clear PASS/FAIL, add oauth_dpop mode wiring, and allow forcing mutual_tls protocol injection for placeholder coverage.
…odule

Centralize 5 server variants into a single VariantConfig-driven
implementation; reduce variant packages to thin shims.
Delete 8 redundant multiprotocol.py/token_verifier.py files.
…covery order

Fix path-relative URL to /.well-known/authorization_servers{path}.
Refactor async_auth_flow to try path-relative then root discovery
sequentially before falling back to PRM.
@nypdmax nypdmax force-pushed the pr/auth-ext-cherrypick branch from 25787aa to 7a2e591 Compare February 10, 2026 01:24
@maxisbey
Copy link
Contributor

Thanks for the effort here, but this is a very large PR introducing spec extensions without prior maintainer approval. Per our contributing guidelines, please open an issue first and get maintainer buy-in before submitting PRs of this scope. Features that touch the protocol (like new auth discovery mechanisms and DPoP) would also need a SEP.

AI Disclaimer

@maxisbey maxisbey closed this Feb 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support multi-protocol authentication with spec-aligned discovery and OAuth fallback

2 participants