{"record":{"id":"170c04cb4df25eb5","repo":"different-ai/openwork","slug":"invalid-mcp-url","errorCode":"invalid_mcp_url","errorMessage":"MCP server URL is invalid.","messagePattern":"MCP server URL is invalid\\.","errorType":"http","errorClass":"PluginArchRouteFailure","httpStatus":400,"severity":"error","filePath":"ee/apps/den-api/src/routes/org/plugin-system/store.ts","lineNumber":4913,"sourceCode":"  return { config: entry.config, name: entry.name, url }\n}\n\nfunction configVersionOwnsImportedExternalMcpConnection(version: ConfigObjectVersionRow, connectionId: string) {\n  const spec = parseConfigObjectVersionSpec(version)\n  const metadata = isRecord(spec.metadata) ? spec.metadata : null\n  const recordedConnectionId = readRecordString(spec, \"externalMcpConnectionId\")\n    || (metadata ? readRecordString(metadata, \"externalMcpConnectionId\") : null)\n  const owned = spec.externalMcpConnectionOwnedByPlugin === true\n    || metadata?.externalMcpConnectionOwnedByPlugin === true\n  return owned && recordedConnectionId === connectionId\n}\n\nasync function assertRemotePluginMcpUrl(url: string) {\n  let parsed: URL\n  try {\n    parsed = new URL(url)\n  } catch {\n    throw new PluginArchRouteFailure(400, \"invalid_mcp_url\", \"MCP server URL is invalid.\")\n  }\n\n  if (parsed.protocol !== \"https:\" && parsed.protocol !== \"http:\") {\n    throw new PluginArchRouteFailure(400, \"invalid_mcp_url\", \"MCP URLs must use HTTP or HTTPS.\")\n  }\n  if (parsed.protocol === \"http:\" && !env.allowPrivateMcpUrls) {\n    throw new PluginArchRouteFailure(400, \"invalid_mcp_url\", \"Hosted MCP connections must use HTTPS.\")\n  }\n  if (parsed.hash) {\n    throw new PluginArchRouteFailure(400, \"invalid_mcp_url\", \"MCP URLs must not contain a fragment.\")\n  }\n  if (parsed.username || parsed.password) {\n    throw new PluginArchRouteFailure(400, \"invalid_mcp_url\", \"MCP URLs must not contain embedded credentials.\")\n  }\n\n  const sensitiveParameters = new Set([\"access_token\", \"api_key\", \"client_secret\", \"token\", \"refresh_token\", \"id_token\", \"code_verifier\"])\n  for (const parameter of parsed.searchParams.keys()) {\n    if (sensitiveParameters.has(parameter.toLowerCase())) {","sourceCodeStart":4895,"sourceCodeEnd":4931,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/routes/org/plugin-system/store.ts#L4895-L4931","documentation":"First gate in assertRemotePluginMcpUrl(): the candidate URL string cannot be parsed by the WHATWG URL constructor. Thrown as PluginArchRouteFailure(400, 'invalid_mcp_url') so callers can distinguish malformed input from policy violations.","triggerScenarios":"Configuring a remote MCP server where the `url` value is not a parseable absolute URL — e.g. 'mcp.example.com' (no scheme), 'localhost:3000/sse' (parsed as scheme localhost), empty string, or containing spaces/illegal characters.","commonSituations":"Users entering a bare hostname without protocol; template placeholders like '${MCP_URL}' left unsubstituted; copy-paste artifacts (trailing spaces, smart quotes); relative URLs pasted from docs.","solutions":["Prepend the scheme: change 'mcp.example.com/sse' to 'https://mcp.example.com/sse'.","Trim whitespace and remove non-ASCII/typographic characters from the stored URL.","Sanity-check in a browser or with `new URL(url)` locally — if it throws, the server will reject it too.","Ensure template variables were substituted before the value reached the config."],"exampleFix":"// before\nurl: \"mcp.example.com:443/sse\"\n// after\nurl: \"https://mcp.example.com/sse\"","handlingStrategy":"validation","validationCode":"function isParseableUrl(value: string): boolean {\n  try { new URL(value.trim()); return true } catch { return false }\n}\nif (!isParseableUrl(url)) throw new Error(`Not an absolute URL: ${url}`)","typeGuard":"function isAbsoluteUrl(value: unknown): value is string {\n  if (typeof value !== \"string\") return false\n  try { new URL(value); return true } catch { return false }\n}","tryCatchPattern":"try {\n  await configureRemoteMcp(url)\n} catch (e) {\n  if (isPluginArchRouteFailure(e) && e.code === \"invalid_mcp_url\") {\n    // prompt user for a full absolute https:// URL\n  }\n}","preventionTips":["Always store MCP URLs with an explicit scheme (https://...)","Trim whitespace before storing URL input","Validate with new URL() in the UI before submitting","Never submit template placeholders unsubstituted"],"tags":["mcp","url","validation"],"backgroundTag":"invalid-url","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}