diff --git a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py index e75cf5d6409..28c95e67550 100644 --- a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py +++ b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py @@ -458,6 +458,91 @@ if MCP_AVAILABLE: } ######################################################## + + async def _list_tools_for_single_server( + server_id: str, + allowed_server_ids: List[str], + rest_client_ip: Optional[str], + mcp_server_auth_headers: dict, + mcp_auth_header: Optional[str], + raw_headers_from_request: dict, + user_api_key_dict: UserAPIKeyAuth, + ) -> dict: + """Handle tool listing for a single server_id request.""" + # Resolve a server name to its UUID if needed + _name_resolved = None + if server_id not in allowed_server_ids: + _name_resolved = global_mcp_server_manager.get_mcp_server_by_name(server_id) + if _name_resolved is not None and _name_resolved.server_id in set(allowed_server_ids): + server_id = _name_resolved.server_id + + if server_id not in allowed_server_ids: + _server = ( + global_mcp_server_manager.get_mcp_server_by_id(server_id) + or _name_resolved + ) + if ( + _server is not None + and rest_client_ip is not None + and not global_mcp_server_manager._is_server_accessible_from_ip( + _server, rest_client_ip + ) + ): + raise HTTPException( + status_code=403, + detail={ + "error": "ip_filtering", + "message": ( + f"MCP server '{server_id}' is not accessible from your IP address " + f"({rest_client_ip}). This server is restricted to internal " + "networks only. To make it externally accessible, set " + "'available_on_public_internet: true' in the server configuration." + ), + }, + ) + raise HTTPException( + status_code=403, + detail={ + "error": "access_denied", + "message": f"The key is not allowed to access server {server_id}", + }, + ) + server = global_mcp_server_manager.get_mcp_server_by_id(server_id) + if server is None: + return { + "tools": [], + "error": "server_not_found", + "message": f"Server with id {server_id} not found", + } + + server_auth_header = _get_server_auth_header( + server, mcp_server_auth_headers, mcp_auth_header + ) + user_oauth_extra_headers = await _get_user_oauth_extra_headers(server, user_api_key_dict) + + try: + list_tools_result = await _get_tools_for_single_server( + server, + server_auth_header, + raw_headers_from_request, + user_api_key_dict, + extra_headers=user_oauth_extra_headers, + ) + except Exception as e: + verbose_logger.exception( + f"Error getting tools from {server.name}: {e}" + ) + return { + "tools": [], + "error": "server_error", + "message": f"Failed to get tools from server {server.name}: {str(e)}", + } + return { + "tools": list_tools_result, + "error": None, + "message": "Successfully retrieved tools", + } + @router.get("/tools/list", dependencies=[Depends(user_api_key_auth)]) async def list_tool_rest_api( request: Request,