database-analysis-mcp
基于 MCP (Model Context Protocol) 的 MySQL 数据库分析工具服务器,支持 stdio 和 SSE 两种传输模式。
技术栈
- 运行时: Node.js >= 18
- 语言: TypeScript
- MCP SDK: @modelcontextprotocol/sdk
- 数据库: mysql2 (连接池)
- 参数校验: zod v4
- 日志: pino (stderr + 文件)
- 构建: tsup
- 包管理: pnpm
功能
连接管理
| 工具 | 说明 | |------|------| | db_connect | 连接到配置中的数据库,默认连接 default | | db_disconnect | 断开指定数据库连接 | | db_status | 查看所有数据库连接状态(已配置/已连接/当前活动) | | db_switch | 切换当前活动的数据库连接 | | db_refresh_schema | 清空表结构缓存并重新加载,表结构变更后需调用此工具刷新 |
查询执行
| 工具 | 说明 | |------|------| | execute_query | 执行 SQL 查询,支持参数化查询、preview_only 先预览 SQL 再确认执行,内置危险操作拦截(DROP DATABASE / TRUNCATE) |
结构分析
| 工具 | 说明 | |------|------| | list_tables | 列出当前数据库所有表(含注释、引擎、预估行数) | | describe_table | 获取表的完整结构:列信息、索引、外键 |
数据统计
| 工具 | 说明 | |------|------| | table_statistics | 获取表/列级统计:总行数、去重数、空值数、最大最小值、平均值、数据大小 |
性能分析
| 工具 | 说明 | |------|------| | slow_query_analysis | 分析慢查询,支持 slow_log 表和 performance_schema 两种来源 | | explain_query | 执行 EXPLAIN 查看查询计划,支持 traditional / json / tree 格式 |
ER 图生成
| 工具 | 说明 | |------|------| | generate_er_diagram | 生成 Mermaid 格式的 ER 关系图,可指定表范围,自动识别外键关系 |
安装
pnpm install
配置
编辑 config/default.json 填入数据库连接信息:
{
"server": {
"name": "database-analysis-mcp",
"version": "1.0.0",
"sse": {
"port": 3000,
"host": "localhost"
}
},
"databases": {
"default": {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "your_password",
"database": "your_database"
},
"production": {
"host": "prod-host",
"port": 3306,
"user": "readonly",
"password": "xxx",
"database": "prod_db"
}
},
"logging": {
"level": "info",
"dir": "./logs"
},
"autoConnect": "default",
"preloadSchema": true
}
支持通过 --config 参数指定自定义配置文件,会与 default.json 深度合并:
pnpm dev -- --config config/local.json
通过 mcp.json 配置数据库(环境变量):
当使用 command + env 方式在 Cursor 的 mcp.json 中启动本 MCP 时,可在 env 中直接填写数据库连接参数,无需修改项目内 config/default.json。环境变量会覆盖 databases.default 的对应字段。
| 环境变量 | 含义 | 示例 | |----------|------|------| | DB_HOST | 主机 | 192.168.1.1(etc) | | DB_PORT | 端口 | 3306 | | DB_USER | 用户 | XXX | | DB_PASSWORD | 密码 | XXX | | DB_NAME | 数据库名 | XXXX |
示例(mcp.json,stdio 模式):
{
"mcpServers": {
"database-analysis-mcp": {
"command": "node",
"args": ["d:/demo/database-analysis-mcp/dist/index.js", "--transport", "stdio"],
"env": {
"DB_HOST": "192.168.1.1(etc)",
"DB_PORT": "3306",
"DB_USER": "XXX",
"DB_PASSWORD": "XXX",
"DB_NAME": "XXXX"
}
}
}
}
说明:
- 仅当至少设置一个上述环境变量时才会覆盖
default;未设置的字段保留配置文件中的值。 - URL 模式(
"url": "http://localhost:3000/sse")下 Cursor 不启动 MCP 进程,无法通过 mcp.json 的env传参,数据库配置仍需在config/default.json或启动 MCP 时的环境变量中配置。
启动优化配置:
| 配置项 | 说明 | |--------|------| | autoConnect | 启动时自动连接的数据库名,true 表示 default;不配置则需手动调用 db_connect | | preloadSchema | 连接成功后是否预加载表结构到缓存,list_tables / describe_table 命中缓存时无 DB 往返,默认 true |
MCP 描述与触发(何时调用本 MCP):
本 MCP 支持两类描述,便于用户在 Cursor 中说「查询数据库 XXX」等话时被正确调用:
- 服务器级 instructions:通过 MCP 协议发给 Cursor 等客户端,说明「在什么情况下应使用本 MCP」。不配置时使用内置默认说明。
- 工具级 description:每个工具都有描述,部分工具已加入「查询数据库」「查表」「表结构」等触发语,便于模型选择对应工具。
默认触发语(内置 instructions 与工具描述中已包含): 查询数据库、查一下数据库、查库、执行 SQL、查表、查表数据、有哪些表、表结构、表有哪些字段、分析表、统计数据、慢查询、ER 图。
自定义说明(可选):在 config/default.json 的 server 中增加 instructions 可覆盖默认说明,例如:
{
"server": {
"name": "database-analysis-mcp",
"version": "1.0.0",
"sse": { "port": 3000, "host": "localhost" },
"instructions": "当用户要查询数据库、执行 SQL、查表、分析数据时,请使用本 MCP 的工具。"
}
}
| 配置项 | 说明 | |--------|------| | server.instructions | 可选。服务器使用说明,会发给 MCP 客户端。不配置则使用内置默认说明(含上述触发语)。 |
使用
开发模式
# SSE 模式(默认,常驻进程)
pnpm dev
# stdio 模式
pnpm dev:stdio
# 显式指定 SSE
pnpm dev:sse
生产模式
pnpm build
pnpm start # SSE(默认)
pnpm start:stdio # stdio
pnpm start:sse # SSE
Windows 控制台中文乱码
Windows 控制台默认使用 GBK,与 Node 输出的 UTF-8 不匹配会导致中文乱码。项目已通过 scripts/launcher.js 在启动时自动执行 chcp 65001 切换为 UTF-8,使用 pnpm dev / pnpm start 即可正常显示。
若直接运行 node dist/index.js 仍乱码,可先执行:
chcp 65001
在 Cursor 中配置
在 .cursor/mcp.json 中添加:
生产模式(需先 pnpm build):
{
"mcpServers": {
"database-analysis-mcp": {
"command": "node",
"args": ["dist/index.js"],
"cwd": "/path/to/database-analysis-mcp"
}
}
}
开发模式:
{
"mcpServers": {
"database-analysis-mcp": {
"command": "npx",
"args": ["tsx", "src/index.ts"],
"cwd": "/path/to/database-analysis-mcp"
}
}
}
SSE 模式:
先启动服务 pnpm dev:sse,然后配置:
{
"mcpServers": {
"database-analysis-mcp": {
"url": "http://localhost:3000/sse"
}
}
}
在其他窗口/项目中使用时出现「没有 tools 子目录」的说明
通过 URL(如 "url": "http://localhost:3000/sse")连接本 MCP 时,Cursor 会在当前项目下为该 MCP 创建 mcps/user-database-analysis-mcp/,但通常只包含 SERVER_METADATA.json 和 INSTRUCTIONS.md,不会自动生成 tools/ 下的工具描述 JSON(工具由 MCP 服务器在运行时注册)。若依赖「从项目文件读取工具描述」的流程,就会报错:只有 SERVER_METADATA.json 和 INSTRUCTIONS.md,没有 tools 子目录或任何工具描述 JSON。
解决办法:本仓库已包含完整的工具描述符,位于 mcps/user-database-analysis-mcp/(含 tools/*.json)。在其他项目/窗口中使用本 MCP 时,请将该目录复制到该项目的 MCP 描述符根目录下(即该项目中 Cursor 使用的 mcps 所在位置,一般为该项目的 .cursor 或工作区下的 mcps),使该窗口下存在 mcps/user-database-analysis-mcp/tools/ 及所有工具 JSON。复制后无需改 URL 配置,MCP 仍通过 http://localhost:3000/sse 连接,只是工具描述从本仓库提供的文件中读取。
本仓库中的 mcps 结构(可直接复制整目录):
mcps/user-database-analysis-mcp/
├── SERVER_METADATA.json
├── INSTRUCTIONS.md
└── tools/
├── db_connect.json
├── db_disconnect.json
├── db_status.json
├── db_switch.json
├── db_refresh_schema.json
├── execute_query.json
├── list_tables.json
├── describe_table.json
├── table_statistics.json
├── slow_query_analysis.json
├── explain_query.json
└── generate_er_diagram.json
故障排除
Cursor 中关闭再开启 MCP 导致命令行服务退出
现象:在 Cursor 的 MCP 页面关闭该 MCP 再重新开启后,命令行里通过 pnpm dev:sse 启动的进程报错并退出:
Error: Already connected to a transport. Call close() before connecting to a new transport, or use a separate Protocol instance per connection.
原因:MCP SDK 规定一个 McpServer 实例只能 connect 一个 transport。原先实现里,所有 GET /sse 请求共用一个 server;当 Cursor 关闭再打开 MCP 时会发起新的 GET /sse,再次对同一 server 执行 connect 就会触发上述错误。未捕获的异常导致 Node 进程退出,表现为“命令行里的服务被关掉”。
解决方案(已实现):SSE 模式下改为每个 GET /sse 连接使用独立的 McpServer 实例,共享同一个 DatabaseManager(数据库连接仍由单例管理)。这样 Cursor 重新连接时会新建 server + transport,不再报错,命令行进程也不会因异常退出。
对话框发起查询时 MCP 无法连接 / 工具列表不显示
现象:在 Cursor 对话框里发起「查询 XXX」等需求时,无法正常使用 MCP;界面显示 MCP 已连接,但工具列表不再显示,对话无法继续自动执行。只有手动关闭该 MCP 再重新启用后,工具列表才恢复,对话才能继续。
原因:
- SSE 连接断开后未清理:客户端(如 Cursor)与 MCP 的 SSE 连接因超时、网络或内部重连等原因断开后,服务端仍保留对旧
sseTransport的引用,后续 POST/messages请求仍发往已关闭的连接,导致无响应或异常,Cursor 端表现为「已连接但工具不可用」。 - POST 处理未捕获异常:
handlePostMessage若抛出未捕获异常(例如连接已关闭时 SDK 报错),会导致连接状态异常,加重「假连接」现象。
解决方案(已实现,见 src/server/transports.ts):
- 连接关闭时清除 transport:在 GET
/sse建立连接后,对响应对象res监听close和error;在回调中若当前全局sseTransport仍是本次连接的 transport,则将其置为null并打日志。这样连接断开后不再向旧连接写数据,Cursor 下次重连(再次 GET/sse)会重新建立连接并正常列出工具。 - POST
/messages异常处理:对sseTransport.handlePostMessage(req, res)做try/catch;发生异常时记录日志、将sseTransport置为null,并在响应仍可写时返回 500。避免未处理异常导致连接挂起,同时便于客户端重连。
若问题仍出现,可查看 logs/mcp-server.log 中是否有「SSE 客户端已断开」或「POST /messages 处理异常」等日志,便于进一步排查。
项目结构
database-analysis-mcp/
├── config/
│ └── default.json # 默认配置文件
├── src/
│ ├── index.ts # 入口:解析 CLI 参数,启动服务
│ ├── config/
│ │ ├── types.ts # AppConfig / DatabaseConfig 等类型
│ │ └── index.ts # 配置加载与深度合并
│ ├── utils/
│ │ ├── logger.ts # pino 日志(stderr + 文件输出)
│ │ ├── errors.ts # 5 种自定义业务错误类
│ │ └── index.ts
│ ├── database/
│ │ ├── types.ts # 表结构 / 统计 / 慢查询 / ER 图类型
│ │ ├── manager.ts # MySQL 多连接池管理器
│ │ ├── schema-cache.ts # 表结构缓存(预加载 / 刷新)
│ │ ├── schema-utils.ts # schema 查询可复用函数
│ │ └── index.ts
│ ├── tools/
│ │ ├── types.ts # ToolDefinition + defineTool 辅助函数
│ │ ├── connection.ts # 连接管理 (5 个工具)
│ │ ├── query.ts # SQL 查询 (1 个工具)
│ │ ├── schema.ts # 表结构分析 (2 个工具)
│ │ ├── statistics.ts # 数据统计 (1 个工具)
│ │ ├── slow-query.ts # 慢查询分析 (2 个工具)
│ │ ├── er-diagram.ts # ER 图生成 (1 个工具)
│ │ └── index.ts # 聚合注册所有工具
│ └── server/
│ ├── mcp-server.ts # McpServer 创建与工具注册
│ ├── transports.ts # stdio / SSE 双传输层
│ └── index.ts
├── package.json
├── tsconfig.json
└── .gitignore
日志
日志同时输出到 stderr 和 文件:
- 文件位置:
logs/mcp-server.log - stdio 模式下 stdout 被 MCP 协议占用,所有日志通过 stderr 输出,不会干扰通信
- 日志级别可在
config/default.json中配置:trace | debug | info | warn | error | fatal
扩展工具
在 src/tools/ 下新建文件,使用 defineTool 定义工具:
import { z } from 'zod';
import { defineTool, type ToolDefinition } from './types.js';
export const createMyTools = (db: DatabaseManager): ToolDefinition[] => [
defineTool({
name: 'my_tool',
description: '工具描述',
inputSchema: {
param1: z.string().describe('参数说明'),
},
handler: async ({ param1 }) => {
return {
content: [{ type: 'text', text: `结果: ${param1}` }],
};
},
}),
];
然后在 src/tools/index.ts 的 createAllTools 中注册即可。
License
MIT











