fix(mcp): address review on tool name length exclusion

Skip speculative preview warnings in short-prefix mode when the payload has
no server_id (the 3 char prefix derives from the id assigned at create time)
and label the exclusion warning with the alias when it differs from the
server name so the prefix in the dropped tool name is traceable.
This commit is contained in:
Tin Chi Lo 2026-07-07 09:28:23 -07:00
parent 036d169276
commit c093858a67
3 changed files with 62 additions and 5 deletions

View file

@ -3198,12 +3198,17 @@ class MCPServerManager:
kept, dropped = split_tools_by_name_length(tools, MCP_MAX_TOOL_NAME_LENGTH)
if dropped:
dropped_names = ", ".join(f"{tool.name} ({len(tool.name)} chars)" for tool in dropped)
server_label = (
server.name
if not server.alias or server.alias == server.name
else f"{server.name} (alias {server.alias})"
)
verbose_logger.warning(
"MCP server %s has %d tool(s) whose name exceeds %d characters, which providers such as "
"AWS Bedrock, OpenAI, and Gemini reject. Excluding them from tool listings: %s. "
"Use a shorter server alias, rename the tools on the MCP server, or set "
"LITELLM_MCP_MAX_TOOL_NAME_LENGTH to change the limit.",
server.name,
server_label,
len(dropped),
MCP_MAX_TOOL_NAME_LENGTH,
dropped_names,

View file

@ -26,6 +26,7 @@ from litellm.constants import MCP_MAX_TOOL_NAME_LENGTH
from litellm.proxy._experimental.mcp_server.utils import (
MCPMissingUserEnvVarsError,
get_server_prefix,
is_short_mcp_tool_prefix_enabled,
merge_mcp_headers,
tool_name_length_warnings,
)
@ -1311,10 +1312,17 @@ if MCP_AVAILABLE:
list_tools_response = await client.run_with_session(_list_tools_session_operation)
list_tools_result: List[MCPTool] = list_tools_response.tools
model_dumped_tools: List[dict] = [tool.model_dump() for tool in list_tools_result]
warnings = tool_name_length_warnings(
[tool.name for tool in list_tools_result],
get_server_prefix(new_mcp_server_request),
MCP_MAX_TOOL_NAME_LENGTH,
# In short-prefix mode the 3-char prefix derives from the server_id
# assigned at create time, so without one the final length is
# unknowable; skip speculative warnings (runtime exclusion still warns).
warnings = (
[]
if is_short_mcp_tool_prefix_enabled() and not new_mcp_server_request.server_id
else tool_name_length_warnings(
[tool.name for tool in list_tools_result],
get_server_prefix(new_mcp_server_request),
MCP_MAX_TOOL_NAME_LENGTH,
)
)
return {
"tools": model_dumped_tools,

View file

@ -644,6 +644,50 @@ class TestTestToolsList:
assert len(result["warnings"]) == 1
assert f"{alias}-{too_long}" in result["warnings"][0]
async def test_no_speculative_warnings_in_short_prefix_mode(self, monkeypatch):
"""In short-prefix mode without a server_id the 3-char runtime prefix is not
knowable yet, so the preview must not warn based on the full alias."""
from types import SimpleNamespace
from mcp.types import Tool as MCPTool
from litellm.constants import MCP_MAX_TOOL_NAME_LENGTH
from litellm.proxy._types import LitellmUserRoles
alias = "network_config_audit"
fits_short_prefix_only = "t" * (MCP_MAX_TOOL_NAME_LENGTH - len(alias))
class FakeClient:
async def run_with_session(self, operation):
return SimpleNamespace(tools=[MCPTool(name=fits_short_prefix_only, inputSchema={})])
async def fake_execute(
request,
operation,
mcp_auth_header=None,
oauth2_headers=None,
raw_headers=None,
):
return await operation(FakeClient())
monkeypatch.setattr(
rest_endpoints, "_execute_with_mcp_client", fake_execute, raising=False
)
monkeypatch.setenv("LITELLM_USE_SHORT_MCP_TOOL_PREFIX", "1")
result = await rest_endpoints.test_tools_list(
_build_request(),
NewMCPServerRequest(
server_name="example",
alias=alias,
url="https://example.com",
auth_type=MCPAuth.none,
),
user_api_key_dict=UserAPIKeyAuth(user_role=LitellmUserRoles.PROXY_ADMIN),
)
assert result["warnings"] == []
class TestListToolsRestAPI:
pytestmark = pytest.mark.asyncio