diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json index aea804d8c6a..6049b3b352a 100644 --- a/ui/litellm-dashboard/.eslintrc.json +++ b/ui/litellm-dashboard/.eslintrc.json @@ -35,7 +35,8 @@ "src/components/logging_settings_view.tsx", "src/components/model_group_alias_settings.tsx", "src/components/cache_dashboard.tsx", - "src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterTestPanel.tsx" + "src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterTestPanel.tsx", + "src/components/mcp_hub_table_columns.tsx" ], "rules": { "litellm-ui/no-banned-ui-imports": "off", diff --git a/ui/litellm-dashboard/src/components/mcp_hub_table_columns.tsx b/ui/litellm-dashboard/src/components/mcp_hub_table_columns.tsx index 6885fd03bb3..a2f31b6de7d 100644 --- a/ui/litellm-dashboard/src/components/mcp_hub_table_columns.tsx +++ b/ui/litellm-dashboard/src/components/mcp_hub_table_columns.tsx @@ -1,7 +1,14 @@ import { ColumnDef } from "@tanstack/react-table"; -import { Button, Badge, Text } from "@tremor/react"; -import { Tooltip, Tag } from "antd"; -import { CopyOutlined, InfoCircleOutlined } from "@ant-design/icons"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { Copy, Info } from "lucide-react"; +import { cn } from "@/lib/utils"; export interface MCPServerData { server_id: string; @@ -11,6 +18,7 @@ export interface MCPServerData { url: string; transport: string; auth_type: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any credentials?: any; created_at: string; created_by: string; @@ -19,24 +27,70 @@ export interface MCPServerData { teams: string[]; mcp_access_groups: string[]; allowed_tools: string[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any extra_headers: any[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any mcp_info: Record; + // eslint-disable-next-line @typescript-eslint/no-explicit-any static_headers: Record; status: string; last_health_check?: string | null; health_check_error?: string | null; command?: string | null; args: string[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any env: Record; + // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; } +function CopyIconButton({ + value, + onCopy, + title, +}: { + value: string; + onCopy: (text: string) => void; + title: string; +}) { + return ( + + + + + + {title} + + + ); +} + +// Categorical status palette. Kept inline (not semantic-token-only) per the +// DEVIATIONS.md categorical-palette policy. +const statusClassMap: Record = { + active: + "bg-emerald-100 text-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-300", + healthy: + "bg-emerald-100 text-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-300", + inactive: "bg-red-100 text-red-800 dark:bg-red-950/40 dark:text-red-300", + unhealthy: "bg-red-100 text-red-800 dark:bg-red-950/40 dark:text-red-300", + unknown: "bg-muted text-muted-foreground", +}; + export const mcpHubColumns = ( showModal: (server: MCPServerData) => void, copyToClipboard: (text: string) => void, + // eslint-disable-next-line @typescript-eslint/no-unused-vars publicPage: boolean = false, ): ColumnDef[] => { - const allColumns: ColumnDef[] = [ + return [ { header: "Server Name", accessorKey: "server_name", @@ -44,21 +98,20 @@ export const mcpHubColumns = ( sortingFn: "alphanumeric", cell: ({ row }) => { const server = row.original; - return (
- {server.server_name} - - copyToClipboard(server.server_name)} - className="cursor-pointer text-gray-500 hover:text-blue-500 text-xs" - /> - + {server.server_name} +
- {/* Show description on mobile */}
- {server.description || "-"} + + {server.description || "-"} +
); @@ -71,16 +124,13 @@ export const mcpHubColumns = ( sortingFn: "alphanumeric", cell: ({ row }) => { const server = row.original; - return ( - + {server.description || "-"} - + ); }, - meta: { - className: "hidden md:table-cell", - }, + meta: { className: "hidden md:table-cell" }, }, { header: "URL", @@ -89,40 +139,30 @@ export const mcpHubColumns = ( sortingFn: "alphanumeric", cell: ({ row }) => { const server = row.original; - return (
- {server.url} - - copyToClipboard(server.url)} - className="cursor-pointer text-gray-500 hover:text-blue-500 text-xs flex-shrink-0" - /> - + {server.url} +
); }, - meta: { - className: "hidden lg:table-cell", - }, + meta: { className: "hidden lg:table-cell" }, }, { header: "Transport", accessorKey: "transport", enableSorting: true, sortingFn: "alphanumeric", - cell: ({ row }) => { - const server = row.original; - - return ( - - {server.transport} - - ); - }, - meta: { - className: "hidden md:table-cell", - }, + cell: ({ row }) => ( + + {row.original.transport} + + ), + meta: { className: "hidden md:table-cell" }, }, { header: "Auth Type", @@ -131,18 +171,16 @@ export const mcpHubColumns = ( sortingFn: "alphanumeric", cell: ({ row }) => { const server = row.original; - - const authColor = server.auth_type === "none" ? "gray" : "green"; - return ( - + {server.auth_type} ); }, - meta: { - className: "hidden md:table-cell", - }, + meta: { className: "hidden md:table-cell" }, }, { header: "Status", @@ -151,21 +189,16 @@ export const mcpHubColumns = ( sortingFn: "alphanumeric", cell: ({ row }) => { const server = row.original; - - const statusColors: Record = { - active: "green", - inactive: "red", - unknown: "gray", - healthy: "green", - unhealthy: "red", - }; - - const color = statusColors[server.status] || "gray"; - + const cls = statusClassMap[server.status] ?? statusClassMap.unknown; return ( - + {server.status || "unknown"} - + ); }, }, @@ -176,48 +209,45 @@ export const mcpHubColumns = ( cell: ({ row }) => { const server = row.original; const tools = server.allowed_tools || []; - return (
- - {tools.length > 0 ? `${tools.length} tool${tools.length !== 1 ? "s" : ""}` : "All tools"} - + + {tools.length > 0 + ? `${tools.length} tool${tools.length !== 1 ? "s" : ""}` + : "All tools"} + {tools.length > 0 && (
{tools.slice(0, 2).map((tool, idx) => ( - + {tool} - + ))} {tools.length > 2 && ( - +{tools.length - 2} + + +{tools.length - 2} + )}
)}
); }, - meta: { - className: "hidden lg:table-cell", - }, + meta: { className: "hidden lg:table-cell" }, }, { header: "Created By", accessorKey: "created_by", enableSorting: true, sortingFn: "alphanumeric", - cell: ({ row }) => { - const server = row.original; - - return ( - - {server.created_by || "-"} - - ); - }, - meta: { - className: "hidden xl:table-cell", - }, + cell: ({ row }) => ( + {row.original.created_by || "-"} + ), + meta: { className: "hidden xl:table-cell" }, }, { header: "Public", @@ -230,38 +260,33 @@ export const mcpHubColumns = ( }, cell: ({ row }) => { const server = row.original; - return server.mcp_info?.is_public === true ? ( - + Yes ) : ( - + No ); }, - meta: { - className: "hidden md:table-cell", - }, + meta: { className: "hidden md:table-cell" }, }, { header: "Details", id: "details", enableSorting: false, - cell: ({ row }) => { - const server = row.original; - - return ( - - ); - }, + cell: ({ row }) => ( + + ), }, ]; - - return allColumns; }; -