Hmbown/CodeWhale · error
MCP HTTP destination blocked by network policy
Error message
MCP HTTP destination blocked by network policy
What it means
When a NetworkPolicyDecider is configured, every MCP HTTP destination host is evaluated before any request (initial connect and each redirect). A Decision::Deny produces this error, meaning the host is explicitly forbidden by network policy (e.g. SSRF protection or allowlist enforcement).
Solutions
- Ask the operator to add the host to the network-policy allowlist
- Connect to an allowed public endpoint instead of the blocked host
- Remove/reconfigure the NetworkPolicyDecider only if you own the policy decision and accept the SSRF risk
Example fix
// before
let policy = NetworkPolicy::deny_all();
let client = McpHttpClient::new(url, ..., Some(&policy))?; // bails
// after
policy.allow_host("mcp.example.com");
let client = McpHttpClient::new(url, ..., Some(&policy))?; Defensive patterns
Strategy: validation
Validate before calling
let host = Url::parse(endpoint)?.host_str().ok_or("no host")?.to_string();
match policy.evaluate(&host, "mcp") {
Decision::Allow => { /* safe to connect */ }
Decision::Deny => return Err("host denied by network policy"),
Decision::Prompt => { /* obtain approval first */ }
} Try / catch
match connect(...).await {
Err(e) if e.to_string().contains("blocked by network policy") => {
// request allowlist change from operator; do not retry blindly
}
other => other?,
} Prevention
- Maintain an up-to-date MCP host allowlist with the operator
- Pre-check hosts against policy in tooling before configuring endpoints
- Avoid private/metadata IPs for MCP endpoints under SSRF-guarding policies
When it happens
Trigger: validate_network_policy calls policy.evaluate(host, "mcp") and gets Decision::Deny — triggered from McpHttpClient::new on the configured URL, or from client_for_target on a redirect target host.
Common situations: Connecting to localhost/metadata IPs while an SSRF-guarding policy denies private ranges; host not on the operator allowlist; DNS rebinding protection flagging the host; corporate deny-list rules.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- MCP HTTP destination is a restricted IP address
- MCP HTTP destination requires network approval
- MCP HTTP discovered URL must not contain credentials
- MCP HTTP redirect must not contain credentials
- MCP HTTP redirect would downgrade HTTPS
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/b68795e6819370bc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp/http_client.rs:226
.build()
.context("building guarded MCP HTTP client")?;
let mut clients = self
.clients
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if !proxied && clients.len() < 32 {
clients.insert(key, client.clone());
}
Ok(client)
}
}
fn validate_network_policy(url: &Url, network_policy: Option<&NetworkPolicyDecider>) -> Result<()> {
let host = url.host_str().context("MCP URL has no host")?;
if let Some(policy) = network_policy {
match policy.evaluate(host, "mcp") {
Decision::Allow => {}
Decision::Deny => bail!("MCP HTTP destination blocked by network policy"),
Decision::Prompt => bail!("MCP HTTP destination requires network approval"),
}
}
Ok(())
}
fn validate_url(url: &Url) -> Result<()> {
if !matches!(url.scheme(), "http" | "https") || url.host_str().is_none() {
bail!("MCP HTTP requires an http:// or https:// URL with a host");
}
Ok(())
}
fn url_has_credentials(url: &Url) -> bool {
!url.username().is_empty() || url.password().is_some()
}
impl McpHttpClient {View on GitHub (pinned to 73e0f67d83)