首页/新闻资讯/正文详情

Dify+fastmcp 实战:从零搭建可复用的 MCP 服务(附完整源码与配置骨架)

发布时间:2026/9/24 17:27:52 来源:云帆数科 栏目:资讯中心
Dify+fastmcp 实战:从零搭建可复用的 MCP 服务(附完整源码与配置骨架)
1. 为什么我要把运维查询做成 MCP 服务Dify 编排 Agent 时最让人头疼的不是提示词而是「实时数据从哪来」。我一开始也走过弯路把机器指标先同步到本地知识库再让 Dify 检索。结果知识库更新慢、数据滞后运维同事问「这台机器现在 CPU 多少」Agent 只能给出十分钟前的快照完全没法用。后来我把思路换成 MCPModel Context Protocol让 Dify 作为 MCP 客户端通过 fastmcp 暴露一个本地服务Agent 需要数据时直接调用工具函数函数内部再去远程执行命令、返回结构化结果。这样知识库可以完全不建Agent 拿到的是实时值还能自己组织语言给出分析建议。这篇就按「Dify fastmcp 搭建可复用 MCP 服务」的完整链路来写包含可复制的服务端骨架、Dify 工具配置片段、settings.json / config.toml 示例以及启动验证和调用排查。适合需要把内部工具接入 AI 工作流的开发者Python 3.10 以上即可跟做。2. 前置准备TaoToken 与运行环境在动手写代码前先把两件事定下来模型调用通道和本地依赖。模型侧我用 TaoToken 统一管理它的 API 地址是https://taotoken.net/api兼容 OpenAI 风格的调用方式Dify 里配置模型供应商时直接填这个 base_url 就行。如果你还没建 Key可以先去控制台生成一个后面 Dify 的 Agent 节点会用到。模型对话入口https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewriteAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite本地环境需要python3 --version # 确认 3.10 pip install fastmcp psutil paramikofastmcp负责把普通 Python 函数注册成 MCP 工具psutil采集本机指标paramiko用于远程执行命令。装完后可以先python3 -c import fastmcp; print(fastmcp.__version__)确认版本。注意远程执行账号密码不要硬编码在源码里示例里我会用环境变量占位你落地时务必替换成自己的密钥管理方式。3. 可复制的 fastmcp 服务端骨架3.1 server.py 主结构核心是用FastMCP创建实例再用mcp_server.tool装饰器注册工具。description 写得越清楚Dify 里的大模型越容易判断该调哪个工具。from fastmcp import FastMCP import psutil import os from remote_execute import RemoteQuickHandler mcp_server FastMCP( nameMy MCP Server, host0.0.0.0, port8002, ) mcp_server.tool(description计算两个整数相加用于验证 MCP 通道是否连通) def add(a: int, b: int) - int: return a b mcp_server.tool(description获取当前服务器 CPU 总使用率及前 10 高 CPU 进程) def get_cpu_usage() - dict: total_cpu psutil.cpu_percent(interval0.1) processes [] for proc in psutil.process_iter([pid, name, cpu_percent]): try: proc.cpu_percent() cpu_pct proc.cpu_percent(interval0.1) processes.append({ pid: proc.info[pid], name: proc.info[name], cpu_percent: cpu_pct, }) except (psutil.NoSuchProcess, psutil.AccessDenied): continue top_processes sorted(processes, keylambda x: x[cpu_percent], reverseTrue)[:10] return {total_cpu_usage: total_cpu, top_10_cpu_processes: top_processes} if __name__ __main__: mcp_server.run(transportsse)transportsse是关键Dify 的 Agent 节点目前对接 MCP 走的就是 SSE 通道两边必须一致。3.2 远程查询工具远程机器指标查询封装成独立工具入参是host_ip内部用 paramiko 执行命令并解析。mcp_server.tool(description查询目标服务器 CPU 使用率及前 10 高 CPU 进程) def get_host_cpu_usage(host_ip: str) - dict: handle RemoteQuickHandler( iphost_ip, usernameos.getenv(REMOTE_USER), passwordos.getenv(REMOTE_PASS), ) cmd_total vmstat 1 2 | tail -1 | awk {print 100 - $15} cmd_proc ps -eo user,comm,pcpu --sort-pcpu | head -n 11 status, result_total handle.command_with_result(cmd_total) status, result_proc handle.command_with_result(cmd_proc) if result_total[FAIL]: return {error: result_total[FAIL][0][msg]} if result_proc[FAIL]: return {error: result_proc[FAIL][0][msg]} cpu_usage float(result_total[SUCCESS][0][msg].strip()) lines result_proc[SUCCESS][0][msg].strip().split(\n) top_processes [] for line in lines[1:11]: parts line.strip().split() if len(parts) 3: top_processes.append({ user: parts[0], command: .join(parts[1:-1]), cpu_usage: parts[-1], }) return {cpu_usage: cpu_usage, top_processes: top_processes}内存和磁盘工具结构类似内存用free -b解析字节再转 GB磁盘用df -h配合单位换算函数。这里有个坑df -h输出单位可能是 G/M/T直接当 GB 用会算错必须写一个_convert_to_gb做归一化。3.3 remote_execute.py 封装import paramiko class RemoteQuickHandler: def __init__(self, ip, username, password, port22): self.ip ip self.username username self.password password self.port port def command_with_result(self, command: str) - tuple: client paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect(self.ip, portself.port, usernameself.username, passwordself.password, timeout10) stdin, stdout, stderr client.exec_command(command) out stdout.read().decode(utf-8, errorsignore) err stderr.read().decode(utf-8, errorsignore) if err.strip(): return FAIL, {FAIL: [{msg: err.strip()}], SUCCESS: []} return OK, {FAIL: [], SUCCESS: [{msg: out}]} except Exception as e: return FAIL, {FAIL: [{msg: str(e)}], SUCCESS: []} finally: client.close()返回结构统一成{FAIL: [...], SUCCESS: [...]}上层工具函数只判断 FAIL 是否为空逻辑会清爽很多。4. Dify 侧配置与 settings.json / config.toml 示例4.1 Dify Agent 节点配置在 Dify 里新建一个 Chatflow添加 Agent 节点。如果找不到 Agent 或 Marketplace多半是版本太低建议 1.2 及以上。进入 Marketplace 安装 Agent 策略策略选择 FunctionCalling它支持 MCP 工具调用。然后在 Agent 节点的 MCP 服务配置里填入{ mcpServers: { ops-mcp: { transport: sse, url: http://127.0.0.1:8002/sse, timeout: 30 } } }如果你用的是 Dify 的 config.toml 方式管理可以写成[[mcp_servers]] name ops-mcp transport sse url http://127.0.0.1:8002/sse timeout 30查询节点选择开始节点的query变量这样用户输入会直接传给 Agent。工具列表在测试阶段可以留空实测下来删掉或禁用工具并不影响 MCP 服务调用具体作用可以后续再研究。4.2 模型供应商配置在 Dify 的模型供应商里新增 OpenAI 兼容类型base_url 填https://taotoken.net/apiAPI Key 填你在控制台生成的 Key。保存后测试连通性能返回模型列表就说明通道没问题。5. 启动验证与调用排查5.1 启动服务python3 server.py看到类似Uvicorn running on http://0.0.0.0:8002就说明 SSE 服务起来了。先用 curl 验证通道curl -N http://127.0.0.1:8002/sse正常会持续输出 SSE 事件流包含 endpoint 信息。如果卡住无输出检查端口是否被占用、防火墙是否放行。5.2 Dify 内测试在 Dify 点击发布更新进入预览聊天页输入「查一下 192.168.1.10 的 CPU 使用率」。Agent 会先调用get_host_cpu_usage拿到结构化数据后组织语言返回。如果返回的是原始 JSON 而不是自然语言说明 Agent 策略没选 FunctionCalling或者模型不支持工具调用。5.3 常见报错对照现象可能原因处理Dify 提示 MCP 连接失败url 路径不对确认是/sse而非根路径工具调用返回空description 太模糊补充工具用途和参数说明远程执行超时目标机不可达或账号错先用 ssh 手动验证连通性内存数值异常字节未转 GB检查free -b解析逻辑磁盘单位混乱df -h 单位未归一补_convert_to_gb函数6. 把 MCP 服务接进长期工作流一次跑通只是起点。如果你打算把这类 MCP 服务长期挂在 Agent 工作流里建议用 Coding Plan 管理调用额度避免临时 Key 过期导致线上中断Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite我自己的做法是把 server.py 拆成工具层和传输层工具层只关心业务逻辑传输层用 fastmcp 的 SSE 暴露。这样以后要加新工具只写一个带mcp_server.tool的函数就行Dify 侧不用改配置。另外远程执行账号一定走环境变量或密钥服务别图省事写死在代码里这是踩过坑之后最想提醒你的一点。

相关推荐

Linux系统(09):线程概念与控制
Linux系统(09):线程概念与控制

💬 :如果你在阅读过程中有任何疑问或想要进一步探讨的内容,欢迎在评论区畅所欲言!我们一起学习、共同成长~! 👍 :如果你觉得这篇文章还不错,不妨顺手点个赞、加入收藏,并… · 2026/9/24 17:27:52

应用案例|兵器重工:某型号装备安全控制子系统研发与模型驱动实践
应用案例|兵器重工:某型号装备安全控制子系统研发与模型驱动实践

一、项目背景随着高端复杂装备向多学科融合、软件功能自定义、智能化协同等方向的快速发展,装备系统的复杂性呈指数级增长。某型号装备安全控制子系统作为核心控制部件,其设计质量直接决定着装备的效能释放与安全使用。此外,随着装备向微型化… · 2026/9/24 17:27:52

Java 工程师在 AI 时代:从实现业务代码到构建支撑 Agent 可靠运行的工程框架
Java 工程师在 AI 时代:从实现业务代码到构建支撑 Agent 可靠运行的工程框架

引言:Java 工程师的位置,正在悄悄改变过去十年,"Java 开发工程师"这个岗位的核心任务很清晰:把业务需求翻译成表结构、接口和业务逻辑,交付一套能稳定跑在服务器上的系统。而今天,当越来越多的需… · 2026/9/24 17:27:51

STAP仿真实战:ACP与AEP算法对比及MATLAB实现
STAP仿真实战:ACP与AEP算法对比及MATLAB实现

简介:空时自适应信号处理(STAP)是雷达目标检测与抗干扰中的关键技术,尤其适用于合成孔径雷达(SAR)系统对弱目标、强杂波场景的探测。面向雷达信号处理学习者和工程开发人员,这里提供 ACP&#x… · 2026/9/24 19:06:56

Apache Thrift 编译器 C++ 编码规范指南:周边风格、clang-format 与 make style 自动化
Apache Thrift 编译器 C++ 编码规范指南:周边风格、clang-format 与 make style 自动化

后端微服务API设计 【免费下载链接】thrift Apache Thrift 项目地址: https://gitcode.com/gh_mirrors/thrift2/thrift 点击查看 免费下载 Apache Thrift 的 IDL 编译器(compiler/cpp)是一个以 C 编写的代码生成工具,负责解析 .t… · 2026/9/24 19:06:49

随机森林实战指南:用sklearn实现花分类并调优模型
随机森林实战指南:用sklearn实现花分类并调优模型

简介:这是一份面向机器学习初学者的随机森林花分类实践代码包,聚焦鸢尾花品种预测这一经典案例,帮助读者理解集成学习原理、Bootstrap抽样机制及sklearn建模流程。压缩包体积仅1KB,内含1个Python源文件,可直接运行&… · 2026/9/24 19:06:49

epoll 为什么快?红黑树 + 就绪链表的设计哲学与实战避坑
epoll 为什么快?红黑树 + 就绪链表的设计哲学与实战避坑

做网络编程的人,大概率都背过这道面试题: “epoll 为什么快?因为用了红黑树 就绪链表。” 但说实话,我见过很多人能背出这两个数据结构的名词,却说不清楚它们各自到底承担什么职责、为什么偏偏选这两种结构&#xf… · 2026/9/24 19:06:37

2026(9.21-9.23)周报
2026(9.21-9.23)周报

推进《七秒记忆》娃娃用品电商平台项目,完成原型页面搭建与需求文档迭代优化,梳理项目整体业务框架,为后续开发工作打下基础。在原型设计方面,我使用墨刀完成项目网站基础页面原型搭建,重点设计平台首页。完成顶部导航… · 2026/9/24 19:06:37

电磁波原理到通信应用:从频谱规划到天线选型全解析
电磁波原理到通信应用:从频谱规划到天线选型全解析

开篇:为什么你天天用着通信,却不认识电磁波手机打电话、连Wi-Fi刷视频、开车用导航、坐地铁刷卡……这些场景背后,真正干活的都是同一个东西——电磁波。电磁波这个概念从中学物理就开始出现,但说实话,我接触过不少通信… · 2026/9/24 19:06:37

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码