diff --git a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py index 1481a027f4b..27a01ee3c30 100644 --- a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py +++ b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py @@ -1294,9 +1294,25 @@ if MCP_AVAILABLE: new_mcp_server_request = _inherit_credentials_from_existing_server(new_mcp_server_request) + def _preview_warnings(tool_names: List[str]) -> List[str]: + # 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). + if is_short_mcp_tool_prefix_enabled() and not new_mcp_server_request.server_id: + return [] + return tool_name_length_warnings( + tool_names, + get_server_prefix(new_mcp_server_request), + MCP_MAX_TOOL_NAME_LENGTH, + ) + # For OpenAPI spec servers, generate tools from the spec directly if new_mcp_server_request.spec_path: - return await _preview_openapi_tools(new_mcp_server_request.spec_path) + openapi_preview = await _preview_openapi_tools(new_mcp_server_request.spec_path) + return { + **openapi_preview, + "warnings": _preview_warnings([tool["name"] for tool in openapi_preview.get("tools") or []]), + } from litellm.proxy._experimental.mcp_server.auth.user_api_key_auth_mcp import ( MCPRequestHandler, @@ -1326,23 +1342,11 @@ 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] - # 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, "error": None, "message": "Successfully retrieved tools", - "warnings": warnings, + "warnings": _preview_warnings([tool.name for tool in list_tools_result]), } return await _execute_with_mcp_client( 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 4d8248e6782..5243e457e0b 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 @@ -688,6 +688,40 @@ class TestTestToolsList: assert result["warnings"] == [] + async def test_openapi_preview_flags_tool_names_exceeding_provider_limit(self, monkeypatch): + """The OpenAPI spec preview must carry the same length warnings as the MCP + preview, since registered OpenAPI tools get the server prefix too.""" + from litellm.constants import MCP_MAX_TOOL_NAME_LENGTH + from litellm.proxy._types import LitellmUserRoles + + alias = "network_config_audit" + fitting = "t" * (MCP_MAX_TOOL_NAME_LENGTH - len(alias) - 1) + too_long = "t" * (MCP_MAX_TOOL_NAME_LENGTH - len(alias)) + + async def fake_preview(spec_path): + return { + "tools": [{"name": fitting}, {"name": too_long}], + "error": None, + "message": "Found 2 tools from OpenAPI spec", + } + + monkeypatch.setattr(rest_endpoints, "_preview_openapi_tools", fake_preview, raising=False) + + result = await rest_endpoints.test_tools_list( + _build_request(), + NewMCPServerRequest( + server_name="example", + alias=alias, + spec_path="/tmp/spec.json", + auth_type=MCPAuth.none, + ), + user_api_key_dict=UserAPIKeyAuth(user_role=LitellmUserRoles.PROXY_ADMIN), + ) + + assert len(result["tools"]) == 2 + assert len(result["warnings"]) == 1 + assert f"{alias}-{too_long}" in result["warnings"][0] + class TestListToolsRestAPI: pytestmark = pytest.mark.asyncio diff --git a/ui/litellm-dashboard/src/hooks/useTestMCPConnection.tsx b/ui/litellm-dashboard/src/hooks/useTestMCPConnection.tsx index 38e9679a850..96a65f63c2d 100644 --- a/ui/litellm-dashboard/src/hooks/useTestMCPConnection.tsx +++ b/ui/litellm-dashboard/src/hooks/useTestMCPConnection.tsx @@ -5,6 +5,7 @@ import { AUTH_TYPE, OAUTH_FLOW, TRANSPORT } from "@/components/mcp_tools/types"; interface MCPServerConfig { server_id?: string; server_name?: string; + alias?: string; url?: string; spec_path?: string; transport?: string; @@ -140,6 +141,7 @@ export const useTestMCPConnection = ({ const mcpServerConfig: MCPServerConfig = { server_id: formValues.server_id || "", server_name: formValues.server_name || "", + alias: formValues.alias, url: formValues.url, spec_path: formValues.spec_path, transport: effectiveTransport, @@ -214,6 +216,7 @@ export const useTestMCPConnection = ({ formValues.spec_path, formValues.transport, formValues.auth_type, + formValues.alias, accessToken, enabled, oauthAccessToken,