-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat: add multi-level initial access token support for OAuth 2.0 Dynamic Client Registration (RFC 7591) #773
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…mic Client Registration (RFC 7591) - Extend OAuthClientProvider interface with optional initialAccessToken() method - Update registerClient() to support multi-level fallback: 1. Explicit parameter (highest priority) 2. Provider method 3. OAUTH_INITIAL_ACCESS_TOKEN environment variable 4. None (existing behavior) - Add initialAccessToken option to StreamableHTTPClientTransport and SSEClientTransport - Update auth flow to pass initial access token through all transport layers - Add Authorization: Bearer header to registration requests when token available - Add comprehensive test coverage for all fallback levels - Maintain backward compatibility with servers not requiring pre-authorization Implements RFC 7591 specification for OAuth 2.0 Dynamic Client Registration with initial access tokens for authorization servers requiring pre-authorization.
IDE-specific files should not be committed to the repository
…mic Client Registration (RFC 7591) - Extend OAuthClientProvider interface with optional initialAccessToken() method - Update registerClient() to support multi-level fallback: 1. Explicit parameter (highest priority) 2. Provider method 3. OAUTH_INITIAL_ACCESS_TOKEN environment variable 4. None (existing behavior) - Add initialAccessToken option to StreamableHTTPClientTransport and SSEClientTransport - Update auth flow to pass initial access token through all transport layers - Add Authorization: Bearer header to registration requests when token available - Add comprehensive test coverage for all fallback levels - Add detailed OAuth client configuration documentation - Maintain backward compatibility with servers not requiring pre-authorization Implements RFC 7591 specification for OAuth 2.0 Dynamic Client Registration with initial access tokens for authorization servers requiring pre-authorization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi,
Generally on-board with supporting this, and appreciate that this is following the RFC:
https://www.rfc-editor.org/rfc/rfc7591.html#section-3.1
The RFC uses the term "initial access token", but informally, and related just to DCR. In this SDK, we'll need to call the token something like "DCR_REGISTRATION_ACCESS_TOKEN" or similar.
Also, I don't think we want 3 levels of fallback. Users can implement their own OAuthProvider, and that provider can fallback to parameters or environment variables, but this is a relatively narrow use case so I don't think it warrants having special handling code in all the different places. (i.e. the single appropriate place I see is in the auth.ts
and by calling an optional function on the OAuthProvider).
- Rename OAuthClientProvider.initialAccessToken() to dcrRegistrationAccessToken() - Update environment variable from OAUTH_INITIAL_ACCESS_TOKEN to DCR_REGISTRATION_ACCESS_TOKEN - Update all documentation and comments to use DCR terminology - Add clarifications that RFC 7591 calls this "initial access token" - Maintains RFC 7591 compliance while using more specific SDK terminology Addresses PR feedback to use clearer naming for Dynamic Client Registration tokens.
BREAKING CHANGE: Removed initialAccessToken parameters from transport constructors - Rename initialAccessToken() to dcrRegistrationAccessToken() in OAuthClientProvider - Remove 3-level fallback complexity per PR feedback - Consolidate DCR token logic in auth.ts with resolveDcrToken() helper - Remove initialAccessToken options from StreamableHTTP and SSE transports - Keep environment variable DCR_REGISTRATION_ACCESS_TOKEN as automatic fallback - Update all documentation to use DCR terminology with RFC 7591 clarifications - Update tests to reflect new 2-level approach: provider method → env var - Users can implement custom fallback logic in their OAuthProvider Addresses PR feedback: "I don't think we want 3 levels of fallback. Users can implement their own OAuthProvider, and that provider can fallback to parameters or environment variables, but this is a relatively narrow use case so I don't think it warrants having special handling code in all the different places." RFC 7591 compliance maintained. Environment variable support preserved for convenience.
…ess token) Add comprehensive support for DCR registration access tokens (called "initial access token" in RFC 7591) for OAuth 2.0 Dynamic Client Registration. This enables pre-authorization for client registration with authorization servers that require it. Features: - Optional `dcrRegistrationAccessToken()` method in OAuthClientProvider interface - Clean 2-level fallback: provider method → DCR_REGISTRATION_ACCESS_TOKEN env var → none - Automatic integration with existing registerClient() function - Comprehensive test coverage with all fallback scenarios - Enhanced examples demonstrating basic and advanced DCR strategies Examples: - Updated simpleOAuthClient.ts with DCR token demonstration - New advancedDcrOAuthClient.ts showing production-ready strategies - Support for CLI arguments, environment variables, and secure storage - Complete documentation with RFC 7591 terminology mapping Implementation follows feedback to: - Use descriptive naming (DCR_REGISTRATION_ACCESS_TOKEN vs generic "initial access token") - Implement clean 2-level fallback without excessive complexity - Place token handling specifically in auth.ts registerClient function - Maintain backward compatibility Resolves: Support for RFC 7591 Dynamic Client Registration initial access tokens"
Hi @pcarleton ! Thank you for the thoughtful feedback! I really appreciate the guidance on the RFC 7591 implementation approach. I've implemented all the suggestions you mentioned: ✅ Naming Convention: Used ✅ Simplified Fallback: Implemented a clean 2-level fallback approach exactly as suggested:
✅ Proper Integration: The implementation is contained specifically in I've also added comprehensive test coverage for all fallback scenarios and created detailed examples showing both basic usage and advanced production strategies (including secure storage integration, token exchange patterns, etc.). The documentation clearly maps our SDK naming to the RFC 7591 terminology so users can easily find this functionality. The implementation maintains full backward compatibility and follows the principle of keeping the core simple while allowing users to implement sophisticated custom logic in their OAuthProvider if needed. Thanks again for the excellent guidance - this approach feels much cleaner and more maintainable! |
* Internal helper to resolve DCR registration access token from provider and environment. | ||
* Implements a clean 2-level fallback: provider method → environment variable. | ||
*/ | ||
async function resolveDcrToken(provider?: OAuthClientProvider): Promise<string | undefined> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should have the fallback, if you want to have the fallback to the environment variable in your Provider implementation, that's okay, but it doesn't need to be in the main flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi!
Great point about the fallback design! Let me explain the reasoning behind including the environment variable fallback in the main SDK flow.
The key benefit is ecosystem-wide DCR support without additional implementation burden. Any project that uses this SDK (like MCP Inspector, or any other tooling built on the SDK) would automatically get DCR token support simply by setting DCR_REGISTRATION_ACCESS_TOKEN
- no code changes required.
If we move the environment variable fallback to only the Provider implementation:
- ✅ Cleaner separation of concerns in the SDK
- ❌ Every downstream project needs to implement their own env var handling
- ❌ Fragmented DCR support across the ecosystem (some tools support it, others don't)
- ❌ More boilerplate for simple use cases
The current approach means:
- ✅ Universal DCR support: All SDK-based tools get DCR token support for free
- ✅ Zero-config experience: Just set the env var and it works everywhere
- ✅ Custom logic still possible: Providers can implement sophisticated strategies via the
dcrRegistrationAccessToken()
method - ✅ Graceful degradation: No token = proceed normally
I think the ecosystem benefit of "set one env var, DCR works everywhere" outweighs the slight complexity in the SDK. It follows the principle of making simple things simple (env var) while keeping complex things possible (custom provider logic).
What are your thoughts on this trade-off? Happy to discuss alternative approaches that might achieve both goals!
Summary
Implements multi-level initial access token support for OAuth 2.0 Dynamic Client Registration according to RFC 7591. This enables clients to register with authorization servers that require pre-authorization for dynamic client registration.
Changes
Core Implementation
OAuthClientProvider
interface with optionalinitialAccessToken()
methodregisterClient()
function with multi-level fallback logicAuthorization: Bearer <token>
header when token availableMulti-Level Fallback Priority
registerClient()
OAuthClientProvider.initialAccessToken()
OAUTH_INITIAL_ACCESS_TOKEN
Usage Examples
Transport-Level Configuration
Provider-Level Configuration
Environment Variable
Testing
Breaking Changes
None - this is a fully backward-compatible addition.
Related