From 9f443a31aa2558d4048fdce62150d11705194a1b Mon Sep 17 00:00:00 2001 From: Noah Nistler <60981020+noahnistler@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:07:06 -0500 Subject: [PATCH] Update MCPServerManager to raise HTTPException with status code 400 for extra headers in OpenAPI-backed servers. Adjust tests to verify the correct status code and exception message. --- .../mcp_server/mcp_server_manager.py | 29 ++++++++++--------- .../mcp_server/test_mcp_hook_extra_headers.py | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py index 3fa14e6ec25..75f0642b950 100644 --- a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py +++ b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py @@ -2235,6 +2235,21 @@ class MCPServerManager: if "arguments" in hook_result: arguments = hook_result["arguments"] + # OpenAPI-backed servers cannot forward hook-injected headers — reject early + # before scheduling any background tasks to avoid orphaned asyncio.Tasks. + if mcp_server.spec_path and hook_result.get("extra_headers"): + raise HTTPException( + status_code=400, + detail={ + "error": ( + "pre_mcp_call hook returned extra_headers for an " + "OpenAPI-backed MCP server, which does not support " + "hook header injection. Use a regular MCP server " + "(SSE/HTTP transport) for hook header support." + ) + }, + ) + # Prepare tasks for during hooks tasks = [] if proxy_logging_obj: @@ -2251,20 +2266,8 @@ class MCPServerManager: # For OpenAPI servers, call the tool handler directly instead of via MCP client if mcp_server.spec_path: verbose_logger.debug( - "Calling OpenAPI tool %s directly via HTTP handler", name + f"Calling OpenAPI tool {name} directly via HTTP handler" ) - if hook_result.get("extra_headers"): - raise HTTPException( - status_code=500, - detail={ - "error": ( - "pre_mcp_call hook returned extra_headers for an " - "OpenAPI-backed MCP server, which does not support " - "hook header injection. Use a regular MCP server " - "(SSE/HTTP transport) for hook header support." - ) - }, - ) tasks.append( asyncio.create_task( self._call_openapi_tool_handler(mcp_server, name, arguments) diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_hook_extra_headers.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_hook_extra_headers.py index 6c97ff244e8..8362193bb0b 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_hook_extra_headers.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_hook_extra_headers.py @@ -459,7 +459,7 @@ class TestCallToolFlowsHookHeaders: proxy_logging_obj=proxy_logging, ) - assert exc_info.value.status_code == 500 + assert exc_info.value.status_code == 400 assert "does not support hook header injection" in str( exc_info.value.detail )