[Bug]: silently strips team-level MCP access for all keys on an affected team

用户使用 LiteLLM Proxy( litellm-proxy ),并通过 Admin UI 管理 MCP Server。在为一个团队配置了明确的 object_permission.mcp_servers (包含 allow_all_keys=False 的 MCP Server)后,在 Ad

[Bug]: silently strips team-level MCP access for all keys on an affected team

[Bug]: silently strips team-level MCP access for all keys on an affected team

快速结论:该 Bug 发生在 LiteLLM Admin UI 中切换某个 MCP Server 的 “Allow All Keys” 开关后,会导致该团队下所有 API Key 的 MCP Server 访问权限被静默剥离。优先排查 mcp_server_manager.pyget_allowed_mcp_servers 函数的 except 落日志,并检查缓存是否因切换操作被污染。

问题场景

用户使用 LiteLLM Proxy(litellm-proxy),并通过 Admin UI 管理 MCP Server。在为一个团队配置了明确的 object_permission.mcp_servers(包含 allow_all_keys=False 的 MCP Server)后,在 Admin UI 中将任意一个 MCP Server 的 “Allow All Keys” 开关切换为 true。随后,原本属于该团队的 API Key 调用 tools/list 时,团队级 MCP Server 权限消失,仅剩下全局开放的服务器。

报错原文

# 核心触发点:mcp_server_manager.get_allowed_mcp_servers 中的 except 块
verbose_logger.warning(f"Failed to get allowed MCP servers: {str(e)}.")
return allow_all_server_ids    # ← BUG: returns ONLY global servers, drops team grants

注意:该异常被记录为 WARNING 级别(非 ERROR),在生产环境中容易漏掉。

原因分析

核心原因在于 mcp_server_manager.pyget_allowed_mcp_servers 方法存在一个过于宽泛的 except 块。当 “Allow All Keys” 开关被切换时:

  • LiteLLM 会更新该 MCP Server 的数据库记录,并无效化内存中的注册表缓存。
  • 后续 MCPRequestHandler.get_allowed_mcp_servers 在执行时,_get_team_object_permission 内的 get_team_object 可能因缓存失效/反序列化失败,或数据库写入窗口期间的锁竞争而抛出异常。
  • 外层的 except 捕获了所有异常,但仅返回全局 allow_all_server_ids,丢弃了之前正确计算的团队级 object_permission.mcp_servers 结果。

可能原因:此外,Admin UI 保存时可能同时修改了 Server 的 name/alias 字段,导致基于名称的 object_permission.mcp_servers 引用失效(UUID 引用不受影响)。

环境排查

  • 确认使用的 LiteLLM 版本(影响 litellm/proxy/_experimental/mcp_server/mcp_server_manager.py 的具体行数)。
  • 确认 MCP 功能启用状态(Experimental)。
  • 检查数据库后端(PostgreSQL/MySQL/SQLite),确认是否存在写锁或部分写入窗口。
  • 检查 MCP Server 配置中 allow_all_keys 字段的初始状态及切换后的状态。

解决步骤

  1. 立即(不修复代码):避免在 Admin UI 中随意切换 “Allow All Keys” 开关,尤其是当团队已配置特定 MCP 权限时。
  2. 修复方案(需部署补丁):
    • 打开 litellm/proxy/_experimental/mcp_server/mcp_server_manager.py,找到 get_allowed_mcp_servers 方法中的 except Exception as e 块。
    • return allow_all_server_ids 之前添加 logger.exception("MCP permission resolution failed, falling back to global-only"),以输出完整堆栈,便于定位真正异常。
    • 建议将宽泛的 except Exception 改为更具体的异常类型(如 except PermissionCacheError),减少误吞。
  3. 架构优化(可选):考虑为 allow_all_keys 状态使用独立的缓存键,避免切换操作导致权限解析用的缓存被污染。
  4. 临时恢复:如果权限已被剥离,可手动调用 Admin API 重新绑定团队与 MCP Server 的 object_permission.mcp_servers,或从备份恢复团队配置。

验证方法

应用上述修复后:

  • 在 Admin UI 中切换一个 MCP Server 的 “Allow All Keys” 开关。
  • 使用同一团队下的 API Key 调用 tools/list
  • 检查返回结果是否仍然包含团队之前配置的所有 MCP Server(如 mcp_jira, mcp_confluence 等)。
  • 同时检查日志,确保未再出现 WARNING 级别的 “Failed to get allowed MCP servers” 且返回列表完整。

参考来源

BerriAI/litellm #30476

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 8059

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注