BerriAI/litellm · error · HTTPException
ip_filtering
ip_filtering
Error message
MCP server '{server_id}' is not accessible from your IP address ({_rest_client_ip}). This server is restricted to internal networks only. To make it externally accessible, set 'available_on_public_internet: true' in the server configuration. What it means
On the REST tool-call route, the requested server exists in the registry but available_on_public_internet is false (the default) and _is_server_accessible_from_ip judges the caller's client IP non-internal, so the proxy refuses with 403 error=ip_filtering. The message embeds the offending client IP and the exact config knob to change.
Source
Thrown at litellm/proxy/_experimental/mcp_server/rest_endpoints.py:467
)
allowed_server_ids_set.update(servers)
allowed_server_ids_set = set(
global_mcp_server_manager.filter_server_ids_by_ip(list(allowed_server_ids_set), _rest_client_ip)
)
canonical_server_id: Final = _resolve_mcp_server_id_for_rest(server_id, allowed_server_ids_set, _rest_client_ip)
if canonical_server_id not in allowed_server_ids_set:
_server: Final = global_mcp_server_manager.get_mcp_server_by_id(
server_id
) or global_mcp_server_manager.get_mcp_server_by_name(server_id)
if (
_server is not None
and _rest_client_ip is not None
and not global_mcp_server_manager._is_server_accessible_from_ip(_server, _rest_client_ip)
):
raise HTTPException(
status_code=403,
detail={
"error": "ip_filtering",
"message": (
f"MCP server '{server_id}' is not accessible from your IP address "
f"({_rest_client_ip}). This server is restricted to internal "
"networks only. To make it externally accessible, set "
"'available_on_public_internet: true' in the server configuration."
),
},
)
if _server is None:
raise HTTPException(
status_code=404,
detail={
"error": "server_not_found",
"message": f"MCP server '{server_id}' was not found",
},View on GitHub (pinned to 77b7c6c40c)
Solutions
- If the server should be internet-reachable, set available_on_public_internet: true on that mcp_servers entry (config.yaml or DB) and reload the proxy.
- Otherwise call from an allowed internal network/VPN.
- If you believe you are internal: check the reported IP in the message and fix X-Forwarded-For / trusted-proxy forwarding so the real client IP is derived.
Example fix
# before
mcp_servers:
internal-wiki:
url: https://wiki.internal
# -> 403 ip_filtering for external callers
# after
mcp_servers:
internal-wiki:
url: https://wiki.internal
available_on_public_internet: true Defensive patterns
Strategy: validation
Validate before calling
import ipaddress
def client_ip_can_reach_server(client_ip: str | None, server_public: bool) -> bool:
if server_public:
return True
if not client_ip:
return False
try:
return ipaddress.ip_address(client_ip).is_private or ipaddress.ip_address(client_ip).is_loopback
except ValueError:
return False
assert client_ip_can_reach_server(my_ip, server_config.get("available_on_public_internet", False)) Try / catch
resp = await client.post(f"{proxy}/mcp/tool-call", json=payload, headers=headers)
if resp.status_code == 403 and resp.json().get("detail", {}).get("error") == "ip_filtering":
raise NetworkLocationError("call must originate from an internal IP or the server must set available_on_public_internet: true") from None
resp.raise_for_status() Prevention
- Decide the exposure of every MCP server at registration time and set available_on_public_internet explicitly.
- Verify egress IP before integrating from CI/external services.
- Keep X-Forwarded-For forwarding correct so internal callers are never misclassified as external.
When it happens
Trigger: Calling a restricted internal MCP server over the REST facade from a public/egress IP; or the client IP is derived incorrectly because a reverse proxy does not forward X-Forwarded-For (or the proxy's trusted-proxy handling is misconfigured), making even internal callers appear external.
Common situations: Exposing the litellm proxy publicly while leaving default servers internal-only; k8s ingress stripping XFF; on-prem callers behind NAT; security policy requires an explicit opt-in per server before internet exposure.
Related errors
- URL targets a blocked address ({resolved_ip}). If this is a
- OpenAPI spec not found at {filepath}
- error.summary
- forbidden
- server_not_found
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/8c49da107dc3995b.
Report an issue: GitHub.