Skip to content

[UI] Polish New MCP Server Add Form #11604

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
251 changes: 251 additions & 0 deletions ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx
Original file line number Diff line number Diff line change
@@ -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<CreateMCPServerProps> = ({
userRole,
accessToken,
onCreateSuccess,
}) => {
const [form] = Form.useForm();
const [isLoading, setIsLoading] = useState(false);

const handleCreate = async (formValues: Record<string, any>) => {
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 (
<div>
<Button
className="mx-auto"
onClick={() => setModalVisible(true)}
>
+ Create New MCP Server
</Button>

<Modal
title={
<div className="flex items-center space-x-3 pb-4 border-b border-gray-100">
<div className="w-10 h-10 bg-white rounded-lg flex items-center justify-center shadow-sm border border-gray-200">
<img
src="/assets/logos/mcp_logo.png"
alt="MCP Logo"
className="w-8 h-8 object-contain"
/>
</div>
<div>
<h2 className="text-xl font-semibold text-gray-900">Create New MCP Server</h2>
<p className="text-sm text-gray-500 mt-1">Configure your MCP server connection</p>
</div>
</div>
}
open={isModalVisible}
width={1000}
onCancel={handleCancel}
footer={null}
className="top-8"
styles={{
body: { padding: '24px' },
header: { padding: '24px 24px 0 24px', border: 'none' },
}}
>
<div className="mt-6">
<Form
form={form}
onFinish={handleCreate}
layout="vertical"
className="space-y-6"
>
<div className="grid grid-cols-1 gap-6">
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
MCP Server Name
<Tooltip title="Best practice: Use a descriptive name that indicates the server's purpose (e.g., 'GitHub Integration', 'Email Service')">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="alias"
rules={[
{ required: false, message: "Please enter a server name" },
]}
>
<TextInput
placeholder="e.g., GitHub MCP, Zapier MCP, etc."
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>

<Form.Item
label={<span className="text-sm font-medium text-gray-700">Description</span>}
name="description"
rules={[
{
required: false,
message: "Please enter a server description",
},
]}
>
<TextInput
placeholder="Brief description of what this server does"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>

<Form.Item
label={
<span className="text-sm font-medium text-gray-700">
MCP Server URL <span className="text-red-500">*</span>
</span>
}
name="url"
rules={[
{ required: true, message: "Please enter a server URL" },
{ type: 'url', message: "Please enter a valid URL" }
]}
>
<TextInput
placeholder="https://your-mcp-server.com"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>

<div className="grid grid-cols-2 gap-4">
<Form.Item
label={
<span className="text-sm font-medium text-gray-700">
Transport Type <span className="text-red-500">*</span>
</span>
}
name="transport"
rules={[{ required: true, message: "Please select a transport type" }]}
>
<Select
placeholder="Select transport"
className="rounded-lg"
size="large"
>
<Select.Option value="sse">Server-Sent Events (SSE)</Select.Option>
<Select.Option value="http">HTTP</Select.Option>
</Select>
</Form.Item>

<Form.Item
label={
<span className="text-sm font-medium text-gray-700">
Authentication <span className="text-red-500">*</span>
</span>
}
name="auth_type"
rules={[{ required: true, message: "Please select an auth type" }]}
>
<Select
placeholder="Select auth type"
className="rounded-lg"
size="large"
>
<Select.Option value="none">None</Select.Option>
<Select.Option value="api_key">API Key</Select.Option>
<Select.Option value="bearer_token">Bearer Token</Select.Option>
<Select.Option value="basic">Basic Auth</Select.Option>
</Select>
</Form.Item>
</div>

<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
MCP Version <span className="text-red-500 ml-1">*</span>
<Tooltip title="Select the MCP specification version your server supports">
<InfoCircleOutlined className="ml-2 text-gray-400 hover:text-gray-600" />
</Tooltip>
</span>
}
name="spec_version"
rules={[
{ required: true, message: "Please select a spec version" },
]}
>
<Select
placeholder="Select MCP version"
className="rounded-lg"
size="large"
>
<Select.Option value="2025-03-26">2025-03-26 (Latest)</Select.Option>
<Select.Option value="2024-11-05">2024-11-05</Select.Option>
</Select>
</Form.Item>
</div>

<div className="flex items-center justify-end space-x-3 pt-6 border-t border-gray-100">
<Button
variant="secondary"
onClick={handleCancel}
>
Cancel
</Button>
<Button
variant="primary"
loading={isLoading}
>
{isLoading ? 'Creating...' : 'Create MCP Server'}
</Button>
</div>
</Form>
</div>
</Modal>
</div>
);
};

export default CreateMCPServer;
Loading
Loading