issue: MCP structuredContent is discarded before tool results reach the model

当 MCP 工具同时返回 content 和 structuredContent 时,Open WebUI 只把 content 交给模型,导致机器可读的 structuredContent 被丢弃,模型只看到摘要看不到真实数据。优先检查 backend/open_webui/utils/mcp/c

快速结论:当 MCP 工具同时返回 content 和 structuredContent 时,Open WebUI 只把 content 交给模型,导致机器可读的 structuredContent 被丢弃,模型只看到摘要看不到真实数据。优先检查 backend/open_webui/utils/mcp/client.py 中 call_tool 对返回结果的处理逻辑。

适用环境:Open WebUI v0.11.0(Docker 安装),操作系统 RHEL 10;Issue 未提供 Ollama、Python、CUDA、显卡等版本信息。

最快修复方案:暂无确认的一步修复方案。Issue 中的修复补丁是社区贡献者提交的候选方案(在 call_tool 中把 structuredContent 序列化为额外的 text content block 追加到原有 content 之后),并未在本次 Issue 中确认合并;可优先尝试按该补丁修改 client.py 后验证。

注意事项:该补丁会改变返回给模型的 content 列表内容(新增一个 “Structured content:” 文本块),属于行为变更;仅在 structuredContent 存在且非空时追加,isError 路径保持不变。应用前请备份文件,且需自行确认与当前分支版本的兼容性。

问题场景

用户在 Open WebUI(Docker 部署,v0.11.0)中通过 MCP 客户端调用一个会同时返回 content 与 structuredContent 的 MCP Server(示例为 ghcr.io/degoog-org/mcp:rebuild,用于抓取 example.com)。工具调用本身成功执行,但模型只收到简短的人类可读摘要(如 “Scraped 1 URLs: 1 useful, 0 failed. Top evidence chunks are in structured content.”),真实的页面抓取内容位于 structuredContent 却被丢弃,模型因此拿不到实际数据。

报错原文

Input:
https://example.com

Output:
Scraped 1 URLs: 1 useful, 0 failed.
Top evidence chunks are in structured content.

相关代码位置:backend/open_webui/utils/mcp/client.py :: call_tool @ line 109

async def call_tool(self, function_name: str, function_args: dict) -> Optional[dict]:
    if not self.session:
        raise RuntimeError('MCP client is not connected.')

    result = await self.session.call_tool(function_name, function_args)
    if not result:
        raise Exception('No result returned from MCP tool call.')

    result_dict = result.model_dump(mode='json')
    result_content = result_dict.get('content', {})

    if result.isError:
        raise Exception(result_content)
    else:
        return result_content

可见代码只取出了 content,没有处理 structuredContent。

原因分析

最可能的原因是 Open WebUI 的 MCP 客户端实现只读取 CallToolResult 中的 content 字段并直接返回,未把 structuredContent 一并传给模型。按照 MCP 规范,Server 应当把机器可读的载荷放在 structuredContent 中,而 content 只承载人类可读的摘要;因此符合规范的 MCP Server 会把真实数据放在 structuredContent,在 Open WebUI 当前实现下这部分数据就会在进入模型前被丢弃。Issue 中确认该缺陷在主分支和 dev 分支均存在(client.py:109-123)。

环境排查

  • 确认 Open WebUI 版本:Issue 中为 v0.11.0(Docker 安装),如需复现请核对自身版本是否相同或更高。
  • 确认部署方式:Docker。
  • 确认操作系统:RHEL 10(如排查环境差异可对照)。
  • 确认 MCP Server 是否真的返回了 structuredContent(可查看 MCP Server 侧日志或工具原始返回),避免误判为 Server 未输出该字段。
  • 确认所调用工具返回结构中同时存在 content 与 structuredContent,且 structuredContent 非空。
  • Issue 未提供 Ollama 版本、Python、CUDA、显卡、相关依赖版本等信息,排查时无需据此比对。

解决步骤

  1. 定位文件 backend/open_webui/utils/mcp/client.py,找到 call_tool 方法(约第 109 行起)。
  2. 在文件顶部导入区加入 import json(原文件只有 import asyncio、import logging 等)。
  3. 把 result_content = result_dict.get('content', {}) 改为 result_content = result_dict.get('content', []),并新增一行取出结构化内容,例如:
    result_content = result_dict.get('content', [])
    structured_content = result_dict.get('structuredContent')
  4. 在 else 分支返回前,当 structuredContent 存在且非空时,把它序列化为一个额外的 text content block 追加到原有 content 之后(可优先尝试):
    {'type': 'text', 'text': f'Structured content:\n{json.dumps(structured_content, indent=2)}'}
  5. 保持 isError 分支不变,仍然抛出原始的 result_content。
  6. 如 content 为非列表的边缘情况,先统一归一化为列表再追加。
  7. 重建/重启 Open WebUI 后端使改动生效,然后重新通过 Open WebUI 调用该 MCP 工具。

Issue 中该补丁来自社区贡献者的修复分支(fix/mcp-structured-content),尚未确认被项目合并,因此以上步骤属于“可优先尝试”的候选方案。

验证方法

重新调用 MCP 工具后,观察模型收到的工具结果:如果内容中除了原有的简短摘要,还出现了以 “Structured content:” 开头的 JSON 文本块,并且该 JSON 能反序列化回与 MCP Server 返回的 structuredContent 完全一致的数据,即说明问题已解决。同时可确认仅返回 content 的工具行为与之前保持一致,且 isError 情况下仍会抛出原始 content 错误。

参考来源

open-webui/open-webui #28926

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 28553

发表回复

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