From f2d2789955a814eafe5e975e17fd9d79cabcfdae Mon Sep 17 00:00:00 2001 From: martimfasantos Date: Wed, 4 Feb 2026 12:21:55 +0000 Subject: [PATCH 1/4] add client_id_metadata_document_supported flag --- src/mcp/server/auth/routes.py | 3 +++ src/mcp/server/auth/settings.py | 1 + tests/client/test_auth.py | 1 + .../mcpserver/auth/test_auth_integration.py | 27 +++++++++++++++++++ 4 files changed, 32 insertions(+) diff --git a/src/mcp/server/auth/routes.py b/src/mcp/server/auth/routes.py index 08f735f36..80ff42ea3 100644 --- a/src/mcp/server/auth/routes.py +++ b/src/mcp/server/auth/routes.py @@ -172,6 +172,9 @@ def build_metadata( op_tos_uri=None, introspection_endpoint=None, code_challenge_methods_supported=["S256"], + client_id_metadata_document_supported=( + client_registration_options.client_id_metadata_document_supported + ), ) # Add registration endpoint if supported diff --git a/src/mcp/server/auth/settings.py b/src/mcp/server/auth/settings.py index 1649826db..ec8017561 100644 --- a/src/mcp/server/auth/settings.py +++ b/src/mcp/server/auth/settings.py @@ -6,6 +6,7 @@ class ClientRegistrationOptions(BaseModel): client_secret_expiry_seconds: int | None = None valid_scopes: list[str] | None = None default_scopes: list[str] | None = None + client_id_metadata_document_supported: bool = False class RevocationOptions(BaseModel): diff --git a/tests/client/test_auth.py b/tests/client/test_auth.py index 7ad24f2df..e124affbe 100644 --- a/tests/client/test_auth.py +++ b/tests/client/test_auth.py @@ -1352,6 +1352,7 @@ def test_build_metadata( "revocation_endpoint": Is(revocation_endpoint), "revocation_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], "code_challenge_methods_supported": ["S256"], + "client_id_metadata_document_supported": Is(bool) } ) diff --git a/tests/server/mcpserver/auth/test_auth_integration.py b/tests/server/mcpserver/auth/test_auth_integration.py index a78a86cf0..e30f67e55 100644 --- a/tests/server/mcpserver/auth/test_auth_integration.py +++ b/tests/server/mcpserver/auth/test_auth_integration.py @@ -303,6 +303,32 @@ async def auth_code( class TestAuthEndpoints: + @pytest.mark.anyio + async def test_metadata_endpoint_with_client_id_metadata_document_supported(self): + """Test metadata endpoint when client_id_metadata_document_supported is enabled.""" + mock_provider = MockOAuthProvider() + auth_routes = create_auth_routes( + mock_provider, + AnyHttpUrl("https://auth.example.com"), + AnyHttpUrl("https://docs.example.com"), + client_registration_options=ClientRegistrationOptions( + enabled=True, + valid_scopes=["read", "write"], + client_id_metadata_document_supported=True, + ), + revocation_options=RevocationOptions(enabled=True), + ) + app = Starlette(routes=auth_routes) + + async with httpx.AsyncClient( + transport=httpx.ASGITransport(app=app), base_url="https://mcptest.com" + ) as client: + response = await client.get("/.well-known/oauth-authorization-server") + assert response.status_code == 200 + + metadata = response.json() + assert metadata["client_id_metadata_document_supported"] is True + @pytest.mark.anyio async def test_metadata_endpoint(self, test_client: httpx.AsyncClient): """Test the OAuth 2.0 metadata endpoint.""" @@ -318,6 +344,7 @@ async def test_metadata_endpoint(self, test_client: httpx.AsyncClient): assert metadata["revocation_endpoint"] == "https://auth.example.com/revoke" assert metadata["response_types_supported"] == ["code"] assert metadata["code_challenge_methods_supported"] == ["S256"] + assert metadata["client_id_metadata_document_supported"] is False assert metadata["token_endpoint_auth_methods_supported"] == ["client_secret_post", "client_secret_basic"] assert metadata["grant_types_supported"] == [ "authorization_code", From 50b133688d13d3ae83cf18354d7ed48f5f028ec9 Mon Sep 17 00:00:00 2001 From: martimfasantos Date: Wed, 4 Feb 2026 12:42:01 +0000 Subject: [PATCH 2/4] fix: remove unnecessary test --- .../mcpserver/auth/test_auth_integration.py | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/tests/server/mcpserver/auth/test_auth_integration.py b/tests/server/mcpserver/auth/test_auth_integration.py index e30f67e55..074603157 100644 --- a/tests/server/mcpserver/auth/test_auth_integration.py +++ b/tests/server/mcpserver/auth/test_auth_integration.py @@ -303,32 +303,6 @@ async def auth_code( class TestAuthEndpoints: - @pytest.mark.anyio - async def test_metadata_endpoint_with_client_id_metadata_document_supported(self): - """Test metadata endpoint when client_id_metadata_document_supported is enabled.""" - mock_provider = MockOAuthProvider() - auth_routes = create_auth_routes( - mock_provider, - AnyHttpUrl("https://auth.example.com"), - AnyHttpUrl("https://docs.example.com"), - client_registration_options=ClientRegistrationOptions( - enabled=True, - valid_scopes=["read", "write"], - client_id_metadata_document_supported=True, - ), - revocation_options=RevocationOptions(enabled=True), - ) - app = Starlette(routes=auth_routes) - - async with httpx.AsyncClient( - transport=httpx.ASGITransport(app=app), base_url="https://mcptest.com" - ) as client: - response = await client.get("/.well-known/oauth-authorization-server") - assert response.status_code == 200 - - metadata = response.json() - assert metadata["client_id_metadata_document_supported"] is True - @pytest.mark.anyio async def test_metadata_endpoint(self, test_client: httpx.AsyncClient): """Test the OAuth 2.0 metadata endpoint.""" From fb70e28154f2a5deeb7aa7404082c7b1129692d8 Mon Sep 17 00:00:00 2001 From: martimfasantos Date: Wed, 4 Feb 2026 12:44:12 +0000 Subject: [PATCH 3/4] fix: linting --- src/mcp/server/auth/routes.py | 4 +--- tests/client/test_auth.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mcp/server/auth/routes.py b/src/mcp/server/auth/routes.py index 80ff42ea3..4ef15eb86 100644 --- a/src/mcp/server/auth/routes.py +++ b/src/mcp/server/auth/routes.py @@ -172,9 +172,7 @@ def build_metadata( op_tos_uri=None, introspection_endpoint=None, code_challenge_methods_supported=["S256"], - client_id_metadata_document_supported=( - client_registration_options.client_id_metadata_document_supported - ), + client_id_metadata_document_supported=client_registration_options.client_id_metadata_document_supported, ) # Add registration endpoint if supported diff --git a/tests/client/test_auth.py b/tests/client/test_auth.py index e124affbe..e096a4a10 100644 --- a/tests/client/test_auth.py +++ b/tests/client/test_auth.py @@ -1352,7 +1352,7 @@ def test_build_metadata( "revocation_endpoint": Is(revocation_endpoint), "revocation_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], "code_challenge_methods_supported": ["S256"], - "client_id_metadata_document_supported": Is(bool) + "client_id_metadata_document_supported": Is(bool), } ) From 17e3fe4a65584078a7004c170be694b211d91df4 Mon Sep 17 00:00:00 2001 From: martimfasantos Date: Wed, 4 Feb 2026 12:49:12 +0000 Subject: [PATCH 4/4] fix: tests --- tests/client/test_auth.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/client/test_auth.py b/tests/client/test_auth.py index e096a4a10..fc1d63a4a 100644 --- a/tests/client/test_auth.py +++ b/tests/client/test_auth.py @@ -1352,7 +1352,33 @@ def test_build_metadata( "revocation_endpoint": Is(revocation_endpoint), "revocation_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], "code_challenge_methods_supported": ["S256"], - "client_id_metadata_document_supported": Is(bool), + "client_id_metadata_document_supported": Is(False), + } + ) + + metadata = build_metadata( + issuer_url=AnyHttpUrl(issuer_url), + service_documentation_url=AnyHttpUrl(service_documentation_url), + client_registration_options=ClientRegistrationOptions( + enabled=True, valid_scopes=["read", "write", "admin"], client_id_metadata_document_supported=True + ), + revocation_options=RevocationOptions(enabled=True), + ) + + assert metadata.model_dump(exclude_defaults=True, mode="json") == snapshot( + { + "issuer": Is(issuer_url), + "authorization_endpoint": Is(authorization_endpoint), + "token_endpoint": Is(token_endpoint), + "registration_endpoint": Is(registration_endpoint), + "scopes_supported": ["read", "write", "admin"], + "grant_types_supported": ["authorization_code", "refresh_token"], + "token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], + "service_documentation": Is(service_documentation_url), + "revocation_endpoint": Is(revocation_endpoint), + "revocation_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], + "code_challenge_methods_supported": ["S256"], + "client_id_metadata_document_supported": Is(True), } )