# guage-mcp **Repository Path**: yangdechao_admin/guage-mcp ## Basic Information - **Project Name**: guage-mcp - **Description**: 基于 MCP(Model Context Protocol)协议的 MySQL 数据库操作 Agent,将 DDL/DML 操作封装为 MCP 工具。 支持三种传输模式:stdio(标准输入输出)、SSE(Server-Sent Events)、Streamable HTTP(MCP 2025-03-26 规范)。 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: https://gitee.com/yangdechao_admin/project-index - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-18 - **Last Updated**: 2026-09-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MySQL MCP Agent 基于 MCP(Model Context Protocol)协议的 MySQL 数据库操作 Agent,将 DDL/DML 操作封装为 MCP 工具,供 AI Agent 通过标准协议调用。 支持三种传输模式:**stdio**(标准输入输出)、**SSE**(Server-Sent Events)、**Streamable HTTP**(MCP 2025-03-26 规范),可灵活适配本地子进程、远程 HTTP、Docker 容器等多种部署场景。 ## 目录结构 ``` guage-mcp/ ├── mcp_server/ # MCP Server 端 │ ├── __init__.py │ ├── config.py # 配置管理(环境变量 + 双模式 + 传输模式) │ ├── db_pool.py # 异步 MySQL 连接池 │ ├── server.py # MCP Server 主入口(MCPServer,三模式切换) │ └── tools/ # MCP 工具实现 │ ├── __init__.py │ ├── ddl.py # DDL 工具(CREATE/ALTER/DROP/TRUNCATE) │ └── dml.py # DML 工具(INSERT/SELECT/UPDATE/DELETE) ├── mcp_agent/ # MCP Agent 客户端 │ ├── __init__.py │ ├── client.py # MCP 客户端封装(支持 stdio/sse/streamable_http) │ └── agent.py # 交互式 Agent 入口 ├── tests/ # 测试脚本 │ ├── __init__.py │ ├── test_server.py # Server 工具直接测试(19 项) │ └── test_agent.py # Agent 客户端 MCP 协议测试(22 项) ├── scripts/ # 启动脚本 │ ├── start_local.bat # Windows 本地启动(支持 server/server-sse/server-http) │ ├── start_local.sh # Linux/Mac 本地启动 │ ├── start_docker.bat # Windows Docker 启动 │ └── start_docker.sh # Linux/Mac Docker 启动 ├── docs/ # 文档目录 │ └── OfficeAce-MCP使用手册.md # OfficeAce 集成使用手册 ├── Dockerfile # Docker 镜像构建文件(EXPOSE 8000) ├── docker-compose.yml # Docker Compose 编排(含端口映射 8000:8000) ├── .dockerignore ├── .gitignore ├── .env.example # 环境变量模板(含传输模式配置) ├── requirements.txt # Python 依赖(mcp>=2.2.0) ├── CHANGELOG.md # 变更日志 ├── guage-mcp-doubao-usage-manual.md # 豆包集成使用手册 └── README.md # 本文件 ``` ## 功能特性 - **DDL 操作**:CREATE / ALTER / DROP / TRUNCATE / RENAME,含风险等级提示 - **DML 操作**:INSERT / SELECT / UPDATE / DELETE / COUNT,全参数化查询 - **安全控制**:禁止 ALTER USER / GRANT 等权限变更语句,DDL 开关(ALLOW_DDL) - **连接池**:aiomysql 异步连接池,复用连接,超时控制 - **双模式运行**:本地调试(localhost)+ Docker 容器(host.docker.internal) - **三种传输模式**: - **stdio**:标准输入输出传输(默认,向后兼容,适合作为子进程被 Agent 调用) - **SSE**:Server-Sent Events 传输(HTTP 长连接,适合远程调用) - **Streamable HTTP**:Streamable HTTP 传输(MCP 2025-03-26 规范,单端点,支持会话管理) - **MCP 协议**:基于 MCP SDK 2.2.0,标准 JSON-RPC 通信 ## 前置条件 ### 1. MySQL 8.0 已有 Docker MySQL 8.0 运行在 `localhost:3306`,账号 `root/root`,数据库 `testdb`。 > ⚠️ 本项目**不会**创建或修改 MySQL 实例、账号、权限。仅连接使用已有数据库。 ### 2. Python 3.11+ ```bash python --version # 确认 >= 3.11 ``` ### 3. 安装依赖 ```bash pip install -r requirements.txt ``` 依赖清单: - `mcp >= 2.2.0` — MCP SDK(MCPServer / ClientSession,支持 Streamable HTTP 传输) - `aiomysql >= 0.2` — 异步 MySQL 驱动 - `python-dotenv` — .env 文件加载 - `pydantic >= 2.0` — 数据校验 ## 传输模式说明 | 模式 | 配置值 | 适用场景 | 端点 | 说明 | |------|--------|----------|------|------| | stdio | `TRANSPORT_MODE=stdio` | 本地子进程调用 | — | 默认模式,通过标准输入输出通信,适合 AI 客户端以子进程方式启动 | | SSE | `TRANSPORT_MODE=sse` | 远程 HTTP 调用 | `http://host:8000/sse` | Server-Sent Events 长连接,适合远程 Agent 连接 | | Streamable HTTP | `TRANSPORT_MODE=streamable_http` | 远程 HTTP 调用 | `http://host:8000/mcp` | MCP 2025-03-26 规范,单端点,支持 `Mcp-Session-Id` 会话管理 | > **向后兼容**:默认 `TRANSPORT_MODE=stdio`,不设置则保持原有行为不变。 ## 本地运行 ### 方式一:命令行直接运行 **stdio 模式(默认):** ```bash # 设置环境变量 set PYTHONPATH=. set RUN_MODE=local set MYSQL_HOST=localhost set MYSQL_PORT=3306 set MYSQL_USER=root set MYSQL_PASSWORD=root set MYSQL_DATABASE=testdb # 启动 MCP Server(stdio 模式,等待 Agent 连接) python -m mcp_server.server # 另开终端,启动交互式 Agent python -m mcp_agent.agent ``` **SSE 模式:** ```bash set TRANSPORT_MODE=sse set HTTP_HOST=0.0.0.0 set HTTP_PORT=8000 set HTTP_PATH=/sse python -m mcp_server.server # Server 启动后监听 http://0.0.0.0:8000/sse ``` **Streamable HTTP 模式:** ```bash set TRANSPORT_MODE=streamable_http set HTTP_HOST=0.0.0.0 set HTTP_PORT=8000 set HTTP_PATH=/mcp python -m mcp_server.server # Server 启动后监听 http://0.0.0.0:8000/mcp ``` ### 方式二:使用启动脚本 **Windows:** ```cmd scripts\start_local.bat server # stdio 模式 scripts\start_local.bat server-sse # SSE 模式 scripts\start_local.bat server-http # Streamable HTTP 模式 scripts\start_local.bat demo # 演示模式 ``` **Linux/Mac:** ```bash chmod +x scripts/start_local.sh ./scripts/start_local.sh server # stdio 模式 ./scripts/start_local.sh server-sse # SSE 模式 ./scripts/start_local.sh server-http # Streamable HTTP 模式 ./scripts/start_local.sh demo # 演示模式 ``` ### 方式三:使用 .env 文件 复制 `.env.example` 为 `.env`,修改配置后直接启动: ```bash copy .env.example .env # 编辑 .env 文件,设置 TRANSPORT_MODE 和数据库连接信息 python -m mcp_server.server ``` ## 本地测试 ### Server 工具直接测试(19 项) 绕过 MCP 协议,直接调用工具函数验证数据库操作: ```bash set PYTHONPATH=. set RUN_MODE=local set MYSQL_DATABASE=testdb python -m tests.test_server ``` 预期输出:`测试完成: 19 通过, 0 失败, 共 19 项` ### Agent 客户端 MCP 协议测试(22 项) 通过 MCP 协议连接 Server,测试完整通信链路: ```bash set PYTHONPATH=. set RUN_MODE=local set MYSQL_DATABASE=testdb python -m tests.test_agent ``` 预期输出:`测试完成: 22 通过, 0 失败, 共 22 项` ## Docker 部署 > ⚠️ Docker 镜像**仅包含 MCP 应用**,不包含 MySQL。MySQL 使用宿主机上已有的 Docker MySQL 实例。 ### 1. 构建镜像 ```bash docker build -t guage-mcp:latest . ``` ### 2. 启动容器 **方式一:docker-compose(stdio 模式)** ```bash docker-compose up -d ``` **方式二:docker run(stdio 模式)** ```bash docker run -d \ --name guage-mcp-agent \ -e RUN_MODE=docker \ -e MYSQL_HOST=host.docker.internal \ -e MYSQL_PORT=3306 \ -e MYSQL_USER=root \ -e MYSQL_PASSWORD=root \ -e MYSQL_DATABASE=testdb \ -e ALLOW_DDL=true \ --add-host=host.docker.internal:host-gateway \ guage-mcp:latest ``` **方式三:docker run(Streamable HTTP 模式)** ```bash docker run -d \ --name guage-mcp-agent \ -e RUN_MODE=docker \ -e TRANSPORT_MODE=streamable_http \ -e HTTP_HOST=0.0.0.0 \ -e HTTP_PORT=8000 \ -e HTTP_PATH=/mcp \ -e MYSQL_HOST=host.docker.internal \ -e MYSQL_PORT=3306 \ -e MYSQL_USER=root \ -e MYSQL_PASSWORD=root \ -e MYSQL_DATABASE=testdb \ -e ALLOW_DDL=true \ -p 8000:8000 \ --add-host=host.docker.internal:host-gateway \ guage-mcp:latest ``` 启动后可通过 `http://localhost:8000/mcp` 访问 MCP 服务。 **方式四:docker run(SSE 模式)** ```bash docker run -d \ --name guage-mcp-agent \ -e RUN_MODE=docker \ -e TRANSPORT_MODE=sse \ -e HTTP_HOST=0.0.0.0 \ -e HTTP_PORT=8000 \ -e HTTP_PATH=/sse \ -e MYSQL_HOST=host.docker.internal \ -e MYSQL_PORT=3306 \ -e MYSQL_USER=root \ -e MYSQL_PASSWORD=root \ -e MYSQL_DATABASE=testdb \ -e ALLOW_DDL=true \ -p 8000:8000 \ --add-host=host.docker.internal:host-gateway \ guage-mcp:latest ``` ### 3. 使用 Docker 启动脚本 **Windows:** ```cmd scripts\start_docker.bat build # 构建镜像 scripts\start_docker.bat server # stdio 模式 scripts\start_docker.bat server-sse # SSE 模式 scripts\start_docker.bat server-http # Streamable HTTP 模式 scripts\start_docker.bat demo # 演示模式 ``` **Linux/Mac:** ```bash chmod +x scripts/start_docker.sh ./scripts/start_docker.sh build # 构建镜像 ./scripts/start_docker.sh server # stdio 模式 ./scripts/start_docker.sh server-sse # SSE 模式 ./scripts/start_docker.sh server-http # Streamable HTTP 模式 ./scripts/start_docker.sh demo # 演示模式 ``` ### 4. 查看容器日志 ```bash docker logs -f guage-mcp-agent ``` ### 5. 进入容器执行 Agent ```bash docker exec -it guage-mcp-agent python -m mcp_agent.agent ``` ## MCP 客户端连接测试 ### Python 代码调用(stdio 模式) ```python import asyncio from mcp_agent.client import MCPClient async def main(): # 创建客户端并连接 Server(stdio 模式) async with MCPClient(env={"RUN_MODE": "local", "MYSQL_DATABASE": "testdb"}) as client: # 发现工具 tools = await client.list_tools() print(f"可用工具: {[t['name'] for t in tools]}") # 测试连接 result = await client.call_tool("test_connection") print(result) # 创建表 result = await client.call_tool("execute_ddl", { "sql": "CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100))" }) print(result) # 插入数据 result = await client.call_tool("insert_data", { "table_name": "users", "data": {"name": "张三"} }) print(result) # 查询数据 result = await client.call_tool("select_data", { "table_name": "users" }) print(result) asyncio.run(main()) ``` ### Python 代码调用(Streamable HTTP 模式) ```python import asyncio from mcp_agent.client import MCPClient async def main(): # 创建客户端并连接 Server(Streamable HTTP 模式) async with MCPClient( transport_mode="streamable_http", url="http://localhost:8000/mcp" ) as client: tools = await client.list_tools() print(f"可用工具: {[t['name'] for t in tools]}") result = await client.call_tool("test_connection") print(result) asyncio.run(main()) ``` ### 交互式 Agent ```bash python -m mcp_agent.agent ``` Agent 提供命令行交互界面,支持以下命令: - `tools` — 列出所有可用工具 - `call ` — 调用指定工具 - `exit` — 退出 ## MCP 工具列表 | 工具名 | 类型 | 说明 | |--------|------|------| | `test_connection` | 辅助 | 测试数据库连接是否正常 | | `list_databases` | DDL | 列出所有数据库 | | `list_tables` | DDL | 列出指定数据库的表 | | `describe_table` | DDL | 查看表结构 | | `show_create_table` | DDL | 查看建表语句 | | `execute_ddl` | DDL | 执行 DDL 语句(含安全检查) | | `select_data` | DML | 查询数据(参数化) | | `insert_data` | DML | 插入单行数据 | | `insert_batch` | DML | 批量插入数据 | | `update_data` | DML | 更新数据(必须 WHERE) | | `delete_data` | DML | 删除数据(必须 WHERE) | | `count_data` | DML | 统计行数 | ## 配置说明 ### 环境变量 | 变量名 | 默认值 | 说明 | |--------|--------|------| | `RUN_MODE` | `local` | 运行模式:`local` / `docker` | | `TRANSPORT_MODE` | `stdio` | 传输模式:`stdio` / `sse` / `streamable_http` | | `HTTP_HOST` | `0.0.0.0` | HTTP 监听地址(sse / streamable_http 模式使用) | | `HTTP_PORT` | `8000` | HTTP 监听端口(sse / streamable_http 模式使用) | | `HTTP_PATH` | `/mcp` | HTTP 端点路径(streamable_http 默认 `/mcp`,sse 默认 `/sse`) | | `JSON_RESPONSE` | `false` | Streamable HTTP 是否使用普通 JSON 响应替代 SSE 流 | | `STATELESS_HTTP` | `false` | Streamable HTTP 是否运行无状态模式 | | `MYSQL_HOST` | `localhost` | MySQL 主机地址(docker 模式自动切换为 `host.docker.internal`) | | `MYSQL_PORT` | `3306` | MySQL 端口 | | `MYSQL_USER` | `root` | MySQL 用户名 | | `MYSQL_PASSWORD` | `root` | MySQL 密码 | | `MYSQL_DATABASE` | `None` | 默认数据库 | | `MYSQL_POOL_SIZE` | `10` | 连接池大小 | | `MYSQL_CONNECT_TIMEOUT` | `10` | 连接超时(秒) | | `MYSQL_QUERY_TIMEOUT` | `30` | 查询超时(秒) | | `ALLOW_DDL` | `true` | 是否允许 DDL 操作 | | `DDL_CONFIRM` | `true` | DDL 操作是否需要确认提示 | ### Docker 模式说明 当 `RUN_MODE=docker` 时: - `MYSQL_HOST` 自动设置为 `host.docker.internal`(如未显式指定) - 容器通过 `--add-host=host.docker.internal:host-gateway` 访问宿主机 MySQL - 需在 docker-compose.yml 或 docker run 中添加 host 映射 ### 传输模式切换说明 - **stdio 模式**:不需要 HTTP 端口,AI 客户端以子进程方式启动 Server - **SSE 模式**:需要暴露 HTTP 端口,端点路径默认 `/sse`,使用 Server-Sent Events 长连接 - **Streamable HTTP 模式**:需要暴露 HTTP 端口,端点路径默认 `/mcp`,支持 `Mcp-Session-Id` 头进行会话管理,兼容 SSE 流响应 ## 安全机制 1. **参数化查询**:所有 DML 操作使用 `%s` 占位符,杜绝 SQL 注入 2. **DDL 开关控制**:`ALLOW_DDL=false` 时拒绝所有 DDL 操作 3. **禁止权限变更**:自动拦截 `ALTER USER`、`GRANT`、`REVOKE` 等语句 4. **强制 WHERE 条件**:UPDATE / DELETE 必须提供 WHERE 条件,防止全表操作 5. **风险等级提示**:DDL 操作返回 LOW / MEDIUM / HIGH 风险等级 6. **查询行数限制**:SELECT 默认限制 100 行,最大 10000 行 7. **超时控制**:连接超时 + 查询超时双重保护 ## 技术架构 ``` ┌──────────────┐ stdio / SSE / HTTP ┌──────────────┐ aiomysql ┌──────────┐ │ MCP Agent │ ←─────────────────────→ │ MCP Server │ ←──────────────→ │ MySQL │ │ (client) │ JSON-RPC │ (MCPServer) │ 连接池 │ 8.0 │ └──────────────┘ └──────────────┘ └──────────┘ ``` - **MCP Server**:基于 `mcp.server.mcpserver.MCPServer`,注册 12 个工具,支持三种传输模式 - **MCP Client**:基于 `mcp.ClientSession`,支持 `stdio_client` / `sse_client` / `streamable_http_client` - **连接池**:`aiomysql.create_pool`,单例模式,懒初始化(在 MCP 事件循环内创建) - **配置管理**:环境变量 + `.env` 文件,自动检测 Docker 模式 ## 常见问题 ### Q: 启动时报 "Event loop is closed" **A:** 已修复。连接池采用懒初始化,在 MCP Server 的事件循环内首次调用时创建,避免跨事件循环问题。 ### Q: 操作报 "No database selected" **A:** 设置环境变量 `MYSQL_DATABASE=testdb`,或在 `.env` 文件中配置。 ### Q: Docker 容器无法连接 MySQL **A:** 确保: 1. 宿主机 MySQL 正在运行 2. docker-compose.yml 中有 `extra_hosts` 配置 3. MySQL 允许从 `host.docker.internal` 连接 ### Q: 如何禁止 DDL 操作 **A:** 设置环境变量 `ALLOW_DDL=false`。 ### Q: Streamable HTTP 模式如何验证服务是否正常? **A:** 启动后用 curl 发送 POST 请求到端点: ```bash curl -X POST http://localhost:8000/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' ``` 正常情况下会返回 JSON-RPC 响应,包含 Server 的 capabilities 信息。 ### Q: SSE 和 Streamable HTTP 有什么区别? **A:** - **SSE**:使用 `/sse` 端点建立长连接,通过 `/messages/` 端点发送请求,是较早的 HTTP 传输方式 - **Streamable HTTP**:MCP 2025-03-26 规范的新传输方式,单端点(默认 `/mcp`),支持会话管理(`Mcp-Session-Id` 头),响应可以是 SSE 流或普通 JSON,更灵活且更符合未来规范 ### Q: 如何在 Docker 中使用 HTTP 传输模式? **A:** 设置 `TRANSPORT_MODE=streamable_http` 或 `TRANSPORT_MODE=sse`,并确保: 1. Dockerfile 中 `EXPOSE 8000`(已配置) 2. docker run 时添加 `-p 8000:8000` 端口映射 3. `HTTP_HOST` 设置为 `0.0.0.0`(容器内监听所有接口) ## MCP Inspector 测试 ```bash npx @modelcontextprotocol/inspector python -m mcp_server.server ``` ## 相关文档 - [豆包集成使用手册](guage-mcp-doubao-usage-manual.md) — 在豆包中接入 guage-mcp 的完整指南 - [OfficeAce 集成使用手册](docs/OfficeAce-MCP使用手册.md) — 在 OfficeAce 中接入 guage-mcp 的完整指南 - [变更日志](CHANGELOG.md) — 版本变更记录