From 5acb52b40aa0481f0c494c43240a495dab6ded33 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Fri, 20 Mar 2026 22:24:02 -0700 Subject: [PATCH] address greptile review feedback (greploop iteration 2) - Handle ValueError on team-link failure as 400 (orphaned server fix) - Wrap delete's remove_from_team in try/except (prevent 500 after successful delete) - Revert DELETE status code to 202 (backwards-compatible) - Add extra_permissions to TeamMemberUpdateResponse Co-Authored-By: Claude Opus 4.6 (1M context) --- litellm/proxy/_types.py | 1 + .../mcp_management_endpoints.py | 25 ++++++++++++++----- .../management_endpoints/team_endpoints.py | 1 + 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index 8c8e5d37f00..d850b6f0525 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -3769,6 +3769,7 @@ class TeamMemberUpdateRequest(TeamMemberDeleteRequest): class TeamMemberUpdateResponse(MemberUpdateResponse): team_id: str max_budget_in_team: Optional[float] = None + extra_permissions: Optional[List[str]] = None tpm_limit: Optional[int] = None rpm_limit: Optional[int] = None diff --git a/litellm/proxy/management_endpoints/mcp_management_endpoints.py b/litellm/proxy/management_endpoints/mcp_management_endpoints.py index e27e5b0bdbe..ac1f7c833d7 100644 --- a/litellm/proxy/management_endpoints/mcp_management_endpoints.py +++ b/litellm/proxy/management_endpoints/mcp_management_endpoints.py @@ -1294,9 +1294,16 @@ if MCP_AVAILABLE: # Auto-assign server to team's ObjectPermissionTable if team-scoped if team_id and new_mcp_server.server_id: - await add_mcp_server_to_team( - prisma_client, team_id, new_mcp_server.server_id - ) + try: + await add_mcp_server_to_team( + prisma_client, team_id, new_mcp_server.server_id + ) + except ValueError as e: + # Team not found — surface as 400 so caller knows + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail={"error": str(e)}, + ) return _redact_mcp_credentials(new_mcp_server) @@ -1489,7 +1496,7 @@ if MCP_AVAILABLE: description="Allows deleting mcp servers in the db", dependencies=[Depends(user_api_key_auth)], response_class=JSONResponse, - status_code=status.HTTP_204_NO_CONTENT, + status_code=status.HTTP_202_ACCEPTED, ) @management_endpoint_wrapper async def remove_mcp_server( @@ -1572,13 +1579,19 @@ if MCP_AVAILABLE: # Remove server from team's ObjectPermissionTable if team_id: - await remove_mcp_server_from_team(prisma_client, team_id, server_id) + try: + await remove_mcp_server_from_team(prisma_client, team_id, server_id) + except Exception as e: + verbose_proxy_logger.warning( + f"Failed to remove server {server_id} from team {team_id} permissions: {e}. " + "Server was deleted but team's ObjectPermissionTable may contain a stale entry." + ) # TODO: Enterprise: Finish audit log trail if litellm.store_audit_logs: pass - return Response(status_code=status.HTTP_204_NO_CONTENT) + return Response(status_code=status.HTTP_202_ACCEPTED) @router.post( "/server/{server_id}/user-credential", diff --git a/litellm/proxy/management_endpoints/team_endpoints.py b/litellm/proxy/management_endpoints/team_endpoints.py index f36ed83e6f5..2c61c894295 100644 --- a/litellm/proxy/management_endpoints/team_endpoints.py +++ b/litellm/proxy/management_endpoints/team_endpoints.py @@ -2487,6 +2487,7 @@ async def team_member_update( user_id=received_user_id, user_email=data.user_email, max_budget_in_team=data.max_budget_in_team, + extra_permissions=data.extra_permissions, tpm_limit=data.tpm_limit, rpm_limit=data.rpm_limit, )