You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: remove scope registration check from authorize handler
The check in validate_scope rejected any requested scope not in the
client's registered metadata. This broke the MCP spec's step-up
authorization flow: when a server returns 403 insufficient_scope with
a WWW-Authenticate challenge containing expanded scopes, the client
(see client/auth/oauth2.py) re-authorizes with those scopes and the
server would reject them.
RFC 7591 Section 2 defines the scope field as scopes the client "can
use", with no language restricting requests to that set. Scope policy
enforcement belongs in OAuthAuthorizationServerProvider.authorize(),
which can already raise AuthorizeError(error="invalid_scope", ...).
The TypeScript SDK removed this check in #983 for the same reason.
InvalidScopeError is removed as it was only raised from this path.
Reported-by: nik1097
Github-Issue: #2216
### Server auth: `InvalidScopeError` removed, `validate_scope` no longer enforces
801
+
802
+
`OAuthClientMetadata.validate_scope()` no longer rejects scopes outside the client's registered set — it now only parses the scope string. The previous check blocked the MCP spec's step-up authorization flow, where a client must be able to request scopes beyond its initial registration in response to a `WWW-Authenticate: insufficient_scope` challenge. See [TypeScript SDK #983](https://github.com/modelcontextprotocol/typescript-sdk/pull/983) for the equivalent change.
803
+
804
+
`InvalidScopeError` (from `mcp.shared.auth`) has been removed — the SDK no longer raises it.
805
+
806
+
If your server needs to reject scopes, enforce policy inside `OAuthAuthorizationServerProvider.authorize()`:
807
+
808
+
```python
809
+
from mcp.server.auth.provider import AuthorizeError
810
+
811
+
asyncdefauthorize(self, client, params):
812
+
if params.scopes and"admin"in params.scopes andnot client_is_trusted(client):
0 commit comments