news 2026/10/8 22:22:20

Fastmcp本地搭建实战:查询本地mysql并接入agent-cursor详细流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Fastmcp本地搭建实战:查询本地mysql并接入agent-cursor详细流程

1. 本地 MySQL 到 Agent 的链路为什么总在 MCP 这步卡住

Fastmcp 是一个用 Python 写 MCP Server 的轻量框架,它能让你把本地 MySQL 的查询能力包装成 Agent 可调用的工具。适合谁?适合手头有本地数据库、想让 Cursor 或 Claude Desktop 这类客户端直接查数据的开发者。我这次的目标很明确:用 conda 建环境,写一个 Fastmcp 服务,连上本地 MySQL,最后在 agent-cursor 里配好 MCP,让 Agent 能回答“年龄大于 28 的用户有几个”这种问题。

为什么不用 uv?我试过,uv 装包确实快,但它替代的是 pip,不是 conda。conda 管的是 Python 版本和系统级依赖,uv 管的是包安装。两者可以配合,但如果你机器上已经有 conda 环境,直接用 conda 更省心,不用再折腾 uv 的虚拟环境路径。所以这篇全程用 conda。

整条链路分四段:MySQL 建库建表、conda 环境装 Fastmcp 和 pymysql、写 MCP 工具函数、在 Cursor 里配 MCP Server。每一段都有坑,尤其是 Cursor 的 MCP 配置格式和 Fastmcp 的启动方式,配错了就是local proxy failed或者reading choices报错。下面按顺序走,每步都给可复制的命令和配置。

先确认你本地有 MySQL。没有的话去官网下 MySQL 9.x 的 Windows 安装包,装完把bin目录加到系统环境变量。验证方式:打开 PowerShell,输入mysql --version,能打印版本号就说明环境变量配好了。这一步不做,后面mysql -u root -p会提示命令找不到。

数据库建好后,创建一个测试库和一张 user 表。我用的库名是mcp,表名user,字段就 id、name、age 三个。数据插 10 条,年龄从 22 到 35 不等,方便后面验证“大于某年龄的个数”这个查询逻辑。SQL 文件放在E:\mysql-9.3.0-winx64\mcp.sql,你可以放任意路径,执行时换成自己的。

CREATE DATABASE mcp; USE mcp; CREATE TABLE user ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, age INT NOT NULL ); INSERT INTO user (name, age) VALUES ('Alice', 23), ('Bob', 30), ('Charlie', 27), ('David', 35), ('Eve', 22), ('Frank', 28), ('Grace', 31), ('Heidi', 26), ('Ivan', 29), ('Judy', 24);

执行导入用重定向命令,注意 PowerShell 里<不是原生支持,得用cmd /c或者直接在 cmd 里跑。我实测 PowerShell 下这样写会报“不支持重定向”,换成下面这条:

cmd /c "mysql -u root -p mcp < E:\mysql-9.3.0-winx64\mcp.sql"

输入密码后没报错就说明导入成功。验证一下:mysql -u root -p登录,然后USE mcp;、SHOW TABLES;、SELECT * FROM user;,能看到 10 行数据就对了。这一步是整个链路的数据基础,数据没进去,后面 MCP 查出来永远是 0。

2. conda 环境与 Fastmcp 依赖安装的完整命令

conda 建环境这步很多人图省事直接用 base,但 base 里包太杂,后面装mcp[cli]和fastmcp容易版本冲突。我建议单独建一个,名字叫mysqlmcp,Python 版本用 3.11,兼容性最好。

conda create -n mysqlmcp python=3.11 -y conda activate mysqlmcp

激活后命令行前面会显示(mysqlmcp)。接下来装三个包:mcp[cli]是 MCP 协议的核心库,fastmcp是 Fastmcp 框架本身,pymysql是 MySQL 的 Python 驱动。注意mcp[cli]带方括号,PowerShell 里方括号可能被解析成通配符,所以要用引号包起来。

python -m pip install "mcp[cli]" pip install fastmcp pip install pymysql

装完验证一下:pip show fastmcp和pip show pymysql,能打印版本和路径就说明装好了。如果pip show mcp报找不到,说明mcp[cli]没装成功,重跑第一条命令,注意引号别丢。

这里有个细节:Fastmcp 的导入方式有两种,旧版是from mcp.server.fastmcp import FastMCP,新版是from fastmcp import FastMCP。我用的新版,导入路径短,而且@mcp.tool()装饰器的行为更稳定。如果你装完发现from fastmcp import FastMCP报ModuleNotFoundError,检查一下是不是装到了 base 环境而不是mysqlmcp环境。conda list里能看到当前环境装了哪些包。

环境建好后,在 Cursor 里新建一个空文件mysql.py,位置随意,我放在项目根目录。这个文件就是 MCP Server 的入口。写之前先确认 conda 环境的 Python 路径,后面 Cursor 配置里要用绝对路径,不能用python这种相对命令,否则 Cursor 启动 MCP 时找不到解释器。

conda activate mysqlmcp where python

输出类似C:\Users\你的用户名\miniconda3\envs\mysqlmcp\python.exe,把这个路径记下来,第 4 节配置 Cursor 时直接填进去。

3. 可复制的 Fastmcp 服务脚本与 MySQL 连接参数

MCP Server 的核心是一个工具函数,输入年龄,返回 user 表里年龄大于该值的记录数。用@mcp.tool()装饰器注册,Fastmcp 会自动把它暴露成 Agent 可调用的工具。连接参数里 host 用localhost,port 默认3306,user 是root,password 填你自己的,database 填mcp。

from fastmcp import FastMCP import pymysql mcp = FastMCP("MySQLMCP") @mcp.tool() def analysis_data(age: int) -> int: try: conn = pymysql.connect( host="localhost", port=3306, user="root", password="你的密码", database="mcp" ) cursor = conn.cursor() cursor.execute("SELECT COUNT(*) FROM user WHERE age > %s", (age,)) result = cursor.fetchone()[0] cursor.close() conn.close() return result except Exception as e: print("数据库操作出错:", e) raise if __name__ == "__main__": mcp.run()

注意 SQL 里我用的是%s占位符加参数元组,不是 f-string 拼接。f-string 拼接在参数是数字时没问题,但如果是字符串会有 SQL 注入风险,养成参数化查询的习惯。cursor.fetchone()[0]取的是 COUNT 的结果,返回 int。

mcp.run()默认用 stdio 传输,这是 MCP 客户端最常用的方式。Cursor 启动这个脚本后,通过标准输入输出和它通信。所以脚本里不要加print调试信息,会污染 stdio 通道,导致 Cursor 解析失败。要调试就用日志文件或者sys.stderr。

保存文件后,先在终端里手动跑一下,确认脚本本身没语法错误:

conda activate mysqlmcp python mysql.py

如果卡住不动,说明服务正常启动了,在等 stdio 输入。按Ctrl+C退出。如果报pymysql.err.OperationalError,检查 MySQL 服务是否启动、密码是否正确、端口是否被占用。

接下来配置 Cursor 的 MCP。Cursor 的 MCP 配置文件在%USERPROFILE%\.cursor\mcp.json,Windows 下就是C:\Users\你的用户名\.cursor\mcp.json。如果文件不存在就新建。配置格式是 JSON,mcpServers下面每个 key 是一个服务名,command填 conda 环境的 python 绝对路径,args填脚本的绝对路径。

{ "mcpServers": { "mysqlmcp": { "command": "C:\\Users\\你的用户名\\miniconda3\\envs\\mysqlmcp\\python.exe", "args": [ "E:\\projects\\mysql.py" ] } } }

路径里的反斜杠要双写,JSON 里\是转义字符。command和args都必须是绝对路径,相对路径 Cursor 解析不了。保存后重启 Cursor,在设置里找到 MCP 面板,应该能看到mysqlmcp显示为绿色或 connected 状态。

如果你用的是 Claude Desktop,配置文件在%APPDATA%\Claude\claude_desktop_config.json,格式一样,把mcpServers那段粘进去就行。Codex 的话配置在auth.json同级的config.toml里,用 TOML 格式写[mcp_servers.mysqlmcp],command 和 args 同上。三件套就是 Base URL、Key、Model ID,MCP 配置里不需要 Base URL 和 Key,那是模型调用才要的,MCP 只关心 command 和 args。

4. 验证请求与成功结果:从 Inspector 到 Cursor Agent

配好之后别急着在 Cursor 里问,先用 MCP Inspector 单独验证服务能不能正常响应。Inspector 是 Node.js 自带的调试工具,不需要额外安装,只要你有 Node.js。检查一下:node --version,能打印版本就行。没有的话去 Node.js 官网下 LTS 版本装上。

启动 Inspector 的命令是npx @modelcontextprotocol/inspector,后面跟启动 MCP Server 的命令。注意一定要先激活 conda 环境,否则 Inspector 用的 Python 不是mysqlmcp环境里的,会报ModuleNotFoundError。

conda activate mysqlmcp npx @modelcontextprotocol/inspector python E:\projects\mysql.py

跑起来后终端会打印一个http://localhost:5173之类的地址,浏览器打开。界面左侧点Connect,然后点Tools标签,再点List Tools。如果配置正确,能看到analysis_data这个工具,参数是age,类型integer。

在 Inspector 里直接调用:age填28,点Run。返回结果应该是4,因为 user 表里年龄大于 28 的有 Bob 30、David 35、Grace 31、Ivan 29,共 4 个。如果返回 0 或者报错,说明数据库连接有问题,回到第 1 节检查数据是否真的插进去了。

Inspector 验证通过后,回到 Cursor。把对话模式切到 Agent 模式(快捷键Ctrl+I或者点输入框旁边的模式切换),然后直接问:“帮我查一下 user 表里年龄大于 28 的有几个人”。Cursor 会自动调用mysqlmcp的analysis_data工具,传入age=28,然后把结果返回给你。第一次调用可能会弹一个确认框,点允许就行。

成功的话你会看到 Cursor 的回复里包含“4 个”或者“4 人”,并且工具调用记录里显示analysis_data(age=28)。这就说明整条链路通了:Cursor Agent → MCP 协议 → Fastmcp Server → pymysql → 本地 MySQL。

如果 Cursor 里问的时候没反应,检查 MCP 面板里mysqlmcp是不是绿色。灰色或者红色说明启动失败,点开看错误日志。常见的是路径写错或者 conda 环境没激活。Cursor 启动 MCP 时不会自动激活 conda 环境,所以command必须指向环境里的 python.exe 绝对路径,不能写python。

5. 本篇常见报错排查:401、local proxy failed 与 reading choices

报错一:pymysql.err.OperationalError: (1045, "Access denied for user 'root'@'localhost'")。这是密码错了。检查mysql.py里的password字段,和你mysql -u root -p登录时输入的密码一致。如果密码里有特殊字符比如@或#,在 Python 字符串里不用转义,直接写就行。

报错二:ModuleNotFoundError: No module named 'fastmcp'。这是环境不对。Cursor 启动 MCP 时用的 python 不是你激活的 conda 环境。检查mcp.json里的command路径,必须是envs\mysqlmcp\python.exe,不能是 base 环境的 python。用where python在激活环境后确认路径。

报错三:local proxy failed或者MCP error -32000: Connection closed。这是 Cursor 启动 MCP Server 后进程立刻退出了。原因通常是脚本里有语法错误,或者mcp.run()之前有print输出污染了 stdio。把mysql.py里的print全删掉,只保留mcp.run()。另外确认if __name__ == "__main__":这行没写错,缩进要对。

报错四:reading 'choices'或Unexpected token之类的 JSON 解析错误。这是 MCP 返回的内容不是合法 JSON。检查analysis_data的返回类型,必须是int、str、dict这些可序列化的类型。如果返回了cursor对象或者conn对象,Fastmcp 序列化时会失败。确保return result返回的是fetchone()[0]这个整数。

报错五:OAuth相关错误。MCP 本身不走 OAuth,如果你在 Cursor 里看到 OAuth 报错,说明你配的不是 MCP Server 而是模型 API。检查mcp.json的格式,mcpServers下面不应该有apiKey或baseUrl字段,那些是模型配置。MCP 只需要command和args。

报错六:Inspector 打不开或者npx卡住。这是 Node.js 版本太低。升级到 18 以上,node --version确认。如果npx下载慢,可以先用npm install -g @modelcontextprotocol/inspector全局装,然后直接跑mcp-inspector命令。

报错七:MySQL 服务没启动。Windows 下services.msc里找 MySQL 服务,状态是“正在运行”才行。如果停了,右键启动。端口被占用的话,netstat -ano | findstr 3306看谁占了,改 MySQL 端口或者杀掉进程。

排查顺序建议:先手动python mysql.py确认脚本能跑,再用 Inspector 确认工具能调,最后在 Cursor 里问。每一步过了再走下一步,不要跳步。跳步的话报错信息会混在一起,很难定位。

6. 把本地数据接进 Agent 的下一步

链路跑通后,你可以把analysis_data换成更复杂的查询,比如按名字模糊搜索、按年龄区间统计、多表关联。Fastmcp 支持多个@mcp.tool()函数,每个函数就是一个独立工具,Agent 会根据你的问题自动选合适的工具调用。

连接参数建议抽成环境变量,不要硬编码在脚本里。用os.environ.get("MYSQL_PASSWORD")读取,然后在 Cursor 的mcp.json里加env字段传入。这样脚本可以提交到 Git,密码不会泄露。

{ "mcpServers": { "mysqlmcp": { "command": "C:\\Users\\你的用户名\\miniconda3\\envs\\mysqlmcp\\python.exe", "args": ["E:\\projects\\mysql.py"], "env": { "MYSQL_PASSWORD": "你的密码" } } } }

如果你想让 Agent 长期跑查询任务,比如定时统计或者批量分析,可以考虑用 Coding Plan 把 MCP 服务和模型调用串起来。模型对话页面可以单独验证analysis_data的返回是否符合预期,接入文档里有 MCP 协议的详细说明和更多客户端配置示例。API Keys 页面管理你的调用凭证,注意 MCP 配置本身不需要 Key,Key 是模型调用才用的。

本地 MySQL 的数据敏感的话,别把生产库直接接进来。建一个只读账号,只授权SELECT权限,GRANT SELECT ON mcp.* TO 'readonly'@'localhost' IDENTIFIED BY '密码';,然后mysql.py里用这个账号连。这样即使 Agent 调用了不该调的工具,也改不了数据。

最后提醒一点:Cursor 的 MCP 配置改完后必须重启 Cursor 才生效,热重载不支持。改mysql.py后也要重启 MCP Server,在 Cursor 的 MCP 面板里点刷新或者重启按钮。Inspector 那边每次改脚本都要重新跑命令,它不会自动重载。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 22:19:33

小白也能轻松玩转龙虾:虾壳云一键部署 OpenClaw 并改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华