From 8a4a40844e12f48820f285619a2896b79e2884e1 Mon Sep 17 00:00:00 2001 From: Cole McIntosh <82463175+colesmcintosh@users.noreply.github.com> Date: Tue, 29 Jul 2025 14:36:19 -0600 Subject: [PATCH] fix: improve MCP server URL validation to support internal/Kubernetes URLs (#13099) * fix: improve MCP server URL validation to support internal/Kubernetes URLs - Replace strict Ant Design URL validator with flexible custom validator - Allow URLs like http://service-name.domain.svc.cluster.:1234/mcp - Update both create and edit MCP server forms for consistency * refactor: extract MCP server validation into reusable utilities - Move URL validation logic to utils.tsx to follow DRY principles - Add validateMCPServerUrl function for flexible URL validation - Add validateMCPServerName function for hyphen validation - Update both create and edit components to use shared utilities - Reduces code duplication and improves maintainability --- .../components/mcp_tools/create_mcp_server.tsx | 10 +++------- .../src/components/mcp_tools/mcp_server_edit.tsx | 16 +++++++--------- .../src/components/mcp_tools/utils.tsx | 16 ++++++++++++++++ 3 files changed, 26 insertions(+), 16 deletions(-) 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 445d857871e..8076a154738 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 @@ -8,6 +8,7 @@ import MCPServerCostConfig from "./mcp_server_cost_config" import MCPConnectionStatus from "./mcp_connection_status" import StdioConfiguration from "./StdioConfiguration" import { isAdminRole } from "@/utils/roles" +import { validateMCPServerUrl, validateMCPServerName } from "./utils" const asset_logos_folder = "../ui/assets/logos/" export const mcpLogoImg = `${asset_logos_folder}mcp_logo.png` @@ -228,12 +229,7 @@ const CreateMCPServer: React.FC = ({ name="server_name" rules={[ { required: false, message: "Please enter a server name" }, - { - validator: (_, value) => - value && value.includes("-") - ? Promise.reject("Server name cannot contain '-' (hyphen). Please use '_' (underscore) instead.") - : Promise.resolve(), - }, + { validator: (_, value) => validateMCPServerName(value) }, ]} > = ({ name="url" rules={[ { required: true, message: "Please enter a server URL" }, - { type: "url", message: "Please enter a valid URL" }, + { validator: (_, value) => validateMCPServerUrl(value) }, ]} > = ({ mcpServer, accessToken, o
- value && value.includes('-') - ? Promise.reject("Server name cannot contain '-' (hyphen). Please use '_' (underscore) instead.") - : Promise.resolve(), + validator: (_, value) => validateMCPServerName(value), }]}> - value && value.includes('-') - ? Promise.reject("Alias cannot contain '-' (hyphen). Please use '_' (underscore) instead.") - : Promise.resolve(), + validator: (_, value) => validateMCPServerName(value), }]} > setAliasManuallyEdited(true)} /> @@ -163,7 +158,10 @@ const MCPServerEdit: React.FC = ({ mcpServer, accessToken, o - + validateMCPServerUrl(value) }, + ]}> diff --git a/ui/litellm-dashboard/src/components/mcp_tools/utils.tsx b/ui/litellm-dashboard/src/components/mcp_tools/utils.tsx index 0ff52296f1d..38d1bf6cafd 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/utils.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/utils.tsx @@ -34,4 +34,20 @@ export const getMaskedAndFullUrl = (url: string): { maskedUrl: string, hasToken: maskedUrl: maskUrl(url), hasToken: !!token }; +}; + +// Validation utilities for MCP server forms +export const validateMCPServerUrl = (value: string) => { + if (!value) return Promise.resolve(); + // More flexible URL validation that allows Kubernetes service names and various URL formats + const urlPattern = /^https?:\/\/[^\s/$.?#].[^\s]*$/i; + return urlPattern.test(value) + ? Promise.resolve() + : Promise.reject("Please enter a valid URL (e.g., http://service-name.domain:1234/path or https://example.com)"); +}; + +export const validateMCPServerName = (value: string) => { + return value && value.includes("-") + ? Promise.reject("Server name cannot contain '-' (hyphen). Please use '_' (underscore) instead.") + : Promise.resolve(); }; \ No newline at end of file