Skip to content

Commit ac16a58

Browse files
committed
fix: normalize oauth redirect uri url types
1 parent 3eb5799 commit ac16a58

2 files changed

Lines changed: 25 additions & 2 deletions

File tree

src/mcp/shared/auth.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Literal
1+
from typing import Any, Literal, cast
22

33
from pydantic import AnyHttpUrl, AnyUrl, BaseModel, Field, field_validator
44

@@ -67,6 +67,17 @@ class OAuthClientMetadata(BaseModel):
6767
software_id: str | None = None
6868
software_version: str | None = None
6969

70+
@field_validator(
71+
"redirect_uris",
72+
mode="before",
73+
)
74+
@classmethod
75+
def _normalize_redirect_uri_types(cls, v: object) -> object:
76+
if isinstance(v, list):
77+
uris = cast(list[Any], v)
78+
return [str(uri) if isinstance(uri, AnyUrl) else uri for uri in uris]
79+
return v
80+
7081
@field_validator(
7182
"client_uri",
7283
"logo_uri",

tests/shared/test_auth.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Tests for OAuth 2.0 shared code."""
22

33
import pytest
4-
from pydantic import ValidationError
4+
from pydantic import AnyHttpUrl, AnyUrl, ValidationError
55

66
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthMetadata
77

@@ -130,6 +130,18 @@ def test_information_full_inherits_coercion():
130130
assert info.jwks_uri is None
131131

132132

133+
def test_redirect_uri_url_subtypes_validate_by_canonical_url():
134+
info = OAuthClientInformationFull(
135+
client_id="abc123",
136+
redirect_uris=[AnyHttpUrl("https://example.com/callback")],
137+
)
138+
incoming = AnyUrl("https://example.com/callback")
139+
140+
assert info.validate_redirect_uri(incoming) == incoming
141+
assert info.redirect_uris == [incoming]
142+
assert info.model_dump(mode="json")["redirect_uris"] == ["https://example.com/callback"]
143+
144+
133145
def test_invalid_non_empty_url_still_rejected():
134146
"""Coercion must only touch empty strings — garbage URLs still raise."""
135147
data = {

0 commit comments

Comments
 (0)