Files
smartmate/infra/smartflow-mcp-server/README.md
LoveLosita 26c350f378 Version: 0.4.4.dev.260307
feat: 🚀 增强会话管理与缓存机制

* 会话 ID 空值兜底,若 `conversation_id` 为空时自动生成 UUID
* 在响应头写入 `X-Conversation-ID`,供前端使用,保持同一会话状态

perf:  会话状态缓存优化

* 当缓存未命中但 DB 已确认/创建会话后,调用 `SetConversationStatus` 回写 Redis
* 缓存写回失败时记录日志,不中断聊天主流程,确保业务流畅性

fix: 🐛 修复历史消息顺序问题与编译错误

* 修复历史消息顺序问题,保证返回的 N 条历史消息按时间正序喂给模型

  * 通过反转 `created_at desc` 查询结果的切片,确保模型输入顺序正确
* 修复 `fmt.Errorf` 参数不匹配问题,修正编译错误
* 整理 `agent-cache.go` 为标准 UTF-8 编码,避免 Go 编译报错 `invalid UTF-8 encoding`

feat: 🛠️ 独立构建 MCP 服务器

* 使用 `Codex` 构建独立于后端的 MCP 服务器,简化与 Codex 的协作
* 通过该服务器方便 Codex 直接测试和查看 Redis 与 MySQL 中的数据
2026-03-07 15:25:40 +08:00

214 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# smartflow-mcp-server (MVP)
用于让 Codex 通过 MCPstdio只读访问 MySQL 与 Redis面向接口联调与测试。
## 1. 功能范围(第一阶段)
只实现 3 个只读工具:
1. `mysql_query_readonly`
2. `redis_get`
3. `redis_scan`
未实现任何写操作工具。
## 2. 目录结构
```text
infra/smartflow-mcp-server
├─ cmd/server/main.go
├─ internal
│ ├─ audit
│ ├─ config
│ ├─ envutil
│ ├─ mcp
│ ├─ ratelimit
│ ├─ security
│ ├─ store
│ └─ tools
├─ .env.example
├─ go.mod
└─ README.md
```
## 3. 快速启动
```bash
go mod tidy
go test ./...
go run ./cmd/server
```
服务采用 stdio MCP 协议,不会启动 HTTP 端口。
## 4. 配置说明(全部来自环境变量)
复制并编辑:
```bash
cp .env.example .env
```
关键变量:
- `MYSQL_HOST` / `MYSQL_PORT` / `MYSQL_USER` / `MYSQL_PASSWORD` / `MYSQL_DATABASE`
- `REDIS_ADDR` / `REDIS_PASSWORD` / `REDIS_DB`
- `MYSQL_ALLOWED_DATABASES`:逗号分隔
- `MYSQL_ALLOWED_TABLES`:逗号分隔,支持 `db.table``table`
- `MCP_ENFORCE_WHITELIST``true` 时无明确表引用会拒绝执行
- `MCP_TOOL_TIMEOUT_MS`:单次工具调用超时
- `MCP_RATE_LIMIT_RPS` + `MCP_RATE_LIMIT_BURST`:基础令牌桶限流
- `MCP_MAX_RESULT_ROWS`MySQL 最大返回行数
- `MCP_REDIS_SCAN_MAX_KEYS``redis_scan` 最大返回 key 数
- `MCP_AUDIT_LOG_PATH`:审计日志路径
## 5. 工具说明
### 5.1 `mysql_query_readonly`
输入:
```json
{
"sql": "SELECT id, name FROM users WHERE id = ?",
"params": [1]
}
```
安全限制:
- 仅允许 `SELECT` / `SHOW` / `DESCRIBE` / `EXPLAIN`
- 禁止分号 `;`(多语句)
- 禁止注释 `--` / `#` / `/* */`
- 禁止 DDL/DML 关键字(`INSERT`/`UPDATE`/`DELETE`/`ALTER`/`DROP`/`TRUNCATE` 等)
- 支持库/表白名单校验
输出(结构化):
- `columns`
- `rows`
- `rowCount`
- `truncated`
- `durationMs`
### 5.2 `redis_get`
输入:
```json
{
"key": "user:1001"
}
```
输出:
- `exists`
- `key`
- `type`
- `value`
- `truncated`
- `durationMs`
### 5.3 `redis_scan`
输入:
```json
{
"pattern": "user:*",
"count": 50
}
```
输出:
- `pattern`
- `keys`
- `returned`
- `nextCursor`
- `truncated`
- `durationMs`
## 6. 审计日志
每次工具调用会记录JSON 行格式):
- 时间
- 工具名
- 调用方caller
- 是否成功
- 耗时
- 脱敏后的输入摘要
- 错误信息(截断)
敏感字段处理:
- SQL 字符串字面量与数字会脱敏
- Redis key 仅保留前后少量字符
## 7. Codex MCP 配置示例stdio
可按客户端配置格式接入,示例:
```json
{
"mcpServers": {
"smartflow-db-readonly": {
"command": "go",
"args": ["run", "./cmd/server"],
"cwd": "E:/SmartFlow-Agent/infra/smartflow-mcp-server",
"env": {
"MYSQL_HOST": "127.0.0.1",
"MYSQL_PORT": "3306",
"MYSQL_USER": "readonly_user",
"MYSQL_PASSWORD": "replace_me",
"MYSQL_DATABASE": "smartflow",
"MYSQL_ALLOWED_DATABASES": "smartflow",
"MYSQL_ALLOWED_TABLES": "smartflow.users,smartflow.tasks",
"REDIS_ADDR": "127.0.0.1:6379",
"REDIS_DB": "0",
"MCP_TOOL_TIMEOUT_MS": "5000",
"MCP_RATE_LIMIT_RPS": "5",
"MCP_RATE_LIMIT_BURST": "10",
"MCP_MAX_RESULT_ROWS": "500",
"MCP_REDIS_SCAN_MAX_KEYS": "200",
"MCP_AUDIT_LOG_PATH": "logs/audit.log"
}
}
}
}
```
## 8. 安全限制生效示例
- SQL 多语句:`SELECT 1; SELECT 2` -> 被拒绝semicolon is not allowed
- SQL 注释绕过:`SELECT * FROM users --x` -> 被拒绝sql comments are not allowed
- 写操作:`DELETE FROM users` -> 被拒绝dangerous sql keyword detected
- 白名单外表:`SELECT * FROM admin.secret` -> 被拒绝table not in whitelist
- Redis 大范围扫描:`redis_scan` 返回数量受 `MCP_REDIS_SCAN_MAX_KEYS` 限制
## 9. 风险说明MVP 已知边界)
1. SQL 校验采用关键字与模式匹配,不是完整 SQL AST 解析,建议二阶段引入 AST 级校验。
2. `SHOW DATABASES` 等无显式表引用语句在非严格模式下可执行;生产建议开启 `MCP_ENFORCE_WHITELIST=true`
3. Redis 复杂类型返回做了截断保护,但仍建议在生产环境设置更小上限。
## 10. 常见问题FAQ
### Q1: 启动时报 `MYSQL_USER and MYSQL_DATABASE are required`
检查环境变量是否正确加载,建议先确认 `.env` 存在于 `infra/smartflow-mcp-server`
### Q2: 为什么调用工具报限流
默认启用了令牌桶限流,调大 `MCP_RATE_LIMIT_RPS``MCP_RATE_LIMIT_BURST` 即可。
### Q3: 为什么 `redis_scan` 返回不全
是预期行为,结果数被 `MCP_REDIS_SCAN_MAX_KEYS` 限制,避免全量扫描拖垮 Redis。
### Q4: 审计日志在哪里
默认在 `logs/audit.log`,可用 `MCP_AUDIT_LOG_PATH` 自定义。