1. Dify Agent 调用 MCP 工具时,endpoint 到底该填什么
Dify 里的 Agent 想用 MCP 协议调外部工具,最容易卡住的地方不是写工具逻辑,而是那个url字段。很多人第一次配的时候会下意识填http://127.0.0.1:8000,结果 Dify 报连接失败;或者填了/messages/路径,工具列表一直拉不出来。这篇就围绕「Dify 通过 MCP 协议调用工具,把 MCP endpoint 改到 TaoToken」这个场景,把配置片段、鉴权字段、验证动作和常见报错一次讲清楚。
先说清楚 MCP 在 Dify 里的角色。Dify 本身是编排器,它不直接执行你的工具,而是通过 MCP 插件去发现工具、调用工具。MCP 有两种通信模式:STDIO 和 SSE。Dify 走的是 SSE 模式,因为 Dify 是独立进程,没法直接和你的本地工具进程共享 stdin/stdout。SSE 模式下,你的工具服务要暴露一个/sse端点,Dify 通过这个端点建立长连接,拿到工具列表,再通过/messages/发调用请求。
所以 endpoint 的格式是http://你的地址:端口/sse,不是根路径,也不是/messages/。这个细节决定了工具能不能被发现。我见过太多人卡在这里,以为服务没起来,其实是路径写错了。
那 TaoToken 在这里扮演什么角色?当你的 MCP 工具服务需要调用大模型能力时——比如工具内部要做意图识别、参数补全、结果总结——这些模型请求可以统一走 TaoToken 的 API。TaoToken 提供兼容 OpenAI 的接口,Base URL 是https://taotoken.net/api,你拿到 Key 之后,工具服务里所有模型调用都指向这个地址,不用再分散配置多个厂商的 Key。这样 MCP 工具服务本身保持轻量,模型能力通过一个 endpoint 统一管理。
适合谁看:正在用 Dify 搭 Agent、需要接自定义工具、或者想把现有工具服务通过 MCP 暴露给 Dify 的开发者。如果你只是用 Dify 内置工具,这篇可能用不上;但只要你写过一行工具代码,下面的配置就能直接抄。
2. TaoToken 前置准备:Key、Base URL 与模型 ID 三件套
在动 Dify 配置之前,先把 TaoToken 这边的三件套准备好。所谓三件套,就是 Base URL、API Key、Model ID。这三个东西缺一个,后面工具服务里的模型调用就会报 401 或者 model not found。
Base URL 固定是https://taotoken.net/api。注意这里不带任何路径后缀,不要写成/v1或者/chat/completions,SDK 会自己拼。如果你用的是 OpenAI 的 Python SDK,就把base_url设成这个值。
API Key 需要你去控制台生成。打开https://taotoken.net/console,登录后在 API Keys 页面创建一个新的 Key。创建的时候建议按用途命名,比如dify-mcp-tool,这样后面排查问题时能一眼看出是哪个服务在用。Key 只在创建时显示一次,复制下来存到环境变量里,别硬编码进代码。
Model ID 取决于你要调哪个模型。在模型对话页面可以先试一下,确认模型能正常返回。常见的比如claude-sonnet-4-5、gpt-4o这类,具体以你账号下可用的为准。工具服务里如果只是做简单的参数解析,用便宜的小模型就够;如果要做复杂的推理链,再上大模型。
把这三个值写进环境变量,后面工具服务和 Dify 配置都从这里读:
export TAOTOKEN_BASE_URL="https://taotoken.net/api" export TAOTOKEN_API_KEY="sk-你的key" export TAOTOKEN_MODEL_ID="claude-sonnet-4-5"为什么要用环境变量而不是直接写死在配置里?因为 Dify 的 MCP 配置里 headers 字段是要填鉴权信息的,如果你把 Key 写死在 JSON 里,一旦 Key 轮换就要改多处。用环境变量,工具服务启动时读取,Dify 那边只需要填工具服务的地址,不用管模型 Key。
这里有个容易混淆的点:Dify 连你的 MCP 工具服务,用的是工具服务自己的鉴权(如果有的话);而工具服务连 TaoToken,用的是 TaoToken 的 Key。这是两层不同的鉴权,不要混在一起。很多人把 TaoToken 的 Key 填到 Dify 的 MCP headers 里,结果工具服务收到一个它不认识的 token,直接拒绝。
如果你还没生成 Key,现在去https://taotoken.net/api-keys创建一个。创建完先别急着配 Dify,用 curl 测一下 Key 能不能通:
curl https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "'"$TAOTOKEN_MODEL_ID"'", "messages": [{"role": "user", "content": "ping"}] }'返回里有choices字段就说明 Key 和模型都没问题。这一步过了,再往下走。
3. 可复制配置:MCP endpoint 与鉴权字段完整片段
这一节给可直接复制的配置。分两部分:工具服务端的配置,和 Dify 侧的 MCP 配置。
先看工具服务端。假设你用 FastMCP 写一个最简单的工具服务,暴露 SSE 端点:
from fastmcp import FastMCP import os from openai import OpenAI mcp = FastMCP("dify-tool-demo", port=9000) client = OpenAI( base_url=os.environ["TAOTOKEN_BASE_URL"], api_key=os.environ["TAOTOKEN_API_KEY"], ) @mcp.tool() def summarize(text: str) -> str: """对输入文本做摘要,内部调用 TaoToken 模型""" resp = client.chat.completions.create( model=os.environ["TAOTOKEN_MODEL_ID"], messages=[ {"role": "system", "content": "你是一个摘要助手,输出不超过50字。"}, {"role": "user", "content": text}, ], ) return resp.choices[0].message.content if __name__ == "__main__": mcp.run(transport="sse")启动命令:
python server.py服务起来后,SSE 端点是http://0.0.0.0:9000/sse。注意 FastMCP 默认会把/sse和/messages/都注册好,你不需要自己写路由。
然后是 Dify 侧的 MCP 配置。在 Dify 的 MCP SSE 插件里,工具配置是一个 JSON,格式如下:
{ "dify-tool-demo": { "url": "http://127.0.0.1:9000/sse", "headers": {}, "timeout": 60, "sse_read_timeout": 300 } }几个字段逐个说:
url必须是/sse结尾。如果你填http://127.0.0.1:9000,Dify 会去请求根路径,拿不到 event-stream,工具列表就是空的。
headers是给工具服务传的额外请求头。如果你的工具服务没有鉴权,留空对象{}就行。如果工具服务要求 Bearer token,这里填{"Authorization": "Bearer 你的工具服务token"}。注意这个 token 不是 TaoToken 的 Key,是工具服务自己的。
timeout是建立连接的超时,单位秒。本地服务设 60 够用;如果工具服务在远端,网络慢的话可以调到 120。
sse_read_timeout是读取 SSE 事件的超时。工具调用如果耗时较长(比如内部要调模型做推理),这个值要设大一点,300 秒是常见值。设太小会导致调用中途断开,报reading choices之类的错误。
如果你有多个工具服务,就在这个 JSON 里加多个 key:
{ "dify-tool-demo": { "url": "http://127.0.0.1:9000/sse", "headers": {}, "timeout": 60, "sse_read_timeout": 300 }, "another-tool": { "url": "http://127.0.0.1:9001/sse", "headers": {"Authorization": "Bearer tool-token-2"}, "timeout": 60, "sse_read_timeout": 300 } }Dify 会分别连这两个端点,把工具合并到同一个工具列表里。Agent 在推理时看到的是合并后的工具集,调用时 Dify 会根据工具名路由到对应的服务。
配置保存后,Dify 会立即尝试连接。如果连接成功,工具列表里会出现summarize。如果没出现,看下一节的排查。
4. 验证请求:从工具发现到执行链路
配置保存只是第一步,真正要确认的是 Agent 能不能发现工具、能不能执行工具、执行结果能不能回到工作流。这一节给一套完整的验证动作。
第一步,验证工具发现。在 Dify 的 MCP 插件页面,点「刷新工具列表」或者重新保存配置。如果配置正确,工具列表里会出现你定义的summarize。如果列表为空,先别往下走,去排查连接问题。
第二步,单独测工具调用。Dify 的 MCP 插件通常提供一个测试入口,可以直接传参数调工具。给summarize传一段文本:
{"text": "Dify 是一个开源的大语言模型应用开发平台,支持工作流编排和 Agent 构建。"}预期返回是一段不超过 50 字的摘要。如果返回正常,说明工具服务、TaoToken 模型调用、SSE 回传这条链路都通了。
第三步,在 Agent 里验证。创建一个 Agent 应用,把 MCP 工具加进去,系统提示词写清楚工具用途:
你是一个助手,可以调用 summarize 工具对长文本做摘要。 当用户提供需要摘要的文本时,调用 summarize 工具,把结果返回给用户。然后输入一段长文本,观察 Agent 的推理过程。正常情况下,Agent 会先输出一个工具调用请求,Dify 转发给 MCP 服务,服务执行后返回结果,Agent 再基于结果生成最终回复。
第四步,看日志确认。工具服务端会打印请求日志,Dify 端也有调用记录。两边对照,确认请求确实到达了工具服务,且返回了结果。如果 Dify 显示调用了工具但结果为空,去工具服务日志看是不是模型调用报错了。
这里有个实测经验:如果工具内部调 TaoToken 模型耗时超过sse_read_timeout,Dify 会认为调用超时,即使工具最终返回了结果也拿不到。所以工具内部如果要做多轮模型调用,要么把sse_read_timeout调大,要么把耗时逻辑改成异步,先返回一个「处理中」的状态,再通过其他方式回传结果。
验证通过后,这套配置就可以复用到其他工具上。每加一个工具,重复「定义工具 → 重启服务 → 刷新 Dify 工具列表 → 测试调用」这个循环。
5. 常见报错排查:401、local proxy failed、reading choices
这一节列几个真实会遇到的报错,以及对应的排查方向。
401 Unauthorized。这个报错通常出现在两个地方。如果是在工具服务日志里看到,说明工具服务调 TaoToken 时 Key 不对。检查TAOTOKEN_API_KEY环境变量有没有正确设置,Key 有没有过期,请求头是不是Authorization: Bearer sk-xxx格式。如果是在 Dify 日志里看到,说明 Dify 连工具服务时鉴权失败,检查 MCP 配置里的headers字段,确认工具服务要求的 token 填对了。
local proxy failed。这个报错一般是 Dify 无法连接到 MCP endpoint。可能原因:工具服务没启动,端口不对,或者url路径写错了。先在服务器上 curl 一下:
curl -N http://127.0.0.1:9000/sse如果返回一串event: endpoint开头的内容,说明服务正常。如果连接被拒绝,检查服务是否在监听、防火墙是否放行。如果 Dify 和工具服务不在同一台机器,127.0.0.1要换成工具服务的实际 IP,且确保 Dify 能访问到那个 IP。
reading choices 相关报错。这个通常出现在工具服务内部调模型时。choices是 OpenAI 兼容接口返回结构里的字段,如果报读取choices失败,说明模型返回的结构不对。可能原因:Base URL 写错了,比如写成了https://taotoken.net而不是https://taotoken.net/api;或者 Model ID 不存在,返回了一个错误结构。用第 2 节的 curl 命令单独测一下模型调用,确认返回里有choices。
OAuth 相关报错。如果你用的 MCP 服务要求 OAuth 鉴权,Dify 的 MCP SSE 插件可能不支持完整的 OAuth 流程。这种情况下,要么改用 API Key 鉴权,要么在工具服务前面加一层网关,把 OAuth 转换成固定 token。TaoToken 的 API Key 鉴权就是固定 token 模式,配置简单,适合 Dify 这种场景。
工具列表为空但服务正常。检查url是不是以/sse结尾。很多人填了http://127.0.0.1:9000/messages/,这是 POST 端点,不是 SSE 端点,Dify 连上去拿不到工具列表。正确的 SSE 端点是/sse。
调用超时。调大sse_read_timeout,同时检查工具内部逻辑有没有阻塞操作。如果工具内部要调模型,模型响应慢会导致整体超时。可以考虑在工具内部设置模型调用的 timeout,避免无限等待。
排查的时候,养成看两边日志的习惯:Dify 端看调用记录和错误信息,工具服务端看请求日志和模型调用日志。两边对照,基本能定位到是哪一层的问题。
6. 把 MCP endpoint 统一到 TaoToken 的接入建议
工具服务跑起来之后,模型调用这块建议统一走 TaoToken。原因很简单:MCP 工具服务可能会越加越多,每个服务如果各自配模型 Key,管理成本会很高。统一到 TaoToken 之后,所有工具服务的模型调用都指向https://taotoken.net/api,Key 也只用管一个。
具体做法是在工具服务的启动环境里注入三件套,代码里通过环境变量读取。这样本地开发和线上部署可以用同一套代码,只换环境变量。如果你用 Docker 部署工具服务,在docker-compose.yml里加:
services: mcp-tool: build: . ports: - "9000:9000" environment: - TAOTOKEN_BASE_URL=https://taotoken.net/api - TAOTOKEN_API_KEY=${TAOTOKEN_API_KEY} - TAOTOKEN_MODEL_ID=claude-sonnet-4-5Dify 侧的 MCP 配置保持不变,还是指向工具服务的/sse端点。这样分层清晰:Dify 管编排,工具服务管工具逻辑,TaoToken 管模型能力。
如果你还在选模型,可以先去模型对话页面试几个,确认哪个模型在你的场景下效果和成本都合适。长期跑 Agent 的话,Coding Plan 这类套餐可能更划算,具体看你的调用量。
接入文档里有更详细的参数说明和示例,配置过程中遇到不确定的字段可以去查。工具服务写好后,把 endpoint 填到 Dify 的 MCP 配置里,刷新工具列表,跑一次调用,整条链路就通了。