BerriAI/litellm · warning · HTTPException

MCP server is already rejected.

Error message

MCP server is already rejected.

What it means

Raised by the LiteLLM proxy's MCP server rejection endpoint when an admin tries to reject an MCP server whose approval_status is already MCPApprovalStatus.rejected. The endpoint first enforces admin-only access, then a 404 for an unknown server_id, and only then this guard, which blocks a duplicate state transition. It exists so the submissions review workflow cannot double-process the same server or overwrite earlier review notes.

Source

Thrown at litellm/proxy/management_endpoints/mcp_management_endpoints.py:1399

        """
        Admin rejects a pending MCP server — sets approval_status=rejected with optional review_notes.
        """
        if LitellmUserRoles.PROXY_ADMIN != user_api_key_dict.user_role:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail={"error": "Admin access required to reject MCP server submissions."},
            )

        prisma_client: Final = get_prisma_client_or_throw("Database not connected. Connect a database to your proxy")

        existing: Final = await get_mcp_server(prisma_client, server_id)
        if existing is None:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail={"error": f"MCP server '{server_id}' not found."},
            )
        if existing.approval_status == MCPApprovalStatus.rejected:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail={"error": "MCP server is already rejected."},
            )

        was_active: Final = existing.approval_status == MCPApprovalStatus.active
        rejected: Final = await reject_mcp_server(
            prisma_client,
            server_id,
            touched_by=user_api_key_dict.user_id or LITELLM_PROXY_ADMIN_NAME,
            review_notes=payload.review_notes,
        )
        # Only evict from the runtime registry if the server was previously active
        if was_active:
            await global_mcp_server_manager.reload_servers_from_database()
        return _redact_mcp_credentials(rejected)

    @router.get(
        "/server/{server_id}",

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. If your goal is only 'server ends up rejected', treat this 400 as a successful no-op: check for status 400 and 'already rejected' in the response body.
  2. Before rejecting, fetch the server (or the submissions list) and confirm approval_status is not already 'rejected'.
  3. Refresh the submissions queue before acting and coordinate reviewers so only one admin rejects a given submission.

Example fix

# before: naive reject that crashes on double-reject
resp = requests.post(f"{PROXY}/mcp/server/{server_id}/reject", headers=AUTH, json={"review_notes": "..."})
resp.raise_for_status()

# after: idempotent reject
resp = requests.post(f"{PROXY}/mcp/server/{server_id}/reject", headers=AUTH, json={"review_notes": "..."})
if resp.status_code == 400 and "already rejected" in resp.text:
    pass  # already in the desired state
else:
    resp.raise_for_status()
Defensive patterns

Strategy: validation

Validate before calling

server = requests.get(f"{PROXY}/v1/mcp/server/{server_id}", headers=AUTH).json()
status = server.get("mcp_server", server).get("approval_status")
if status != "rejected":
    requests.post(f"{PROXY}/mcp/server/{server_id}/reject", headers=AUTH, json={"review_notes": notes})

Try / catch

try:
    reject(server_id)
except HTTPError as e:
    if e.response.status_code == 400 and "already rejected" in e.response.text:
        return  # desired state already reached
    raise

Prevention

When it happens

Trigger: Calling the MCP server rejection route (admin UI 'Reject' action, or the REST reject endpoint on the mcp management router) twice for the same server_id; calling reject on a submission that another admin already rejected; a script retrying a reject call whose first response was lost even though it committed.

Common situations: Two admins working the same submissions queue; double-click / double-submit in the UI; automation retrying on network timeout after the first reject already succeeded.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/0ac89d6ec5d18149. Report an issue: GitHub.