diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json
index 0bdf5a6375b..c7111b5ee79 100644
--- a/ui/litellm-dashboard/.eslintrc.json
+++ b/ui/litellm-dashboard/.eslintrc.json
@@ -67,6 +67,7 @@
"src/components/guardrails/GuardrailTestResults.tsx",
"src/components/guardrails/GuardrailTestPlayground.tsx",
"src/components/vector_store_management/S3VectorsConfig.tsx",
+ "src/components/mcp_tools/mcp_server_cost_config.tsx",
"src/components/prompts/prompt_editor_view/PromptEditorHeader.tsx",
"src/components/prompts/prompt_editor_view/VersionHistorySidePanel.tsx",
"src/app/(dashboard)/teams/components/TeamsTable/ModelsCell.tsx",
diff --git a/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_cost_config.tsx b/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_cost_config.tsx
index 3f3986d5a2e..f242f8ee4fa 100644
--- a/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_cost_config.tsx
+++ b/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_cost_config.tsx
@@ -1,16 +1,71 @@
import React from "react";
-import { Tooltip, InputNumber, Collapse, Badge } from "antd";
-import { InfoCircleOutlined, DollarOutlined, ToolOutlined } from "@ant-design/icons";
-import { Card, Title, Text } from "@tremor/react";
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/components/ui/accordion";
+import { Badge } from "@/components/ui/badge";
+import { Card } from "@/components/ui/card";
+import { Input } from "@/components/ui/input";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@/components/ui/tooltip";
+import { DollarSign, Info, Wrench } from "lucide-react";
import { MCPServerCostInfo } from "./types";
interface MCPServerCostConfigProps {
value?: MCPServerCostInfo;
onChange?: (value: MCPServerCostInfo) => void;
- tools?: any[]; // Receive tools from connection component
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ tools?: any[];
disabled?: boolean;
}
+const InfoTip: React.FC<{ children: React.ReactNode }> = ({ children }) => (
+
+
+
+
+
+ {children}
+
+
+);
+
+const MoneyInput: React.FC<{
+ value?: number | null;
+ onChange: (v: number | null) => void;
+ placeholder?: string;
+ disabled?: boolean;
+ className?: string;
+}> = ({ value, onChange, placeholder, disabled, className }) => (
+
+ $
+ {
+ const raw = e.target.value;
+ if (raw === "") {
+ onChange(null);
+ return;
+ }
+ const n = Number(raw);
+ onChange(isNaN(n) ? null : n);
+ }}
+ placeholder={placeholder}
+ disabled={disabled}
+ className="border-0 rounded-none shadow-none"
+ />
+
+);
+
const MCPServerCostConfig: React.FC = ({
value = {},
onChange,
@@ -18,136 +73,139 @@ const MCPServerCostConfig: React.FC = ({
disabled = false,
}) => {
const handleDefaultCostChange = (defaultCost: number | null) => {
- const updated = {
+ onChange?.({
...value,
default_cost_per_query: defaultCost,
- };
- onChange?.(updated);
+ });
};
const handleToolCostChange = (toolName: string, cost: number | null) => {
- const updated = {
+ onChange?.({
...value,
tool_name_to_cost_per_query: {
...value.tool_name_to_cost_per_query,
[toolName]: cost,
},
- };
- onChange?.(updated);
+ });
};
return (
-
+
-
-
Cost Configuration
-
-
-
+
+ Cost Configuration
+
+ Configure costs for this MCP server's tool calls. Set a
+ default rate and per-tool overrides.
+
-
{tools.length > 0 && (
-
+
Tool-Specific Costs ($)
-
-
-
+
+ Override the default cost for specific tools. Leave blank
+ to use the default rate.
+
-
-
- Available Tools
-
-
- ),
- children: (
-
- {tools.map((tool, index) => (
-
-
- {tool.name}
- {tool.description && (
- {tool.description}
- )}
-
-
- handleToolCostChange(tool.name, cost)}
- disabled={disabled}
- style={{ width: "120px" }}
- addonBefore="$"
- />
-
+
+
+
+
+
+ Available Tools
+
+ {tools.length}
+
+
+
+
+
+ {tools.map((tool, index) => (
+
+
+
+ {tool.name}
+
+ {tool.description && (
+
+ {tool.description}
+
+ )}
- ))}
-
- ),
- },
- ]}
- />
+
+
+ handleToolCostChange(tool.name, cost)
+ }
+ placeholder="Use default"
+ disabled={disabled}
+ className="w-[160px]"
+ />
+
+
+ ))}
+
+
+
+
)}
{(value.default_cost_per_query ||
- (value.tool_name_to_cost_per_query && Object.keys(value.tool_name_to_cost_per_query).length > 0)) && (
-
-
Cost Summary:
+ (value.tool_name_to_cost_per_query &&
+ Object.keys(value.tool_name_to_cost_per_query).length > 0)) && (
+
+
+ Cost Summary:
+
{value.default_cost_per_query && (
-
- • Default cost: ${value.default_cost_per_query.toFixed(4)} per query
-
+
+ • Default cost: $
+ {value.default_cost_per_query.toFixed(4)} per query
+
)}
{value.tool_name_to_cost_per_query &&
Object.entries(value.tool_name_to_cost_per_query).map(
([toolName, cost]) =>
cost !== null &&
cost !== undefined && (
-
+
• {toolName}: ${cost.toFixed(4)} per query
-
+
),
)}