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 中的数据
This commit is contained in:
213
infra/smartflow-mcp-server/README.md
Normal file
213
infra/smartflow-mcp-server/README.md
Normal file
@@ -0,0 +1,213 @@
|
||||
# smartflow-mcp-server (MVP)
|
||||
|
||||
用于让 Codex 通过 MCP(stdio)只读访问 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` 自定义。
|
||||
Reference in New Issue
Block a user