@@ -824,11 +824,10 @@ async def handle_sse(scope: Scope, receive: Receive, send: Send):
824
824
# Determine resource metadata URL
825
825
resource_metadata_url = None
826
826
if self .settings .auth and self .settings .auth .resource_server_url :
827
- from pydantic import AnyHttpUrl
827
+ from mcp . server . auth . routes import build_resource_metadata_url
828
828
829
- resource_metadata_url = AnyHttpUrl (
830
- str (self .settings .auth .resource_server_url ).rstrip ("/" ) + "/.well-known/oauth-protected-resource"
831
- )
829
+ # Build compliant metadata URL for WWW-Authenticate header
830
+ resource_metadata_url = build_resource_metadata_url (self .settings .auth .resource_server_url )
832
831
833
832
# Auth is enabled, wrap the endpoints with RequireAuthMiddleware
834
833
routes .append (
@@ -937,18 +936,10 @@ def streamable_http_app(self) -> Starlette:
937
936
# Determine resource metadata URL
938
937
resource_metadata_url = None
939
938
if self .settings .auth and self .settings .auth .resource_server_url :
940
- from urllib .parse import urlparse
941
-
942
- from pydantic import AnyHttpUrl
939
+ from mcp .server .auth .routes import build_resource_metadata_url
943
940
944
- # RFC 9728 §3.1: Insert /.well-known/oauth-protected-resource between host and resource path
945
- # This URL will be used in WWW-Authenticate header for client discovery
946
- parsed = urlparse (str (self .settings .auth .resource_server_url ))
947
- # Handle trailing slash: if path is just "/", treat as empty
948
- resource_path = parsed .path if parsed .path != "/" else ""
949
- resource_metadata_url = AnyHttpUrl (
950
- f"{ parsed .scheme } ://{ parsed .netloc } /.well-known/oauth-protected-resource{ resource_path } "
951
- )
941
+ # Build compliant metadata URL for WWW-Authenticate header
942
+ resource_metadata_url = build_resource_metadata_url (self .settings .auth .resource_server_url )
952
943
953
944
routes .append (
954
945
Route (
@@ -967,32 +958,13 @@ def streamable_http_app(self) -> Starlette:
967
958
968
959
# Add protected resource metadata endpoint if configured as RS
969
960
if self .settings .auth and self .settings .auth .resource_server_url :
970
- from urllib .parse import urlparse
971
-
972
- from mcp .server .auth .handlers .metadata import ProtectedResourceMetadataHandler
973
- from mcp .server .auth .routes import cors_middleware
974
- from mcp .shared .auth import ProtectedResourceMetadata
975
-
976
- protected_resource_metadata = ProtectedResourceMetadata (
977
- resource = self .settings .auth .resource_server_url ,
978
- authorization_servers = [self .settings .auth .issuer_url ],
979
- scopes_supported = self .settings .auth .required_scopes ,
980
- )
981
-
982
- # RFC 9728 §3.1: Register route at /.well-known/oauth-protected-resource + resource path
983
- parsed = urlparse (str (self .settings .auth .resource_server_url ))
984
- # Handle trailing slash: if path is just "/", treat as empty
985
- resource_path = parsed .path if parsed .path != "/" else ""
986
- well_known_path = f"/.well-known/oauth-protected-resource{ resource_path } "
961
+ from mcp .server .auth .routes import create_protected_resource_routes
987
962
988
- routes .append (
989
- Route (
990
- well_known_path ,
991
- endpoint = cors_middleware (
992
- ProtectedResourceMetadataHandler (protected_resource_metadata ).handle ,
993
- ["GET" , "OPTIONS" ],
994
- ),
995
- methods = ["GET" , "OPTIONS" ],
963
+ routes .extend (
964
+ create_protected_resource_routes (
965
+ resource_url = self .settings .auth .resource_server_url ,
966
+ authorization_servers = [self .settings .auth .issuer_url ],
967
+ scopes_supported = self .settings .auth .required_scopes ,
996
968
)
997
969
)
998
970
0 commit comments