diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json index 3b9b0ed0ec2..f8b51083a4f 100644 --- a/ui/litellm-dashboard/.eslintrc.json +++ b/ui/litellm-dashboard/.eslintrc.json @@ -65,6 +65,7 @@ "src/components/playground/chat_ui/A2AMetrics.tsx", "src/components/common_components/PassThroughGuardrailsSection.tsx", "src/components/claude_code_plugins/MakeSkillPublicForm.tsx", + "src/components/mcp_tools/MCPPermissionManagement.tsx", "src/components/permissions/VectorStorePermissions.tsx", "src/components/permissions/AgentPermissions.tsx", "src/components/permissions/MCPServerPermissions.tsx", diff --git a/ui/litellm-dashboard/src/components/mcp_tools/MCPPermissionManagement.tsx b/ui/litellm-dashboard/src/components/mcp_tools/MCPPermissionManagement.tsx index dcb7298c830..adb311973a3 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/MCPPermissionManagement.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/MCPPermissionManagement.tsx @@ -1,9 +1,34 @@ import React, { useEffect } from "react"; -import { Form, Select, Tooltip, Collapse, Input, Space, Button, Switch } from "antd"; -import { InfoCircleOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons"; +import { + Form, + Select, + Collapse, + Input as AntInput, + Space, +} from "antd"; +import { Button } from "@/components/ui/button"; +import { Switch } from "@/components/ui/switch"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { Info, MinusCircle, Plus } from "lucide-react"; import { MCPServer } from "./types"; const { Panel } = Collapse; +const InfoTip: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + + + + + + {children} + + +); + interface MCPPermissionManagementProps { availableAccessGroups: string[]; mcpServer: MCPServer | null; @@ -47,15 +72,23 @@ const MCPPermissionManagement: React.FC = ({ }, [mcpServer, form]); return ( - +
-

Permission Management / Access Control

+

+ Permission Management / Access Control +

-

Configure access permissions and security settings (Optional)

+

+ Configure access permissions and security settings (Optional) +

} key="permissions" @@ -65,13 +98,15 @@ const MCPPermissionManagement: React.FC = ({
- + Allow All LiteLLM Keys - - - + + When enabled, every API key can access this MCP server. + -

Enable if this server should be "public" to all keys.

+

+ Enable if this server should be "public" to all keys. +

= ({
- + Internal network only - - - + + When on, only requests from within your internal network are + accepted. Turn off to allow external clients (other clusters, + ChatGPT, etc). API key authentication is always required + regardless of this setting. + -

Turn on to restrict access to callers within your internal network only.

+

+ Turn on to restrict access to callers within your internal + network only. +

= ({ + MCP Access Groups - - - + + Specify access groups for this MCP server. Users must be in + at least one of these groups to access the server. + } name="mcp_access_groups" @@ -122,7 +164,11 @@ const MCPPermissionManagement: React.FC = ({ showSearch placeholder="Select existing groups or type to create new ones" optionFilterProp="value" - filterOption={(input, option) => (option?.value ?? "").toLowerCase().includes(input.toLowerCase())} + filterOption={(input, option) => + (option?.value ?? "") + .toLowerCase() + .includes(input.toLowerCase()) + } onSearch={(value) => setSearchValue(value)} tokenSeparators={[","]} options={getAccessGroupOptions()} @@ -133,16 +179,18 @@ const MCPPermissionManagement: React.FC = ({ + Extra Headers - - - - {mcpServer?.extra_headers && mcpServer.extra_headers.length > 0 && ( - - {mcpServer.extra_headers.length} configured - - )} + + Forward custom headers from incoming requests to this MCP + server (e.g., Authorization, X-Custom-Header, User-Agent) + + {mcpServer?.extra_headers && + mcpServer.extra_headers.length > 0 && ( + + {mcpServer.extra_headers.length} configured + + )} } name="extra_headers" @@ -163,11 +211,12 @@ const MCPPermissionManagement: React.FC = ({ + Static Headers - - - + + Send these key-value headers with every request to this MCP + server. + } required={false} @@ -176,14 +225,24 @@ const MCPPermissionManagement: React.FC = ({ {(fields, { add, remove }) => (
{fields.map(({ key, name, ...restField }) => ( - + - = ({ {...restField} name={[name, "value"]} className="flex-1" - rules={[{ required: true, message: "Header value is required" }]} + rules={[ + { + required: true, + message: "Header value is required", + }, + ]} > - - remove(name)} - className="text-gray-500 hover:text-red-500 cursor-pointer" + className="h-4 w-4 text-muted-foreground hover:text-destructive cursor-pointer" /> ))} -