张高兴的大模型开发实战:(八)在 Dify 中使用 MCP 协议

目录

  • [MCP 是什么](#MCP 是什么)
  • [Dify 作为 Client:调用外部 MCP 工具](#Dify 作为 Client:调用外部 MCP 工具)
    • [搭建 MCP 天气服务端](#搭建 MCP 天气服务端)
    • [在 Dify 中接入"天气感知"能力](#在 Dify 中接入“天气感知”能力)
  • [Dify 作为 Server:被外部应用调用](#Dify 作为 Server:被外部应用调用)

在之前的博客中已经介绍了 MCP 的概念,以及在 LangChain 中如何使用 MCP 协议。今天这篇博客,将带大家实战如何在 Dify 中实现 MCP 场景。在开始正式的内容前,还是先简单的介绍一下 MCP。

MCP 是什么

想象一下,你想要构建一个超级 AI 助手,它不仅能陪你聊天,还能帮你查询实时天气、读取本地数据库里的库存信息等。为了实现这些功能,在过去,你需要为每一个外部工具编写特定的"适配器"。AI 模型本该是通用的智能大脑,但连接外部世界(工具和数据)的方式却极其割裂和破碎,需要花费大量时间在"对齐接口"这种低效的重复劳动上,MCP 协议应运而生。可以把 MCP 想象成 AI 世界的 USB 接口。USB 的出现改变了一切,它提供了一个统一的标准:无论你是鼠标、键盘还是 U 盘,只要符合 USB 协议,插上就能用。MCP 就是要成为 AI 与外部数据/工具连接的 USB 标准。它将世界分成了两端:

  • Host (主机端):需要使用工具的 AI 应用,比如 Claude Desktop 客户端、Dify。
  • Server (服务端):提供特定能力的工具,比如一个能查天气的 Python 脚本,或者一个连接 MySQL 数据库的服务。

只要 Host 和 Server 都支持 MCP 协议,它们就能瞬间"握手"成功,Host 能够自动理解 Server 提供了什么工具,需要什么参数,而无需人工再去编写复杂的接口定义。

Dify 在 MCP 的生态中,它既可以是"插U盘的主机",也可以是"被别人插的U盘"。

  • Dify 作为 Client (主机端):调用外部能力。
  • Dify 作为 Server (服务端):暴露自身能力。 这可能是更有趣的一点,比如在 Dify 里精心编排了一个复杂的工作流,这个工作流本身可以被封装成一个标准的 MCP 工具。这意味着,在其他 AI 应用中,可以直接调用在 Dify 里搭建好的这个强大的 Agent。

Dify 作为 Client:调用外部 MCP 工具

在这一部分,想让 Dify 的 AI 助手拥有"感知"当下天气的能力,而不是在那胡诌过去的训练数据。即将 Dify 作为一个"主机",让它去连接一个 MCP Server。

搭建 MCP 天气服务端

首先,需要一个能够"说" MCP 协议的服务端。这里用到了 Python 的 mcp 库。

shell 复制代码
pip install mcp httpx

创建一个 Python 文件 weather_server.py 实现天气查询的 MCP 服务,不需要手写复杂的协议握手代码,只需要用几个简单的装饰器即可。使用免费的 Open-Meteo API 进行天气查询。

python 复制代码
import httpx
from mcp.server.fastmcp import FastMCP

# 初始化 FastMCP 服务器
mcp = FastMCP("Weather Service", host="0.0.0.0", port=8000)

async def _get_lat_long(city_name: str):
    """
    内部辅助函数:使用 Open-Meteo Geocoding API 将城市名称转换为经纬度。
    """
    url = "https://geocoding-api.open-meteo.com/v1/search"
    params = {"name": city_name, "count": 1, "language": "zh", "format": "json"}
    
    async with httpx.AsyncClient() as client:
        response = await client.get(url, params=params)
        data = response.json()
        
    if not data.get("results"):
        return None
        
    location = data["results"][0]
    return {
        "name": location["name"],
        "latitude": location["latitude"],
        "longitude": location["longitude"],
        "timezone": location.get("timezone", "UTC")
    }

@mcp.tool()
async def get_weather(city_name: str) -> str:
    """
    获取指定城市的当前天气情况。
    输入城市名称(如 'Beijing', 'San Francisco', '上海'),返回温度、风速等信息。
    """
    # 1. 首先获取经纬度
    location = await _get_lat_long(city_name)
    if not location:
        return f"错误:未找到城市 '{city_name}'。请尝试使用更具体的名称或英文名称。"

    # 2. 构建 Open-Meteo API 请求
    url = "https://api.open-meteo.com/v1/forecast"
    params = {
        "latitude": location["latitude"],
        "longitude": location["longitude"],
        "current": ["temperature_2m", "relative_humidity_2m", "apparent_temperature", "weather_code", "wind_speed_10m"],
        "timezone": location["timezone"]
    }

    async with httpx.AsyncClient() as client:
        response = await client.get(url, params=params)
        weather_data = response.json()

    # 3. 解析并返回数据
    current = weather_data.get("current", {})
    units = weather_data.get("current_units", {})
    
    # 将天气代码 (WMO Code) 转换为文字描述 (简化版)
    weather_code = current.get("weather_code")
    weather_desc = "未知"
    if weather_code == 0: weather_desc = "晴朗"
    elif weather_code in [1, 2, 3]: weather_desc = "多云/阴"
    elif weather_code in [45, 48]: weather_desc = "有雾"
    elif 51 <= weather_code <= 67: weather_desc = "有雨"
    elif 71 <= weather_code <= 77: weather_desc = "有雪"
    elif weather_code >= 80: weather_desc = "雷雨/阵雨"

    return (
        f"--- {location['name']} 天气报告 ---\n"
        f"天气状况: {weather_desc}\n"
        f"当前温度: {current.get('temperature_2m')} {units.get('temperature_2m')}\n"
        f"体感温度: {current.get('apparent_temperature')} {units.get('apparent_temperature')}\n"
        f"相对湿度: {current.get('relative_humidity_2m')} {units.get('relative_humidity_2m')}\n"
        f"风速: {current.get('wind_speed_10m')} {units.get('wind_speed_10m')}"
    )

if __name__ == "__main__":
    # 运行 MCP 服务器
    mcp.run(transport="sse")

在 Dify 中接入"天气感知"能力

现在 MCP 服务已经跑起来了,下面需要告诉 Dify 去哪里找到这个服务。回到 Dify 的网页界面:

  1. 点击顶部菜单栏的 工具 -> MCP -> 添加 MCP 服务
  2. 在弹出的窗口中填写配置:
    服务端点 URL:http://host.docker.internal:8000/sse
    名称:Weather Service
    服务器标识符:weather-service

如果连接成功,列表里会出现了一个绿色的"已连接"状态,点击展开,Dify 已经自动解析出了在 Python 代码里定义的 get_weather 函数,甚至连代码里写的注释都变成了工具的描述。

最后,来验证一下效果。

  1. 创建一个新的 Chatflow 应用 出行小助手

  2. 删除原有的 LLM 节点,添加一个 Agent 节点。

  3. 设置 AGENT 策略,如果下拉列表为空,可以在插件市场进行下载。

  4. 配置要使用的 模型,并在 工具列表 中新增刚刚添加的 MCP 服务。在 指令 中设置提示词。查询 设置为用户输入。

    markdown 复制代码
    # Role
    你是一位专业且贴心的出行规划专家。你擅长分析实时气象数据,提供包含穿衣、交通、安全及活动建议在内的全方位出行方案。
    
    # Constraints
    1. 语气专业、友好且富有亲和力。
    2. 必须基于 MCP 工具返回的真实数据进行建议,严禁编造天气数值。
    3. 输出应条理清晰,多使用列清单,避免大段文字。
    
    # Goals
    4. 数据调用:主动调用获取天气的 MCP 工具,获取用户指定目标的实时天气。
    5. 多维分析:不仅报告气温,更要分析该天气对出行的具体影响。
    6. 精准建议:给出极具参考价值的穿衣指南、交通方式推荐以及针对性提醒(如带伞、涂防晒霜或调整户外行程)。

以上配置完成后,先在右侧进行预览测试。例如"我明天要去北京,查一下天气和穿衣建议。"观察结果发现,Dify 成功获取了北京的天气,并根据天气给出了具体的出行建议。

Dify 作为 Server:被外部应用调用

有时,当你在 Dify 中配置了一个复杂的工作流(Workflow),想要在外部的 AI 应用中进行调用,这时就需要反转视角,将 Dify 作为一个 MCP 服务。在开始案例之前,先添加一个"翻译专家"工作流,作为要被调用的 MCP 服务。

搭建"翻译专家"工作流

  1. 在 Dify 首页点击 创建空白应用,选择 工作流,命名为 翻译专家,开始节点选择 用户输入

  2. 点击 用户输入 节点,添加输入变量 chinese,即要翻译的中文。

  3. 添加一个 LLM 节点,并设置提示词。

    markdown 复制代码
    # Role
    你是一位资深的翻译专家,擅长将中文翻译为英文。用户的输入是一段中文,请将其翻译成最地道、最专业、最简洁的英文。直接输出翻译后的英文,不要包含任何解释或废话。
    
    # Input
    {{#1769390459829.chinese#}}
  4. 添加一个 输出 节点,并设置输出变量 english

启用 MCP 服务

  1. 进入工作流,点击左侧列表的 设置
  2. 启用 MCP 服务,并添加描述。
  3. 复制 服务端点 URL 留存备用。

在外部 AI 应用中调用

拿到了 URL 后,在任意支持 MCP 调用的应用中都可以使用刚刚配置好的工作流,这里以 Visual Studio Code 为例。

  1. 点击聊天框中的 配置工具 按钮,在弹出的顶部菜单中点击 添加 MCP 服务器
  2. 选择 HTTP,输入刚刚复制的 URL,并设置唯一的 服务器 ID
  3. 配置完成后,可以看到 Visual Studio Code 输出的日志,提示已经连接到 MCP 服务。
  4. 配置工具 列表中,只勾选刚刚添加的 MCP 服务,用于测试。
  5. 尝试进行对话,Dify 中配置的"翻译专家"被成功调用。

AI 的未来,不在于拥有一个多么巨大的单一模型,而在于协作,MCP 正在迅速成为这种协作的标准语言。这篇博客通过两个简单的案例,介绍了 MCP 在 Dify 中的用法,后续不妨尝试一些更有趣的玩法:

  • 连接物理世界:写一个 MCP Server 控制家里的智能家居(Home Assistant)。想象一下,在 Dify 的对话框里输入"我得睡觉了",AI 自动帮你关灯、拉窗帘、定闹钟。
  • 连接私有数据:使用 mcp-server-sqlitemcp-server-postgres,让 Dify 直接拥有查询你本地业务数据库的能力,生成报表。
  • 打造个人超级助理:在 Dify 里编排好你专属的"周报生成器"、"代码审查器",然后在 VS Code 里随时呼叫它们,让 AI 真正融入你的工作流。
相关推荐
饮哉8 小时前
LLM生成文本每次是把之前所有的token都输入,还是只输入上一个token?
人工智能·大模型
xixixi777778 小时前
RAG越权检索与变形指令/隐写规避常态化:攻击者通过Base64、TokenBreak、字符插入与多轮引导,诱导模型泄露知识库或训练集中的敏感信息
网络·安全·大模型·网络攻击模型·攻击·rag·越权检索
laplace01239 小时前
PPO到GRPO自己话总结
人工智能·python·大模型·agent·rag
红尘炼丹客10 小时前
论文《LLM-in-Sandbox Elicits General Agentic Intelligence》解析
人工智能·深度学习·大模型·llm-in-sandbox
Java后端的Ai之路13 小时前
【AI大模型开发】-NotebookLM 使用
人工智能·大模型·谷歌·notebooklm
山顶夕景13 小时前
【Agent】Agentic Reasoning for Large Language Models
大模型·llm·agent·智能体·agentic
黑客-雨1 天前
DeepSeek-V3.2深度拆解:开源模型逆袭,GPT-5迎来劲敌!
人工智能·程序员·大模型·知识图谱·agent·大模型教程·deepseek-v3.2
山顶夕景1 天前
【MLLM】Qwen3-TTS语音生成模型
大模型·语音合成·tts·tokenizer
北邮刘老师2 天前
【热点关注】三国演义:工具调用(MCP)、技能仓库(Skills)和智能体互联(IoA),到底选哪个?
大模型·智能体·mcp·a2a·智能体互联网