diff --git a/ui/litellm-dashboard/out/assets/logos/mcp_logo.png b/ui/litellm-dashboard/out/assets/logos/mcp_logo.png new file mode 100644 index 000000000000..d920e50e7f22 Binary files /dev/null and b/ui/litellm-dashboard/out/assets/logos/mcp_logo.png differ diff --git a/ui/litellm-dashboard/public/assets/logos/mcp_logo.png b/ui/litellm-dashboard/public/assets/logos/mcp_logo.png new file mode 100644 index 000000000000..d920e50e7f22 Binary files /dev/null and b/ui/litellm-dashboard/public/assets/logos/mcp_logo.png differ diff --git a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx new file mode 100644 index 000000000000..3faeb50dd713 --- /dev/null +++ b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx @@ -0,0 +1,251 @@ +import React, { useState } from "react"; +import { + Modal, + Tooltip, + Form, + Select, + message, + Button as AntdButton, +} from "antd"; +import { InfoCircleOutlined } from "@ant-design/icons"; +import { Button, TextInput } from "@tremor/react"; +import { createMCPServer } from "../networking"; +import { MCPServer } from "./types"; +import { isAdminRole } from "@/utils/roles"; + +interface CreateMCPServerProps { + userRole: string; + accessToken: string | null; + onCreateSuccess: (newMcpServer: MCPServer) => void; +} + +const CreateMCPServer: React.FC = ({ + userRole, + accessToken, + onCreateSuccess, +}) => { + const [form] = Form.useForm(); + const [isLoading, setIsLoading] = useState(false); + + const handleCreate = async (formValues: Record) => { + setIsLoading(true); + try { + console.log(`formValues: ${JSON.stringify(formValues)}`); + + if (accessToken != null) { + const response: MCPServer = await createMCPServer( + accessToken, + formValues + ); + + message.success("MCP Server created successfully"); + form.resetFields(); + setModalVisible(false); + onCreateSuccess(response); + } + } catch (error) { + message.error("Error creating MCP Server: " + error, 20); + } finally { + setIsLoading(false); + } + }; + + // state + const [isModalVisible, setModalVisible] = useState(false); + + const handleCancel = () => { + form.resetFields(); + setModalVisible(false); + }; + + // rendering + if (!isAdminRole(userRole)) { + return null; + } + + return ( +
+ + + +
+ MCP Logo +
+
+

Create New MCP Server

+

Configure your MCP server connection

+
+
+ } + open={isModalVisible} + width={1000} + onCancel={handleCancel} + footer={null} + className="top-8" + styles={{ + body: { padding: '24px' }, + header: { padding: '24px 24px 0 24px', border: 'none' }, + }} + > +
+
+
+ + MCP Server Name + + + + + } + name="alias" + rules={[ + { required: false, message: "Please enter a server name" }, + ]} + > + + + + Description} + name="description" + rules={[ + { + required: false, + message: "Please enter a server description", + }, + ]} + > + + + + + MCP Server URL * + + } + name="url" + rules={[ + { required: true, message: "Please enter a server URL" }, + { type: 'url', message: "Please enter a valid URL" } + ]} + > + + + +
+ + Transport Type * + + } + name="transport" + rules={[{ required: true, message: "Please select a transport type" }]} + > + + + + + Authentication * + + } + name="auth_type" + rules={[{ required: true, message: "Please select an auth type" }]} + > + + +
+ + + MCP Version * + + + + + } + name="spec_version" + rules={[ + { required: true, message: "Please select a spec version" }, + ]} + > + + +
+ +
+ + +
+
+
+ + + ); +}; + +export default CreateMCPServer; \ No newline at end of file diff --git a/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.tsx b/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.tsx index 6b5a66c11692..6922788d0a41 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.tsx @@ -6,12 +6,8 @@ import { PencilAltIcon, TrashIcon } from "@heroicons/react/outline"; import { Modal, Tooltip, - Form, - Select, message, - Button as AntdButton, } from "antd"; -import { InfoCircleOutlined } from "@ant-design/icons"; import { Table, @@ -29,7 +25,6 @@ import { } from "@tremor/react"; import { - createMCPServer, deleteMCPServer, fetchMCPServers, } from "../networking"; @@ -41,158 +36,13 @@ import { } from "./types"; import { isAdminRole } from "@/utils/roles"; import { MCPServerView } from "./mcp_server_view"; +import CreateMCPServer from "./create_mcp_server"; const displayFriendlyId = (id: string) => { return `${id.slice(0, 7)}...`; }; -interface CreateMCPServerProps { - userRole: string; - accessToken: string | null; - onCreateSuccess: (newMcpServer: MCPServer) => void; -} - -const CreateMCPServer: React.FC = ({ - userRole, - accessToken, - onCreateSuccess, -}) => { - const [form] = Form.useForm(); - - const handleCreate = async (formValues: Record) => { - try { - console.log(`formValues: ${JSON.stringify(formValues)}`); - - if (accessToken != null) { - const response: MCPServer = await createMCPServer( - accessToken, - formValues - ); - - message.success("MCP Server created successfully"); - form.resetFields(); - setModalVisible(false); - onCreateSuccess(response); - } - } catch (error) { - message.error("Error creating the team: " + error, 20); - } - }; - - // state - const [isModalVisible, setModalVisible] = useState(false); - // rendering - if (!isAdminRole(userRole)) { - return null; - } - - return ( -
- - - setModalVisible(false)} - okButtonProps={{ style: { display: "none" } }} - > -
- <> - - - - - - - - - - - - - - - - - MCP Version{" "} - - - - - } - name="spec_version" - rules={[ - { required: true, message: "Please enter a spec version" }, - ]} - > - - - -
- Create MCP Server -
-
-
-
- ); -}; interface DeleteModalProps { isModalOpen: boolean;