different-ai/openwork · error · Error

An enterprise MCP server URL must use HTTP or HTTPS.

Error message

An enterprise MCP server URL must use HTTP or HTTPS.

What it means

discoverConnectionRequirements validates the serverUrl with the URL constructor and rejects any protocol other than http: or https: before making any network request. Enterprise MCP servers are HTTP-based, so schemes like file:, ws:, or ftp: cannot be discovered. The message comes from a plain Error thrown at the very start of discovery.

Source

Thrown at packages/enterprise-mcp-client/src/requirements-discovery.ts:190

    input.authenticationRequired
    && !input.authorizationServers.some((server) => server.clientIdMetadataDocumentSupported || server.registrationEndpoint)
  ) {
    requirements.unshift({
      code: "oauth_client_registration",
      label: "Register an OAuth client",
      reason: "The authorization server does not advertise client metadata documents or dynamic registration.",
      required: true,
    })
  }
  return requirements
}

export async function discoverConnectionRequirements(
  input: DiscoverEnterpriseMcpConnectionRequirementsInput,
): Promise<EnterpriseMcpConnectionRequirements> {
  const serverUrl = new URL(input.serverUrl)
  if (serverUrl.protocol !== "http:" && serverUrl.protocol !== "https:") {
    throw new Error("An enterprise MCP server URL must use HTTP or HTTPS.")
  }
  if (serverUrl.username || serverUrl.password || serverUrl.hash) {
    throw new Error("An enterprise MCP server URL cannot contain credentials or a fragment.")
  }

  const controller = new AbortController()
  const timeout = setTimeout(() => controller.abort(new Error("MCP requirements discovery timed out.")), input.timeoutMs ?? DEFAULT_TIMEOUT_MS)
  let lastStatus: number | undefined
  let resourceMetadataUrl: URL | undefined
  let challengeScope: string | undefined
  const fetch = scopedFetch({
    fetch: input.fetch,
    signal: controller.signal,
    observe: (response) => {
      lastStatus = response.status
      if (response.status !== 401 && response.status !== 403) return
      const challenge = extractWWWAuthenticateParams(response)
      resourceMetadataUrl = challenge.resourceMetadataUrl ?? resourceMetadataUrl

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Prefix the URL with https:// (or http:// for local dev).
  2. Fix config that stores scheme-less hosts: normalize by adding the scheme before calling discovery.
  3. Use the streamable-HTTP MCP transport for enterprise servers, not raw ws:// URLs, in this discovery API.

Example fix

// before
serverUrl: "mcp.internal.example.com/mcp"
// after
serverUrl: "https://mcp.internal.example.com/mcp"
Defensive patterns

Strategy: validation

Validate before calling

function assertHttpUrl(serverUrl: string): URL {
  const u = new URL(serverUrl)
  if (u.protocol !== "http:" && u.protocol !== "https:") {
    throw new Error(`serverUrl must start with http:// or https://, got "${u.protocol}"`)
  }
  return u
}

Type guard

function isHttpUrl(value: string): boolean {
  try { const u = new URL(value); return u.protocol === "http:" || u.protocol === "https:" }
  catch { return false }
}

Try / catch

try { const reqs = await discoverConnectionRequirements({ serverUrl }) }
catch (e) {
  if (e.message.includes("must use HTTP or HTTPS")) {
    throw new Error(`Invalid server URL "${serverUrl}": add an http:// or https:// scheme`)
  }
  throw e
}

Prevention

When it happens

Trigger: Passing a serverUrl whose parsed protocol is not http/https — e.g. "mcp.example.com" with no scheme (URL parsing fails or yields a file: style path is a different error; here explicitly ws://, ftp://, etc.), or a URL like "localhost:8080" which parses as protocol "localhost:".

Common situations: Omitting the scheme entirely so "localhost:8080" is parsed with protocol "localhost:"; hardcoding a ws:// URL meant for a raw WebSocket MCP transport; copying a non-HTTP endpoint from another tool's config.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/eec243f1c6b58b7c. Report an issue: GitHub.