mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix(mcp): handle integer progressToken in host progress capture
Per the MCP spec, ProgressToken is `str | int`. The host progress
capture path logged the token with `f"...{host_token[:8]}..."`, which
raises `TypeError: 'int' object is not subscriptable` when a client
sends an integer progress token. The exception was swallowed by the
surrounding try/except and surfaced as a misleading "Could not capture
host progress context: 'int' object is not subscriptable" warning on
every such tool call.
The f-string is built eagerly regardless of log level, so the error
fired even with debug logging off. The progress callback itself is
assigned before the failing log line, so progress forwarding still
worked; the only effect was log noise.
Wrap the token in str() before slicing so both str and int tokens
format safely.
This commit is contained in:
parent
69b0dd2da0
commit
cb7309c891
2 changed files with 55 additions and 1 deletions
|
|
@ -714,7 +714,7 @@ if MCP_AVAILABLE:
|
|||
|
||||
host_progress_callback = forward_progress
|
||||
verbose_logger.debug(
|
||||
f"Host progressToken captured: {host_token[:8]}..."
|
||||
f"Host progressToken captured: {str(host_token)[:8]}..."
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Could not capture host progress context: {e}")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import asyncio
|
||||
import contextvars
|
||||
from datetime import datetime, timedelta
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
|
@ -110,6 +111,59 @@ async def test_mcp_server_tool_call_body_contains_request_data():
|
|||
assert body["arguments"] == tool_arguments
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mcp_server_tool_call_handles_integer_progress_token():
|
||||
"""An integer progressToken must not break host progress capture.
|
||||
|
||||
Per the MCP spec ``ProgressToken = str | int``. A client sending an integer
|
||||
token previously tripped ``f"...{host_token[:8]}..."`` with
|
||||
``TypeError: 'int' object is not subscriptable``, which got swallowed into a
|
||||
misleading "Could not capture host progress context" warning on every such
|
||||
tool call. Regression test: that warning must not be emitted.
|
||||
"""
|
||||
try:
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
|
||||
from litellm.proxy._experimental.mcp_server.server import (
|
||||
mcp_server_tool_call,
|
||||
set_auth_context,
|
||||
)
|
||||
except ImportError:
|
||||
pytest.skip("MCP server not available")
|
||||
|
||||
set_auth_context(UserAPIKeyAuth(api_key="test_key", user_id="test_user"))
|
||||
|
||||
# Drive the real request context the proxy reads, with an int progressToken
|
||||
# (e.g. a client SDK that uses an incrementing counter).
|
||||
host_ctx = SimpleNamespace(
|
||||
meta=SimpleNamespace(progressToken=12345),
|
||||
session=MagicMock(send_progress_notification=AsyncMock()),
|
||||
)
|
||||
ctx_token = request_ctx.set(host_ctx)
|
||||
try:
|
||||
with patch(
|
||||
"litellm.proxy._experimental.mcp_server.server.verbose_logger"
|
||||
) as mock_logger:
|
||||
try:
|
||||
await mcp_server_tool_call("test_tool", {"param": "value"})
|
||||
except Exception:
|
||||
# Downstream tool dispatch is out of scope; we only assert that
|
||||
# capturing the host progress context did not warn.
|
||||
pass
|
||||
finally:
|
||||
request_ctx.reset(ctx_token)
|
||||
|
||||
progress_warnings = [
|
||||
call
|
||||
for call in mock_logger.warning.call_args_list
|
||||
if "Could not capture host progress context" in str(call)
|
||||
]
|
||||
assert not progress_warnings, (
|
||||
"integer progressToken should be handled gracefully, "
|
||||
f"got warning(s): {progress_warnings}"
|
||||
)
|
||||
|
||||
|
||||
def test_prepare_mcp_server_headers_case_insensitive_extra_headers():
|
||||
try:
|
||||
from litellm.proxy._experimental.mcp_server.server import (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue