Skip to content

Commit 818f0f2

Browse files
Kludexpcarleton
authored andcommitted
Preserve empty URL paths on OAuth metadata models (#2925)
(cherry picked from commit b7a5bff)
1 parent 8c2fa6e commit 818f0f2

2 files changed

Lines changed: 9 additions & 3 deletions

File tree

‎src/mcp/shared/auth.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Any, Literal
22

3-
from pydantic import AnyHttpUrl, AnyUrl, BaseModel, Field, field_validator
3+
from pydantic import AnyHttpUrl, AnyUrl, BaseModel, ConfigDict, Field, field_validator
44

55

66
class OAuthToken(BaseModel):
@@ -41,6 +41,8 @@ class OAuthClientMetadata(BaseModel):
4141
for the full specification.
4242
"""
4343

44+
model_config = ConfigDict(url_preserve_empty_path=True)
45+
4446
redirect_uris: list[AnyUrl] | None = Field(..., min_length=1)
4547
# supported auth methods for the token endpoint
4648
token_endpoint_auth_method: (
@@ -132,6 +134,8 @@ class OAuthMetadata(BaseModel):
132134
See https://datatracker.ietf.org/doc/html/rfc8414#section-2
133135
"""
134136

137+
model_config = ConfigDict(url_preserve_empty_path=True)
138+
135139
issuer: AnyHttpUrl
136140
authorization_endpoint: AnyHttpUrl
137141
token_endpoint: AnyHttpUrl
@@ -162,6 +166,8 @@ class ProtectedResourceMetadata(BaseModel):
162166
See https://datatracker.ietf.org/doc/html/rfc9728#section-2
163167
"""
164168

169+
model_config = ConfigDict(url_preserve_empty_path=True)
170+
165171
resource: AnyHttpUrl
166172
authorization_servers: list[AnyHttpUrl] = Field(..., min_length=1)
167173
jwks_uri: AnyHttpUrl | None = None

‎tests/client/test_auth.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,10 +522,10 @@ async def test_handle_metadata_response_success(self, oauth_provider: OAuthClien
522522
}"""
523523
response = httpx.Response(200, content=content)
524524

525-
# Should set metadata
525+
# Should set metadata; the empty path is preserved (no trailing slash added)
526526
await oauth_provider._handle_oauth_metadata_response(response)
527527
assert oauth_provider.context.oauth_metadata is not None
528-
assert str(oauth_provider.context.oauth_metadata.issuer) == "https://auth.example.com/"
528+
assert str(oauth_provider.context.oauth_metadata.issuer) == "https://auth.example.com"
529529

530530
@pytest.mark.anyio
531531
async def test_prioritize_www_auth_scope_over_prm(

0 commit comments

Comments
 (0)