Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-mcp for openSUSE:Factory checked in at 2026-05-30 22:57:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-mcp (Old) and /work/SRC/openSUSE:Factory/.python-mcp.new.1937 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-mcp" Sat May 30 22:57:25 2026 rev:3 rq:1355963 version:1.27.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-mcp/python-mcp.changes 2026-04-17 20:54:15.173050151 +0200 +++ /work/SRC/openSUSE:Factory/.python-mcp.new.1937/python-mcp.changes 2026-05-30 23:00:00.452883361 +0200 @@ -1,0 +2,11 @@ +Fri May 29 16:58:45 UTC 2026 - Matej Cepl <[email protected]> + +- Update to 1.27.1: + - fix: catch PydanticUserError when generating output schema + (pydantic 2.13 compat) + - fix(auth): coerce empty-string optional URL fields to None in + OAuthClientMetadata + - build: restrict httpx to <1.0.0 + - refactor: import SSEError from httpx_sse public API + +------------------------------------------------------------------- Old: ---- mcp-1.27.0.tar.gz New: ---- mcp-1.27.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-mcp.spec ++++++ --- /var/tmp/diff_new_pack.6fW0lo/_old 2026-05-30 23:00:01.332919537 +0200 +++ /var/tmp/diff_new_pack.6fW0lo/_new 2026-05-30 23:00:01.332919537 +0200 @@ -26,7 +26,7 @@ %bcond_without libalternatives %{?sle15_python_module_pythons} Name: python-mcp%{psuffix} -Version: 1.27.0 +Version: 1.27.1 Release: 0 Summary: Python implementation of the Model Context Protocol License: MIT ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.6fW0lo/_old 2026-05-30 23:00:01.384921675 +0200 +++ /var/tmp/diff_new_pack.6fW0lo/_new 2026-05-30 23:00:01.388921839 +0200 @@ -1,5 +1,5 @@ -mtime: 1776178632 -commit: 6c52a8ad445a1d4865134bf7705797bd4ed8b0c4b0b229847f357e906a96e39a -url: https://src.opensuse.org/AI_MCP/python-mcp +mtime: 1780075977 +commit: b88951a85a4cfa4ebde098ef887234aa6a0fd8965abdb1d3090c2e73630d2903 +url: https://src.opensuse.org/AI/python-mcp revision: main ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-05-29 19:32:57.000000000 +0200 @@ -0,0 +1,6 @@ +_build.* +*.obscpio +*.osc +.pbuild +_service:* +python-mcp-*-build/ ++++++ mcp-1.27.0.tar.gz -> mcp-1.27.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mcp-1.27.0/PKG-INFO new/mcp-1.27.1/PKG-INFO --- old/mcp-1.27.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 +++ new/mcp-1.27.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: mcp -Version: 1.27.0 +Version: 1.27.1 Summary: Model Context Protocol SDK Project-URL: Homepage, https://modelcontextprotocol.io Project-URL: Repository, https://github.com/modelcontextprotocol/python-sdk @@ -21,7 +21,7 @@ Requires-Python: >=3.10 Requires-Dist: anyio>=4.5 Requires-Dist: httpx-sse>=0.4 -Requires-Dist: httpx>=0.27.1 +Requires-Dist: httpx<1.0.0,>=0.27.1 Requires-Dist: jsonschema>=4.20.0 Requires-Dist: pydantic-settings>=2.5.2 Requires-Dist: pydantic<3.0.0,>=2.11.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mcp-1.27.0/pyproject.toml new/mcp-1.27.1/pyproject.toml --- old/mcp-1.27.0/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 +++ new/mcp-1.27.1/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 @@ -23,7 +23,7 @@ ] dependencies = [ "anyio>=4.5", - "httpx>=0.27.1", + "httpx>=0.27.1,<1.0.0", "httpx-sse>=0.4", "pydantic>=2.11.0,<3.0.0", "starlette>=0.27", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mcp-1.27.0/src/mcp/client/sse.py new/mcp-1.27.1/src/mcp/client/sse.py --- old/mcp-1.27.0/src/mcp/client/sse.py 2020-02-02 01:00:00.000000000 +0100 +++ new/mcp-1.27.1/src/mcp/client/sse.py 2020-02-02 01:00:00.000000000 +0100 @@ -8,8 +8,7 @@ import httpx from anyio.abc import TaskStatus from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream -from httpx_sse import aconnect_sse -from httpx_sse._exceptions import SSEError +from httpx_sse import SSEError, aconnect_sse import mcp.types as types from mcp.shared._httpx_utils import McpHttpClientFactory, create_mcp_http_client diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mcp-1.27.0/src/mcp/server/fastmcp/utilities/func_metadata.py new/mcp-1.27.1/src/mcp/server/fastmcp/utilities/func_metadata.py --- old/mcp-1.27.0/src/mcp/server/fastmcp/utilities/func_metadata.py 2020-02-02 01:00:00.000000000 +0100 +++ new/mcp-1.27.1/src/mcp/server/fastmcp/utilities/func_metadata.py 2020-02-02 01:00:00.000000000 +0100 @@ -10,6 +10,7 @@ BaseModel, ConfigDict, Field, + PydanticUserError, RootModel, WithJsonSchema, create_model, @@ -411,9 +412,16 @@ # Use StrictJsonSchema to raise exceptions instead of warnings try: schema = model.model_json_schema(schema_generator=StrictJsonSchema) - except (TypeError, ValueError, pydantic_core.SchemaError, pydantic_core.ValidationError) as e: + except ( + PydanticUserError, + TypeError, + ValueError, + pydantic_core.SchemaError, + pydantic_core.ValidationError, + ) as e: # These are expected errors when a type can't be converted to a Pydantic schema - # TypeError: When Pydantic can't handle the type + # PydanticUserError: When Pydantic can't handle the type (e.g. PydanticInvalidForJsonSchema); + # subclasses TypeError on pydantic <2.13 and RuntimeError on pydantic >=2.13 # ValueError: When there are issues with the type definition (including our custom warnings) # SchemaError: When Pydantic can't build a schema # ValidationError: When validation fails diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mcp-1.27.0/src/mcp/shared/auth.py new/mcp-1.27.1/src/mcp/shared/auth.py --- old/mcp-1.27.0/src/mcp/shared/auth.py 2020-02-02 01:00:00.000000000 +0100 +++ new/mcp-1.27.1/src/mcp/shared/auth.py 2020-02-02 01:00:00.000000000 +0100 @@ -71,6 +71,24 @@ software_id: str | None = None software_version: str | None = None + @field_validator( + "client_uri", + "logo_uri", + "tos_uri", + "policy_uri", + "jwks_uri", + mode="before", + ) + @classmethod + def _empty_string_optional_url_to_none(cls, v: object) -> object: + # RFC 7591 §2 marks these URL fields OPTIONAL. Some authorization servers + # echo omitted metadata back as "" instead of dropping the keys, which + # AnyHttpUrl would otherwise reject — throwing away an otherwise valid + # registration response. Treat "" as absent. + if v == "": + return None + return v + def validate_scope(self, requested_scope: str | None) -> list[str] | None: if requested_scope is None: return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mcp-1.27.0/tests/shared/test_auth.py new/mcp-1.27.1/tests/shared/test_auth.py --- old/mcp-1.27.0/tests/shared/test_auth.py 2020-02-02 01:00:00.000000000 +0100 +++ new/mcp-1.27.1/tests/shared/test_auth.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,9 @@ """Tests for OAuth 2.0 shared code.""" -from mcp.shared.auth import OAuthMetadata +import pytest +from pydantic import ValidationError + +from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthMetadata class TestOAuthMetadata: @@ -59,3 +62,80 @@ "token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"], } ) + + +# RFC 7591 §2 marks client_uri/logo_uri/tos_uri/policy_uri/jwks_uri as OPTIONAL. +# Some authorization servers echo the client's omitted metadata back as "" +# instead of dropping the keys; without coercion, AnyHttpUrl rejects "" and +# the whole registration response is thrown away even though the server +# returned a valid client_id. + + [email protected]( + "empty_field", + ["client_uri", "logo_uri", "tos_uri", "policy_uri", "jwks_uri"], +) +def test_optional_url_empty_string_coerced_to_none(empty_field: str): + data = { + "redirect_uris": ["https://example.com/callback"], + empty_field: "", + } + metadata = OAuthClientMetadata.model_validate(data) + assert getattr(metadata, empty_field) is None + + +def test_all_optional_urls_empty_together(): + data = { + "redirect_uris": ["https://example.com/callback"], + "client_uri": "", + "logo_uri": "", + "tos_uri": "", + "policy_uri": "", + "jwks_uri": "", + } + metadata = OAuthClientMetadata.model_validate(data) + assert metadata.client_uri is None + assert metadata.logo_uri is None + assert metadata.tos_uri is None + assert metadata.policy_uri is None + assert metadata.jwks_uri is None + + +def test_valid_url_passes_through_unchanged(): + data = { + "redirect_uris": ["https://example.com/callback"], + "client_uri": "https://udemy.com/", + } + metadata = OAuthClientMetadata.model_validate(data) + assert str(metadata.client_uri) == "https://udemy.com/" + + +def test_information_full_inherits_coercion(): + """OAuthClientInformationFull subclasses OAuthClientMetadata, so the + same coercion applies to DCR responses parsed via the full model.""" + data = { + "client_id": "abc123", + "redirect_uris": ["https://example.com/callback"], + "client_uri": "", + "logo_uri": "", + "tos_uri": "", + "policy_uri": "", + "jwks_uri": "", + } + info = OAuthClientInformationFull.model_validate(data) + assert info.client_id == "abc123" + assert info.client_uri is None + assert info.logo_uri is None + assert info.tos_uri is None + assert info.policy_uri is None + assert info.jwks_uri is None + + +def test_invalid_non_empty_url_still_rejected(): + """Coercion must only touch empty strings — garbage URLs still raise.""" + data = { + "redirect_uris": ["https://example.com/callback"], + "client_uri": "not a url", + } + with pytest.raises(ValidationError): + OAuthClientMetadata.model_validate(data) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mcp-1.27.0/uv.lock new/mcp-1.27.1/uv.lock --- old/mcp-1.27.0/uv.lock 2020-02-02 01:00:00.000000000 +0100 +++ new/mcp-1.27.1/uv.lock 2020-02-02 01:00:00.000000000 +0100 @@ -819,7 +819,7 @@ [package.metadata] requires-dist = [ { name = "anyio", specifier = ">=4.5" }, - { name = "httpx", specifier = ">=0.27.1" }, + { name = "httpx", specifier = ">=0.27.1,<1.0.0" }, { name = "httpx-sse", specifier = ">=0.4" }, { name = "jsonschema", specifier = ">=4.20.0" }, { name = "pydantic", specifier = ">=2.11.0,<3.0.0" },
