BerriAI/litellm · error · HTTPException
server_not_found
server_not_found
Error message
MCP server '{server_id}' was not found What it means
The REST tool-call route could not resolve server_id to any registered MCP server (looked up by id and by name), so it returns 404 error=server_not_found. The server is unknown to this proxy instance's registry (config.yaml + DB), distinct from 403 which means known-but-not-allowed.
Source
Thrown at litellm/proxy/_experimental/mcp_server/rest_endpoints.py:480
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",
},
)
raise HTTPException(
status_code=403,
detail={
"error": "access_denied",
"message": f"The key is not allowed to access server {server_id}",
},
)
# Build allowed_mcp_servers list (only include allowed servers)
allowed_mcp_servers: Final[list[MCPServer]] = []
for allowed_server_id in allowed_server_ids_set:
server = global_mcp_server_manager.get_mcp_server_by_id(allowed_server_id)View on GitHub (pinned to 77b7c6c40c)
Solutions
- List what this proxy actually knows: GET /mcp/tools/list (or check config.yaml / the dashboard) and use the exact server_id.
- If you just added the server, restart or hot-reload the proxy so the registry picks it up.
- Confirm you are hitting the right proxy instance/environment and that the DB-backed servers are visible (database connected).
Defensive patterns
Strategy: validation
Validate before calling
async def server_exists(client, server_id: str) -> bool:
listing = await client.get(f"{proxy}/mcp/tools/list", headers=headers)
known = {t.get("server_info", {}).get("server_id") for t in listing.json().get("tools", [])}
known |= set(listing.json().get("mcp_servers", []))
return server_id in {k for k in known if k} Try / catch
resp = await client.post(f"{proxy}/mcp/tool-call", json=payload, headers=headers)
if resp.status_code == 404 and resp.json().get("detail", {}).get("error") == "server_not_found":
raise UnknownMCPServer(payload["server_id"]) from None # surface the bad id, never blind-retry
resp.raise_for_status() Prevention
- Discover server ids at runtime via tools/list instead of hardcoding them.
- Re-check ids after proxy config changes, restarts, and environment promotions.
- Treat 404 server_not_found as a permanent configuration error in callers - do not retry.
When it happens
Trigger: POST tool call with a server_id that is a typo, refers to a removed server, was added to config.yaml after the proxy started (no reload), or lives in a DB the proxy is not connected to; also using a server alias/name that was renamed.
Common situations: Environment mix-ups (dev server_id against prod proxy); renaming servers; adding servers via config without restart; pointing at a proxy without the Prisma DB that stores DB-registered servers.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Prompt version '{prompt_version_id}' not found
- OpenAPI spec not found at {filepath}
- error.summary
- ip_filtering
- Toolset '{toolset_name}' not found
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/9f239f1918af31d6.
Report an issue: GitHub.