From 1c9f51b26ba5f712ec3f9f3ff92f42351c2c7e72 Mon Sep 17 00:00:00 2001 From: RoyVivat Date: Fri, 3 Apr 2026 15:33:18 -0700 Subject: [PATCH] fix: add user_api_key_auth to MCP health route; add HEAD test --- litellm/proxy/proxy_server.py | 6 +++- .../mcp_server/test_mcp_health_route.py | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 1926bb9bf15..6e79a0289c1 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -13401,7 +13401,11 @@ async def dynamic_mcp_route(mcp_server_name: str, request: Request): "/{mcp_server_name}/health", methods=["GET", "HEAD"], ) -async def dynamic_mcp_health_route(mcp_server_name: str, request: Request): +async def dynamic_mcp_health_route( + mcp_server_name: str, + request: Request, + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +): """Handle health check passthrough for MCP servers like /github_mcp/health""" from litellm.proxy._experimental.mcp_server.mcp_server_manager import ( global_mcp_server_manager, diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_health_route.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_health_route.py index f5d163b5a71..4e7b998b0c3 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_health_route.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_health_route.py @@ -188,6 +188,38 @@ class TestDynamicMcpHealthRoute: assert exc_info.value.status_code == 502 assert "connection refused" in exc_info.value.detail + @pytest.mark.asyncio + async def test_health_route_head_method(self): + """HEAD requests are forwarded; response body should be empty.""" + try: + from litellm.proxy.proxy_server import dynamic_mcp_health_route + except ImportError: + pytest.skip("proxy_server not available") + + mcp_server = _make_server() + if mcp_server is None: + pytest.skip("MCP types not available") + + upstream_response = MagicMock() + upstream_response.content = b"" + upstream_response.status_code = 200 + upstream_response.headers = {"content-type": "application/json"} + + mock_http_client = AsyncMock() + mock_http_client.get = AsyncMock(return_value=upstream_response) + + with ( + patch(_MCP_MANAGER_PATH) as mock_manager, + patch(_IP_UTILS_PATH) as mock_ip_utils, + patch(_HTTP_CLIENT_PATH, return_value=mock_http_client), + ): + mock_ip_utils.get_mcp_client_ip.return_value = "127.0.0.1" + mock_manager.get_mcp_server_by_name.return_value = mcp_server + + response = await dynamic_mcp_health_route("my_mcp", _make_request()) + + assert response.status_code == 200 + @pytest.mark.asyncio async def test_health_route_forwards_upstream_status_code(self): """Non-200 status codes from the upstream server are forwarded as-is."""