From bc4c4393d4aa0b8eea06335697503dbfd1a3b629 Mon Sep 17 00:00:00 2001 From: ryan-crabbe-berri Date: Thu, 2 Jul 2026 18:44:33 -0700 Subject: [PATCH] chore(mcp): fix lint failures (ruff strict budget + prettier) Drop UP007 by moving MCPServerGrant to X | Y union syntax and remove the now-unused Union import in permission_grant.py. Extract the org-ceiling block of get_allowed_mcp_servers into _apply_org_ceiling so the function falls back under the C901 complexity ceiling. Reformat the three MCP dashboard components prettier flagged. --- .../mcp_server/auth/user_api_key_auth_mcp.py | 47 +++++++++++++------ .../mcp_server/permission_grant.py | 3 +- .../MCPServerSelector.test.tsx | 6 +-- .../MCPServerSelector.tsx | 7 +-- .../permissions/MCPServerPermissions.tsx | 4 +- 5 files changed, 36 insertions(+), 31 deletions(-) diff --git a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py index f16b702eafe..5fc2881869a 100644 --- a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py +++ b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py @@ -676,27 +676,44 @@ class MCPRequestHandler: f"Applied agent intersection filter. Final allowed servers: {allowed_mcp_servers}" ) - ######################################################### - # Apply org-level ceiling if org_id is set - ######################################################### - if user_api_key_auth and user_api_key_auth.org_id: - allowed_mcp_servers_for_org = await MCPRequestHandler._get_allowed_mcp_servers_for_org( - user_api_key_auth - ) - if len(allowed_mcp_servers_for_org) > 0: - if has_lower_level_mcp_restrictions: - # Lower-level restrictions exist, so org can only cap them. - allowed_mcp_servers = [s for s in allowed_mcp_servers if s in allowed_mcp_servers_for_org] - else: - # No lower-level restrictions → org list becomes the ceiling - allowed_mcp_servers = allowed_mcp_servers_for_org - verbose_logger.debug(f"Applied org ceiling filter. Final allowed servers: {allowed_mcp_servers}") + allowed_mcp_servers = await MCPRequestHandler._apply_org_ceiling( + user_api_key_auth, + allowed_mcp_servers, + has_lower_level_mcp_restrictions, + ) return list(set(allowed_mcp_servers)) except Exception as e: verbose_logger.warning(f"Failed to get allowed MCP servers: {str(e)}") return [] + @staticmethod + async def _apply_org_ceiling( + user_api_key_auth: Optional[UserAPIKeyAuth], + allowed_mcp_servers: List[str], + has_lower_level_mcp_restrictions: bool, + ) -> List[str]: + """Cap the running allowed set to the org's MCP servers when the org sets one. + + When lower-level restrictions already exist the org can only intersect + them; otherwise the org's list becomes the ceiling. An empty org list + means the org places no restriction. + """ + if not (user_api_key_auth and user_api_key_auth.org_id): + return allowed_mcp_servers + + allowed_mcp_servers_for_org = await MCPRequestHandler._get_allowed_mcp_servers_for_org(user_api_key_auth) + if len(allowed_mcp_servers_for_org) == 0: + return allowed_mcp_servers + + capped = ( + [s for s in allowed_mcp_servers if s in allowed_mcp_servers_for_org] + if has_lower_level_mcp_restrictions + else allowed_mcp_servers_for_org + ) + verbose_logger.debug(f"Applied org ceiling filter. Final allowed servers: {capped}") + return capped + @staticmethod def _get_key_object_permission( user_api_key_auth: Optional[UserAPIKeyAuth] = None, diff --git a/litellm/proxy/_experimental/mcp_server/permission_grant.py b/litellm/proxy/_experimental/mcp_server/permission_grant.py index 95c02e29af6..decccc03630 100644 --- a/litellm/proxy/_experimental/mcp_server/permission_grant.py +++ b/litellm/proxy/_experimental/mcp_server/permission_grant.py @@ -8,7 +8,6 @@ identifiers into concrete deployments. from collections.abc import Iterable from dataclasses import dataclass -from typing import Union from litellm.proxy._types import SpecialMCPServerNames @@ -48,7 +47,7 @@ class ExplicitServers: identifiers: frozenset[str] -MCPServerGrant = Union[AllServers, AllTeamServers, NoServers, ExplicitServers] +MCPServerGrant = AllServers | AllTeamServers | NoServers | ExplicitServers def parse_mcp_server_grant(raw: Iterable[str]) -> MCPServerGrant: diff --git a/ui/litellm-dashboard/src/components/mcp_server_management/MCPServerSelector.test.tsx b/ui/litellm-dashboard/src/components/mcp_server_management/MCPServerSelector.test.tsx index 0c601679dd7..04fe246064c 100644 --- a/ui/litellm-dashboard/src/components/mcp_server_management/MCPServerSelector.test.tsx +++ b/ui/litellm-dashboard/src/components/mcp_server_management/MCPServerSelector.test.tsx @@ -3,11 +3,7 @@ import userEvent from "@testing-library/user-event"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { renderWithProviders } from "../../../tests/test-utils"; import MCPServerSelector from "./MCPServerSelector"; -import { - ALL_PROXY_MCPS_SENTINEL, - ALL_TEAM_MCPS_SENTINEL, - NO_MCP_SERVERS_SENTINEL, -} from "../mcp_tools/constants"; +import { ALL_PROXY_MCPS_SENTINEL, ALL_TEAM_MCPS_SENTINEL, NO_MCP_SERVERS_SENTINEL } from "../mcp_tools/constants"; vi.mock("@/app/(dashboard)/hooks/mcpServers/useMCPServers", () => ({ useMCPServers: vi.fn(), diff --git a/ui/litellm-dashboard/src/components/mcp_server_management/MCPServerSelector.tsx b/ui/litellm-dashboard/src/components/mcp_server_management/MCPServerSelector.tsx index fee616387d6..c39cf03f742 100644 --- a/ui/litellm-dashboard/src/components/mcp_server_management/MCPServerSelector.tsx +++ b/ui/litellm-dashboard/src/components/mcp_server_management/MCPServerSelector.tsx @@ -112,12 +112,7 @@ const MCPServerSelector: React.FC = ({ ...(value?.toolsets || []).map((id) => `${TOOLSET_PREFIX}${id}`), ]; - const exclusiveSentinels = buildExclusiveSentinels( - allowNoMcpServers, - allowAllTeamMcps, - allowAllProxyMcps, - teamId, - ); + const exclusiveSentinels = buildExclusiveSentinels(allowNoMcpServers, allowAllTeamMcps, allowAllProxyMcps, teamId); const selectedExclusive = exclusiveSentinels.find((s) => selectedValues.includes(s.value)) ?? null; const hasExclusiveSelected = selectedExclusive !== null; diff --git a/ui/litellm-dashboard/src/components/permissions/MCPServerPermissions.tsx b/ui/litellm-dashboard/src/components/permissions/MCPServerPermissions.tsx index be45e702d50..644e53d03a7 100644 --- a/ui/litellm-dashboard/src/components/permissions/MCPServerPermissions.tsx +++ b/ui/litellm-dashboard/src/components/permissions/MCPServerPermissions.tsx @@ -104,9 +104,7 @@ export function MCPServerPermissions({ ...mcpServers .filter( (server) => - server !== NO_MCP_SERVERS_SENTINEL && - server !== ALL_PROXY_MCPS_SENTINEL && - server !== ALL_TEAM_MCPS_SENTINEL, + server !== NO_MCP_SERVERS_SENTINEL && server !== ALL_PROXY_MCPS_SENTINEL && server !== ALL_TEAM_MCPS_SENTINEL, ) .map((server) => ({ type: "server", value: server })), ...mcpAccessGroups.map((group) => ({ type: "accessGroup", value: group })),