
1. dify 里 MCP 工具调用为什么总卡在 Agent 节点dify 的 MCP 工具调用本质是让 Agent 节点通过 SSE 长连接去发现远端 MCP Server 暴露的工具再在推理循环里决定调哪个、传什么参数。听起来顺但真正落地时很多人会卡在三个地方插件装完找不到工具、Agent 策略选错导致call_tool找不到、SSE 流式返回被截断。这篇就按「MCP 服务端配置 → dify 工具注册 → TaoToken 统一 Key 接入 → 端到端验证」的顺序把整条链路走一遍。先说清楚适用对象你已经在本地或内网跑了一个 MCP Server比如基于 FastMCP 的 MySQL 查询服务希望把它挂到 dify 的 Chatflow 里让 Agent 能自动查库、返回结果并且前端能拿到 SSE 流式输出。如果你还没写过 MCP Server也没关系文末的配置片段可以直接套。核心检索词先摆出来dify MCP 工具调用、Agent 节点接入 SSE、TaoToken 统一 Key。这三个词贯穿全文你按这个思路读就不会迷路。我试过用 FunctionCalling 策略去接 FastMCP结果一直报找不到call_tool换成 ReAct 就通了。这个坑后面会单独讲。整条链路里TaoToken 的作用是给 Agent 背后的模型调用提供一个统一的 Base URL 和 Key省得你在 dify 里到处填不同厂商的地址。它的 API 入口是https://taotoken.net/api模型对话、Coding Plan、API Keys 都在这个域名下。下面从最容易被忽略的 MCP 服务端配置开始。2. TaoToken 统一 Key 与 MCP SSE 插件前置准备在动 dify 之前先把两样东西准备好一个是能跑的 MCP SSE 服务端一个是 TaoToken 的 Key。很多人一上来就装插件结果 SSE 地址填进去发现连不上回头查半天其实是服务端根本没起。MCP 服务端这块用 FastMCP 写一个最小可用的 SSE 服务核心就是暴露一个/sse路径。下面是一个 MySQL 查询服务的骨架你可以按自己的库改from fastmcp import FastMCP import pymysql mcp FastMCP(mysql_mcp_server_pro) mcp.tool() def query_students(class_id: str) - list: conn pymysql.connect(host127.0.0.1, userroot, passwordyourpass, databaseschool) cur conn.cursor(pymysql.cursors.DictCursor) cur.execute(SELECT * FROM students WHERE classId%s, (class_id,)) rows cur.fetchall() conn.close() return rows if __name__ __main__: mcp.run(transportsse, host0.0.0.0, port9090)跑起来之后http://你的内网IP:9090/sse就是 dify 要填的地址。注意这里用0.0.0.0是为了让 dify 容器能访问到如果你 dify 跑在 Docker 里别用127.0.0.1否则容器内回环地址指向的是容器自己。TaoToken 这边去控制台建一个 API Key。地址是https://taotoken.net/console建完 Key 之后Base URL 统一用https://taotoken.net/api。这个 Key 后面会填到 dify 的模型配置里让 Agent 节点背后的 LLM 走 TaoToken 转发。如果你用的是 Claude Code 这类编码工具TaoToken 也有对应的 Coding Plan但本文聚焦 dify不展开。注意MCP 服务端和 dify 如果在同一台机器SSE 地址用内网 IP跨机器的话确认防火墙放行 9090 端口。这一步没通后面全白搭。前置准备就这两件事SSE 服务能curl通TaoToken Key 拿到手。接下来进 dify 装插件。3. dify 插件安装与 MCP 工具注册可复制配置dify 里要装两个插件缺一不可。第一个是Agent 策略支持 MCP 工具第二个是MCP SSE。前者负责在 Agent 推理时发现和调用 MCP 工具后者负责通过 HTTP with SSE 传输去连你的 MCP Server。装插件的位置在 dify 的「插件」市场里搜关键词或者直接从 GitHub 装。装完之后点开 MCP SSE 插件添加 SSE 地址。这里填的是一个 JSON格式如下{ mysql_mcp_server_pro: { url: http://172.16.0.45:9090/sse, headers: {}, timeout: 60, sse_read_timeout: 300 } }如果你有多个 MCP 应用就往这个 JSON 里加多个键{ server_name1: { url: http://127.0.0.1:8000/sse, headers: {}, timeout: 60, sse_read_timeout: 300 }, server_name2: { url: http://127.0.0.1:8001/sse } }timeout是连接超时sse_read_timeout是读取超时。查库这种操作可能慢sse_read_timeout建议给到 300 秒不然长查询会被掐断。保存之后插件列表里能看到你注册的 MCP 服务器。然后是 Agent 策略插件。这个插件提供ReAct (Support MCP Tools)策略是后面 Agent 节点必须选的。装完这两个dify 的插件层就齐了。接下来建工作流。类型选Chatflow名字随意比如test-mcp-mysql8。建好之后默认会有一个 LLM 节点把它删掉换成 Agent 节点。Agent 节点的配置分四块Agent 策略、工具列表、MCP 服务器、指令。这四块每一块都不能空尤其是工具列表不选的话 Agent 根本不知道有哪些工具可用。Agent 策略这里必须选ReAct (Support MCP Tools)。为什么不能用 FunctionCalling因为 FastMCP 框架暴露的工具不需要你手动指定call_tool方法而 FunctionCalling 策略会去找这个方法找不到就报错。就算你手动加了call_tool它还是提示找不到索性直接用 ReAct省事。工具列表这块点右侧添加按钮选「通过 SSE 发现和调用 MCP 工具」然后添加你需要的工具。MCP 服务器这里把前面那段 JSON 再填一遍{ mysql_mcp_server_pro: { url: http://172.16.0.45:9090/sse } }指令这块是提示词必须写。它告诉 Agent 什么时候该调 MCP 工具、表结构长什么样。比如你要查学生成绩就得把students、scores、courses这些表的字段说明写进去。指令写得好Agent 调工具的准确率会高很多。最大迭代次数默认是 3也必须设一下否则保存不了。这个参数控制工具调用的深度防止无限循环。最后把 Agent 节点的输出接到「直接回复」节点变量选Agent.text。这样整条链路就串起来了。4. 端到端验证SSE 流式返回与工具调用结果确认配置完别急着高兴先做一次端到端验证。验证分两步先确认 MCP 工具能被发现再确认 Agent 能调工具并流式返回。第一步在 dify 的 Agent 节点里工具列表应该能看到你注册的 MCP 工具比如query_students。如果看不到说明 SSE 地址没连上回去检查服务端是否在跑、地址是否可达。第二步在 Chatflow 的调试窗口里发一句「查询 202301 班级的所有学生」。正常情况下你会看到 Agent 先思考然后调用query_students工具拿到结果后再组织语言回复。前端如果是 SSE 流式输出你会看到文字一个字一个字蹦出来而不是等半天一次性出现。这里有个细节SSE 流式返回和工具调用是两回事。工具调用是 Agent 内部的推理循环SSE 是最终输出到前端的传输方式。如果工具调用成功但前端没流式效果检查「直接回复」节点是否开启了流式输出。dify 的 Chatflow 默认是流式的但如果你中间加了非流式节点可能会打断。验证通过的标准是Agent 能正确识别用户意图、调用对应 MCP 工具、拿到数据、以流式方式返回。三个环节缺一不可。如果工具调用了但返回空多半是 MCP 服务端查库逻辑有问题跟 dify 无关。5. 常见报错排查401、local proxy failed 与 reading choices落地过程中报错基本集中在这几个。我按真实遇到的顺序列一下你对照着查。401 Unauthorized这个多半是 TaoToken 的 Key 没填对或者填到了错误的位置。检查 dify 模型配置里的 API Key 是否是https://taotoken.net/api-keys里建的那个Base URL 是否是https://taotoken.net/api。如果 Key 是对的还报 401看看是不是 Key 被禁用或者额度用完了。local proxy failed这个报错通常出现在 dify 容器访问 MCP SSE 地址时。原因是容器内的127.0.0.1指向容器自己不是宿主机。解决办法是把 SSE 地址换成宿主机的内网 IP比如http://172.16.0.45:9090/sse而不是http://127.0.0.1:9090/sse。如果你 dify 和 MCP 都在 Docker 里可以用 Docker 网络别名互访。reading choices 相关报错这个一般出现在模型返回格式不符合预期时。比如 Agent 策略选了 FunctionCalling但模型返回的是 ReAct 格式解析就会失败。解决办法就是前面说的Agent 策略统一用ReAct (Support MCP Tools)。另外检查 TaoToken 转发的模型 ID 是否和 dify 里填的一致模型 ID 填错也会导致返回格式异常。OAuth 相关报错如果你接的 MCP Server 需要 OAuth 鉴权而 dify 的 MCP SSE 插件没配对应的 token就会报 OAuth 失败。这种情况要么在 MCP 服务端关掉鉴权要么在 SSE 配置的headers里加上Authorization。比如{ mysql_mcp_server_pro: { url: http://172.16.0.45:9090/sse, headers: { Authorization: Bearer your_token } } }工具找不到 call_tool 方法这是 FunctionCalling 策略的典型报错。FastMCP 不需要call_tool所以直接换 ReAct 策略即可不用折腾。排查顺序建议先确认 MCP 服务端能curl通再确认 dify 插件里 SSE 地址能保存成功然后确认 Agent 策略是 ReAct最后确认 TaoToken Key 和 Base URL 正确。按这个顺序走大部分问题都能定位。6. 把统一 Key 和 MCP 链路固定下来的做法整条链路跑通之后建议把配置固定下来别每次重建工作流都重填。MCP SSE 的 JSON 配置可以存成一个文件Agent 节点的指令也可以模板化。TaoToken 的 Key 建议单独建一个专门给 dify 用方便后续轮换。如果你后面要接更多 MCP 工具比如文件操作、HTTP 请求直接在 SSE 的 JSON 里加 server 就行Agent 节点里重新发现一次工具列表即可。模型侧不用动因为 TaoToken 的 Base URL 和 Key 是统一的换模型只改 Model ID。需要查 Key 和接入文档的话API Keys 在https://taotoken.net/api-keys接入文档在https://taotoken.net/doc。想先验证模型对话是否正常可以用https://taotoken.net/models试一下。长期做编码和 Agent 的话Coding Plan 在https://taotoken.net/coding-plan。最后留一个实用技巧dify 的 Agent 节点调试时把「最大迭代次数」临时调大一点比如 5方便观察多轮工具调用的过程。等稳定了再调回 3。这个参数不影响线上性能只影响单次请求的推理深度。