Skip to content

Commit e65bd53

Browse files
fix: validate_scope should allow all scopes when no restriction
When client registration has scope=None (no restriction), validate_scope was incorrectly rejecting all requested scopes by treating None as an empty allowed list. Now when scope is None, all requested scopes are allowed, which matches the expected behavior described in the auth flow. Fixes #2216
1 parent b33c811 commit e65bd53

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

src/mcp/shared/auth.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ def validate_scope(self, requested_scope: str | None) -> list[str] | None:
7171
if requested_scope is None:
7272
return None
7373
requested_scopes = requested_scope.split(" ")
74-
allowed_scopes = [] if self.scope is None else self.scope.split(" ")
74+
# When no scope is required (None), allow all requested scopes
75+
if self.scope is None:
76+
return requested_scopes
77+
allowed_scopes = self.scope.split(" ")
7578
for scope in requested_scopes:
7679
if scope not in allowed_scopes: # pragma: no branch
7780
raise InvalidScopeError(f"Client was not registered with scope {scope}")

test_validate_scope_fix.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""Test for validate_scope fix when self.scope is None"""
2+
import pytest
3+
from mcp.shared.auth import ClientRegistration, InvalidScopeError
4+
5+
6+
def test_validate_scope_with_none_scope_allows_all():
7+
"""When client has no scope restriction (None), all requested scopes should be allowed."""
8+
client = ClientRegistration(
9+
client_id="test-client",
10+
client_secret="secret",
11+
scope=None, # No scope restriction
12+
redirect_uris=["http://localhost/callback"],
13+
)
14+
15+
# Should not raise - all scopes allowed when no restriction
16+
result = client.validate_scope("read write admin")
17+
assert result == ["read", "write", "admin"]
18+
19+
20+
def test_validate_scope_with_empty_requested_returns_none():
21+
"""When requested_scope is None, return None."""
22+
client = ClientRegistration(
23+
client_id="test-client",
24+
client_secret="secret",
25+
scope="read write",
26+
redirect_uris=["http://localhost/callback"],
27+
)
28+
29+
result = client.validate_scope(None)
30+
assert result is None
31+
32+
33+
def test_validate_scope_with_restrictions_enforced():
34+
"""When client has scope restrictions, only allowed scopes pass."""
35+
client = ClientRegistration(
36+
client_id="test-client",
37+
client_secret="secret",
38+
scope="read write",
39+
redirect_uris=["http://localhost/callback"],
40+
)
41+
42+
# Allowed scope
43+
result = client.validate_scope("read")
44+
assert result == ["read"]
45+
46+
# Disallowed scope should raise
47+
with pytest.raises(InvalidScopeError):
48+
client.validate_scope("admin")

0 commit comments

Comments
 (0)