前言
本文旨在记录个人如何构建一个 MySQL MCP Server,让 Claude 等 AI 助手能够安全、可控地查询和操作 MySQL 数据库。
项目概览
我们先看一下项目的核心结构:
bash
mysql-mcp-server/
├── src/
│ └── index.ts # 主入口文件
├── package.json
└── README.md
核心依赖
json
{
"dependencies": {
"@modelcontextprotocol/sdk": "^1.29.0", // MCP 官方 SDK
"mysql2": "^3.22.3", // MySQL 驱动
"node-sql-parser": "^5.4.0", // SQL 解析器(安全验证的关键)
"zod": "^4.4.3" // 环境变量校验
}
}
安全设计:核心亮点
在让 AI 操作数据库之前,安全是第一要务。本项目实现了两层安全防护:
1. 写操作开关
默认情况下,服务器只允许读取操作 。只有显式配置 MYSQL_ALLOW_WRITE_SQL=true 时,才会启用 INSERT、UPDATE、DELETE 等写操作。
typescript
const env = z.object({
// ... 其他配置
MYSQL_ALLOW_WRITE_SQL: z.preprocess(
(value) => {
if (typeof value === "string") {
const normalized = value.trim().toLowerCase();
if (["1", "true", "yes", "y", "on"].includes(normalized)) {
return true;
}
}
return false;
},
z.boolean().default(false),
),
}).parse(process.env);
2. SELECT 行数限制
防止 AI 执行 SELECT * FROM huge_table 导致内存溢出,服务器会自动给 SELECT 语句添加 LIMIT:
typescript
function setSelectLimit(statement: any, maxRows: number): boolean {
if (getStatementType(statement) !== "SELECT") {
return false;
}
if (!statement.limit) {
statement.limit = { seperator: "", value: [{ type: "number", value: maxRows }] };
return true;
}
// 如果用户指定的 LIMIT 超过最大值,强制覆盖
const currentLimit = Number(statement.limit.value[0]?.value);
if (!Number.isFinite(currentLimit) || currentLimit > maxRows) {
statement.limit.value[0] = { type: "number", value: maxRows };
return true;
}
return false;
}
核心实现
1. 数据库连接池
使用 mysql2 的连接池,支持并发请求:
typescript
const pool = mysql.createPool({
host: env.MYSQL_HOST,
port: env.MYSQL_PORT,
user: env.MYSQL_USER,
password: env.MYSQL_PASSWORD,
database: env.MYSQL_DATABASE,
waitForConnections: true,
connectionLimit: 10,
});
2. 注册 MCP 工具
MCP Server 需要注册工具,供 AI 助手调用。我们注册了三个核心工具:
工具一:列出所有表
typescript
server.registerTool(
"query_tables_list",
{
description: "List all tables in the database.",
inputSchema: z.object({}),
},
async () => {
const [rows] = await pool.query("SHOW TABLES");
const tables = (rows as any[]).map((row) => Object.values(row)[0]);
return {
content: [{ type: "text", text: `tables:\n${tables.join("\n")}` }],
};
},
);
工具二:查看表结构
typescript
server.registerTool(
"query_table_description",
{
description: "Describe a table in the database.",
inputSchema: { tableName: z.string().describe("The name of the table to describe") },
},
async ({ tableName }) => {
const [rows] = await pool.query("DESCRIBE ??", [tableName]);
return {
content: [{ type: "text", text: JSON.stringify(rows, null, 2) }],
};
},
);
工具三:执行 SQL(带安全验证)
typescript
server.registerTool(
"execute_query_sql",
{
description: "Execute a SQL. UPDATE, INSERT, DELETE require MYSQL_ALLOW_WRITE_SQL=true.",
inputSchema: { sql: z.string().describe("The SQL to execute") },
},
async ({ sql }) => {
// 1. 解析 SQL
const ast = sqlParser.astify(sql, { database: "mysql" });
// 2. 检查是否为写操作
if (statements.some(isWriteStatement) && !env.MYSQL_ALLOW_WRITE_SQL) {
return {
content: [{ type: "text", text: "Write SQL is disabled." }],
isError: true,
};
}
// 3. 应用 SELECT LIMIT
const executableSql = applySelectLimit(sql, ast);
// 4. 执行
const [rows] = await pool.query(executableSql);
return {
content: [{ type: "text", text: JSON.stringify(rows, null, 2) }],
};
},
);
快速开始
安装
bash
npm install @mikechan2224/mysql-mcp-server
配置 Claude Desktop
在 Claude Desktop 的配置文件中添加:
json
{
"mcpServers": {
"mysql": {
"command": "npx",
"args": ["-y", "@mikechan2224/mysql-mcp-server"],
"env": {
"MYSQL_HOST": "localhost",
"MYSQL_PORT": "3306",
"MYSQL_USER": "root",
"MYSQL_PASSWORD": "your_password",
"MYSQL_DATABASE": "your_database",
"MYSQL_ALLOW_WRITE_SQL": "false",
"MYSQL_SELECT_LIMIT": "100"
}
}
}
}
配置说明
| 环境变量 | 说明 | 默认值 |
|---|---|---|
MYSQL_HOST |
MySQL 主机地址 | localhost |
MYSQL_PORT |
MySQL 端口 | 3306 |
MYSQL_USER |
用户名 | 必填 |
MYSQL_PASSWORD |
密码 | 空字符串 |
MYSQL_DATABASE |
数据库名 | 必填 |
MYSQL_ALLOW_WRITE_SQL |
是否允许写操作 | false |
MYSQL_SELECT_LIMIT |
SELECT 最大返回行数 | 100 |
实际使用场景
配置完成后,你可以这样与 Claude 对话:
sql
User: 帮我看看数据库里有哪些表?
Claude: [调用 query_tables_list]
数据库中有以下表:
- users
- orders
- products
- ...
User: 查看 users 表的结构
Claude: [调用 query_table_description]
users 表结构:
- id: int, PRIMARY KEY, AUTO_INCREMENT
- name: varchar(255)
- email: varchar(255), UNIQUE
- created_at: datetime
...
User: 查询最近注册的 10 个用户
Claude: [调用 execute_query_sql]
SELECT * FROM users ORDER BY created_at DESC LIMIT 10
...
开源地址
项目已发布至 npm:@mikechan2224/mysql-mcp-server
GitHub:github.com/zhanghang20...
结语
通过 MCP 协议,我们可以让 AI 助手安全地访问数据库,同时保持对操作的精细控制,本文只做使用记录。
参考资料: