{"record":{"id":"9b4dd01f67dd8ed1","repo":"n8n-io/n8n","slug":"mcp-server-server-name-invalid-url-server","errorCode":null,"errorMessage":"MCP server \"${server.name}\": invalid URL \"${server.url}\"","messagePattern":"MCP server \"(.+?)\": invalid URL \"(.+?)\"","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/instance-ai/src/mcp/mcp-client-manager.ts","lineNumber":232,"sourceCode":"\t\t})();\n\n\t\tinFlight.set(key, promise);\n\t\ttry {\n\t\t\treturn await promise;\n\t\t} finally {\n\t\t\tinFlight.delete(key);\n\t\t}\n\t}\n\n\tprivate async validateConfigs(configs: McpServerConfig[]): Promise<void> {\n\t\tfor (const server of configs) {\n\t\t\tif (!server.url) continue;\n\n\t\t\tlet parsed: URL;\n\t\t\ttry {\n\t\t\t\tparsed = new URL(server.url);\n\t\t\t} catch {\n\t\t\t\tthrow new UserError(`MCP server \"${server.name}\": invalid URL \"${server.url}\"`);\n\t\t\t}\n\n\t\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n\t\t\t\tthrow new UserError(\n\t\t\t\t\t`MCP server \"${server.name}\": only http(s) URLs are allowed, got \"${parsed.protocol}\"`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (this.ssrfValidator) {\n\t\t\t\tconst result = await this.ssrfValidator.validateUrl(server.url);\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\tthrow new UserError(\n\t\t\t\t\t\t`MCP server \"${server.name}\": URL blocked by SSRF policy - ${result.error.message}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/instance-ai/src/mcp/mcp-client-manager.ts#L214-L250","documentation":"Thrown by McpClientManager.validateConfigs when a configured MCP server has a non-empty url that cannot be parsed by the URL constructor. This is a UserError — the user supplied an invalid configuration. The check is the first of three (parseability, http(s) protocol, SSRF safety); only the parse step throws this specific message.","triggerScenarios":"server.url is a relative path, a bare hostname without scheme, contains illegal characters, has malformed port, or is otherwise not a valid absolute URL string.","commonSituations":"User enters 'localhost:3000' (missing scheme) instead of 'http://localhost:3000'; a trailing slash in an unexpected position; copy-paste introduced a stray character; env-var templating left a placeholder unresolved.","solutions":["Provide an absolute URL with an explicit scheme, e.g. 'https://mcp.example.com/sse'.","If using a local server, prefix 'http://' (e.g. 'http://localhost:3000').","Validate the URL string with `new URL(server.url)` in a scratch script to reproduce the exact parse failure."],"exampleFix":"// before — missing scheme\n{ name: 'my-mcp', url: 'mcp.local:3000/sse' }\n\n// after — absolute http(s) URL\n{ name: 'my-mcp', url: 'http://mcp.local:3000/sse' }","handlingStrategy":"validation","validationCode":"function isValidMcpUrl(url: string): boolean {\n  try {\n    const parsed = new URL(url);\n    return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n  } catch {\n    return false;\n  }\n}\n\nfor (const server of configs) {\n  if (server.url && !isValidMcpUrl(server.url)) {\n    throw new Error(`server ${server.name} has an invalid MCP url: ${server.url}`);\n  }\n}","typeGuard":"function isParseableHttpUrl(url: string): boolean {\n  try {\n    const p = new URL(url);\n    return p.protocol === 'http:' || p.protocol === 'https:';\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":"import { UserError } from 'n8n-workflow';\n\ntry {\n  await manager.validateConfigs(configs);\n} catch (e) {\n  if (e instanceof UserError && /invalid URL/.test(e.message)) {\n    // surface the offending server config to the user; do not retry as-is\n  }\n  throw e;\n}","preventionTips":["Always include the scheme (http:// or https://) in MCP server URLs.","Validate URLs in the config form before persisting.","Reject empty/bare-hostname URLs at the input boundary."],"tags":["mcp","url-validation","user-error","configuration"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}