FastMCP + MySQL实战:让Claude和Cursor直接查询数据库
关键词FastMCP、MySQL、MCP Server、Python、Claude Desktop、Cursor、AI Agent、SQL、安全开发在上一篇文章中我们深入分析了tool()装饰器的工作原理了解了FastMCP如何把一个普通的Python函数变成AI可以调用的工具。但很多开发者真正关心的是能不能让Claude或Cursor直接查询公司的MySQL数据库答案是可以但不能简单地把数据库权限直接交给AI。本文将通过一个完整案例带大家开发一个支持MySQL查询的MCP Server并介绍企业项目中如何保证数据安全、权限控制和SQL防护。一、为什么AI不能直接连接数据库很多人认为AI调用数据库应该是这样的Claude ↓ MySQL实际上企业中几乎不会采用这种架构。正确的流程应该是用户 ↓ Claude / Cursor ↓ MCP Client ↓ FastMCP Server ↓ 业务服务(Service) ↓ MySQL为什么要多一层MCP Server主要有三个原因安全数据库账号和密码不会暴露给AI客户端。权限控制可以限制AI只能访问指定的数据。业务封装AI无需了解复杂SQL只需调用业务工具。因此MCP Server既是AI工具层也是数据库安全层。二、项目结构设计一个简单但易于扩展的项目结构可以设计为mcp-mysql/ │ ├── server.py ├── config.py ├── tools/ │ └── customer.py ├── services/ │ └── customer_service.py ├── database.py └── requirements.txt职责划分如下模块作用server.pyMCP Server入口tools定义AI可调用工具services编写业务逻辑database.py数据库连接管理config.py配置数据库信息这种结构便于后续扩展订单、库存、财务等多个业务模块。三、安装依赖安装FastMCP及MySQL驱动pip install mcp pymysql如果使用SQLAlchemy也可以安装pip install sqlalchemy pymysql对于企业项目更推荐SQLAlchemy因为它更容易管理连接池、事务和模型。四、连接MySQL数据库例如import pymysql connection pymysql.connect( host127.0.0.1, port3306, userdemo, password******, databasecrm, charsetutf8mb4 )安全建议数据库账号、密码不要直接写在代码中应放入环境变量或配置文件并避免提交到Git仓库。五、编写业务Service不要把SQL直接写在Tool中。推荐# services/customer_service.py class CustomerService: def query_by_id(self, customer_id): ...例如import pymysql class CustomerService: def query_by_id(self, customer_id): conn get_connection() cursor conn.cursor() cursor.execute( SELECT id,name,phone FROM customer WHERE id%s , (customer_id,) ) return cursor.fetchone()以后。所有数据库操作都集中在Service层。六、开发MCP Tool真正暴露给AI的代码非常简单from mcp.server.fastmcp import FastMCP from services.customer_service import CustomerService app FastMCP(CRM) service CustomerService() app.tool() def query_customer(customer_id:int): 查询客户信息 return service.query_by_id(customer_id)Claude、Cursor看到的就是Tool ↓ query_customer()AI根本不知道数据库如何连接。七、AI如何完成数据库查询假设用户输入查询10086号客户。后台流程用户 ↓ LLM理解 ↓ 发现 query_customer() ↓ 调用Tool ↓ CustomerService ↓ MySQL ↓ 返回JSON ↓ LLM整理回复例如数据库ID10086 姓名张三 等级VIP 手机号138****AI最终回答客户10086姓名为张三当前会员等级为VIP。整个过程中AI没有写SQL。八、为什么不建议让AI直接执行SQL很多初学者会想到app.tool() def execute_sql(sql:str):然后AI生成SQL。数据库执行。这种方式存在较大风险例如DELETE FROM customer;或者DROP TABLE orders;一旦模型误生成或误理解指令可能导致严重的数据破坏。因此在生产环境中应避免开放任意SQL执行能力。九、更推荐的企业方案企业一般采用Tool ↓ 固定业务接口 ↓ Service ↓ SQL例如query_customer() query_order() query_inventory() query_sales()而不是execute_sql()这样AI只能调用业务。不能操作数据库。安全性提高很多。十、需要复杂查询怎么办例如用户查询最近30天成交金额最高的10位客户。可以开发app.tool() def top_customer(days:int):Service里面提前写好SQL。AI只负责传参数。不要拼SQL。这样最安全。十一、如何返回AI更容易理解的数据很多数据库驱动默认返回元组( 1001, 张三, VIP )更推荐返回{ id:1001, name:张三, level:VIP }原因LLM更容易理解JSON。输出质量也更高。统一返回结构还能方便后续接入其他系统。十二、异常处理不能忽略数据库查询并不总是成功。例如app.tool() def query_customer(customer_id:int): try: ... except Exception as e: return { success:False, message:str(e) }不要直接抛异常。否则AI很难理解。建议统一返回{ success: false, message: Customer not found }这样更方便模型生成清晰的反馈。十三、企业级权限控制真实项目中不同角色通常拥有不同的数据权限。例如用户角色可访问数据销售自己负责的客户客服客户基本信息财务订单、发票管理员全部数据MCP Tool不应只根据参数查询数据还应结合当前用户身份进行权限校验。例如query_customer() ↓ 权限验证 ↓ 允许访问 ↓ 查询数据库这样才能满足企业安全要求。十四、日志与审计企业部署时建议记录每一次Tool调用。例如时间 2026-07-16 14:30 用户 sales01 Tool query_customer 参数 10086 结果 Success日志不仅便于排查问题还能满足部分行业的审计要求。总结FastMCP让AI访问数据库变得非常简单但真正的企业实践远不止连上数据库这么简单。推荐的设计原则可以总结为不要让AI直接执行任意SQL。将数据库能力封装为固定用途的Tool。业务逻辑放在Service层Tool保持简单。统一返回JSON结构提高模型理解能力。做好权限控制、异常处理和日志审计。使用环境变量管理数据库配置和敏感信息。最终形成的调用链应当是Claude / Cursor ↓ MCP Tool ↓ Service ↓ MySQL ↓ JSON结果 ↓ AI生成自然语言回复这种架构不仅安全、清晰而且易于维护和扩展非常适合构建企业级AI Agent。本文知识点✅ FastMCP连接MySQL✅ Tool与Service分层设计✅ 数据库查询最佳实践✅ JSON结果封装✅ SQL安全防护✅ 企业级权限控制✅ 日志审计与异常处理