{"record":{"id":"326ae897e0e98f7c","repo":"BerriAI/litellm","slug":"call-not-allowed-to-delete-mcp-server-user-is-not","errorCode":null,"errorMessage":"Call not allowed to delete MCP server. User is not a proxy admin. route={}","messagePattern":"Call not allowed to delete MCP server\\. User is not a proxy admin\\. route=(.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"litellm/proxy/management_endpoints/mcp_management_endpoints.py","lineNumber":1998,"sourceCode":"        ),\n    ):\n        \"\"\"\n        Delete MCP Server from db and associated MCP related server entities.\n\n        Parameters:\n        - server_id: str - Required. The unique identifier of the mcp server to delete.\n        ```\n        curl -X \"DELETE\" --location 'http://localhost:4000/v1/mcp/server/server_id' \\\n        --header 'Authorization: Bearer your_api_key_here'\n        ```\n        \"\"\"\n        prisma_client: Final = get_prisma_client_or_throw(\n            \"Database not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keys\"\n        )\n\n        # Authz - restrict only admins to delete mcp servers\n        if LitellmUserRoles.PROXY_ADMIN != user_api_key_dict.user_role:\n            raise HTTPException(\n                status_code=status.HTTP_403_FORBIDDEN,\n                detail={\n                    \"error\": \"Call not allowed to delete MCP server. User is not a proxy admin. route={}\".format(\n                        \"DELETE /v1/mcp/server\"\n                    )\n                },\n            )\n\n        # try to delete the mcp server\n        mcp_server_record_deleted: Final = await delete_mcp_server(prisma_client, server_id)\n\n        if mcp_server_record_deleted is None:\n            raise HTTPException(\n                status_code=status.HTTP_404_NOT_FOUND,\n                detail={\"error\": f\"MCP Server not found, passed server_id={server_id}\"},\n            )\n        global_mcp_server_manager.remove_server(mcp_server_record_deleted)\n","sourceCodeStart":1980,"sourceCodeEnd":2016,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/mcp_management_endpoints.py#L1980-L2016","documentation":"Returned (403) by the delete MCP server endpoint: deletion is restricted to exactly LitellmUserRoles.PROXY_ADMIN, checked after the prisma client is obtained but before any deletion work. The error text helpfully embeds the route ('DELETE /v1/mcp/server') so callers can identify which management call was denied.","triggerScenarios":"DELETE /v1/mcp/server/{server_id} with an internal-user, team, or org-admin key; cleanup scripts run with a team virtual key; a non-admin attempting to remove a server they can view but not manage.","commonSituations":"Tearing down test servers with the wrong key in CI; team admins assuming view access implies delete rights; automation that authenticates with a per-team key for lifecycle operations.","solutions":["Perform deletions with the proxy master key or a PROXY_ADMIN user's key.","Gate lifecycle automation on the key's role (check /key/info) before issuing DELETE calls.","Route deletion requests from non-admins through an admin-owned workflow."],"exampleFix":"# before\nrequests.delete(f\"{PROXY}/v1/mcp/server/{server_id}\", headers={\"Authorization\": f\"Bearer {TEAM_KEY}\"})\n\n# after\nrequests.delete(f\"{PROXY}/v1/mcp/server/{server_id}\", headers={\"Authorization\": f\"Bearer {os.environ['LITELLM_MASTER_KEY']}\"})","handlingStrategy":"validation","validationCode":"info = requests.get(f\"{PROXY}/key/info\", headers=AUTH, params={\"key\": KEY}).json()\nif info.get(\"key_info\", info).get(\"user_role\") != \"proxy_admin\":\n    raise PermissionError(\"MCP server deletion requires a PROXY_ADMIN key\")","typeGuard":"def can_delete_mcp_server(user_role: str | None) -> bool:\n    return user_role == \"proxy_admin\"","tryCatchPattern":"try:\n    delete_server(server_id)\nexcept HTTPError as e:\n    if e.response.status_code == 403:\n        raise PermissionError(\"re-run DELETE with the master/admin key\")\n    raise","preventionTips":["Use an admin key for all MCP lifecycle operations.","Audit CI jobs that call DELETE endpoints for hard-coded non-admin keys."],"tags":["litellm","mcp","forbidden","authorization","delete","proxy-admin"],"backgroundTag":"authorization-forbidden","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}