一文说明白为什么Dify的MCP策略插件不支持流式返回

解析Dify MCP插件无流式返回原因

说在前面

最近mcp大火,相信很多人已经搭建了自己的mcp服务,然后通过dify或者cherry studio这种工具调用过mcp服务了,不知道大家是否遇到一个问题,通过dify + mcp策略插件接入的方式,回答的内容无法流式输出,也就是需要等到所有结果生成完成后一并返回,这是为什么呢?

定位问题

首先看一下前端代码

这个比较直观,主要关注何种情况下会渲染回答。

# 相对路径web\service\base.ts
... existing code ...
if (bufferObj.status === 400 || !bufferObj.event) {
    onData('', false, {
      conversationId: undefined,
      messageId: '',
      errorMessage: bufferObj?.message,
      errorCode: bufferObj?.code,
    })
    hasError = true
    onCompleted?.(true, bufferObj?.message)
    return
  }
  if (bufferObj.event === 'message' || bufferObj.event === 'agent_message') {
    // can not use format here. Because message is splitted.
    onData(unicodeToChar(bufferObj.answer), isFirstMessage, {
      conversationId: bufferObj.conversation_id,
      taskId: bufferObj.task_id,
      messageId: bufferObj.id,
    })
    isFirstMessage = false
  }
  else if (bufferObj.event === 'agent_thought') {
    onThought?.(bufferObj as ThoughtItem)
  }
  else if (bufferObj.event === 'message_file') {
    onFile?.(bufferObj as VisionFile)
  }
... existing code ...

大概是可以看出来一些端倪,只有当回复消息的eventmessage或者agent_message时,才会赋值answer,进而渲染回答的textarea

然后我们看一下mcp策略的代码,

Github地址在这里

# 相对路径strategies\ReAct.py
... existing code ...
while run_agent_state and iteration_step <= max_iteration_steps:
  # continue to run until there is not any tool call
   run_agent_state = False
   round_started_at = time.perf_counter()
   round_log = self.create_log_message(
       label=f"ROUND {iteration_step}",
       data={},
       metadata={
           LogMetadata.STARTED_AT: round_started_at,
       },
       status=ToolInvokeMessage.LogMessage.LogStatus.START,
   )
   yield round_log
... existing code ...

通过查看策略的实现,发现全程都是通过日志的方式打印,用于跟踪智能体执行的步骤、耗时,详情等信息,并没有返回eventmessage的信息。

最后看一下实际返回

在这里插入图片描述
通过打印调试,证明确实当event:message的消息返回之后,才会渲染回复信息。
如果希望得到流式回复,需要对message这个生成器对象进行遍历
大概是这么个逻辑:

 if isinstance(chunk.delta.message.content, list):
	for content in chunk.delta.message.content:
	   response += content.data
	   if (
	       not function_call_state
	       or iteration_step == max_iteration_steps
	   ):
	       yield self.create_text_message(content.data)

说到最后

打包插件的offline版本
以上。

Dify Agent 中实现内置工具调用结果的流式接收,主要依赖于其对 MCP(Multi-Component Protocol)工具的支持和 Streamable HTTP 的配置。通过流式接收,用户可以在工具执行过程中逐步获取结果,而不是等待整个操作完成后一次性接收全部输出。以下是实现方法和技术要点: ### 3.1 使用 MCP 工具与 SSE 配置 Dify 支持通过 SSE(Server-Sent Events)机制发现和调用 MCP 工具,从而实现流式响应。在应用配置中,需在“工具列表”中选择 “通过SSE发现和调用MCP工具”,这样工具调用的结果可以通过事件流的形式持续返回给客户端[^1]。 在 Agent 节点中,策略类型应选择 **ReAct (Support MCP Tools)**,该策略允许 Agent 在推理过程中动态调用 MCP 工件,并通过事件驱动的方式接收其输出MCP 服务的配置需要提供相应的 JSON 描述文件,定义工具的接口、输入输出格式及流式支持能力[^1]。 ### 3.2 启用 Streamable HTTP(可选) 如果使用的是支持流式响应的 HTTP 工具,可以不依赖 MCP 工具列表的显式配置,而是启用 **Streamable HTTP** 模式。在这种模式下,Dify 会自动发现并处理流式响应,无需手动添加工具条目。这种方式适用于自定义工具或第三方 API 提供流式输出的情况。 ### 3.3 Agent Runner 的流式处理能力 从类设计角度,Dify 的 `FunctionCallAgentRunner` 负责处理工具调用的生命周期,包括异步接收流式响应。该类继承自 `BaseAgentRunner`,并扩展了对函数调用和流式数据处理的支持。当工具返回的是流式内容时,`FunctionCallAgentRunner` 会将每个事件片段逐步传递给前端界面或 API 调用方,实现逐步输出的效果[^2]。 ### 3.4 示例:流式响应的工具调用 假设有一个工具用于获取实时天气数据并以流式方式返回,其 MCP 配置如下(简化示例): ```json { "name": "weather-stream", "description": "流式返回指定城市的实时天气数据", "endpoint": "https://api.example.com/weather/stream", "method": "GET", "parameters": { "city": "string" }, "stream": true } ``` 在 Dify 的 Chatflow 中配置 Agent 节点时,选择该工具并启用流式处理。当用户输入指令如“显示北京的实时天气”,Agent 会启动该工具并持续接收来自服务器的天气更新信息,逐步展示在界面上。 ### 3.5 总结 Dify Agent 实现内置工具调用结果的流式接收,主要依赖以下机制: - 使用 MCP 工具并通过 SSE 实现事件流式传输; - 或启用 Streamable HTTP 自动发现流式工具; - 在 Agent Runner 层面对流式响应进行异步处理和逐步输出。 这些机制共同确保了 Dify 能够在复杂任务中提供即时反馈和持续交互的能力,提升用户体验和系统响应性。 ---
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值