mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
Refactor MCPServerManager to raise HTTPException for extra headers in OpenAPI-backed servers. Update tests to reflect this change, ensuring proper exception handling instead of logging warnings.
This commit is contained in:
parent
94da7e688a
commit
4af352aac8
2 changed files with 33 additions and 44 deletions
|
|
@ -2251,15 +2251,19 @@ class MCPServerManager:
|
|||
# For OpenAPI servers, call the tool handler directly instead of via MCP client
|
||||
if mcp_server.spec_path:
|
||||
verbose_logger.debug(
|
||||
f"Calling OpenAPI tool {name} directly via HTTP handler"
|
||||
"Calling OpenAPI tool %s directly via HTTP handler", name
|
||||
)
|
||||
if hook_result.get("extra_headers"):
|
||||
verbose_logger.warning(
|
||||
"pre_mcp_call hook returned extra_headers, but OpenAPI-backed "
|
||||
"MCP servers do not support hook header injection. "
|
||||
f"Headers will be dropped for tool '{name}' on server "
|
||||
f"'{server_name}'. Use a regular MCP server (SSE/HTTP transport) "
|
||||
"for hook header support."
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -6,15 +6,12 @@ Validates that:
|
|||
2. pre_call_tool_check returns hook-provided extra_headers AND modified arguments
|
||||
3. call_tool flows hook headers and modified arguments downstream
|
||||
4. Hook-provided headers take highest priority (merge after static_headers)
|
||||
5. OpenAPI-backed servers emit a warning when hook headers are present
|
||||
5. OpenAPI-backed servers raise HTTPException when hook headers are present
|
||||
6. JWT claims are propagated in both standard and virtual-key fast paths
|
||||
7. Backward compatibility: hooks without extra_headers continue to work
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
|
|
@ -425,8 +422,8 @@ class TestCallToolFlowsHookHeaders:
|
|||
assert call_kwargs.kwargs.get("arguments") == modified_args
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_openapi_server_warns_on_hook_headers(self, caplog):
|
||||
"""OpenAPI-backed servers should log a warning when hook injects headers."""
|
||||
async def test_openapi_server_raises_on_hook_headers(self):
|
||||
"""OpenAPI-backed servers should raise HTTPException when hook injects headers."""
|
||||
manager = MCPServerManager()
|
||||
server = MCPServer(
|
||||
server_id="test-id",
|
||||
|
|
@ -452,30 +449,24 @@ class TestCallToolFlowsHookHeaders:
|
|||
"_create_during_hook_task",
|
||||
return_value=asyncio.create_task(asyncio.sleep(0)),
|
||||
):
|
||||
with patch.object(
|
||||
manager,
|
||||
"_call_openapi_tool_handler",
|
||||
new_callable=AsyncMock,
|
||||
return_value=MagicMock(),
|
||||
):
|
||||
proxy_logging = MagicMock(spec=ProxyLogging)
|
||||
proxy_logging = MagicMock(spec=ProxyLogging)
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
await manager.call_tool(
|
||||
server_name="openapi_server",
|
||||
name="test_tool",
|
||||
arguments={},
|
||||
proxy_logging_obj=proxy_logging,
|
||||
)
|
||||
|
||||
assert any(
|
||||
"do not support hook header injection" in record.message
|
||||
for record in caplog.records
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await manager.call_tool(
|
||||
server_name="openapi_server",
|
||||
name="test_tool",
|
||||
arguments={},
|
||||
proxy_logging_obj=proxy_logging,
|
||||
)
|
||||
|
||||
assert exc_info.value.status_code == 500
|
||||
assert "does not support hook header injection" in str(
|
||||
exc_info.value.detail
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_openapi_server_no_warning_without_hook_headers(self, caplog):
|
||||
"""No warning when OpenAPI server has no hook-injected headers."""
|
||||
async def test_openapi_server_no_error_without_hook_headers(self):
|
||||
"""No exception when OpenAPI server has no hook-injected headers."""
|
||||
manager = MCPServerManager()
|
||||
server = MCPServer(
|
||||
server_id="test-id",
|
||||
|
|
@ -509,17 +500,11 @@ class TestCallToolFlowsHookHeaders:
|
|||
):
|
||||
proxy_logging = MagicMock(spec=ProxyLogging)
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
await manager.call_tool(
|
||||
server_name="openapi_server",
|
||||
name="test_tool",
|
||||
arguments={},
|
||||
proxy_logging_obj=proxy_logging,
|
||||
)
|
||||
|
||||
assert not any(
|
||||
"do not support hook header injection" in record.message
|
||||
for record in caplog.records
|
||||
await manager.call_tool(
|
||||
server_name="openapi_server",
|
||||
name="test_tool",
|
||||
arguments={},
|
||||
proxy_logging_obj=proxy_logging,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue