关于 MySQL (security-first)
MySQL (security-first) 是面向 AI 客户端的 MySQL MCP 服务,以 SQL AST 解析、默认拒绝的表白名单和多层执行限制控制数据库访问。它还提供表结构资源、查询计划分析和查询统计。
主要功能
- 01通过 SQL AST 校验语句
- 02默认拒绝的表白名单
- 03按语句类型配置访问权限
- 04限制行数、超时和多语句执行
- 05提供表结构资源与查询计划
- 06记录查询统计并可选审计
适用场景
- 01允许 Agent 在受限规则下查询 MySQL
- 02隔离多个数据库连接配置
- 03查看慢查询和执行计划
- 04通过表结构资源向客户端提供架构信息
MCP 相关
作为 MCP 服务,它向客户端提供 MySQL 查询、受控写入、脚本、表清单和统计工具,并为白名单中的基础表提供结构资源。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e MYSQL_MCP_PASSWORD ghcr.io/kurok1/mcp-server-mysql:2.1.0MYSQL_MCP_PASSWORD密钥MySQL password, referenced from config.yaml as ${MYSQL_MCP_PASSWORD}本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/kurok1/mcp-server-mysql:2.1.0stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mcp-server-mysql
English | 简体中文
以安全为先的 MySQL MCP 服务。 每条 SQL 语句在访问数据库前,都必须通过工业级 SQL 解析器(TiDB parser)的完整 AST 解析——并由只读事务回退机制和驱动程序级多语句锁定提供支持。三层相互独立的纵深防御:让 AI 查询数据库,但不让它带走整个数据库。
为什么选择它?
大多数 MySQL MCP 服务通过正则表达式/关键词匹配,或将查询包装在只读事务中来实现“只读”。这两种方式都不可靠:
- 正则检查可被 SQL 注释和精心改写的语句绕过。
- 仅依赖只读事务无法防范
COMMIT; DROP TABLE ...这样的堆叠语句注入——这正是 Datadog 曾针对官方 Postgres 参考服务展示的攻击方式,该服务此后已归档。
本项目改为将安全边界建立在真正的 SQL 语义解析之上。每条语句都会由 TiDB parser 解析为 AST(兼容 MySQL 8.0 语法);解析器无法理解的任何内容都会被拒绝——默认拒绝,因此语法覆盖不完整只会导致过度拦截,而不会拦截不足。并且,由于解析器识别的是真正的 MySQL 语义,像将 JOIN mysql.user 隐藏在版本注释 /*!80000 ... */ 中这样的技巧,也会被提取出来,并像其他表引用一样进行检查。
亮点
- 独立连接配置 — 一个进程管理多个 MySQL 连接,每个连接都有自己的连接池、安全规则、审计文件和统计信息。使用
list_profile查看名称和描述,然后在每个 SQL 工具中传入明确的profile。 - 语句类别控制 —
SELECT/INSERT/UPDATE/DELETE/ DDL 可分别启用或禁用;默认仅允许读取。SET、GRANT、CALL、USE、LOAD DATA、LOCK TABLES和事务控制(BEGIN/COMMIT/ROLLBACK)一律拒绝——分类本身采用允许列表,因此未知语句类型必然落入拒绝范围。 - 默认拒绝的表白名单 — 未列入白名单的内容均不可见;支持
db.*、db.table、app_*.logs等模式(两侧分别使用 glob 匹配,且不区分大小写)。从 AST 中提取每个表引用:JOIN、子查询、派生表、CTE(可识别作用域——CTE 名称不能遮蔽真实表以绕过检查)、多表 DML、INSERT ... SELECT和版本化注释。 - MCP 表结构资源 — MCP 连接初始化后,每个权限可见且在白名单中的基础表都会以
mysql:///schema/{profile}/{database}/{table}的形式公开。读取资源会返回实时的SHOW CREATE TABLESQL,仅移除易变的表级AUTO_INCREMENT=N计数器。 - 执行护栏 — 包括硬性行数上限、单条查询超时、单语句校验,以及针对不带
WHERE的UPDATE/DELETE的拦截机制。 - 内置可观测性 — 记录每条查询的延迟和行数、标记慢查询,并提供
mysql_stats工具,让你能直接在对话中询问“哪条查询最慢?”。 - 结构化审计,可选启用 — 使用按日轮换的 JSONL;被拒绝的 SQL 会连同触发的具体规则一起记录。默认关闭:除非启用,否则不会生成日志文件。
- 原子脚本 —
mysql_script在单个事务中运行多语句脚本,并逐条重新验证每条语句;任何失败都会回滚全部操作。脚本中禁止 DDL,因为 MySQL 的隐式提交会破坏原子性。 - 查询计划分析 —
mysql_explain支持traditional/json/tree格式以及EXPLAIN ANALYZE。 - 交互式查询结果 — 支持 MCP Apps 的宿主会将
mysql_query渲染为可筛选、可排序的表格,提供独立的视图历史记录、选择功能、列控制,以及 TSV/CSV/JSON 复制功能;其他宿主仍会收到原始文本结果。 - 易于运行,轻量可信 — 单个静态 Go 二进制文件,默认使用 stdio,基于官方 MCP Go SDK 构建;Docker 镜像采用 distroless,并以非 root 用户运行。
工具
所有七个 mysql_* 工具都需要非空的 profile 字符串,且必须与已配置的名称匹配。没有默认连接:缺失或未知的配置会在访问数据库前被拒绝。mysql_describe_table 的可选参数 database 默认为所选配置的数据库。
| 工具 | 功能 |
|---|---|
list_profile | 无参数;以文本和结构化格式 {profiles: [{name, description}]} 返回按名称排序的名称和描述;不探测连接,也不读取凭据 |
mysql_query | 执行一条只读语句(SELECT / SHOW / DESCRIBE / EXPLAIN) |
mysql_execute | 执行一条写入语句(INSERT / UPDATE / DELETE / DDL——每种类型都必须在配置中启用);返回受影响的行数 |
mysql_script | 在单个事务中原子地执行以 ; 分隔的多语句脚本——要么全部执行,要么全部不执行;禁止使用 DDL |
mysql_explain | 返回单条 SELECT 的执行计划(format:traditional / json / tree;analyze: true 会运行 EXPLAIN ANALYZE) |
mysql_list_tables | 列出白名单中可见的基表 |
mysql_describe_table | 返回白名单内表的列结构 |
mysql_stats | 所选配置在进程生命周期内的统计窗口:配置名称、总数 / 拒绝数、平均延迟和 P95 延迟、耗时最长的前 N 条查询、各表访问次数 |
例如,先使用 {} 调用 list_profile,然后使用 {"profile":"dev","sql":"SELECT * FROM myapp.orders LIMIT 10"} 调用 mysql_query,或使用 {"profile":"dev","top_n":5} 调用 mysql_stats。检查、更改和验证数据时,请始终使用相同的配置。
资源
MCP 初始化 / 发现期间,服务会为每个配置获取一份表快照,并为每个可见基表注册一个直接资源。资源名称也会标识配置,因此不同服务上名称相同的数据库和表仍能区分:
| URI | MIME 类型 | 内容 |
|---|---|---|
mysql:///schema/{profile}/{database}/{table} | application/sql | 当前规范化后的 SHOW CREATE TABLE 输出 |
“可见”指该配置的 MySQL 帐户可见的内容与 security.table_whitelist 的交集。不会注册视图。资源发现不受 security.max_rows 限制;即使 allowed_statements 中未包含 select,资源读取仍然可用,因为这两种操作执行的都是由服务端固定提供的元数据 SQL,而不是用户提交的 SQL。
资源集合是发现时的快照:之后创建的表会在下次发现或重新连接后出现;已删除或新近无法访问的表会返回 MCP Resource Not Found。资源内容是实时的,因此 ALTER TABLE 的更改会在下次读取时反映出来。资源发现和读取不会记录到审计日志或 mysql_stats 中;发现失败时,会记录配置名称,并且只清除该配置的表资源;其他配置、工具和共享的查询结果 App 仍可用。
根级别的 resources.enabled 开关适用于所有配置。将其设为 false 可禁用整个资源功能。默认值为 true;禁用时,服务不会声明 Resources,不会注册表资源或 MCP App 资源,也不会在初始化 / 发现期间查询任何配置的 MySQL。因此,交互式 MCP App 将不可用,但包括 mysql_query 的文本和结构化结果在内的全部八个工具仍可用。
快速开始
1. 获取二进制文件
预构建版本——从 Releases 下载适用于你平台(linux_amd64 / linux_arm64 / darwin_arm64)的 tarball(含校验和),或使用 Go 安装:
go install github.com/Kurok1/mcp-server-mysql/cmd/mcp-server-mysql@latest
Docker——多架构镜像已发布到 GitHub Container Registry:
docker pull ghcr.io/kurok1/mcp-server-mysql:latest
2. 配置
复制 config.example.yaml 并进行调整:
mkdir -p ~/.mcp-server-mysql
cp config.example.yaml ~/.mcp-server-mysql/config.yaml
最简配置:
resources:
enabled: true
profiles:
dev:
description: Development database
mysql:
host: 127.0.0.1
port: 3306
user: mcp_dev # use a dedicated least-privilege account, not root
password: ${MYSQL_MCP_PASSWORD}
database: myapp
security:
allowed_statements: [select] # add insert/update/delete/ddl only if you need them
table_whitelist:
- "myapp.*"
在 profiles 下添加同级条目以配置其他连接;每个条目都接受相同的 mysql、security 和 audit 字段。带注释的示例包含两个配置。以下客户端示例使用此最简配置;对于其他配置,请将所有引用的密码环境变量传递给 MCP 进程。
3. 接入 MCP 客户端
Claude Code:
claude mcp add mysql --env MYSQL_MCP_PASSWORD=your-password -- \
~/go/bin/mcp-server-mysql --config ~/.mcp-server-mysql/config.yaml
Claude Desktop 或任何使用 JSON 配置的客户端:
{
"mcpServers": {
"mysql": {
"command": "/usr/local/bin/mcp-server-mysql",
"args": ["--config", "/Users/me/.mcp-server-mysql/config.yaml"],
"env": { "MYSQL_MCP_PASSWORD": "..." }
}
}
}
Docker:
{
"mcpServers": {
"mysql": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/Users/me/.mcp-server-mysql:/data",
"-e", "MYSQL_MCP_PASSWORD",
"ghcr.io/kurok1/mcp-server-mysql:latest",
"--config", "/data/config.yaml"
],
"env": { "MYSQL_MCP_PASSWORD": "..." }
}
}
}
Docker 说明 1 — 审计日志必须存储在挂载卷上。 容器会随会话结束而销毁;如果启用了审计日志,请将
audit.log_dir指向挂载卷(例如/data/logs),否则日志会随容器一起消失。Docker 说明 2 — 访问主机上的 MySQL。 在 macOS/Windows 上设置
mysql.host: host.docker.internal;在 Linux 上还需将"--add-host=host.docker.internal:host-gateway"追加到args。
交互式查询结果(MCP Apps)
对于支持 MCP Apps 的宿主,mysql_query 会公布内嵌的 ui://mcp-server-mysql/query-results 资源。成功调用会同时返回现有的易读文本和包含必需 profile 字段的结构化查询数据,因此较旧或仅支持文本的宿主也能正常使用,不会丢失任何结果信息。查询出错时会保留文本,并在结果元数据中附带原始 {profile, sql},以便 App 识别请求。list_profile 也会返回文本和结构化数据;其余六个工具则返回文本结果。
结果视图会在当前 View 中保留最多 20 个快照,支持全局筛选和可选的 status 筛选、自然数值排序、列显示设置、行选择,以及复制为 TSV/CSV/JSON。结果和历史记录都会标明其配置,包括失败和取消的请求。刷新操作会通过宿主,使用所选快照的原始 {profile, sql} 调用 mysql_query,切换历史记录后也同样如此;如果宿主不向应用提供工具调用功能,视图会说明无法刷新,同时仍可使用所有只读控件。视图历史仅保存在内存中,关闭 View 后即会消失。
当重叠请求收到 Host 错误或取消通知,且信息不足以识别请求时,历史记录会将其来源标记为未确定,并保留候选输入。它不会根据通知到达顺序将通知归属到某个配置。
本地 Basic Host 开发
生产环境/默认传输方式仍为 stdio。此处提供无状态的 Streamable HTTP 端点,专用于本地 MCP Apps 开发:
MYSQL_MCP_PASSWORD=your-password mcp-server-mysql \
--config ~/.mcp-server-mysql/config.yaml \
--transport streamable-http \
--listen 127.0.0.1:3001
将官方 Basic Host 连接到 http://127.0.0.1:3001/mcp。HTTP 监听器会拒绝通配地址和非回环地址,其 CORS 策略仅接受本地 8080 端口上的 Basic Host 来源;此模式不适用于经过身份验证的远程部署。
安全模型
MCP client (Claude Code / Claude Desktop / …)
│ stdio
▼
┌─────────────────────── mcp-server-mysql ───────────────────────┐
│ │
│ Table resources: mysql:///schema/{profile}/{database}/{table} │
│ fixed metadata SQL · base tables only · whitelist-filtered │
│ │
│ mysql_query · mysql_execute · mysql_script · mysql_explain │
│ mysql_list_tables · mysql_describe_table · mysql_stats │
│ required profile → Manager.Get → independent runtime │
│ list_profile → configured names/descriptions (no database IO) │
│ │ │
│ ▼ │
│ ┌ Layer 1 · AST main gate (TiDB parser) ───────────────────┐ │
│ │ unparseable ⇒ denied (fail-closed) → single statement │ │
│ │ → statement-class allowlist + read/write tool check │ │
│ │ → per-class switches (default: select only) │ │
│ │ → dangerous constructs (INTO OUTFILE / LOAD_FILE) │ │
│ │ → missing-WHERE tripwire │ │
│ │ → default-deny table whitelist (JOIN / subquery / │ │
│ │ CTE scope-aware / versioned comments) │ │
│ └────────────┬───────────────────────────────┬─────────────┘ │
│ │ allowed │ denied │
│ ▼ ▼ │
│ ┌ Layer 2 · executor ─────────────┐ DENIED [rule]: reason │
│ │ single-stmt reads: READ ONLY tx │ is returned to the model │
│ │ row cap · query timeout │ with the rule name │
│ └────────────┬────────────────────┘ │
│ ▼ │
│ ┌ Layer 3 · driver ───────────────┐ │
│ │ multiStatements=false: stacked │ │
│ │ injection impossible │ │
│ └────────────┬────────────────────┘ │
│ │ guard decisions — allowed & denied — go to │
│ │ audit: ring buffer (+ optional JSONL files) │
└───────────────┬──────────────────────────────────────────────────┘
▼
MySQL — Layer 0: dedicated least-privilege account
第 0 层——你的 MySQL 账户(强烈建议)。 使用专用账户运行服务,并且仅授予你打算使用的权限(只读工作负载只需 SELECT 权限)。切勿使用 root。这是下面所有防护措施共同强化的隔离层。
第 1 层——AST 主闸门。 每条语句都会由 TiDB 解析器解析(解析失败 ⇒ 拒绝),然后必须依次通过:单语句强制检查 → 语句类别允许列表(并交叉检查读写工具:即使已启用写操作,通过 mysql_query 发送写语句也会被拒绝)→ 各类别的启用开关 → 危险结构扫描(任意嵌套深度的 SELECT ... INTO OUTFILE / DUMPFILE、LOAD_FILE())→ 缺少 WHERE 的触发检查 → 提取所有表引用并依据默认拒绝的白名单进行检查。
第 2 层——只读事务兜底。 通过单语句读取路径(mysql_query、mysql_explain、mysql_list_tables、mysql_describe_table)和固定资源元数据路径执行的读取,都会在 START TRANSACTION READ ONLY 中运行——如果解析器曾将写操作误判为读取,MySQL 本身也会拒绝它。(明确启用的写语句,以及 mysql_script 中的所有内容——包括读取——均在此兜底机制之外运行;这时由第 1 层和第 0 层负责控制。)
第 3 层——驱动程序级锁定。 连接会设置 multiStatements=false,因此即使上面的所有层都失效,COMMIT; DROP TABLE ... 这类堆叠注入也无法在协议层实现。
每次拒绝都会返回机器可读文本——DENIED [rule_name]: reason——规则名称固定:
| 规则 | 触发条件 |
|---|---|
parse_error | SQL 解析失败(失败时关闭——语法错误和解析器缺口一律如此) |
multi_statement | 单次调用中包含多条语句 |
unsupported_statement | SET / GRANT / CALL / USE / LOAD DATA / LOCK TABLES / 事务控制 |
wrong_tool | 通过 mysql_query 执行写语句,或通过 mysql_execute 执行读语句 |
statement_not_enabled | 语句类别未列入 allowed_statements |
table_whitelist | 任意被引用的表不在白名单内 |
dangerous_construct | INTO OUTFILE / INTO DUMPFILE / LOAD_FILE() |
unfiltered_write | UPDATE / DELETE 缺少 WHERE 子句 |
script_ddl / script_too_long / script_empty | 脚本中包含 DDL / 脚本超过语句数量上限 / 脚本为空 |
invalid_query / not_select / invalid_format / invalid_identifier | mysql_explain / mysql_describe_table 的参数验证 |
mysql_script 的拒绝消息会在原因前加上违规语句的位置:DENIED [rule]: statement N: reason。
防护机制是测试套件的核心:约 100 个表驱动测试用例覆盖堆叠语句注入、版本化注释伪装、CTE 影子遮蔽导致的白名单绕过、INSERT ... SELECT 表提取等情况;端到端测试——包括白名单强制执行、READ ONLY 兜底机制拒绝写操作、脚本回滚、EXPLAIN 树拒绝——均通过 testcontainers 对真实的 MySQL 8.0 运行。
细则
无法验证的安全文档只是营销宣传。具体边界如下:
- 只读事务保护措施适用于单条语句读取路径。你明确启用的写入类型——以及
mysql_script中的每条语句,包括读取语句,因为它们共用脚本的读写事务——都不会受到此保护;这些场景由 AST 检查和你的数据库账户权限(第 0 层)进行控制。 unfiltered_write是用于检测缺少WHERE子句的警报机制,并不能阻止全表写入:UPDATE t SET a=1 WHERE 1=1可以通过检查。它能发现错误,而非恶意行为。mysql_list_tables和 MCP 资源发现/读取使用固定的、非用户提供的元数据 SQL。表发现会查询information_schema获取基表,并通过白名单筛选每个结果;资源读取会在执行SHOW CREATE TABLE前再次检查白名单。EXPLAIN FORMAT=TREE也是固定前缀路径:内部的SELECT仍会先通过完整防护流程(TiDB 解析器无法将FORMAT=TREE作为完整语句解析)。- 审计记录涵盖进入防护流程的 SQL,无论是允许还是拒绝。以下操作不会被审计:MCP 资源发现/读取、
mysql_stats调用、mysql_describe_table的预检查拒绝(invalid_identifier及其table_whitelist名称检查),以及mysql_explain的参数拒绝(invalid_query、not_select、invalid_format)。脚本审计遵循实际执行情况:被防护流程拒绝的脚本会生成一条涵盖整个脚本的记录;失败语句之后的语句虽经过验证,但从未执行,因此不会被记录。 - MySQL 连接使用纯 TCP——目前既不支持 TLS 选项,也不支持 Unix socket。请确保服务端和数据库位于可信网络中,或通过隧道连接。
配置
profiles 是一个非空映射。名称必须匹配 [a-z0-9][a-z0-9_-]*;description 为可选项,默认为空字符串。每个配置文件独立应用相同的默认值,不会继承其他配置文件的设置。下表中,mysql.*、security.*、audit.* 和 description 位于 profiles.<name> 下;只有 resources.enabled 是全局设置。
完整的带注释示例:config.example.yaml。基本原则是默认安全:省略 allowed_statements 即为只读;省略 table_whitelist 即拒绝所有访问;不设置 block_unfiltered_writes 时,该选项默认开启。
并且,服务启动时会采取失败关闭策略:文件无法读取、键名未知或拼写错误、时长无效、白名单模式格式错误、语句类型未知、脚本上限为负数,或缺少 mysql.user/mysql.database,都会中止进程——服务会拒绝以异常状态运行,而不是悄悄降级。
| 键 | 默认值 | 说明 |
|---|---|---|
description | "" | 人类可读的连接用途说明,由 list_profile 返回 |
mysql.host | 127.0.0.1 | 在 Docker 容器内使用 host.docker.internal |
mysql.port | 3306 | |
mysql.user | — 必填 | 建议使用专用的最小权限账户 |
mysql.password | "" | 使用 ${MYSQL_MCP_PASSWORD}——见下文 |
mysql.database | — 必填 | 也用于限定未限定表名的数据库 |
mysql.pool.max_open / max_idle | 5 / 2 | 连接池 |
security.allowed_statements | [select] | 可选值包括 select / insert / update / delete / ddl;SHOW/DESCRIBE/EXPLAIN 归入 select |
security.table_whitelist | [] = 拒绝所有访问 | db.table 模式,每侧均支持 glob(myapp.*、app_*.logs),不区分大小写 |
security.max_rows | 1000 | 超出此数量的结果集会被截断,并附带标记 |
security.query_timeout | 30s | 每个查询的上下文超时时间 |
security.block_unfiltered_writes | true | 拒绝不带 WHERE 的 UPDATE/DELETE |
security.max_script_statements | 50 | 每次 mysql_script 调用的语句上限 |
resources.enabled | true | 设为 false 可省略表和 UI 资源,并跳过初始化/发现元数据查询 |
audit.enabled | false | JSONL 磁盘日志记录;无论此项设置如何,内存会话统计都会正常工作 |
audit.log_dir | ~/.mcp-server-mysql/logs | 在 Docker 下必须是已挂载的卷 |
audit.slow_query_threshold | 1s | 超过此时长的查询会被标记为慢查询 |
audit.ring_buffer_size | 1000 | 为 mysql_stats 提供数据的内存窗口大小 |
密钥无需保存在文件中:解析前会先通过环境变量展开处理整个配置,因此 ${ENV_VAR} 可用于任何字段。配置路径也可以通过 MYSQL_MCP_CONFIG 环境变量指定,而不必使用 --config。
迁移单连接配置
- 将旧的根级
mysql、security和audit部分原样移至名为profiles.dev之类的配置文件下;将resources保留在根级。 - 在所有七个
mysql_*工具调用中添加profile。使用list_profile查看可用名称。不存在隐式的default配置文件,即使只有一个连接也一样。 - 重启服务,并重新连接客户端,以刷新工具架构和新的、带配置文件限定的 Resource URI。
旧版根级连接设置、空配置文件/无效配置文件以及未知配置字段都会被拒绝。配置文件在重启前保持静态。连接池会延迟创建:如果数据库无法访问,只有在访问该配置文件对应的工具/资源时才会失败,而 list_profile 仍会列出已配置的条目。单条 SQL 语句或脚本只能使用一个配置文件;该连接内已获白名单批准的跨架构访问仍可使用。不支持跨配置文件事务和运行时配置文件管理。
审计日志
磁盘日志由每个配置文件的 audit.enabled 独立控制——默认为 false:不会生成日志文件,也不会创建日志目录。每个配置文件都有自己的内存统计环形缓冲区和慢查询阈值;mysql_stats 只读取所请求配置文件的统计窗口,并包含其名称。使用该配置文件的调用方会在进程内共享统计数据;无论是否启用磁盘日志,统计都会正常工作,并在重启后重置。
启用后,JSONL 文件会按日轮转,命名为 audit-<profile>-<YYYY-MM-DD>.jsonl(例如,audit-dev-2026-09-15.jsonl)。多个配置文件可以共用 audit.log_dir,但不会共用日志文件。每行是一个 JSON 对象:
| 字段 | 含义 |
|---|---|
profile | 所属连接配置文件,由其日志记录器填充 |
ts / tool / sql | 时间戳、工具名称、原始 SQL |
decision / rule | allowed 或 denied,以及拒绝时触发的规则 |
class / tables | 语句类别、引用的表 |
duration_ms / rows | 延迟、返回或影响的行数 |
slow / truncated / error | 慢查询标记、截断标记、错误消息 |
Claude Code 技能
skills/mysql-mcp 是一项配套技能,指导 Claude 如何妥善使用这些工具:选择合适的工具、遵守安全边界(单条语句、白名单、WHERE 触发器),并正确理解 DENIED [rule] 消息,而不是盲目重试。安装:
cp -r skills/mysql-mcp ~/.claude/skills/
兼容性
- MySQL 8.x——E2E 测试套件通过 testcontainers 使用 MySQL 8.0(8.0.45)运行。MySQL 5.7 和 MariaDB 未经测试。
- MCP——Go SDK v1.7.0,提供直接的 MySQL 表结构资源、
io.modelcontextprotocol/ui扩展,以及一个内嵌的 MCP App 资源。不支持 MCP Apps 的宿主仍可使用文本回退。 - 传输——默认使用 stdio;本地开发可使用仅限环回连接的无状态 Streamable HTTP。服务身份为
mcp-server-mysql;它提供 8 个工具、直接的表结构资源、一个共享 UI 资源,且不提供提示词。
开发
go test ./... -short # unit tests (no Docker needed)
go test -race ./... -short # concurrency checks, including profile isolation
go test ./... -timeout 600s # full suite incl. testcontainers integration/E2E (needs Docker)
cd ui/query-results
npm ci
npm run typecheck
npm test
npm run build # rebuilds the committed internal/ui/query-results.html
npm run test:sites
前端使用 React/TypeScript、@modelcontextprotocol/ext-apps 和 vite-plugin-singlefile。构建会生成一个完全内联的 HTML 文件,并将其复制到 internal/ui/query-results.html,由 Go 嵌入二进制文件;因此,常规的 go build 无需 Node。Dockerfile 会在 Node 阶段重新构建前端,并在编译 Go 之前覆盖已提交的构建产物,避免发布镜像包含过期 UI。
设计文档位于 docs/superpowers——每项功能都附有一份规范和一份实施计划。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。