diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index 3282baae6..e1a1e85f0 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -790,6 +790,12 @@ async def handle_streamable_http( middleware: list[Middleware] = [] required_scopes = [] + # Always mount both /mcp and /mcp/ for full compatibility, regardless of default + # Verify that _main_path has root format -> /mcp + _main_path = self.settings.streamable_http_path.removesuffix("/") + # Format _alt_path so it ends with '/' -> /mcp/ + _alt_path = _main_path + "/" + # Add auth endpoints if auth provider is configured if self._auth_server_provider: assert self.settings.auth @@ -815,19 +821,27 @@ async def handle_streamable_http( revocation_options=self.settings.auth.revocation_options, ) ) - routes.append( + routes.extend([ Mount( - self.settings.streamable_http_path, + _main_path, app=RequireAuthMiddleware(handle_streamable_http, required_scopes), - ) + ), + Mount( + _alt_path, + app=RequireAuthMiddleware(handle_streamable_http, required_scopes), + )] ) else: # Auth is disabled, no wrapper needed - routes.append( + routes.extend([ Mount( - self.settings.streamable_http_path, + _main_path, app=handle_streamable_http, - ) + ), + Mount( + _alt_path, + app=handle_streamable_http, + )] ) routes.extend(self._custom_starlette_routes) @@ -1051,4 +1065,4 @@ async def warning(self, message: str, **extra: Any) -> None: async def error(self, message: str, **extra: Any) -> None: """Send an error log message.""" - await self.log("error", message, **extra) + await self.log("error", message, **extra) \ No newline at end of file