前言

​ 在之前使用dify来编排AI智能体,有这样的一个场景,希望智能体能自动读取数据库数据,获得统计数据(问数),最终生成报告。

​ 当时实现思路是,通过知识库告诉大模型相关表的字段定义,然后让大模型根据提示词生成对应统计指标SQL语句,然后调用mysql工具去执行,返回结果。这其中,需要整理一堆表定义的知识库,且最终效果也不好。

​ MCP(Model Context Protocol,模型上下文协议 )协议出现后,大量MCP服务涌出,其中mysql 类的MCP服务,使用cline可以得出不错的问数效果。但基本都是Typescript实现的,且安全性无法保证。在实际使用中,更愿意自己去维护一个本地MCP服务。该文档即是探究使用python开发调试本地mysql MCP服务的方法。

功能分析

  • 执行查询SQL功能

    由大模型生成相关问题查询SQL语句,发送给MCP服务执行,并返回结果给大模型

  • 查询指定表的模式

    要想让大模型生成正确的SQL,需要告诉大模型指定表的结构模式

  • 查询指定数据库所有表

    想要获取指定表名,需要先列出所有的表名

初始化项目环境

uv init mysql-mcp
cd mysql-mcp
# 创建mcp服务虚拟环境
uv venv
# 激活该环境
.venv\Scripts\activate

代码实现

安装依赖包

pip install mysql-connector-python
uv add "mcp[cli]"

代码如下:

mysql-mcp.py

from mcp.server.fastmcp import FastMCP
from config import DB_CONFIG
import pymysql
import utils# 初始化mcp服务
mcp = FastMCP("mysql-mcp")@mcp.tool()
def list_tables():"""获取数据库所有表名"""try:mydb = pymysql.connect(**DB_CONFIG)mycursor = mydb.cursor()mycursor.execute("SHOW TABLES")tables = mycursor.fetchall()table_names = [table[0] for table in tables]return table_namesexcept pymysql.Error as err:print(f"MySQL Error: {err}")return {"error": str(err)}finally:if 'mycursor' in locals():mycursor.close()if 'mydb' in locals():mydb.close()@mcp.tool()
def describ_table(table_name:str):"""返回表的结构"""try:mydb = pymysql.connect(**DB_CONFIG)mycursor = mydb.cursor()mycursor.execute("SELECT column_name, data_type FROM information_schema.columns WHERE table_name = %s",table_name)table_desc = mycursor.fetchall()return table_descexcept pymysql.Error as err:print(f"MySQL Error: {err}")return {"error": str(err)}finally:if 'mycursor' in locals():mycursor.close()if 'mydb' in locals():mydb.close()@mcp.tool()
def execute_sql(sql:str):"""执行SQL语句,返回查询结果"""try:mydb = pymysql.connect(**DB_CONFIG)mycursor = mydb.cursor()mycursor.execute(sql)# 获取列名column_names = [desc[0] for desc in mycursor.description]if mycursor.rowcount == 0:mydb.commit()return {"message": "执行成功,无返回结果"}else:return utils.data_transformer(column_names,mycursor.fetchall())except pymysql.Error as err:print(f"MySQL Error: {err}")return {"error": str(err)}finally:if 'mycursor' in locals():mycursor.close()if 'mydb' in locals():mydb.close()if __name__ == "__main__":print("启动mysql-mcp服务")mcp.run(transport="stdio")

config.py,配置数据库连接

DB_CONFIG = {"host": "127.0.0.1","port": 3306,"user": "root","password": "XXXX@123456","database": "XXX",}

调试

调试bug

在写完代码后,可以使用如下命令去调试是否存在语法错误

python ./mysql-mcp.py

在这里插入图片描述

可以看到mcp包未安装

在这里插入图片描述

mysql 包未安装

在这里插入图片描述

目录名和mysql包名重复了,修改目录名

经过多次安装,还是提示不存在。在这个目录层次下,使用conda 虚拟了一个python环境,python版本为3.10,在mysql目录下又使用uv venv虚拟了一个环境,但该虚拟环境是用的conda环境下的python包,所以有点乱;

于是直接将uv venv虚拟环境删掉,直接新建目录mysqlmcp,然后复制如上的代码。

执行

mcp dev ./mysql-mcp.py

这时将会启动成功。浏览器输入地址 http://127.0.0.1:6274

输入如下参数:

command

uv

Arguments

run --with mcp mcp run ./mysql-mcp.py

Proxy Session Token 从启动的控制台Session Token 复制

点击连接,即可连接成功。

在这里插入图片描述

调试MCP工具

连上去后就可以开始调试Tools了。

先点击list Tools列出MCP服务提供的工具,如上图。

点击list_tables,执行run tools

在这里插入图片描述

可以看出该工具成功返回结果,数据库中的表,history面板展示了调用工具的请求和返回通信信息。

这里的数据库连接信息是配置在代码侧的。

其他的工具调试类似。但存在一个问题,这种调试方式是没法debug的,没法单步调试的,所以推荐可以对工具函数,单独写python代码进行调试。调试好再同步到MCP服务里。

使用cline连接

开发好MCP服务,就可以用cline去用了。

在 mcp inspector 界面左侧面板复制 servers file,然后粘贴到cline的mcp服务配置文档里(需要调整下),调整后的如下:

"mysql-server": {"disabled": false,"timeout": 60,"type": "stdio","command": "uv","args": ["run","--with","mcp","mcp","run","D:\\source\\mcp\\mysqlmcp\\mysql-mcp.py"]}

点击连接报错

在这里插入图片描述

后面证实这其实不是报错,只是连接MCP服务的日志信息。

现在是已经正常连接了。

执行数据统计问答

正常连接后,向其提问:

查看数据库有多少个党员,并按年龄段统计展示

在这里插入图片描述

可以看到cline利用LLM,已经为这个问题做好了规划,一共5步。后续就是按照这5步去执行。

首先,cline识别出了mysql-server的list_tables工具,获取数据库所有表

在这里插入图片描述

其次,调用describ_table工具去获取表的字段描述

在这里插入图片描述

再次,对字段进行分析,写SQL语句

在这里插入图片描述

执行SQL报错,自动修改SQL,

在这里插入图片描述

最终执行成功,返回结果。

经验总结

1、MCP服务整体开发思路大致是 使用uv初始化环境,写MCP服务代码,代码单点调试,启用mcp inspector调试、使用cline连接,具体使用;uv虚拟环境有时候感觉需要,有时候又感觉不需要,后续整个全新的项目去研究一下;

2、应用过程中,我在想,使用cline去调用mcp服务的工具,和基于http协议调用接口有啥区别嘞,为啥不能直接去调用http应用的接口嘞?待后续慢慢思考;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87334.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87334.shtml
英文地址,请注明出处:http://en.pswp.cn/web/87334.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OA退位,如何打造安全便捷的跨网文件传输与即时通讯平台?

随着医院信息化建设深入推进,OA 系统在日常流程审批和文件流转中扮演着不可或缺的角色。然而,面对“内网⇄外网”强隔离的安全要求,OA 在跨域传输上仍然存在审批延迟、人工干预、病毒风险等痛点。 一、OA 在跨网传输中的 “ 最后一公里 ” 难…

LlamaIndex的多轮对话引擎使用说明

一、背景 LlamaIndex提供2种交互引擎:查询引擎和聊天引擎。(详情请看这里)查询引擎默认没有上下文信息,也就是说默认是单轮对话。 在RAG系统中,单轮对话/单次查询的场景较少,而多轮对话则是最常见的场景&…

【CSS-14.1-全局样式表common.css】构建高效可维护的 common.css:现代前端CSS架构指南

在前端开发中,CSS管理一直是项目可维护性的关键挑战。据统计,约35%的样式问题源于缺乏统一的CSS架构规范。common.css(或称全局样式表)作为项目的基础样式层,能够有效解决以下问题: 样式碎片化&#xff1a…

laravel基础:php artisan make:model Flight --all 详解

在 Laravel 中执行命令: php artisan make:model Flight --all这个命令会为你创建与模型 Flight 相关的一整套文件结构。Laravel 的 Artisan 命令行工具是一个强大的代码生成器,可以帮助你快速生成常见的应用组件。我们来详细解析一下这个命令的各个部分以及它产生的效果。 …

poi java 删除word的空白页

开发的时候遇到的问题,特此记录一下 使用Apache POI(Java库)删除Word文档中的空白页时,需针对不同场景处理。以下是具体实现方法和代码示例: 基础删除(段落/分页符)‌ 通过删除多余段落标记或…

获取Android应用日志教程

ADB,全称为Android Debug Bridge,是Android开发中一个重要的命令行工具。它用于与Android设备进行通信,提供了多种功能来帮助开发者进行调试和应用管理。 一、环境准备 1.PC下载附件中的安装包。 2.在设备上启用开发者选项和 USB 调试 在安卓…

【Axum】Rust Web 高效构建:Axum 框架从入门到精通指南

目录 一、环境准备与项目创建1.1 安装 Rust 工具链1.2 创建项目并添加依赖 二、Axum 核心架构解析三、项目结构设计四、核心代码实现4.1 应用入口 (src/main.rs)4.2 数据模型 (src/models.rs)4.3 路由配置 (src/routes.rs)4.4 认证服务 (src/services/auth.rs)4.5 用户处理器 (…

康谋分享 | 基于多传感器数据的自动驾驶仿真确定性验证

目录 01 引言 02 随机性的前因与后果 03 确定性的验证——以aiSim为例 1、传感器选型与配置 2、场景与方法 3、验证结果 04 总结 01 引言 随着自动驾驶技术的飞速发展,仿真测试已成为替代成本高昂且充满风险的道路测试的关键环节。它能够在虚拟环境中模拟…

FASTAPI+VUE3平价商贸管理系统

一、项目概述 PJMall 是一个基于 FastAPI 构建的商城管理系统后端服务,提供商品管理、订单处理、用户认证等核心功能。系统采用分层架构设计,支持高并发访问,适用于多角色用户(管理员、客户、供应商)。 核心特性 &a…

客服机器人知识库怎么搭?智能客服机器人3种方案深度对比(含零售落地案例)

一、知识库技术缺陷的权威数据 IDC 2025报告:89%企业因知识库更新延迟导致智能客服机器人解决率下降40%,传统规则引擎日均失效对话超2000次。 二、三大技术方案架构解析 1.LLM动态知识图谱方案 基于Transformer架构实时抓取政策/价格数据 知识关联度…

JavaScript 性能优化实战:减少 DOM 操作引发的重排与重绘

在前端开发中,DOM 操作是 JavaScript 性能优化的核心痛点之一。频繁的 DOM 操作会触发浏览器的 重排(Reflow) 和 重绘(Repaint),导致性能显著下降。本文将深入分析这一瓶颈,并通过实际案例展示优…

力扣 hot100 Day33

24. 两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 //抄的 class Solution { public:ListNode* swapP…

DevExpress V25.1 版本更新,开启控件AI新时代

WinForms Controls v25.1 AI 驱动的语义搜索 我们的 WinForms 数据网格、GridLookUpEdit 和 SearchLookUpEdit 控件具有增强的搜索体验,使用户能够更快/更准确地在大型数据集中查找相关数据。与基于关键字的标准搜索不同,语义搜索利用自然语言处理 &…

【分层图 虚拟节点】 P11327 [NOISG 2022 Finals] Voting Cities|普及+

本文涉及知识点 C图论 P11327 [NOISG 2022 Finals] Voting Cities 题目描述 你所在的国家的国家主席 L o r d P o o t y \bf{Lord\ Pooty} Lord Pooty 将要退休了!他希望选择他的一个儿子作为他的继承人,出于各方面因素的考虑,他决定进行…

Web3云服务商安全性怎么选

Web3安全之锚:为何阿里云是企业级应用的首选​ 随着Web3、去中心化金融(DeFi)和数字资产的浪潮席卷全球,无数开发者和企业涌入这个充满机遇的新赛道。然而,机遇背后是同样巨大的安全挑战。从智能合约漏洞到大规模DDoS…

uniapp加上全局水印

文章目录 一、效果图二、创建watermark.js文件三、在main.js中引入四、运行 前言:uniapp页面加水印你还在傻乎乎的一个个页面加吗,今天教你一招,一步到位 一、效果图 未登录效果 登录后效果 二、创建watermark.js文件 这里的水印因为我…

thinkphp8.0七牛云直传图片

环境&#xff1a;tp8\php8.3; 服务器&#xff1a;centOS Stream 9; 场景&#xff1a;通过html页面直传七牛云服务器&#xff0c;速度更快&#xff1b; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta na…

Godot x openKylin 全国开发大赛正式启动

从2023年开始&#xff0c;Godot Hub 每年举办一次 Godot Hub Festival 开发大赛&#xff0c;现已成为国内 Godot 社区规模最大的开发比赛。本届 Godot Hub Festival 2025将与 OpenAtom openKylin 开源社区合作举办&#xff0c;定名为 Godot x openKylin 全国开发大赛&#xff0…

工控机Linux修改网口

修改Ip:sudo nmcli connection modify net1-static ipv4.addresses 192.168.200.225/24 修改dns:sudo nmcli connection modify net1-static ipv4.dns 114.114.114.114 修改网关:sudo nmcli connection modify net1-static ipv4.gateway 192.168.200.1 IP生效&#xff1a;nm…

CRMEB Pro版v3.3源码全开源+PC端+Uniapp前端+搭建教程

一.介绍 crmeb Pro版 v3.3版本正式发布&#xff0c;全新UI重磅上线&#xff0c;焕然一新&#xff0c;不负期待&#xff01;页面DIY设计功能全面升级&#xff0c;组件更丰富&#xff0c;样式设计更全面&#xff1b;移动端商家管理&#xff0c;让商城管理更便捷&#xff0c;还从…