Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/mcp/server/lowlevel/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ async def main():

import anyio
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
from pydantic import AnyHttpUrl
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.authentication import AuthenticationMiddleware
Expand Down Expand Up @@ -595,8 +596,11 @@ def streamable_http_app(
# Determine resource metadata URL
resource_metadata_url = None
if auth and auth.resource_server_url:
# The protected resource URL must include the transport path
# (e.g. http://localhost:8000/mcp) per RFC 9728
actual_resource_url = AnyHttpUrl(str(auth.resource_server_url).rstrip("/") + streamable_http_path)
# Build compliant metadata URL for WWW-Authenticate header
resource_metadata_url = build_resource_metadata_url(auth.resource_server_url)
resource_metadata_url = build_resource_metadata_url(actual_resource_url)

routes.append(
Route(
Expand All @@ -615,9 +619,10 @@ def streamable_http_app(

# Add protected resource metadata endpoint if configured as RS
if auth and auth.resource_server_url: # pragma: no cover
actual_resource_url = AnyHttpUrl(str(auth.resource_server_url).rstrip("/") + streamable_http_path)
routes.extend(
create_protected_resource_routes(
resource_url=auth.resource_server_url,
resource_url=actual_resource_url,
authorization_servers=[auth.issuer_url],
scopes_supported=auth.required_scopes,
)
Expand Down
12 changes: 10 additions & 2 deletions src/mcp/server/mcpserver/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -982,10 +982,15 @@ async def handle_sse(scope: Scope, receive: Receive, send: Send): # pragma: no
# Determine resource metadata URL
resource_metadata_url = None
if self.settings.auth and self.settings.auth.resource_server_url:
from pydantic import AnyHttpUrl

from mcp.server.auth.routes import build_resource_metadata_url

# The protected resource URL must include the transport path
# (e.g. http://localhost:8000/sse) per RFC 9728
actual_resource_url = AnyHttpUrl(str(self.settings.auth.resource_server_url).rstrip("/") + sse_path)
# Build compliant metadata URL for WWW-Authenticate header
resource_metadata_url = build_resource_metadata_url(self.settings.auth.resource_server_url)
resource_metadata_url = build_resource_metadata_url(actual_resource_url)

# Auth is enabled, wrap the endpoints with RequireAuthMiddleware
routes.append(
Expand Down Expand Up @@ -1023,11 +1028,14 @@ async def sse_endpoint(request: Request) -> Response: # pragma: no cover
)
# Add protected resource metadata endpoint if configured as RS
if self.settings.auth and self.settings.auth.resource_server_url: # pragma: no cover
from pydantic import AnyHttpUrl

from mcp.server.auth.routes import create_protected_resource_routes

actual_resource_url = AnyHttpUrl(str(self.settings.auth.resource_server_url).rstrip("/") + sse_path)
routes.extend(
create_protected_resource_routes(
resource_url=self.settings.auth.resource_server_url,
resource_url=actual_resource_url,
authorization_servers=[self.settings.auth.issuer_url],
scopes_supported=self.settings.auth.required_scopes,
)
Expand Down