Skip to content

Commit 100590c

Browse files
feat: add initial access token support for OAuth 2.0 Dynamic Client Registration (RFC 7591)
- Add initial_access_token parameter to OAuthClientProvider constructor - Implement multi-level fallback for token resolution: 1. Explicit parameter (highest priority) 2. Provider method (initial_access_token()) 3. Environment variable (OAUTH_INITIAL_ACCESS_TOKEN) 4. No token (existing behavior) - Add Authorization Bearer header to registration requests when token available - Add comprehensive test coverage for all fallback scenarios - Update documentation with usage examples and configuration details - Maintain full backward compatibility with existing OAuth flows This enables clients to register with protected OAuth endpoints that require initial access tokens per RFC 7591 Dynamic Client Registration specification.
1 parent b609fc5 commit 100590c

File tree

3 files changed

+7
-6
lines changed

3 files changed

+7
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,7 @@ class CustomOAuthProvider(OAuthClientProvider):
14971497
```
14981498

14991499
The fallback order is:
1500+
15001501
1. Explicit `initial_access_token` parameter
15011502
2. Provider's `initial_access_token()` method
15021503
3. `OAUTH_INITIAL_ACCESS_TOKEN` environment variable

src/mcp/client/auth.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,10 @@ async def _handle_oauth_metadata_response(self, response: httpx.Response, is_fal
323323

324324
async def _register_client(self, initial_access_token: str | None = None) -> httpx.Request | None:
325325
"""Build registration request or skip if already registered.
326-
326+
327327
Supports initial access tokens for OAuth 2.0 Dynamic Client Registration according to RFC 7591.
328328
Uses multi-level fallback approach:
329-
329+
330330
1. Explicit parameter (highest priority)
331331
2. Provider's initial_access_token() method
332332
3. OAUTH_INITIAL_ACCESS_TOKEN environment variable
@@ -541,7 +541,7 @@ async def initial_access_token(self) -> str | None:
541541
# Return constructor parameter if available
542542
if self._initial_access_token:
543543
return self._initial_access_token
544-
544+
545545
# Subclasses can override this method to provide tokens from other sources
546546
return None
547547

tests/client/test_auth.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ async def test_register_client_with_explicit_initial_access_token(self, oauth_pr
430430
@pytest.mark.anyio
431431
async def test_register_client_with_provider_initial_access_token(self, client_metadata, mock_storage):
432432
"""Test client registration with provider method initial access token."""
433-
433+
434434
class CustomOAuthProvider(OAuthClientProvider):
435435
async def initial_access_token(self) -> str | None:
436436
return "provider-token"
@@ -460,7 +460,7 @@ async def callback_handler() -> tuple[str, str | None]:
460460
@pytest.mark.anyio
461461
async def test_register_client_explicit_overrides_provider(self, client_metadata, mock_storage):
462462
"""Test explicit initial access token overrides provider method."""
463-
463+
464464
class CustomOAuthProvider(OAuthClientProvider):
465465
async def initial_access_token(self) -> str | None:
466466
return "provider-token"
@@ -511,7 +511,7 @@ async def test_register_client_without_initial_access_token(self, oauth_provider
511511
@pytest.mark.anyio
512512
async def test_initial_access_token_constructor_parameter(self, client_metadata, mock_storage):
513513
"""Test OAuthClientProvider with initial access token constructor parameter."""
514-
514+
515515
async def redirect_handler(url: str) -> None:
516516
pass
517517

0 commit comments

Comments
 (0)