From 4d855766e21717a5a238afd3f9ce9b779bdafc39 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 23 Feb 2026 23:13:57 +0800 Subject: [PATCH] Add form validation for MCP config modal --- frontend/src/components/mcp-config-modal.tsx | 65 +++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/mcp-config-modal.tsx b/frontend/src/components/mcp-config-modal.tsx index f0476b4..f5d0532 100644 --- a/frontend/src/components/mcp-config-modal.tsx +++ b/frontend/src/components/mcp-config-modal.tsx @@ -80,6 +80,11 @@ export function MCPConfigModal({ isOpen, onClose }: MCPConfigModalProps) { const [url, setUrl] = useState(""); const [isLoading, setIsLoading] = useState(true); const [showAddServerForm, setShowAddServerForm] = useState(false); + const [errors, setErrors] = useState<{ + serverName?: string; + command?: string; + url?: string; + }>({}); // Calculate server statistics const totalServers = Object.keys(configs).length; @@ -98,23 +103,60 @@ export function MCPConfigModal({ isOpen, onClose }: MCPConfigModalProps) { }, [agentState]); const addConfig = () => { - if (!serverName) return; + // Reset errors + setErrors({}); + + // Validate inputs + const newErrors: { + serverName?: string; + command?: string; + url?: string; + } = {}; + + if (!serverName.trim()) { + newErrors.serverName = "Server name is required"; + } else if (configs[serverName.trim()]) { + newErrors.serverName = "Server name already exists"; + } + + if (connectionType === "stdio" && !command.trim()) { + newErrors.command = "Command is required"; + } + + if (connectionType === "sse") { + if (!url.trim()) { + newErrors.url = "URL is required"; + } else { + try { + new URL(url.trim()); + } catch { + newErrors.url = "Invalid URL format"; + } + } + } + + // If there are errors, display them + if (Object.keys(newErrors).length > 0) { + setErrors(newErrors); + return; + } + const trimmedServerName = serverName.trim(); const newConfig = connectionType === "stdio" ? { - command, + command: command.trim(), args: args.split(" ").filter((arg) => arg.trim() !== ""), transport: "stdio" as const, } : { - url, + url: url.trim(), transport: "sse" as const, }; setConfigs({ ...configs, - [serverName]: newConfig, + [trimmedServerName]: newConfig, }); // Reset form @@ -295,9 +337,12 @@ export function MCPConfigModal({ isOpen, onClose }: MCPConfigModalProps) { type="text" value={serverName} onChange={(e) => setServerName(e.target.value)} - className="w-full px-3 py-2 border rounded-md text-sm" + className={`w-full px-3 py-2 border rounded-md text-sm ${errors.serverName ? 'border-red-500' : ''}`} placeholder="e.g., api-service, data-processor" /> + {errors.serverName && ( +

{errors.serverName}

+ )}
@@ -342,9 +387,12 @@ export function MCPConfigModal({ isOpen, onClose }: MCPConfigModalProps) { type="text" value={command} onChange={(e) => setCommand(e.target.value)} - className="w-full px-3 py-2 border rounded-md text-sm" + className={`w-full px-3 py-2 border rounded-md text-sm ${errors.command ? 'border-red-500' : ''}`} placeholder="e.g., python, node" /> + {errors.command && ( +

{errors.command}

+ )}
)}