fix(mcp): stop 'Team doesn't exist' warnings for UI dashboard sessions - #32348
Conversation
UI session tokens carry the virtual team_id litellm-dashboard (UI_TEAM_ID), which is never persisted. The MCP team-permission helpers passed it to get_team_object anyway, so every dashboard MCP listing raised a 404 per lookup that was swallowed into per-server 'Failed to get allowed tools for server' warnings (plus the sibling 'allowed MCP servers for team' and 'MCP access groups for team' warnings) and wasted DB queries. The 404 also escaped past the key-level permission handling in get_allowed_tools_for_server, dropping key tool restrictions for such sessions. Short-circuit the virtual team before the DB lookup in the three helpers, mirroring the existing UI_TEAM_ID handling in agent_permission_handler. Also reject /team/new with the reserved team_id, since a real row would bind its budget and permissions to every UI session
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Greptile SummaryThis PR fixes spurious
Confidence Score: 5/5Safe to merge — the changes are narrow, additive guards on a well-understood constant, and the existing auth critical path is unaffected. All three MCP helpers and the team creation endpoint receive minimal, targeted guards with no changes to surrounding logic. The pattern mirrors the already-merged handling in agent_permission_handler.py. The new tests fail on the parent commit and pass here, the get_team_object mock correctly captures the source-module attribute, and ProxyException.code is stringified so the '400' assertion is valid. No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py | Adds UI_TEAM_ID short-circuit guards in _get_team_object_permission, _get_allowed_mcp_servers_for_team, and _get_mcp_access_groups_for_team to prevent spurious DB lookups and log floods for virtual UI dashboard sessions. |
| litellm/proxy/management_endpoints/team_endpoints.py | Adds a reserved-ID guard in new_team that rejects UI_TEAM_ID before the duplicate-check DB query, preventing a real team row from shadowing every UI session's budget and permissions. |
| tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py | Adds four new async tests covering the UI_TEAM_ID short-circuits: the three helpers return their zero-value without calling get_team_object, and get_allowed_tools_for_server still applies key-level tool restrictions for UI sessions. |
| tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py | Adds a test asserting that /team/new raises a 400 ProxyException for the reserved UI_TEAM_ID and that the DB duplicate-check query is never reached. |
Reviews (1): Last reviewed commit: "fix(mcp): stop 'Team doesn't exist' warn..." | Re-trigger Greptile
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit e84cefa. Configure here.
Relevant issues
Linear ticket
Resolves LIT-4227
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
A customer reported their proxy logs flooding with
Failed to get allowed tools for server: 404: {'error': "Team doesn't exist in db. Team=litellm-dashboard. ..."}, one line per configured MCP server on every MCP tools listing from the dashboard, and was confused because they never created a team with that id. They are right that it does not exist;litellm-dashboardis the virtual team id LiteLLM stamps on every UI session token (UI_TEAM_ID), which is never persisted. The MCP team-permission helpers passed it toget_team_objectanywaySetup for both runs: fresh Postgres, 3 MCP servers pointing at the public DeepWiki MCP server,
EXPERIMENTAL_UI_LOGIN=true(with plain sk- session keys the main auth flow happens to mask the 404 by caching a fabricated team object atuser_api_key_auth.py:1916; the experimental UI JWT branch returns early atuser_api_key_auth.py:1541before that fallback runs, so it reproduces the exact flow the customer hit)Before (parent commit 5e73994): tools/list returns 9 tools and the log gets one warning per configured server, the customer's exact flood
Before, second defect:
/team/newhappily creates a real team with the reserved id, whose budget and permissions would then bind to every UI session because the auth flow resolves the session's team against the DB rowAfter (this PR, e84cefa), same commands: tools/list still returns the same 9 tools and the log stays clean
After,
/team/newrejects the reserved id and regular team creation is untouchedType
🐛 Bug Fix
Changes
MCPRequestHandler._get_team_object_permission,_get_allowed_mcp_servers_for_teamand_get_mcp_access_groups_for_teamnow short-circuit to their empty result whenuser_api_key_auth.team_id == UI_TEAM_ID, before hittingget_team_object. The virtual UI team can never have a DB row, so the lookup always raised HTTPException 404, which each helper swallowed into its own WARNING (the tools one fires once per server per tools/list, producing the flood) plus a wasted DB query. The 404 also abortedget_allowed_tools_for_serverbefore the key-level tool permission handling ran, silently dropping key tool restrictions for such sessions; with the short-circuit the key/agent/org intersections apply normally. This mirrors the existingUI_TEAM_IDhandling inagent_permission_handler.py/team/newnow rejectsteam_id == UI_TEAM_IDwith a 400 before the duplicate check, so nobody can create a real team under the reserved id and silently attach its budget and permissions to every UI dashboard sessionRegression tests: the three MCP helpers return their empty result for the UI team without calling
get_team_object(asserted viaassert_not_called),get_allowed_tools_for_serverkeeps key-level tool restrictions when the team lookup would 404, and/team/newreturns 400 for the reserved id without reaching the DB duplicate check. All of them fail on the parent commit and pass with this changeLink to Devin session: https://app.devin.ai/sessions/f03da2725ec94d28b3facf766871b102
Note
Low Risk
Targeted auth guards on a known virtual team id plus team-creation validation; behavior for real teams is unchanged and tests cover the main paths.
Overview
Stops MCP team-permission code from calling
get_team_objectwhen the session carries the virtual dashboard team idUI_TEAM_ID(litellm-dashboard)._get_team_object_permission,_get_allowed_mcp_servers_for_team, and_get_mcp_access_groups_for_teamnow return empty/Noneimmediately, which removes per-server "Team doesn't exist" log noise on dashboard MCPtools/listand avoids a regression where a 404 from team lookup could skip key-level MCP tool restrictions./team/newnow returns 400 ifteam_idisUI_TEAM_ID, so operators cannot create a real team row that would bind budget and permissions to every UI session.Regression tests cover the MCP short-circuits, preserved key tool permissions for UI sessions, and rejection of the reserved id on team creation.
Reviewed by Cursor Bugbot for commit e84cefa. Bugbot is set up for automated code reviews on this repo. Configure here.