-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Summary
Server SDK authors currently have no ergonomic way to trigger OAuth scope challenges during tool execution. While the MCP spec (SEP-835) supports returning 403 responses with WWW-Authenticate headers to request additional scopes, server SDKs don't provide facilities to easily declare required scopes per tool or dynamically trigger scope challenges during tool execution.
Use Case
Consider a server like GitHub's MCP server that wraps an API with granular permissions:
- A user connects with a valid OAuth token but minimal/no scopes
- They call a tool that may or may not need additional scopes depending on the specific resource (e.g., accessing a public vs private repo)
- The server makes a request to its backend service, which responds indicating more scopes are needed
- The server wants to pass this back as a scope challenge rather than a failed tool call
Currently, server authors must implement this entirely outside SDK land:
- Parse raw JSON-RPC
- Match tool names
- Check required scopes against active scopes
- Manually construct and return the 403 response with WWW-Authenticate header
Proposed Features
1. Declare required scopes when registering a tool (minimum viable)
server.registerTool(
'get_private_repo',
{
description: 'Get private repository details',
inputSchema: { ... },
requiredScopes: ['repo:read'] // New field
},
async (args) => { ... }
);The SDK would automatically check scopes before tool execution and return a 403 scope challenge if the token lacks required scopes.
2. Dynamically trigger scope challenge during tool execution (ideal)
server.registerTool(
'get_repo_issue',
{
description: 'Get repository issue',
inputSchema: { ... }
},
async (args, context) => {
const response = await fetchFromBackend(args);
if (response.needsAdditionalScopes) {
// Trigger scope challenge mid-execution
throw new ScopeChallengeError(['repo:read']);
// or: context.requestScopes(['repo:read']);
}
return { content: [...] };
}
);This would allow servers to defer scope decisions to downstream services and pass through their authorization requirements.
Additional Considerations
- Scope hierarchy: Some OAuth systems have hierarchical scopes (e.g.,
repoincludesrepo:read). SDKs may need to support scope resolution/comparison utilities. - Access to current scopes: Tool handlers need a way to inspect what scopes the current token has (perhaps via context parameter).
Related
- SEP-835 (Scope Challenge Handling): https://modelcontextprotocol.io/specification/draft/basic/authorization#scope-challenge-handling
- Conformance test for client-side handling: https://github.com/modelcontextprotocol/conformance/blob/main/src/scenarios/client/auth/scope-handling.ts#L237
- Python SDK client implementation: https://github.com/modelcontextprotocol/python-sdk/blob/main/src/mcp/client/auth/oauth2.py#L591-L608
Context
Discussion from Discord with @SamMorrowDrums (GitHub MCP server author) about server-side SDK support for scope challenges.
https://discord.com/channels/1358869848138059966/1441013745496227870