mysql-mcp-server
# mysql-mcp-server
一个基于 stdio 的只读 MySQL MCP Server。它为支持 Model Context Protocol 的客户端提供 MySQL 查询、库表浏览和表结构查看能力,并在执行前对 SQL 做只读校验。
## 功能特性
- 通过 MCP stdio transport 暴露 MySQL 只读工具
- 支持 `SELECT`、`WITH SELECT`、`SHOW`、`DESCRIBE` / `DESC` 和安全的 `EXPLAIN`
- 拒绝多语句、写入语句、管理语句、锁相关语句和高风险函数
- 使用 `START TRANSACTION READ ONLY` 执行查询,并在查询后回滚事务
- 支持结果行数上限、查询超时、连接池和可选 SSL
## 环境要求
- Node.js >= 20
- MySQL 兼容数据库
- 一个建议只授予读取权限的 MySQL 用户
## 安装与构建
```bash
npm install
npm run build
```
本地开发可使用:
```bash
npm run dev
```
构建后启动:
```bash
npm start
```
使用 MCP Inspector 调试:
```bash
npm run inspect
```
## 配置
服务通过环境变量读取 MySQL 连接配置。可以参考 `.env.example`:
```env
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=readonly_user
MYSQL_PASSWORD=change-me
MYSQL_DATABASE=
MYSQL_SSL=false
MYSQL_SSL_REJECT_UNAUTHORIZED=true
MYSQL_CONNECTION_LIMIT=5
MYSQL_CONNECT_TIMEOUT_MS=10000
MYSQL_QUERY_TIMEOUT_MS=30000
MYSQL_MAX_ROWS=500
```
| 变量 | 必填 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `MYSQL_HOST` | 否 | `127.0.0.1` | MySQL 主机 |
| `MYSQL_PORT` | 否 | `3306` | MySQL 端口 |
| `MYSQL_USER` | 是 | - | MySQL 用户名 |
| `MYSQL_PASSWORD` | 是 | - | MySQL 密码 |
| `MYSQL_DATABASE` | 否 | - | 默认数据库,留空则不指定 |
| `MYSQL_SSL` | 否 | `false` | 是否启用 SSL |
| `MYSQL_SSL_REJECT_UNAUTHORIZED` | 否 | `true` | SSL 是否校验证书 |
| `MYSQL_CONNECTION_LIMIT` | 否 | `5` | 连接池连接数上限 |
| `MYSQL_CONNECT_TIMEOUT_MS` | 否 | `10000` | 建连超时时间,单位毫秒 |
| `MYSQL_QUERY_TIMEOUT_MS` | 否 | `30000` | 查询超时时间,单位毫秒 |
| `MYSQL_MAX_ROWS` | 否 | `500` | 单次返回的最大行数 |
布尔值支持 `1`、`true`、`yes`、`on` 和 `0`、`false`、`no`、`off`。
## MCP 客户端配置示例
发布到 npm 后,可以在 MCP 客户端配置中加入:
```json
{
"mcpServers": {
"mysql": {
"command": "npx",
"args": [
"-y",
"@xujcbiz/mysql-mcp-server"
],
"env": {
"MYSQL_HOST": "127.0.0.1",
"MYSQL_PORT": "3306",
"MYSQL_USER": "readonly_user",
"MYSQL_PASSWORD": "change-me",
"MYSQL_DATABASE": "",
"MYSQL_SSL": "false",
"MYSQL_MAX_ROWS": "500"
}
}
}
}
```
也可以参考仓库中的 `mcp-config.example.json`。本地开发调试时,可以先执行 `npm run build`,再临时使用 `node D:/project/mysql-mcp-server/dist/index.js` 这种绝对路径方式。
## 可用工具
### `mysql_query`
执行只读 SQL。
输入:
```json
{
"sql": "SELECT * FROM users LIMIT 10",
"maxRows": 100
}
```
`maxRows` 可选,不能超过 `MYSQL_MAX_ROWS`。
### `mysql_list_databases`
列出当前 MySQL 用户可见的数据库。
输入:
```json
{
"pattern": "app_%"
}
```
`pattern` 可选,使用 MySQL `LIKE` 语法。
### `mysql_list_tables`
列出当前或指定数据库下的表和视图。
输入:
```json
{
"database": "app_db",
"pattern": "user%",
"includeViews": true
}
```
### `mysql_describe_table`
查看表字段信息,可选返回索引信息。
输入:
```json
{
"database": "app_db",
"table": "users",
"includeIndexes": true
}
```
### `mysql_connection_info`
返回当前数据库、连接用户、有效用户和 MySQL 版本。
输入:
```json
{}
```
## 返回格式
查询类工具会返回 JSON 文本和结构化结果,结构大致如下:
```json
{
"rows": [],
"fields": [],
"rowCount": 0,
"truncated": false,
"executionMs": 0
}
```
- `rows`:返回的数据行
- `fields`:字段名列表
- `rowCount`:查询得到的总行数
- `truncated`:结果是否因 `maxRows` 被截断
- `executionMs`:执行耗时,单位毫秒
## 只读安全策略
服务会在执行前对 SQL 做校验:
- 仅允许 `SELECT`、`WITH SELECT`、`SHOW`、`DESCRIBE` / `DESC` 和 `EXPLAIN`
- 禁止多条 SQL 语句
- 禁止 `INSERT`、`UPDATE`、`DELETE`、`ALTER`、`DROP`、`CREATE`、`TRUNCATE` 等写入或管理语句
- 禁止 `SELECT ... INTO`、`FOR UPDATE`、`LOCK IN SHARE MODE` 等可能产生副作用或锁的语法
- 禁止 `SLEEP`、`BENCHMARK`、`GET_LOCK` 等高风险函数
仍然建议在数据库侧使用只读账号,并只授予必要库表的读取权限。
## 项目结构
```text
src/
config.ts 环境变量配置读取与校验
database.ts MySQL 连接池和只读查询封装
index.ts MCP Server 入口和工具注册
sqlSafety.ts SQL 只读校验与标识符转义
```
## 常用命令
```bash
npm run build # 编译 TypeScript 到 dist/
npm run dev # 使用 tsx 运行源码
npm start # 运行 dist/index.js
npm run inspect # 使用 MCP Inspector 调试
```
TDQS
Scored across 5 tools
Each tool has a distinct purpose: querying, listing databases, listing tables, describing table structure, and retrieving connection metadata. There is no overlap or ambiguity between them.
All tools share the mysql_ prefix and most follow a verb_noun pattern (list_databases, list_tables, describe_table, query). mysql_connection_info is slightly inconsistent as it uses a noun phrase instead of a verb, but the pattern is still clear and predictable.
Five tools is well-scoped for a read-only MySQL introspection server. Each tool serves a clear and necessary function without redundancy or bloat.
The toolset covers the core read-only operations: generic querying, database/table listing, schema description, and connection info. The only minor gap is a lack of a dedicated tool for viewing table indexes without using describe_table, but that is covered by the optional indexes parameter. Overall, the surface is complete for its intended purpose.