diff --git a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py index 0f92485f0b0..53905c7b7a7 100644 --- a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py +++ b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py @@ -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, diff --git a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py index 581a2f5dc72..955a418c208 100644 --- a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py +++ b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py @@ -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, diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_rest_endpoints.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_rest_endpoints.py index 1e609dbc882..a9cddc676a1 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_rest_endpoints.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_rest_endpoints.py @@ -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