feat(server): OAuth scope challenge support (step-up auth)#1624
Draft
SamMorrowDrums wants to merge 2 commits intomodelcontextprotocol:mainfrom
Draft
feat(server): OAuth scope challenge support (step-up auth)#1624SamMorrowDrums wants to merge 2 commits intomodelcontextprotocol:mainfrom
SamMorrowDrums wants to merge 2 commits intomodelcontextprotocol:mainfrom
Conversation
Implement server-side scope challenge handling per MCP spec §10.1. This enables servers to declare required OAuth scopes per tool and automatically return HTTP 403 with WWW-Authenticate headers when a client's token lacks sufficient scopes. Key additions: - ToolScopeConfig type for declaring required/accepted scopes per tool - ScopeChallengeConfig on StreamableHTTP transport options - Pre-execution scope check in transport layer (before SSE stream opens) - McpServer.registerTool() accepts scopes option (string[] or config) - McpServer.setToolScopes() for decoupled/centralized scope declaration - Auto-wiring of scope resolver in McpServer.connect() - NodeStreamableHTTPServerTransport delegates setScopeResolver() - Additive scoping: challenges include union of existing + required scopes - 17 tests covering scope checks, overrides, batches, and auto-wiring - Proposal document for SDK devs and Tool Scopes Working Group Scope challenges are HTTP-only (ignored for stdio), operate at the transport layer before handlers execute, and follow the additive scoping pattern established by github/github-mcp-server. Relates to modelcontextprotocol#1151 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🦋 Changeset detectedLatest commit: b7c3ad1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@modelcontextprotocol/client
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Server-side OAuth scope challenge (step-up auth) support per MCP spec §10.1.
Servers can now declare required OAuth scopes per tool and the transport automatically returns HTTP 403 with
WWW-Authenticateheaders when a client's token lacks sufficient scopes — triggering the client's existing re-authorization flow.Relates to #1151
Design
Scope challenges are enforced at the transport layer before the SSE stream opens (not in tool handlers). This is the only viable architecture because HTTP status codes are committed before handlers execute. The existing client-side 403 handling already works unchanged.
Developer API
Key decisions
requiredvsaccepted:acceptedscopes let the call through without challenge;requiredscopes are what's recommended in the 403 challenge. This supports scope hierarchies (e.g.repoimpliesrepo:read)scopevalue inWWW-Authenticateis always the union of existing token scopes + required scopes, so clients never lose scopes during step-up (matching github/github-mcp-server pattern)authInfo.scopesas populated by the implementer's auth middleware — it does not determine what scopes are activeWhat's included
packages/server/src/server/mcp.tsToolScopeConfig,scopesonregisterTool(),setToolScopes(),getToolScopes(), auto-wiringpackages/server/src/server/streamableHttp.tsScopeChallengeConfig,setScopeResolver(),_checkScopeChallenge()packages/middleware/node/src/streamableHttp.tssetScopeResolver()delegationpackages/server/test/server/scopeChallenge.test.tsdocs/proposals/scope-challenge-server-sdk.mdWhat's NOT included (out of scope)
Toolschema changes (scope metadata is server-side only for now)Testing