MySQL只读MCP服务器
Python MCP(模型上下文协议)服务器,提供 只读 访问MySQL数据库。
- 中文文档:
README.zh-CN.md
- 运输: 标准 (建议MCP客户使用)和 HTTP/SSE (独立服务)
- 安全:仅
SELECT,SHOW,DESCRIBE,DESC,以及EXPLAIN允许发表声明
- 配置: 标准 --MySQL设置通过
mcp.jsonenv; 上海证券交易所 --进程启动时的环境,可选MCP_BEARER_TOKEN用于HTTP身份验证
- 表黑名单:
QUERY_TABLE_BLACKLIST块 数据 通过以下方式访问query;describe_table仍然有效 用于列出表上的模式
______________________________________________________________________
需求
- 安装程序和MCP运行时: python 3.10+.
install.py检查口译员
就是这样 之前 任何其他步骤;如果版本太低,它会立即退出 (使用 python3.12 install.py, py -3.12 install.py等等)。
- 可选:
install.py --python /path/to/python3.12创造.venv说完这个
二进制而不是 sys.executable (该二进制文件也必须为3.10+)。
- 一个可访问的MySQL实例。
安装
首次安装(推荐)
跑 install.py 带着一个 3.10+ 口译员(python, python3,或 py -3).
脚本创建 .venv 和 python -m venv那么 python -m pip install -r requirements.txt.
成功安装后 交互式向导 (如果stdin是TTY)要求: 运输(标准 或 SSE)、核心MySQL字段, 查询表黑名单 (总是), 可选超时/ QUERY_DEFAULT_LIMIT /TLS路径,以及SSE MCP_HOST / MCP端口 / MCP_ber_TOKEN。它打印一个 完成 mcp.json 片段 (和为 SSE,外壳 export 行加上服务器命令)。使用 --no-wizard 跳过(CI/ 自动化)。非交互式stdin会自动跳过向导。
视窗 (CMD或在资源管理器中双击):
cd \path\to\MySQL_MCP
install.batmacOS/Linux:
cd /path/to/MySQL_MCP
python3 install.py有用的标志:
| 标志 | 含义 |
|---|---|
--recreate | 删除 .venv 并重新安装 |
--dry-run | 仅显示计划的venv/pip步骤(仍需要3.10+才能运行脚本) |
--no-wizard | 不要运行安装后配置向导 |
--python EXE | 创建 .venv 使用3.10+解释器(EXE 在PATH或完整路径上) |
如果Windows上缺少Python启动器,请从以下位置安装Python 3.10+ python.org 并启用“添加到PATH”。
手动安装(无脚本)
cd /path/to/MySQL_MCP
python3 -m venv .venv
# Windows: .venv\Scripts\pip install -r requirements.txt
# Unix: .venv/bin/pip install -r requirements.txt在任一方法之后,设置 mcp.json command 到 venv python / python.exe 绝对路径——不是裸露的 python 在PATH上。
______________________________________________________________________
通过mcp.json配置
所有MySQL连接参数都通过标准MCP配置文件传递。 选择 选项A (stdio)或 选项B (SSE)取决于您的客户。
选项A-stdio传输(推荐)
MCP客户端启动 server.py 作为子流程,并通过 env 块。不需要单独的服务器进程。
将以下块复制到客户的MCP设置中(例如Cursor mcp.json, 克劳德桌面 claude_desktop_config.json,或项目级别 .cursor/mcp.json):
{
"mcpServers": {
"mysql-readonly": {
"command": "/absolute/path/to/MySQL_MCP/.venv/bin/python",
"args": ["/absolute/path/to/MySQL_MCP/server.py"],
"env": {
"MYSQL_HOST": "127.0.0.1",
"MYSQL_PORT": "3306",
"MYSQL_USER": "your_mysql_user",
"MYSQL_PASSWORD": "your_mysql_password",
"MYSQL_DATABASE": "your_database_name",
"MYSQL_CONNECT_TIMEOUT": "10",
"MYSQL_SSL": "false",
"QUERY_DEFAULT_LIMIT": "100",
"QUERY_TABLE_BLACKLIST": "sensitive_table,internal_audit_log"
}
}
}
}args 必须包含 绝对路径 到 server.py.\ 在Windows上,使用 "command": "C:\\path\\to\\MySQL_MCP\\.venv\\Scripts\\python.exe" (在JSON中转义反斜杠)。
替换 env 值与您的实际MySQL凭据。
选项B——HTTP/SSE传输
首先将服务器作为独立的HTTP服务启动。MySQL设置来自 进程环境(或您的shell/systemd/Docker) environment 块)。
export MYSQL_HOST=127.0.0.1
export MYSQL_PORT=3306
export MYSQL_USER=your_mysql_user
export MYSQL_PASSWORD=your_mysql_password
export MYSQL_DATABASE=your_database_name
# Default bind is 127.0.0.1 (safer). Use 0.0.0.0 only on trusted networks or
# behind a reverse proxy; set MCP_BEARER_TOKEN so clients must send
# Authorization: Bearer on SSE and message requests.
export MCP_BEARER_TOKEN=your-long-random-secret # optional but recommended if exposed
# Use the venv interpreter (from repo root after install):
# Unix/macOS: .venv/bin/python server.py --transport sse --port 8000
# Windows: .venv\Scripts\python.exe server.py --transport sse --port 8000
.venv/bin/python server.py --transport sse --port 8000然后将MCP客户端指向SSE端点(并配置客户端以发送 如果 MCP_BEARER_TOKEN 已设置):
{
"mcpServers": {
"mysql-readonly": {
"url": "http://localhost:8000/sse"
}
}
}______________________________________________________________________
环境变量引用
| 变量 | 必填 | 默认 | 描述 |
|---|---|---|---|
MYSQL_HOST | 没有 | 127.0.0.1 | MySQL主机名或IP |
MYSQL_PORT | 没有 | 3306 | MySQL端口 |
MYSQL_USER | 是 | -- | MySQL用户名 |
MYSQL_PASSWORD | 没有 | "" | MySQL密码 |
MYSQL_DATABASE | 是 | -- | 目标数据库名称 |
MYSQL_CONNECT_TIMEOUT | 没有 | 10 | TCP连接超时(秒) |
MYSQL_READ_TIMEOUT | 没有 | 30 | 套接字读取超时(秒) |
MYSQL_WRITE_TIMEOUT | 没有 | 30 | 套接字写入超时(秒) |
MYSQL_MAX_EXECUTION_TIME | 没有 | 30000 | 每个查询服务器限制(毫秒); SET SESSION MAX_EXECUTION_TIME |
MYSQL_SSL | 没有 | false | 启用MySQL的TLS: "true" / "false" |
MYSQL_SSL_CA | 没有 | "" | CA证书的路径(使用TLS时) |
MYSQL_SSL_CERT | 没有 | "" | 客户端证书的路径 |
MYSQL_SSL_KEY | 没有 | "" | 客户端私钥路径 |
MYSQL_SSL_VERIFY_CERT | 没有 | true | 设置 "false" 跳过服务器证书验证(不建议) |
QUERY_DEFAULT_LIMIT | 没有 | 100 | 行上限为 SELECT;明确的 LIMIT 也受此限制(在应用 limit 工具论证) |
QUERY_TABLE_BLACKLIST | 没有 | "" | 以逗号分隔的表名。这 query 工具 拒绝引用它们的SQL(包括 JOIN); describe_table 仍然返回模式 对于那些桌子。不能替代DB赠款。 |
MCP_HOST | 没有 | 127.0.0.1 | 绑定SSE传输地址(CLI --host 运行时覆盖) |
MCP_PORT | 没有 | 8000 | 绑定SSE端口(CLI --port 覆盖) |
MCP_BEARER_TOKEN | 没有 | "" | 如果非空,则SSE HTTP请求需要 Authorization: Bearer |
______________________________________________________________________
可用工具
query
执行只读SQL语句,并将结果作为结构化JSON返回。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
sql | str | -- | SQL语句(SELECT / SHOW / DESCRIBE / EXPLAIN) |
limit | int | QUERY_DEFAULT_LIMIT | 上限为 QUERY_DEFAULT_LIMIT;结合服务器重写 SELECT 返回的行数永远不会超过此有效上限(即使SQL包含更大的 LIMIT) |
退货:
{
"columns": ["id", "name", "email"],
"rows": [
{"id": 1, "name": "Alice", "email": "alice@example.com"}
],
"row_count": 1
}list_tables
列出已配置数据库中的所有表。
退货:
{
"database": "mydb",
"tables": ["users", "orders", "products"],
"count": 3
}describe_table
获取特定表的列架构。
对于以下表格 QUERY_TABLE_BLACKLIST,将此工具用于模式-- query 工具 拒绝任何SQL(包括 DESCRIBE)它引用了这些表格。
| 参数 | 类型 | 说明 |
|---|---|---|
table_name | str | 表名(仅限字母、数字、下划线) |
退货:
{
"table": "users",
"columns": [
{"Field": "id", "Type": "int", "Null": "NO", "Key": "PRI", "Default": null, "Extra": "auto_increment"},
{"Field": "name", "Type": "varchar(255)", "Null": "YES", "Key": "", "Default": null, "Extra": ""},
{"Field": "email", "Type": "varchar(255)", "Null": "YES", "Key": "UNI", "Default": null, "Extra": ""}
]
}______________________________________________________________________
安全——只读执行
服务器通过两级保护在应用层强制执行只读访问:
- 白名单 --第一个关键字必须是以下之一
SELECT,SHOW,DESCRIBE,DESC,EXPLAIN. - 黑名单 --扫描完整语句以查找禁止的模式:
INSERT,UPDATE,
DELETE, DROP, ALTER, CREATE, TRUNCATE, REPLACE, GRANT, REVOKE, COMMIT, ROLLBACK, LOAD DATA, INTO OUTFILE, SLEEP, BENCHMARK以及更多。
- 多语句拒绝 --任何包含以下内容的SQL
;(剥离一条拖尾后
分号)被拒绝。
- 标识符验证 --传递给的表名
describe_table已验证包含
仅 [A-Za-z0-9_] 字符插入查询之前。
- 表黑名单 --表列在
QUERY_TABLE_BLACKLIST不能用于 数据
通过访问 query 工具(包括子查询/ JOIN是指他们)。 这 describe_table 工具仍然被允许 对于这些名称,代理可以检查模式。 错误使用双语JSON有效负载(message_en / message_zh).
对于生产使用,还可以配置MySQL用户 SELECT-只有特权在 数据库级别作为额外的防御层。将应用程序级黑名单视为 便利性,而不是主要的授权边界。______________________________________________________________________
验证
配置后,使用以下查询测试服务器:
-- Should succeed
SHOW TABLES
SELECT * FROM your_table LIMIT 5
DESCRIBE your_table
EXPLAIN SELECT id FROM your_table
-- Should be rejected with an error
DELETE FROM your_table WHERE id = 1
INSERT INTO your_table (name) VALUES ('x')
SELECT 1; DROP TABLE your_table
SELECT SLEEP(5)______________________________________________________________________
本地运行(无MCP客户端)
您可以使用MCP CLI直接从命令行测试服务器:
# Install dev dependency
pip install "mcp[cli]"
# stdio mode — interactive inspector
MYSQL_HOST=127.0.0.1 MYSQL_USER=root MYSQL_PASSWORD=secret MYSQL_DATABASE=mydb \
mcp dev server.py
# SSE mode — start server, then open http://localhost:8000/sse in a browser or curl
MYSQL_HOST=127.0.0.1 MYSQL_USER=root MYSQL_PASSWORD=secret MYSQL_DATABASE=mydb \
.venv/bin/python server.py --transport sse______________________________________________________________________
项目结构
MySQL_MCP/
├── server.py # MCP server: tools, SQL guard, MySQL connector
├── install.py # First-time setup: venv + pip install (all platforms)
├── install.bat # Windows launcher for install.py
├── mcp.json # MCP configuration template (stdio + SSE examples)
├── requirements.txt # Python dependencies
├── pyproject.toml # Package metadata
├── Dockerfile # Container image definition
├── docker-compose.yml # Compose file (MCP server + optional local MySQL)
└── README.md # This file______________________________________________________________________
Docker部署
使用Docker Compose构建和运行
创建一个 .env 使用MySQL凭据在项目根目录中创建文件:
MYSQL_HOST=host.docker.internal # use host.docker.internal to reach the host machine
MYSQL_PORT=3306
MYSQL_USER=your_mysql_user
MYSQL_PASSWORD=your_mysql_password
MYSQL_DATABASE=your_database_name取消注释 ports 挡住 (见 127.0.0.1:${MCP_PORT:-8000}:8000 示例),以便主机可以到达容器;它是 出于安全考虑,默认情况下已删除。
然后启动容器:
docker compose up -d集 MCP_BEARER_TOKEN 在 .env 当暴露SSE时。然后,MCP SSE端点为 http://localhost:8000/sse (或您选择的映射主机/端口)。
将您的MCP客户端指向它:
{
"mcpServers": {
"mysql-readonly": {
"url": "http://localhost:8000/sse"
}
}
}手动构建和运行
docker build -t mysql-mcp-server .
docker run -d \
--name mysql-mcp-server \
-p 8000:8000 \
-e MYSQL_HOST=host.docker.internal \
-e MYSQL_USER=your_user \
-e MYSQL_PASSWORD=your_password \
-e MYSQL_DATABASE=your_db \
mysql-mcp-server使用本地MySQL容器
取消注释 mysql 服务块 docker-compose.yml 启动本地MySQL 在MCP服务器旁边。该服务使用 healthcheck 因此,仅MCP服务器 MySQL准备就绪后启动。
______________________________________________________________________
延伸
建议在生产使用前进行以下改进:
- 连接池 --将按请求连接替换为
DBUtils或SQLAlchemy池 - SQL AST验证 --使用
sqlglot或sqlparse用于结构分析而不是正则表达式 - 审核日志记录 --使用时间戳、客户端标识和行数记录每个执行的查询
- 行级速率限制 --强制每个客户端的查询频率限制
- 边缘的TLS/mTLS --反向终止HTTPS和可选客户端证书
在上交所面前的代理人;与...结合 MCP_BEARER_TOKEN 用于纵深防御
______________________________________________________________________
许可证
该项目根据MIT许可证获得许可。看 LICENSE.
