fix: normalize OAuth redirect URI URL subtypes
Closed
FE
4mo ago+31+31+01234567890123456789-3-3-0123456789
Summary
Fixes #2687 by normalizing OAuthClientMetadata.redirect_uris entries at the model boundary. If callers pass a Pydantic URL subtype such as AnyHttpUrl, the value is revalidated through the declared AnyUrl field type instead of being stored as the stricter subtype.
Root cause
Pydantic v2 URL equality is type-strict. A stored AnyHttpUrl("https://example.com/callback") and an incoming AnyUrl("https://example.com/callback") serialize to the same string, but compare non-equal. That makes validate_redirect_uri() reject a registered redirect URI during OAuth flows.
Changes
- Added a
redirect_urisfield validator that stringifies existingAnyUrlinstances before Pydantic validates the field. - Added regression coverage for
OAuthClientInformationFull(redirect_uris=[AnyHttpUrl(...)])validating an incoming equivalentAnyUrl(...). - Kept JSON serialization unchanged and still reject unrelated redirect URIs.
Validation
uv run pytest tests/shared/test_auth.py::test_redirect_uri_subtypes_normalized_for_validation -qfailed before the fix withInvalidRedirectUriError.uv run ruff format --check src/mcp/shared/auth.py tests/shared/test_auth.pyuv run ruff check src/mcp/shared/auth.py tests/shared/test_auth.pyuv run pytest tests/shared/test_auth.py tests/client/test_auth.py tests/interaction/auth/test_authorize_token.py -q-> 155 passed, 1 xfailedgit diff --check