Skip to content

Conversation

@chrisguidry
Copy link
Collaborator

Updates FastMCP to work with the latest MCP SDK (currently tracking main branch) which includes:

  1. OAuth client_secret_basic support (SDK PR Remove reference to stacked decorators #1334) - The SDK now supports HTTP Basic auth for client credentials. This required updating our TokenHandler to wrap the SDK's handle() method since auth errors now bypass response().

  2. SEP-1686 fields - New fields in MCP types: task in RequestParams, execution in Tool, _meta at message level.

  3. Expanded SamplingContent types - CreateMessageResult.content now supports ToolUseContent, ToolResultContent, and lists.

class TokenHandler(_SDKTokenHandler): """Wraps SDK to transform 401 unauthorized_client -> invalid_client for OAuth 2.1.""" async def handle(self, request): response = await super().handle(request) if response.status_code == 401: body = json.loads(response.body) if body.get("error") == "unauthorized_client": return PydanticJSONResponse( content=TokenErrorResponse(error="invalid_client", ...), status_code=401, ) return response

🤖 Generated with Claude Code

Updates for SDK auth and SEP-1686 changes: - Add `client_secret_basic` authentication support (SDK PR #1334) - TokenHandler now wraps SDK's handle() to maintain OAuth 2.1 error semantics - Update `SamplingContent` return type for new content types - Update test expectations for SEP-1686 fields (`task`, `execution`, `_meta`) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
@chrisguidry chrisguidry added the DON'T MERGE PR is not ready for merging. Used by authors to prevent premature merging. label Dec 1, 2025
@marvin-context-protocol marvin-context-protocol bot added enhancement Improvement to existing functionality. For issues and smaller PR improvements. auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. labels Dec 1, 2025
@marvin-context-protocol
Copy link
Contributor

Test Failure Analysis

Summary: Integration test test_github_oauth_with_mock is failing with "Client secret is required" error during OAuth token exchange.

Root Cause: The MCP SDK (now tracking main branch at c92bb2f) has added support for client_secret_basic authentication (SDK PR #1334). The SDK's OAuth client now defaults to using HTTP Basic authentication for client credentials, but the test's mocked OAuth flow doesn't properly handle this authentication method.

The failure occurs because:

  1. The MCP SDK client performs Dynamic Client Registration (DCR) and likely registers with both client_secret_basic and client_secret_post support
  2. When making the token exchange request, the SDK client sends credentials using HTTP Basic auth (Authorization: Basic header)
  3. The server's ClientAuthenticator (from the SDK) expects to find the client secret in the request, but something in the mock setup isn't providing it correctly

Suggested Solution: Update the integration test to properly support client_secret_basic authentication:

  1. Option A (Recommended): Update test_github_oauth_with_mock to ensure the mocked OAuth flow properly handles HTTP Basic authentication:

    • Verify that the HeadlessOAuth client's token exchange requests include proper Authorization: Basic headers
    • Ensure the mock server's client registration includes both client_secret_basic and client_secret_post in supported methods
  2. Option B: Explicitly configure the test to use client_secret_post only:

    • Modify the test to override the SDK client's default authentication method
    • This would maintain backward compatibility but wouldn't test the new client_secret_basic support
  3. Option C: Add a separate test specifically for client_secret_basic while keeping the existing test for client_secret_post

Detailed Analysis

Failed test: tests/integration_tests/auth/test_github_provider_integration.py::test_github_oauth_with_mock

Error traceback:

mcp.client.auth.exceptions.OAuthTokenError: Token exchange failed (401): {"error":"invalid_client","error_description":"Client secret is required"} 

Key code changes in this PR:

  • Added client_secret_basic to supported authentication methods (line 377 in test_auth_integration.py)
  • Updated TokenHandler to wrap SDK's handle() method for proper error transformation
  • Server now advertises both client_secret_post and client_secret_basic in /.well-known/oauth-authorization-server

The disconnect:

  • The test at line 235 of test_github_provider_integration.py manually registers with only "token_endpoint_auth_method": "client_secret_post"
  • But the failing test (test_github_oauth_with_mock) uses HeadlessOAuth which relies on the SDK's automatic DCR
  • The SDK client now likely defaults to or prefers client_secret_basic, causing a mismatch
Related Files

Test file: tests/integration_tests/auth/test_github_provider_integration.py:361 - Failing test
OAuth proxy: src/fastmcp/server/auth/oauth_proxy.py:541 - Updated TokenHandler with new handle() method
MCP SDK: Updated from 1.21.0 → 1.22.1.dev12+c92bb2f (PR #1334 adds client_secret_basic)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. DON'T MERGE PR is not ready for merging. Used by authors to prevent premature merging. enhancement Improvement to existing functionality. For issues and smaller PR improvements.

2 participants