{"record":{"id":"1bd3a6d52df36f35","repo":"different-ai/openwork","slug":"an-enterprise-mcp-server-url-must-use-http-or-http","errorCode":null,"errorMessage":"An enterprise MCP server URL must use HTTP or HTTPS.","messagePattern":"An enterprise MCP server URL must use HTTP or HTTPS\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/enterprise-mcp-client/src/enterprise-mcp-client.ts","lineNumber":105,"sourceCode":"  observer: EnterpriseMcpRequestObserver\n  controller: AbortController\n  requestOptions: RequestOptions\n  lifecycle: EnterpriseMcpLifecycle\n}\n\nfunction requestInit(authorization: EnterpriseMcpAuthorization): RequestInit | undefined {\n  if (authorization.type !== \"api-key\") return undefined\n  return { headers: { authorization: `Bearer ${authorization.token}` } }\n}\n\nfunction validateConnection(connection: EnterpriseMcpConnection): URL {\n  const parsed = connectionSchema.parse({ id: connection.id, serverUrl: connection.serverUrl })\n  if (connection.authorization.type === \"api-key\" && !connection.authorization.token.trim()) {\n    throw new Error(\"An API key connection requires a non-empty token.\")\n  }\n  const url = new URL(parsed.serverUrl)\n  if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n    throw new Error(\"An enterprise MCP server URL must use HTTP or HTTPS.\")\n  }\n  if (url.username || url.password) {\n    throw new Error(\"An enterprise MCP server URL cannot contain embedded credentials.\")\n  }\n  if (url.hash) throw new Error(\"An enterprise MCP server URL cannot contain a fragment.\")\n  return url\n}\n\nfunction validateRedirectUri(redirectUri: string): string {\n  const parsed = redirectUriSchema.parse(redirectUri)\n  const url = new URL(parsed)\n  if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n    throw new Error(\"An enterprise MCP OAuth redirect URI must use HTTP or HTTPS.\")\n  }\n  if (url.username || url.password || url.hash) {\n    throw new Error(\"An enterprise MCP OAuth redirect URI cannot contain credentials or a fragment.\")\n  }\n  return parsed","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/enterprise-mcp-client/src/enterprise-mcp-client.ts#L87-L123","documentation":"validateConnection in packages/enterprise-mcp-client/src/enterprise-mcp-client.ts parses the serverUrl with a zod URL schema and then checks the resulting URL's protocol; anything other than http: or https: throws. The MCP transport (StreamableHTTPClientTransport) only speaks HTTP, so schemes like ws:, ftp:, or file: are rejected up front.","triggerScenarios":"Creating a connection with serverUrl using a non-HTTP(S) scheme, e.g. \"ws://mcp.example.com\", \"ftp://host\", or a URL that zod accepted but new URL() resolved to another protocol.","commonSituations":"Confusing WebSocket (ws://) URLs — used by the older SSE-style MCP transports — with the HTTP streamable transport; copy-pasting a scheme-less host and a library adding a wrong prefix; typos like \"http//\" that parse oddly.","solutions":["Use an http:// or https:// URL for serverUrl (https:// in production).","If you have a ws:// or wss:// endpoint, find its HTTP streamable equivalent (usually the same host/path without the ws scheme).","Validate the configured URL's protocol before constructing the connection."],"exampleFix":"// before\nserverUrl: \"wss://mcp.example.com/mcp\"\n\n// after\nserverUrl: \"https://mcp.example.com/mcp\"","handlingStrategy":"validation","validationCode":"function assertHttpUrl(serverUrl: string) {\n  const u = new URL(serverUrl)\n  if (u.protocol !== \"https:\" && u.protocol !== \"http:\") {\n    throw new Error(`serverUrl must be http(s), got ${u.protocol}`)\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store canonical https:// URLs in configuration, never ws:// or scheme-less hosts","Normalize endpoints at config load time with new URL() and re-serialize","Add a startup config lint that checks all serverUrl values"],"tags":["configuration","url","validation"],"backgroundTag":"invalid-url-scheme","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}