+
)}
))}
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
index 22654fa67d..65d493a495 100644
--- a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx
+++ b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx
@@ -6,15 +6,15 @@ import {
Select,
message,
Button as AntdButton,
- Space,
Input,
} from "antd";
-import { InfoCircleOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
+import { InfoCircleOutlined } from "@ant-design/icons";
import { Button, TextInput } from "@tremor/react";
import { createMCPServer } from "../networking";
import { MCPServer, MCPServerCostInfo } from "./types";
import MCPServerCostConfig from "./mcp_server_cost_config";
import MCPConnectionStatus from "./mcp_connection_status";
+import StdioConfiguration from "./StdioConfiguration";
import { isAdminRole } from "@/utils/roles";
@@ -38,6 +38,7 @@ const CreateMCPServer: React.FC = ({
const [mcpAccessGroups, setMcpAccessGroups] = useState([]);
const [formValues, setFormValues] = useState>({});
const [tools, setTools] = useState([]);
+ const [transportType, setTransportType] = useState('sse');
const handleCreate = async (formValues: Record) => {
setIsLoading(true);
@@ -46,9 +47,51 @@ const CreateMCPServer: React.FC = ({
const accessGroups = formValues.mcp_access_groups
+ // Process stdio configuration if present
+ let stdioFields = {};
+ if (formValues.stdio_config && transportType === 'stdio') {
+ try {
+ const stdioConfig = JSON.parse(formValues.stdio_config);
+
+ // Handle both formats:
+ // 1. Full mcpServers structure: {"mcpServers": {"server-name": {...}}}
+ // 2. Direct config: {"command": "...", "args": [...], "env": {...}}
+
+ let actualConfig = stdioConfig;
+
+ // If it's the full mcpServers structure, extract the first server config
+ if (stdioConfig.mcpServers && typeof stdioConfig.mcpServers === 'object') {
+ const serverNames = Object.keys(stdioConfig.mcpServers);
+ if (serverNames.length > 0) {
+ const firstServerName = serverNames[0];
+ actualConfig = stdioConfig.mcpServers[firstServerName];
+
+ // If no alias is provided, use the server name from the JSON
+ if (!formValues.alias) {
+ formValues.alias = firstServerName.replace(/-/g, '_'); // Replace hyphens with underscores
+ }
+ }
+ }
+
+ stdioFields = {
+ command: actualConfig.command,
+ args: actualConfig.args,
+ env: actualConfig.env
+ };
+
+ console.log('Parsed stdio config:', stdioFields);
+ } catch (error) {
+ message.error("Invalid JSON in stdio configuration");
+ return;
+ }
+ }
+
// Prepare the payload with cost configuration
const payload = {
...formValues,
+ ...stdioFields,
+ // Remove the raw stdio_config field as we've extracted its components
+ stdio_config: undefined,
mcp_info: {
server_name: formValues.alias || formValues.url,
description: formValues.description,
@@ -89,7 +132,15 @@ const CreateMCPServer: React.FC = ({
setModalVisible(false);
};
-
+ const handleTransportChange = (value: string) => {
+ setTransportType(value);
+ // Clear fields that are not relevant for the selected transport
+ if (value === 'stdio') {
+ form.setFieldsValue({ url: undefined, auth_type: undefined });
+ } else {
+ form.setFieldsValue({ command: undefined, args: undefined, env: undefined });
+ }
+ };
// rendering
if (!isAdminRole(userRole)) {
@@ -186,41 +237,48 @@ const CreateMCPServer: React.FC = ({
- MCP Server URL
+ Transport Type
}
- name="url"
- rules={[
- { required: true, message: "Please enter a server URL" },
- { type: 'url', message: "Please enter a valid URL" }
- ]}
+ name="transport"
+ rules={[{ required: true, message: "Please select a transport type" }]}
>
-
+
-
+ {/* URL field - only show for HTTP and SSE */}
+ {transportType !== 'stdio' && (
- Transport Type
+ MCP Server URL
}
- name="transport"
- rules={[{ required: true, message: "Please select a transport type" }]}
+ name="url"
+ rules={[
+ { required: true, message: "Please enter a server URL" },
+ { type: 'url', message: "Please enter a valid URL" }
+ ]}
>
-
+
+ )}
+ {/* Authentication - only show for HTTP and SSE */}
+ {transportType !== 'stdio' && (
@@ -241,7 +299,10 @@ const CreateMCPServer: React.FC = ({
Basic Auth
-
+ )}
+
+ {/* Stdio Configuration - only show for stdio transport */}
+ {
export interface InputSchemaProperty {
type: string;
description?: string;
+ properties?: Record; // For nested object properties
+ required?: string[]; // For required fields in nested objects
+ enum?: string[]; // For enum values
+ default?: any; // For default values
}
// Define the structure for the input schema of a tool