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 ?? resourceMetadataUrlView on GitHub (pinned to 2b7df46e8a)
Solutions
- Prefix the URL with https:// (or http:// for local dev).
- Fix config that stores scheme-less hosts: normalize by adding the scheme before calling discovery.
- 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
- Always store MCP server URLs with an explicit scheme in configuration
- Validate URL scheme at config-load time with a Zod schema (z.url() + protocol refine)
- Remember scheme-less "host:port" strings parse with a bogus protocol — always normalize first
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
- DEN_API_PUBLIC_URL cannot contain credentials, a query strin
- An enterprise MCP server URL must use HTTP or HTTPS.
- An enterprise MCP server URL cannot contain a fragment.
- OpenWork-managed OAuth requires a remote MCP URL.
- invalid_payload
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/eec243f1c6b58b7c.
Report an issue: GitHub.