MCP Toolbox MySQL 执行 SQL 工具(mysql-execute-sql)完整指南:配置、原理与实战
【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox
本篇技术指南围绕 MCP Toolbox for Databases 开源项目中的mysql-execute-sql工具展开,详细讲解它如何通过 MCP Server 让 LLM/Agent 对 MySQL 数据库执行 SQL 语句,覆盖工具配置、数据源对接、参数说明、底层调用链与安全注解机制。读完本文,你将掌握如何在自己的 MySQL 实例上配置并使用该工具,理解它与mysql数据源之间的协作方式,并能基于源码与测试用例深入排查问题。
工具概述:mysql-execute-sql 是什么
mysql-execute-sql是 MCP Toolbox for Databases(项目根目录)为 MySQL 集成提供的一个工具(tool)。根据官方文档(mysql-execute-sql.md)的定义,它负责对 MySQL 数据库执行一条 SQL 语句。
该工具的行为非常简单直接:
- 接收一个输入参数
sql(要执行的 SQL 语句字符串); - 将该语句在工具配置中指定的
source(数据源)上执行,并返回执行结果。
注意(源自官方文档):此工具面向开发者辅助工作流(developer assistant workflows),强调 human-in-the-loop(人在回路),不应用于生产环境中的自动化 Agent。这是因为它可以执行任意 SQL(包括 DDL/DML 写操作),在生产场景下风险过高。
从源码看,该工具在 mysqlexecutesql.go 中以mysql-execute-sql为注册名,通过包内init()函数调用tools.Register注册到全局工具注册表,与 MySQL 集成下其他工具(如mysql-list-tables、mysql-get-query-plan等,见 tools 目录)并列。
兼容的数据源
mysql-execute-sql需要挂在某个数据源(source)之上。官方文档通过{{< compatible-sources others="integrations/cloud-sql-mysql">}}声明其兼容来源,即:
- 原生 MySQL 数据源(
type: mysql,详见 source.md); - Google Cloud SQL for MySQL 数据源(
integrations/cloud-sql-mysql,见 cloud-sql-mysql 集成文档)。
这一约束在源码中有严格校验。工具定义了compatibleSource接口(mysqlexecutesql.go),要求数据源必须实现:
type compatibleSource interface { MySQLPool() *sql.DB RunSQL(context.Context, string, []any) (any, error) }当调用方传入不兼容的数据源时,Invoke会返回客户端错误 "source used is not compatible with the tool"(mysqlexecutesql.go);ValidateSource也会在初始化阶段拒绝类型不匹配的数据源。原生mysql数据源(mysql.go)同时实现了MySQLPool()与RunSQL(),因此天然兼容。
配置 mysql-execute-sql 工具
最小 YAML 配置示例
官方文档给出的工具配置示例如下:
kind: tool name: execute_sql_tool type: mysql-execute-sql source: my-mysql-instance description: Use this tool to execute sql statement.四个字段均为必填,含义如下(依据 Reference 表格 与 Config 结构体):
| field | type | required | description |
|---|---|---|---|
| kind | string | true | 声明资源类型为工具,固定为tool |
| name | string | true | 工具实例名称,在配置文件中唯一(例如execute_sql_tool) |
| type | string | true | 工具类型,必须为mysql-execute-sql |
| source | string | true | 执行 SQL 的数据源名称,必须指向配置文件中已定义的type: mysql数据源 |
| description | string | true | 传递给 LLM 的工具描述,LLM 会据此决定何时调用该工具,建议写清楚适用场景 |
name、description、authRequired等通用字段来自tools.ConfigBase(内联到 Config 中)。其中description在Initialize阶段被强制校验——为空会直接报错description is required for tool %q(mysqlexecutesql.go)。
可选配置:authRequired 与 annotations
虽然官方文档的 Reference 只列了三个核心字段,但源码表明工具还支持两个可选配置项:
kind: tool name: execute_sql_tool type: mysql-execute-sql source: my-mysql-instance description: Use this tool to execute sql statement. authRequired: - my-google-auth-service annotations: destructiveHint: trueauthRequired:声明调用该工具所需的认证服务列表,解析行为已被单元测试覆盖(见 mysqlexecutesql_test.go 中的TestParseFromYamlExecuteSql);annotations:覆盖默认的 MCP Tool Annotations(destructiveHint/readOnlyHint/idempotentHint/openWorldHint),与 MCP 规范中的 tool annotations 对应(见 tools.go)。
配置 MySQL 数据源(source)
工具本身不携带连接信息,真正的数据库连接由mysql数据源负责。参考 source.md,一个完整的 source 配置如下:
kind: source name: my-mysql-instance type: mysql host: 127.0.0.1 port: 3306 database: my_db user: ${USER_NAME} password: ${PASSWORD} # Optional TLS and other driver parameters. For example, enable preferred TLS: # queryParams: # tls: preferred queryTimeout: 30s # Optional: query timeout duration| field | type | required | description |
|---|---|---|---|
| type | string | true | 必须为mysql |
| host | string | true | 连接地址(如127.0.0.1) |
| port | string | true | 连接端口(如3306) |
| user | string | false | MySQL 用户名 |
| password | string | false | 用户密码 |
| database | string | false | 要连接的数据库名 |
| queryTimeout | string | false | 查询执行超时时间(如30s、2m),默认不设超时 |
| queryParams | map<string,string> | false | 传递给驱动的任意 DSN 参数(如tls: preferred、charset: utf8mb4),可用于启用 TLS 或其他连接选项 |
| sqlCommenter | boolean | false | 覆盖全局--sql-commenter开关,设置时优先于全局标志,省略时遵循全局设置 |
在源码层面,数据源初始化逻辑位于 mysql.go 的initMySQLConnectionPool:
- 基于
go-sql-driver/mysql构建 DSN,user与password成对生效(无 user 时忽略 password); - 默认注入
parseTime=true参数,用户自定义的queryParams会合并进参数表(空值被跳过); queryTimeout通过time.ParseDuration解析后映射为驱动层的ReadTimeout,解析失败会返回 "invalid queryTimeout" 错误;- 将当前进程的 UserAgent 写入 DSN 的
ConnectionAttributes(program_name),便于在 MySQL 侧追踪流量来源; - 连接池建立后会执行
PingContext验证连通性,失败则关闭连接池并报错(mysql.go)。
安全建议(源自官方文档 tip):使用
${ENV_NAME}形式的环境变量替换(例如${MYSQL_USER}、${MYSQL_PASSWORD}),不要把明文密钥硬编码进配置文件。仓库预置配置 mysql.yaml 正是这样做的。
底层执行原理:一条 SQL 的完整旅程
当 LLM 调用该工具时,MCP Server 会路由到Tool.Invoke,其执行链路(mysqlexecutesql.go)大致如下:
- 类型断言:将
sources.Source断言为compatibleSource,失败则返回错误; - 参数提取:从
paramsMap中取出sql字符串,非字符串类型返回 Agent 错误; - 日志记录:以 Debug 级别记录将要执行的 SQL(
executing 'mysql-execute-sql' tool query: ...),便于排障; - 执行:调用
source.RunSQL(ctx, sqlStr, nil)执行,参数列表为空切片; - 错误归一化:执行失败时通过
util.ProcessGeneralError转换为统一格式的 ToolboxError 返回。
数据源侧 RunSQL 的实现
原生mysql数据源的RunSQL(mysql.go)完成真正的数据库交互:
- 先用
sqlcommenter.PrependComment为语句附加 SQLCommenter 注释(受全局--sql-commenter或 source 级sqlCommenter控制,该参数定义于 mysql.go); - 通过连接池
QueryContext执行语句并取出列名与列类型; - 逐行
Scan数据,使用mysqlcommon.ConvertToType做类型归一化; - 结果按
orderedmap.Row保持列顺序组装为 JSON 友好的结构返回。
类型转换细节:JSON 列的防双重序列化
ConvertToType(mysqlcommon.go)有一个值得注意的细节:当列类型为字符串/字节/sql.NullString且数据库类型名为JSON时,会先对原始字节做json.Unmarshal再返回对象,避免后续再次序列化造成"双重编码";其余数值类型保持原样返回。这意味着查询JSON类型的列时,返回给 LLM 的是可直接使用的结构化对象,而非转义后的字符串。
安全注解:只读数据源下的动态降级
mysql-execute-sql默认被标记为**破坏性(destructive)**注解——Initialize中调用tools.NewDestructiveAnnotations作为默认值(mysqlexecutesql.go),因为任意 SQL 可能包含INSERT/UPDATE/DELETE/DDL。
但源码实现了动态注解翻转(mysqlexecutesql.go):当所连接的数据源处于只读模式(src.IsReadOnly()返回 true)时,工具会自动把destructiveHint翻转为 false、readOnlyHint翻转为 true,同时保留用户自定义的idempotentHint、openWorldHint。这一行为在 TestGetAnnotations 中有完整覆盖:
- nil source → 保持默认破坏性注解;
- 读写 source → 保持默认破坏性注解;
- 只读 source → 动态翻转为只读注解;
- 只读 source + 显式只读 base → 仍为只读;
- 只读 source + 自定义 hints → 仅翻转 readOnly/destructive 两项,保留其余自定义 hint。
这意味着在只读副本上配置该工具时,MCP 客户端与 LLM 会自动感知到它只读的属性,从而减少误写风险。
开箱即用:预置配置与工具集
仓库为 MySQL 提供了开箱即用的预置配置 mysql.yaml,其中:
- 定义了一个名为
mysql-source的 source,主机/端口/账号/密码全部通过环境变量注入(MYSQL_HOST、MYSQL_PORT、MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD),queryTimeout预设为30s; - 定义了名为
execute_sql的mysql-execute-sql工具实例,直接指向mysql-source; - 同时定义了两个工具集(toolset):
data:由execute_sql、list_tables、get_query_plan组成,面向数据读写与查询场景;monitor:由get_query_plan、list_active_queries、list_all_locks、list_table_fragmentation、list_table_stats、list_tables_missing_unique_indexes、show_query_stats组成,面向实例监控与诊断。
你可以直接复用这份预置配置,只需把工具名改成符合自己语义的名字,并确保source字段与实际的 source 名称一致。
测试与验证:如何确认配置正确
仓库为mysql-execute-sql提供了单元测试 mysqlexecutesql_test.go,可用于验证:
- YAML 解析正确性(
TestParseFromYamlExecuteSql):模拟一个包含authRequired的完整配置,断言解析出的Config(Name/Description/AuthRequired/Type/Source)与期望完全一致; - 注解动态翻转逻辑(
TestGetAnnotations):覆盖只读/读写数据源与自定义注解的各种组合。
在本地执行go test ./internal/tools/mysql/...即可运行上述测试,快速确认工具注册、配置解析链路没有问题(真实数据库联调则需要可访问的 MySQL 实例或 Cloud SQL for MySQL 环境)。
最佳实践小结
- 限定使用场景:仅在开发者辅助、human-in-the-loop 的工作流中使用;生产 Agent 不应直接暴露任意 SQL 执行能力;
- 严格的最小权限:为工具配置独立、最小权限的 MySQL 用户(该数据源仅使用标准认证,需先创建可登录的 MySQL 用户,参考 source.md);
- 使用环境变量注入密钥:
${ENV_NAME}占位符替代硬编码密码; - 善用只读数据源:查询类场景可指向只读副本,工具注解会自动降级为只读,降低误写风险;
- 写好 description:该字段直接决定 LLM 何时选择调用此工具,描述应覆盖典型用途(如"执行 SQL 查询/写入语句")与限制;
- 合理设置 queryTimeout:避免长时间运行的查询拖垮连接池,
30s是仓库预置配置的默认值。
更完整的 MySQL 工具集清单(查询计划、表统计、锁分析、碎片整理等)可在 tools 文档目录 中继续探索。
【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考