← 返回文章列表

Dify MCP 集成实验(03):MCP 接入 Dify 全链路——MCP Server 如何接入 Dify 应用?

1. 业务场景

先讲一个我们实际遇到的场景。

一家做客服工单 SaaS 的公司,客服门户的 AI 助手要能回答「我的工单 T12345 什么状态」——状态数据在 107-02 的 MCP server 里。现在要把这个 server 真正接进 Dify:Console 添加 MCP server → 工作流 tool 节点调用 → 冒烟验证。这是集成单最典型的场景:外部系统数据通过 MCP 进入 Dify 应用。

我们第一次接这类需求时,第一反应是「Console 里填个 URL 就能连」。真正动手才发现——接入的未知点全藏在网络路径和 DSL 格式里:api 容器访问外部 server 要过 SSRF 代理,白名单没覆盖就 403;MCP 工具节点在 DSL 里的准确字段网上查不到权威格式,只能从 UI 导出反推。不实测,排障全靠试。

这不是个例。任何「外部系统数据通过 MCP 进入 Dify 应用」的集成都是这个模式:网络路径通不通、DSL 字段怎么写——两个未知点不实测,后面全凭猜。

2. 场景痛点

这个流程的痛点,在接入时体现得最直接:

本质上,接入的未知点集中在「网络路径」和「DSL 权威格式」两处——不实测,排障全靠试

3. 方案:为什么是 Console + UI 导出实证

把 107-01/02 的 MCP server 接入 Dify 全链路,最可靠的方法是 Console 添加 + UI 导出权威 DSL + 运行级实证。

选它的理由:

这篇文章我们就用它把「工单状态查询」MCP 工具接入客服门户应用,跑通全链路并固化 DSL 权威格式。

4. 整体架构

graph TD server["本地开发机:dify107_02_support_server(Streamable HTTP :8902)"] dify["Dify 服务器"] api["api(FastAPI)"] unk1["未知点1:MCP 客户端是否走 squid 代理"] ssrf["SSRF_PROXY 白名单 172.16.0.0/12 是否覆盖"] web["web(控制台 → 工具页 → MCP tab)"] app["应用 dify107_03_验证应用(workflow)"] st["start(ticket_id)"] tool["tool(MCP)"] llm["LLM"] en["end"] server -- "HTTP" --> dify dify --> api dify --> web dify --> app api --> unk1 --> ssrf app --> st --> tool --> llm --> en

链路很清晰:本地 server(Streamable HTTP)→ Dify api(经 squid 代理)→ web 控制台配置 → 工作流 tool 节点 → LLM → end。关键设计是验证应用用最简链路(start → tool → LLM → end),把未知点集中在 MCP 工具节点本身。

5. 模块设计

5.1 SSRF 双层 403 的修复(未知点 1,根因链)

graph TD a["Dify api 容器(core/mcp MCP 客户端)"] b["SSRF 代理(ssrf_proxy/squid :3128)"] c["host.docker.internal(.env 白名单已加)"] d["本机 uvicorn :8902/mcp(SDK 2.0 server)"] a -- "※ MCP 客户端也走代理(create_ssrf_proxy_mcp_http_client)" --> b b --> c --> d
问题 修复
① SDK 2.0 server streamable-http 默认 DNS rebinding protection,Host=host.docker.internal 不在白名单 → 403 run(transport_security=TransportSecuritySettings(enable_dns_rebinding_protection=False))(开发环境;生产用 allowed_hosts)
② squid SSRF 代理 MCP 客户端也走 ssrf_proxy,host.docker.internal 不在 squid 白名单 → 403 .envSSRF_PROXY_ALLOW_PRIVATE_DOMAINS=localhost,host.docker.internal + docker compose up -d --force-recreate ssrf_proxyrestart 不重跑 entrypoint,必须 recreate

排错关键证据:api 容器内 curl(不走代理)POST /mcp 返回 200,Dify 客户端(走代理)403 → 锁定代理层。

5.2 MCP 工具节点 DSL 权威格式(未知点 2,UI 导出实测)

- data:

    provider_id: dify107_02_support_server   # = MCP provider 的 server_identifier

    provider_name: dify107_02_support_server

    provider_show_name: dify107_02_support_server

    provider_type: mcp                        # ⚠️ 字符串 "mcp"(区分 builtin/workflow 工具)

    tool_name: get_ticket_status

    tool_node_version: '2'

    tool_parameters:

      ticket_id:

        type: mixed

        value: '{{#start.ticket_id#}}'

    tool_configurations: {}

    plugin_id: null

    plugin_unique_identifier: null

    output_schema: {}

    type: tool

与 builtin/workflow 工具同 node 类型(type: tool),靠 provider_type: mcp 区分;provider_id = MCP provider 的 server_identifier(不是行 UUID)。

6. 运行验证

输入 预期 结果
T1002(存在 open) 工单 T1002 当前状态是 open(最后更新于 2026-08-04 09:30:00) 通过
T1001(存在 closed) 工单 T1001 当前状态是 closed(最后更新于 2026-08-01 10:00:00) 通过
T9999(不存在) 未找到该工单,请核对工单号 通过
abc(格式错 → 工具 isError) workflow failed(显式失败非静默) 通过(显式失败)
Console 工具列表 只见 search_tickets / get_ticket_status(tools),resources/prompts 无入口 通过(三原语运行级实证)

7. 实战坑

现象 修复
SSRF 双层 403 ① SDK 2.0 streamable-http 默认 DNS rebinding protection(Host=host.docker.internal → 403)② MCP 客户端也走 squid 代理,host.docker.internal 不在白名单 → 403 ① server.run 关掉或配 allowed_hosts ② .envSSRF_PROXY_ALLOW_PRIVATE_DOMAINS + force-recreate(restart 不生效)(实测)
MCP 工具输出 text 为空 结构化工具(outputSchema)输出=字段直接展开(ticket_id/status/updated_at),text="" 下游引用展开字段{{#tool_status.status#}}),别引用 text——首版 LLM 收空白误报「未找到」(实测)
DSL provider_type MCP 工具节点不认 builtin/workflow 的 provider_type 值 provider_type: "mcp"(graphon 枚举),provider_id=server_identifier(实测)
Model is disabled DSL 写 disabled 模型(本机 deepseek-chat disabled)→ run 400 用 active 模型(deepseek-v4-flash);查 GET model-providers/{provider}/models 的 status(实测)
MCP 删除/列表 UUID 语义 列表接口 id=server_identifier,删除/工具端点按 DB 行 UUID 查 行 UUID 从 DB 查 SELECT id FROM tool_mcp_providers;创建响应 id=行 UUID(实测)
工具错误行为 MCP 工具 isError → Dify tool 节点失败 → workflow failed 显式非静默;优雅降级 107-06 验收时按需加 fail 分支(实测)

8. 实验文档及源码获取

文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。

联系我

15088711270

手机端点击号码可直接拨打 · 桌面端可复制

微信二维码

扫码加微信 · 备注「门户」更快通过