different-ai/openwork · error · LocalManagedMcpPrivateUrlError
managed MCP egress requires HTTPS
Error message
managed MCP egress requires HTTPS
What it means
Managed MCP server connections must use HTTPS so outbound traffic from the host is encrypted. assertLocalManagedMcpUrl rejects any http:// URL before a connection is created, throwing LocalManagedMcpPrivateUrlError with this message. It is a deliberate egress-security policy: the guard only allows plain HTTP when private URLs are explicitly permitted.
Source
Thrown at apps/server/src/local-managed-mcp-url-guard.ts:173
return;
}
if (options.all) {
callback(null, addresses);
return;
}
const first = addresses[0];
callback(null, first.address, first.family);
}, (error: unknown) => {
callback(error instanceof Error ? error : new Error("Managed MCP hostname lookup failed."), []);
});
};
}
export async function assertLocalManagedMcpUrl(rawUrl: string): Promise<void> {
const url = parseHttpUrl(rawUrl);
if (allowPrivateUrls()) return;
if (url.protocol !== "https:") {
throw new LocalManagedMcpPrivateUrlError(rawUrl, "managed MCP egress requires HTTPS");
}
const hostname = url.hostname.replace(/^\[|\]$/g, "");
if (isIP(hostname)) {
if (isLocalManagedMcpPrivateAddress(hostname)) {
throw new LocalManagedMcpPrivateUrlError(rawUrl, "the address is private or reserved");
}
return;
}
let addresses: LookupAddress[];
try {
addresses = await resolveAddresses(hostname, { all: true, verbatim: true });
} catch {
throw new LocalManagedMcpPrivateUrlError(rawUrl, "the hostname does not resolve");
}
validateResolvedAddresses(hostname, addresses);
}
type FetchLike = (url: string | URL, init?: RequestInit) => Promise<Response>;View on GitHub (pinned to 2b7df46e8a)
Solutions
- Serve the MCP endpoint over HTTPS and change the URL scheme to https://
- Put a TLS-terminating proxy (e.g. ngrok, caddy) in front of a local HTTP server and use the https URL
- Enable the private-URL allowance for the environment (the allowPrivateUrls() switch) if this is intentionally a local/dev connection
- Verify the URL was not truncated or rewritten, losing an https scheme
Example fix
// before
await createLocalManagedMcpConnection({ url: "http://mcp.example.com/mcp" });
// after
await createLocalManagedMcpConnection({ url: "https://mcp.example.com/mcp" }); Defensive patterns
Strategy: validation
Validate before calling
const url = new URL(rawUrl);
if (url.protocol !== "https:") {
throw new Error(`MCP URL must use https://, got: ${url.protocol}`);
} Type guard
function isHttpsUrl(rawUrl: string): boolean {
try {
return new URL(rawUrl).protocol === "https:";
} catch {
return false;
}
} Try / catch
try {
await createLocalManagedMcpConnection({ url });
} catch (error) {
if (error instanceof LocalManagedMcpPrivateUrlError && error.message === "managed MCP egress requires HTTPS") {
// surface a config-fix message: switch endpoint to https://
}
throw error;
} Prevention
- Always configure MCP endpoints with explicit https:// schemes
- Put local dev servers behind a TLS proxy (ngrok, caddy) instead of using http://
- Add a startup config validation that rejects non-https MCP URLs early
- Keep dev-only insecure-URL allowances limited to local environments
When it happens
Trigger: Calling createLocalManagedMcpConnection or withRemoteClient with a rawUrl whose parsed protocol is http: while allowPrivateUrls() is false (the default).
Common situations: Pointing a managed MCP connection at a local dev server (http://localhost:3000/mcp) or an internal test endpoint without TLS; configuring an MCP server URL copied from docs that default to http; missing the env/config flag that permits private/insecure URLs in dev.
Related errors
- External URL protocol "${parsed.protocol}" is not allowed.
- the address is private or reserved
- an HTTPS request cannot redirect to a less secure protocol
- connect-link claims contain a non-https URL: ${insecure}
- Only valid web links can be opened externally.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/a2adc6e7cbd1b3d0.
Report an issue: GitHub.