{"record":{"id":"b4aeaefaa704be9d","repo":"BerriAI/litellm","slug":"mcp-server-with-id-server-id-not-found","errorCode":null,"errorMessage":"MCP Server with id {server_id} not found","messagePattern":"MCP Server with id (.+?) not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"litellm/proxy/management_endpoints/mcp_management_endpoints.py","lineNumber":1459,"sourceCode":"\n        if mcp_server is None:\n            # Fallback: check registry (config-based servers) - list endpoint uses get_registry()\n            from litellm.proxy.auth.ip_address_utils import IPAddressUtils\n\n            client_ip: Final = IPAddressUtils.get_mcp_client_ip(request)\n            registry_server = global_mcp_server_manager.get_mcp_server_by_id(server_id)\n            if registry_server is not None and not global_mcp_server_manager._is_server_accessible_from_ip(\n                registry_server, client_ip\n            ):\n                registry_server = None\n            if registry_server is None:\n                # Try lookup by server_name or alias (client may use display name in URL)\n                registry_server = global_mcp_server_manager.get_mcp_server_by_name(server_id, client_ip=client_ip)\n            if registry_server is not None:\n                mcp_server = global_mcp_server_manager._build_mcp_server_table(registry_server)\n\n        if mcp_server is None:\n            raise HTTPException(\n                status_code=status.HTTP_404_NOT_FOUND,\n                detail={\"error\": f\"MCP Server with id {server_id} not found\"},\n            )\n\n        # Implement authz restriction from requested user\n        is_admin_view: Final = _user_has_admin_view(user_api_key_dict)\n        is_restricted_virtual_key: Final = _is_restricted_virtual_key_request(user_api_key_dict)\n\n        if not is_admin_view:\n            # Perform authz check BEFORE any health check (avoid side-effects for\n            # unauthorized callers).\n            if from_db:\n                mcp_server_records: Final = await get_all_mcp_servers_for_user(prisma_client, user_api_key_dict)\n                exists = does_mcp_server_exist(mcp_server_records, server_id)\n            else:\n                # Registry/config server: use same access logic as list endpoint\n                allowed_server_ids: Final = await global_mcp_server_manager.get_allowed_mcp_servers(user_api_key_dict)\n                exists = mcp_server.server_id in allowed_server_ids","sourceCodeStart":1441,"sourceCodeEnd":1477,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/mcp_management_endpoints.py#L1441-L1477","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before: guessing the id\nrequests.get(f\"{PROXY}/v1/mcp/server/{server_id}\", headers=AUTH).raise_for_status()\n\n# after: resolve the real id from the list endpoint first\nservers = requests.get(f\"{PROXY}/v1/mcp/server\", headers=AUTH).json()\nresolved = next(s for s in servers[\"servers\"] if s[\"server_id\"] == server_id or s.get(\"server_name\") == server_id)\nrequests.get(f\"{PROXY}/v1/mcp/server/{resolved['server_id']}\", headers=AUTH).raise_for_status()","handlingStrategy":"validation","validationCode":"servers = requests.get(f\"{PROXY}/v1/mcp/server\", headers=AUTH).json()[\"servers\"]\nknown = {s[\"server_id\"] for s in servers} | {s.get(\"server_name\", \"\") for s in servers}\nassert server_id in known, f\"unknown server id: {server_id}\"","typeGuard":"def is_known_server_id(server_id: str, servers: list[dict]) -> bool:\n    return server_id in {s[\"server_id\"] for s in servers} | {s.get(\"server_name\") for s in servers}","tryCatchPattern":"try:\n    fetch(server_id)\nexcept HTTPError as e:\n    if e.response.status_code == 404:\n        # re-resolve id from list endpoint, check IP allowlist config, then retry once\n        raise\n    raise","preventionTips":["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."],"tags":["litellm","mcp","not-found","lookup","ip-allowlist"],"backgroundTag":"resource-not-found","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}