Skip to content

Commit 7400109

Browse files
committed
Refactor client metadata endpoint
1 parent 6b119d9 commit 7400109

File tree

3 files changed

+25
-43
lines changed

3 files changed

+25
-43
lines changed
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
from dataclasses import dataclass
2-
from typing import Any
32

43
from starlette.requests import Request
5-
from starlette.responses import JSONResponse, Response
4+
from starlette.responses import Response
5+
6+
from mcp.server.auth.json_response import PydanticJSONResponse
7+
from mcp.shared.auth import OAuthMetadata
68

79

810
@dataclass
911
class MetadataHandler:
10-
metadata: dict[str, Any]
12+
metadata: OAuthMetadata
1113

1214
async def handle(self, request: Request) -> Response:
13-
# Remove any None values from metadata
14-
clean_metadata = {k: v for k, v in self.metadata.items() if v is not None}
15-
16-
return JSONResponse(
17-
content=clean_metadata,
15+
return PydanticJSONResponse(
16+
content=self.metadata,
1817
headers={"Cache-Control": "public, max-age=3600"}, # Cache for 1 hour
1918
)

src/mcp/server/auth/router.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from dataclasses import dataclass
2-
from typing import Any
32

43
from pydantic import AnyUrl
54
from starlette.routing import Route, Router
@@ -11,6 +10,7 @@
1110
from mcp.server.auth.handlers.token import TokenHandler
1211
from mcp.server.auth.middleware.client_auth import ClientAuthenticator
1312
from mcp.server.auth.provider import OAuthServerProvider
13+
from mcp.shared.auth import OAuthMetadata
1414

1515

1616
@dataclass
@@ -139,29 +139,29 @@ def build_metadata(
139139
service_documentation_url: AnyUrl | None,
140140
client_registration_options: ClientRegistrationOptions,
141141
revocation_options: RevocationOptions,
142-
) -> dict[str, Any]:
142+
) -> OAuthMetadata:
143143
issuer_url_str = str(issuer_url).rstrip("/")
144144
# Create metadata
145-
metadata = {
146-
"issuer": issuer_url_str,
147-
"service_documentation": str(service_documentation_url).rstrip("/")
145+
metadata = OAuthMetadata(
146+
issuer=issuer_url_str,
147+
service_documentation=str(service_documentation_url).rstrip("/")
148148
if service_documentation_url
149149
else None,
150-
"authorization_endpoint": f"{issuer_url_str}{AUTHORIZATION_PATH}",
151-
"response_types_supported": ["code"],
152-
"code_challenge_methods_supported": ["S256"],
153-
"token_endpoint": f"{issuer_url_str}{TOKEN_PATH}",
154-
"token_endpoint_auth_methods_supported": ["client_secret_post"],
155-
"grant_types_supported": ["authorization_code", "refresh_token"],
156-
}
150+
authorization_endpoint=f"{issuer_url_str}{AUTHORIZATION_PATH}",
151+
response_types_supported=["code"],
152+
code_challenge_methods_supported=["S256"],
153+
token_endpoint=f"{issuer_url_str}{TOKEN_PATH}",
154+
token_endpoint_auth_methods_supported=["client_secret_post"],
155+
grant_types_supported=["authorization_code", "refresh_token"],
156+
)
157157

158158
# Add registration endpoint if supported
159159
if client_registration_options.enabled:
160-
metadata["registration_endpoint"] = f"{issuer_url_str}{REGISTRATION_PATH}"
160+
metadata.registration_endpoint = f"{issuer_url_str}{REGISTRATION_PATH}"
161161

162162
# Add revocation endpoint if supported
163163
if revocation_options.enabled:
164-
metadata["revocation_endpoint"] = f"{issuer_url_str}{REVOCATION_PATH}"
165-
metadata["revocation_endpoint_auth_methods_supported"] = ["client_secret_post"]
164+
metadata.revocation_endpoint = f"{issuer_url_str}{REVOCATION_PATH}"
165+
metadata.revocation_endpoint_auth_methods_supported = ["client_secret_post"]
166166

167167
return metadata

src/mcp/shared/auth.py

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@ class OAuthClientMetadata(BaseModel):
5151
software_version: Optional[str] = None
5252

5353

54-
class OAuthClientInformation(BaseModel):
54+
class OAuthClientInformationFull(OAuthClientMetadata):
5555
"""
56-
RFC 7591 OAuth 2.0 Dynamic Client Registration client information.
56+
RFC 7591 OAuth 2.0 Dynamic Client Registration full response
57+
(client information plus metadata).
5758
"""
5859

5960
client_id: str
@@ -62,24 +63,6 @@ class OAuthClientInformation(BaseModel):
6263
client_secret_expires_at: Optional[int] = None
6364

6465

65-
class OAuthClientInformationFull(OAuthClientMetadata, OAuthClientInformation):
66-
"""
67-
RFC 7591 OAuth 2.0 Dynamic Client Registration full response
68-
(client information plus metadata).
69-
"""
70-
71-
pass
72-
73-
74-
class OAuthClientRegistrationError(BaseModel):
75-
"""
76-
RFC 7591 OAuth 2.0 Dynamic Client Registration error response.
77-
"""
78-
79-
error: str
80-
error_description: Optional[str] = None
81-
82-
8366
class OAuthMetadata(BaseModel):
8467
"""
8568
RFC 8414 OAuth 2.0 Authorization Server Metadata.

0 commit comments

Comments
 (0)