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 中的数据
4.8 KiB
4.8 KiB
smartflow-mcp-server (MVP)
用于让 Codex 通过 MCP(stdio)只读访问 MySQL 与 Redis,面向接口联调与测试。
1. 功能范围(第一阶段)
只实现 3 个只读工具:
mysql_query_readonlyredis_getredis_scan
未实现任何写操作工具。
2. 目录结构
infra/smartflow-mcp-server
├─ cmd/server/main.go
├─ internal
│ ├─ audit
│ ├─ config
│ ├─ envutil
│ ├─ mcp
│ ├─ ratelimit
│ ├─ security
│ ├─ store
│ └─ tools
├─ .env.example
├─ go.mod
└─ README.md
3. 快速启动
go mod tidy
go test ./...
go run ./cmd/server
服务采用 stdio MCP 协议,不会启动 HTTP 端口。
4. 配置说明(全部来自环境变量)
复制并编辑:
cp .env.example .env
关键变量:
MYSQL_HOST/MYSQL_PORT/MYSQL_USER/MYSQL_PASSWORD/MYSQL_DATABASEREDIS_ADDR/REDIS_PASSWORD/REDIS_DBMYSQL_ALLOWED_DATABASES:逗号分隔MYSQL_ALLOWED_TABLES:逗号分隔,支持db.table或tableMCP_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
输入:
{
"sql": "SELECT id, name FROM users WHERE id = ?",
"params": [1]
}
安全限制:
- 仅允许
SELECT/SHOW/DESCRIBE/EXPLAIN - 禁止分号
;(多语句) - 禁止注释
--/#//* */ - 禁止 DDL/DML 关键字(
INSERT/UPDATE/DELETE/ALTER/DROP/TRUNCATE等) - 支持库/表白名单校验
输出(结构化):
columnsrowsrowCounttruncateddurationMs
5.2 redis_get
输入:
{
"key": "user:1001"
}
输出:
existskeytypevaluetruncateddurationMs
5.3 redis_scan
输入:
{
"pattern": "user:*",
"count": 50
}
输出:
patternkeysreturnednextCursortruncateddurationMs
6. 审计日志
每次工具调用会记录(JSON 行格式):
- 时间
- 工具名
- 调用方(caller)
- 是否成功
- 耗时
- 脱敏后的输入摘要
- 错误信息(截断)
敏感字段处理:
- SQL 字符串字面量与数字会脱敏
- Redis key 仅保留前后少量字符
7. Codex MCP 配置示例(stdio)
可按客户端配置格式接入,示例:
{
"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 已知边界)
- SQL 校验采用关键字与模式匹配,不是完整 SQL AST 解析,建议二阶段引入 AST 级校验。
SHOW DATABASES等无显式表引用语句在非严格模式下可执行;生产建议开启MCP_ENFORCE_WHITELIST=true。- 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 自定义。