diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json index a5d8e6a05bf..a16d6a90d1e 100644 --- a/ui/litellm-dashboard/.eslintrc.json +++ b/ui/litellm-dashboard/.eslintrc.json @@ -61,6 +61,7 @@ "src/components/guardrails/guardrail_table.tsx", "src/components/prompts/prompt_table.tsx", "src/components/common_components/ModelAliasManager.tsx", + "src/components/mcp_tools/mcp_server_columns.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/mcp_server_columns.tsx b/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_columns.tsx index ea5ccf1c847..d3007371125 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_columns.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_columns.tsx @@ -1,11 +1,15 @@ import { useState } from "react"; import { ColumnDef } from "@tanstack/react-table"; import { MCPServer } from "./types"; -import { Icon } from "@tremor/react"; -import { PencilAltIcon, TrashIcon } from "@heroicons/react/outline"; +import { Check, Pencil, Trash2 } from "lucide-react"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { cn } from "@/lib/utils"; import { getMaskedAndFullUrl } from "./utils"; -import { Tooltip } from "antd"; -import { CheckOutlined } from "@ant-design/icons"; const HealthStatusBadge: React.FC<{ server: MCPServer; @@ -20,8 +24,8 @@ const HealthStatusBadge: React.FC<{ if (isLoadingHealth || isRechecking) { return ( - - + + Checking ); @@ -30,11 +34,11 @@ const HealthStatusBadge: React.FC<{ const getStatusColor = (status: string) => { switch (status) { case "healthy": - return "text-green-700 bg-green-50 border border-green-200"; + return "text-emerald-700 bg-emerald-50 border border-emerald-200 dark:text-emerald-300 dark:bg-emerald-950/30 dark:border-emerald-900"; case "unhealthy": - return "text-red-700 bg-red-50 border border-red-200"; + return "text-red-700 bg-red-50 border border-red-200 dark:text-red-300 dark:bg-red-950/30 dark:border-red-900"; default: - return "text-gray-600 bg-gray-50 border border-gray-200"; + return "text-muted-foreground bg-muted border border-border"; } }; @@ -54,36 +58,58 @@ const HealthStatusBadge: React.FC<{ const tooltipContent = (
Health Status: {status}
- {lastCheck &&
Last Check: {new Date(lastCheck).toLocaleString()}
} + {lastCheck && ( +
+ Last Check: {new Date(lastCheck).toLocaleString()} +
+ )} {error && (
-
Error:
+
Error:
{error}
)} - {!lastCheck && !error &&
No health check data available
} - {isClickable &&
Click to recheck
} + {!lastCheck && !error && ( +
+ No health check data available +
+ )} + {isClickable && ( +
Click to recheck
+ )}
); return ( - - setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - onClick={isClickable ? () => onRecheck(server.server_id) : undefined} - > - {isHovered && isClickable ? "↻" : getStatusIcon(status)} - {isHovered && isClickable - ? "Recheck" - : status.charAt(0).toUpperCase() + status.slice(1)} - - + + + + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + onClick={isClickable ? () => onRecheck(server.server_id) : undefined} + > + + {isHovered && isClickable ? "↻" : getStatusIcon(status)} + + {isHovered && isClickable + ? "Recheck" + : status.charAt(0).toUpperCase() + status.slice(1)} + + + {tooltipContent} + + ); }; export const mcpServerColumns = ( + // eslint-disable-next-line @typescript-eslint/no-unused-vars userRole: string, onView: (serverId: string) => void, onEdit: (serverId: string) => void, @@ -100,7 +126,7 @@ export const mcpServerColumns = ( cell: ({ row }) => ( @@ -116,11 +142,14 @@ export const mcpServerColumns = ( return (
{logoUrl ? ( + // eslint-disable-next-line @next/next/no-img-element {`${name { (e.target as HTMLImageElement).style.display = "none"; }} + onError={(e) => { + (e.target as HTMLImageElement).style.display = "none"; + }} /> ) : null} {name} @@ -139,7 +168,7 @@ export const mcpServerColumns = ( cell: ({ row }) => { const url = row.original.url; if (!url) { - return —; + return —; } const { maskedUrl } = getMaskedAndFullUrl(url); return {maskedUrl}; @@ -152,10 +181,11 @@ export const mcpServerColumns = ( cell: ({ row }) => { const transport = row.original.transport || "http"; const specPath = row.original.spec_path; - const displayTransport = specPath && transport !== "stdio" ? "OPENAPI" : transport; + const displayTransport = + specPath && transport !== "stdio" ? "OPENAPI" : transport; const label = displayTransport.toUpperCase(); return ( - + {label} ); @@ -168,7 +198,7 @@ export const mcpServerColumns = ( cell: ({ getValue }) => { const authType = (getValue() as string) || "none"; return ( - + {authType} ); @@ -195,20 +225,27 @@ export const mcpServerColumns = ( if (typeof groups[0] === "string") { const joined = groups.join(", "); return ( - -
- - {groups[0]} - - {groups.length > 1 && ( - +{groups.length - 1} - )} -
-
+ + + +
+ + {groups[0]} + + {groups.length > 1 && ( + + +{groups.length - 1} + + )} +
+
+ {joined} +
+
); } } - return —; + return —; }, }, { @@ -217,12 +254,12 @@ export const mcpServerColumns = ( cell: ({ row }) => { const isPublic = row.original.available_on_public_internet; return isPublic ? ( - - + + Public ) : ( - + Internal @@ -236,12 +273,20 @@ export const mcpServerColumns = ( sortingFn: "datetime", cell: ({ row }) => { const server = row.original; - if (!server.created_at) return —; + if (!server.created_at) + return —; const date = new Date(server.created_at); return ( - - {date.toLocaleDateString()} - + + + + + {date.toLocaleDateString()} + + + {date.toLocaleString()} + + ); }, }, @@ -252,12 +297,20 @@ export const mcpServerColumns = ( sortingFn: "datetime", cell: ({ row }) => { const server = row.original; - if (!server.updated_at) return —; + if (!server.updated_at) + return —; const date = new Date(server.updated_at); return ( - - {date.toLocaleDateString()} - + + + + + {date.toLocaleDateString()} + + + {date.toLocaleString()} + + ); }, }, @@ -267,17 +320,17 @@ export const mcpServerColumns = ( cell: ({ row }) => { const server = row.original; if (!server.is_byok) { - return —; + return —; } if (server.has_user_credential) { return (
- - Connected + + Connected {onByokConnect && ( - - - - + + + + + + Edit + + + + + + + + Delete + +
), },