different-ai/openwork · critical

MCP_URL_BLOCKED

MCP_URL_BLOCKED

Error message

MCP_URL_BLOCKED

What it means

MCP_URL_BLOCKED is raised when the configured MCP endpoint fails the gateway's SSRF guard, thrown as PrivateUrlError and classified as CONFIGURATION / security_blocked. The gateway deliberately refuses to call private/internal network addresses (loopback, RFC1918, link-local, metadata endpoints) from external MCP sources. It is non-retryable and owned by the organization admin since it requires either a public URL or an explicit policy change through security review.

Source

Thrown at ee/apps/den-api/src/capability-sources/external-mcp-diagnostics.ts:1201

        ? "Retry the capability, and reduce provider latency for this tool if it keeps running past the bounded deadline."
        : "Reduce provider latency or catalog pagination so the complete MCP lifecycle finishes within the bounded deadline, then retry.",
    }
  }
  if (error instanceof ExternalMcpResponseBodyLimitError) {
    return {
      phase: fallbackPhase,
      category: "response_too_large",
      code: "MCP_RESPONSE_BODY_LIMIT",
      retryable: false,
      actionOwner: "provider_admin",
      operatorAction: "Reduce the provider response size, tool catalog, or event-stream payload before retrying.",
    }
  }
  if (error instanceof PrivateUrlError) {
    return {
      phase: "CONFIGURATION",
      category: "security_blocked",
      code: "MCP_URL_BLOCKED",
      retryable: false,
      actionOwner: "organization_admin",
      operatorAction: "Use a public HTTPS MCP URL or change the deployment's private-network policy through security review.",
    }
  }
  if (hasForbiddenPortMessage(error)) {
    return {
      phase: "CONFIGURATION",
      category: "unsupported_endpoint_port",
      code: "MCP_FETCH_FORBIDDEN_PORT",
      retryable: false,
      actionOwner: "organization_admin",
      operatorAction: "Use the provider's supported HTTPS MCP port or place the endpoint behind a standard HTTPS listener.",
    }
  }

  const code = errorCode(error)
  if (code) {

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Use a public HTTPS MCP URL that the gateway can reach from its network.
  2. If internal access is genuinely required, change the deployment's private-network policy through security review to allowlist the address.
  3. Expose the internal MCP server via an approved public gateway/tunnel that passes the private-URL check.

Example fix

// before: private dev URL in external source config
{ "url": "http://localhost:8080/mcp" }
// after
{ "url": "https://mcp.mycompany.example.com/mcp" }
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight the configured URL against the private-address rules
function isPublicHttpsUrl(raw: string): boolean {
  const u = new URL(raw)
  if (u.protocol !== 'https:') return false
  const host = u.hostname
  if (host === 'localhost' || host.endsWith('.local')) return false
  if (/^(10\.|127\.|192\.168\.|169\.254\.|172\.(1[6-9]|2\d|3[01])\.)/.test(host)) return false
  return true
}
if (!isPublicHttpsUrl(config.url)) throw new Error('MCP URL must be public HTTPS')

Type guard

function isUrlBlocked(d: { code: string }): boolean {
  return d.code === 'MCP_URL_BLOCKED'
}

Try / catch

try {
  return await connectExternalMcp(config)
} catch (e) {
  if (isUrlBlocked(e.diagnostic)) {
    // non-retryable: configuration must change; do not attempt to bypass the SSRF guard
    throw new Error(`blocked private MCP URL: ${config.url} — use public HTTPS or request a policy exception`)
  }
  throw e
}

Prevention

When it happens

Trigger: Registering or invoking an external MCP capability whose URL resolves to a private address — e.g. http://localhost:8080/mcp, http://10.x.x.x/mcp, http://192.168.x.x/mcp, or a hostname that DNS-resolves to a private IP — triggering the PrivateUrlError check during request setup.

Common situations: Developers pointing the external MCP source at a local dev server; internal-only providers behind VPC addresses; DNS names that resolve to private IPs inside the deployment network; attempts to reach cloud metadata services (accidental or malicious).

Related errors


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