BerriAI/litellm · error · HTTPException
MCP Server with id {server_id} not found
Error message
MCP Server with id {server_id} not found What it means
Returned (404) by the single MCP server fetch endpoint when the server cannot be resolved through its whole lookup chain: the database record, then the in-memory registry by server_id (dropped if _is_server_accessible_from_ip fails), and finally the registry by server_name/alias. It means the caller-supplied identifier matched nothing the proxy can serve for this request's from_db mode and client IP.
Source
Thrown at litellm/proxy/management_endpoints/mcp_management_endpoints.py:1459
if mcp_server is None:
# Fallback: check registry (config-based servers) - list endpoint uses get_registry()
from litellm.proxy.auth.ip_address_utils import IPAddressUtils
client_ip: Final = IPAddressUtils.get_mcp_client_ip(request)
registry_server = global_mcp_server_manager.get_mcp_server_by_id(server_id)
if registry_server is not None and not global_mcp_server_manager._is_server_accessible_from_ip(
registry_server, client_ip
):
registry_server = None
if registry_server is None:
# Try lookup by server_name or alias (client may use display name in URL)
registry_server = global_mcp_server_manager.get_mcp_server_by_name(server_id, client_ip=client_ip)
if registry_server is not None:
mcp_server = global_mcp_server_manager._build_mcp_server_table(registry_server)
if mcp_server is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={"error": f"MCP Server with id {server_id} not found"},
)
# Implement authz restriction from requested user
is_admin_view: Final = _user_has_admin_view(user_api_key_dict)
is_restricted_virtual_key: Final = _is_restricted_virtual_key_request(user_api_key_dict)
if not is_admin_view:
# Perform authz check BEFORE any health check (avoid side-effects for
# unauthorized callers).
if from_db:
mcp_server_records: Final = await get_all_mcp_servers_for_user(prisma_client, user_api_key_dict)
exists = does_mcp_server_exist(mcp_server_records, server_id)
else:
# Registry/config server: use same access logic as list endpoint
allowed_server_ids: Final = await global_mcp_server_manager.get_allowed_mcp_servers(user_api_key_dict)
exists = mcp_server.server_id in allowed_server_idsView on GitHub (pinned to 77b7c6c40c)
Solutions
- List all servers visible to your key (GET the mcp server list endpoint) and copy the exact server_id.
- If you are using a display name or alias, retry with the canonical server_id (or vice versa if you know it is a registry/config server).
- For IP-restricted servers, verify the allowed_ips configuration and that the proxy sees the correct client IP (X-Forwarded-For handling) — an IP mismatch suppresses the server and reports 404.
- Confirm the server still exists (it may have been deleted or rejected).
Example fix
# before: guessing the id
requests.get(f"{PROXY}/v1/mcp/server/{server_id}", headers=AUTH).raise_for_status()
# after: resolve the real id from the list endpoint first
servers = requests.get(f"{PROXY}/v1/mcp/server", headers=AUTH).json()
resolved = next(s for s in servers["servers"] if s["server_id"] == server_id or s.get("server_name") == server_id)
requests.get(f"{PROXY}/v1/mcp/server/{resolved['server_id']}", headers=AUTH).raise_for_status() Defensive patterns
Strategy: validation
Validate before calling
servers = requests.get(f"{PROXY}/v1/mcp/server", headers=AUTH).json()["servers"]
known = {s["server_id"] for s in servers} | {s.get("server_name", "") for s in servers}
assert server_id in known, f"unknown server id: {server_id}" Type guard
def is_known_server_id(server_id: str, servers: list[dict]) -> bool:
return server_id in {s["server_id"] for s in servers} | {s.get("server_name") for s in servers} Try / catch
try:
fetch(server_id)
except HTTPError as e:
if e.response.status_code == 404:
# re-resolve id from list endpoint, check IP allowlist config, then retry once
raise
raise Prevention
- Always resolve ids from the list endpoint instead of hardcoding them.
- Keep server_id (canonical) and server_name/alias straight in configs and scripts.
- For IP-restricted servers, verify the proxy sees the true client IP before debugging 'missing' servers.
When it happens
Trigger: GET /v1/mcp/server/{server_id} with a typo'd or stale id; passing a display name/alias where the from_db branch expects the canonical server_id; the server was deleted after the caller cached its id; the registry entry exists but the request's client IP is not allowed for that server, so it is nulled out and the request falls through to 404.
Common situations: Mixing up server_id with server_name/alias between config-defined and DB-defined servers; servers deleted by another admin while a script holds old ids; IP-restricted MCP servers (allowed_ips) accessed through a proxy that mangles the client IP, turning what should be a 403 into a 404.
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
- MCP server {server_id} not found
- MCP Server not found, passed server_id={server_id}
- LiteLLM Managed File object with id={file_id} not found
- 404
- Prompt '{prompt_id}'{version_str} not found. Available promp
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/b4aeaefaa704be9d.
Report an issue: GitHub.