Files
opsxdb/docs/15-AI-MCP-Agent.md
T
logan 0b68c8344d feat(mcp): P0 只读 MCP tool runtime + opsxdb-mcp stdio
- aitools 共用 runtime:list/describe/schema/query/redis(纯只读,无写确认)
- 白名单 ~/.opsxdb/mcp.json;审计 mcp-audit.jsonl;复用 danger.go
- 桌面 connections 双写 ~/.opsxdb/connections.json(ox1. 解码)
- Cursor 配置示例与任务书验收勾选更新;写操作与 Agent UI 留 P1
2026-10-15 11:14:08 +08:00

194 lines
11 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.
# OpsxDB AI / MCP / Agent 任务书
> 更新:2026-10-15 · 用户拍板:**先 MCP,再内部会话,最后 GUI 联动**
> 对标:优先 [DBX MCP](https://github.com/t8y2/dbx)(`packages/mcp-server` / `crates/dbx-mcp`);架构思路参考 oh-my-pi;可选对照 Google MCP Toolbox for Databases、DBHub、官方 MCP SDK。
## 产品结论(已采纳用户补充)
### 2026-10-15 产品 / PM / 设计确认(锁定)
| 项 | 决议 |
|----|------|
| 顺序 | MCP-first → 内部会话共用 Tools → GUI 插入/回写 |
| 首版引擎 | **仅** MySQL 族 + PostgreSQL + Redis;其它库不进 P0 |
| 写操作 | **P0 纯只读**;「确认后才可写」复用现有 dangerConfirm,进 **P1**,MCP 首版不可写 |
| 代码边界 | 只动根级 `src` + `server`;禁止 `packages/ui`(死树) |
| Redis | 对齐现有精确 TYPE / 集群 SCAN,不另起搜键 |
| UI | P0 无新重界面;Ask\|Agent Seg / 步骤时间线 / MCP 状态点属阶段 2–4(见文末设计备忘) |
| 冲突 | 与未推「补偿包」冲突先停报,勿 silently 覆盖 |
| 问题 | 结论 |
|------|------|
| 能不能用 AI 做 MySQL/Redis 等操作? | 能。底座 `/api/db/*` + danger 已有,缺的是工具层。 |
| 借鉴谁? | **优先 DBX**(MCP 工具粒度、只读/可写、连接 scope、审计)。oh-my-pi 借工具调用/会话规范,不当成 DB 产品抄。 |
| 要不要先做 MCP? | **要,优先做 MCP**。内部 AI 会话与 Cursor/Claude/Codex/omp **共用同一套 Tools**,避免两套逻辑。 |
| 形态 | GUI 管连接与会话;MCP 暴露安全的数据操作;Gin 仍是官网/docs,**不是**远程协作后端。 |
## P0 / P1 边界(2026-10-15 收紧)
| 阶段 | 范围 |
|------|------|
| **P0(本轮)** | **纯只读**。`execute_query` 只允许 SELECT/SHOW/EXPLAIN/DESCRIBE/PRAGMA/WITH…SELECT;任何写/DDL **一律拒绝**(**不做** write mode / confirm token)。Redis 仅白名单读命令(GET/SCAN/TYPE/TTL…);FLUSH*/KEYS/写命令拒。MCP stdio + tool runtime + 连接落盘 + 审计。 |
| **P1** | 可写 + 确认令牌/策略;内部 Ask \| Agent UI(设计阶段 2,**先只记文档不实现**);GUI 联动(插入编辑器 / 结果网格);设置页 MCP 白名单 UI。 |
设计阶段 2(内部会话 Ask \| Agent):Agent 调同一 `aitools` runtime;Ask 保持现有生成/解释/优化。**本轮不实现 UI。**
## 落地顺序(锁定)
1. **核心 MCP Tools(最小集)** + 连接落盘可读
2. **安全策略**:默认只读、危险 SQL 拦截、连接白名单、审计日志
3. **内部 AI 会话**:Ask \| Agent;Agent 调同一工具层(进程内调用,不必绕 stdio)
4. **GUI 联动**:SQL 一键插入编辑器;结果可回写网格 / 展示
## P0 工具契约
| Tool | 说明 | 安全默认 |
|------|------|----------|
| `opsxdb_list_connections` | 列出可见连接(id/name/driver/host,无密码) | 受白名单过滤 |
| `opsxdb_list_databases` | 列库 | 连接须在白名单 |
| `opsxdb_list_tables` | 列表/视图(及引擎等价物) | 只读 |
| `opsxdb_describe_table` | 字段与表元数据 | 只读 |
| `opsxdb_get_schema_context` | 紧凑 schema 文本,供模型上下文 | 截断上限(与现 AI schema cap 对齐,约 4k) |
| `opsxdb_execute_query` | 执行 SQL;最多 N 行(建议 100) | **P0 纯只读**(非读语句直接拒绝);可写+确认 = P1 |
| `opsxdb_execute_redis_command` | 执行一条 Redis 命令 | **P0 仅读命令白名单**;FLUSH*/KEYS/写一律拒;P1 再开确认写 |
首版引擎验收:**MySQL 族 + PostgreSQL + Redis(单机)**;其余引擎有连接即可试,不阻塞发版。
## 安全策略(MCP 层统一)
- **P0 强制只读**:`execute_query` 非读类 SQL 一律拒绝;`mcp.json` 的 `mode=read_write` 本轮不生效(P1 才启用写+确认)
- 复用 `server/internal/db/danger.go` 的危险词表;无 WHERE 的 DELETE/UPDATE 拦截
- **连接白名单**(配置文件 `~/.opsxdb/mcp.json`:`allowed_connection_ids`;空=拒绝全部或仅显式 allow——首版建议「空=拒绝」,避免默认放开)
- **行数 / 字节上限**;超时;取消
- **审计**:`~/.opsxdb/logs/mcp-audit.jsonl`(时间、tool、connection_id、只读/写、摘要、错误;不含密码/全文大结果)
- 不暴露:增删连接、原始密码、远程 HTTP 无 token 的开放端口(stdio 默认;本机 HTTP 可选且必须 bearer)
## 连接存储(MCP 可读)
现状:连接在桌面 `localStorage`(`opsxdb.connections.v1`),独立 MCP 进程读不到。
**本轮必做:** GUI `saveConnections` 同步写 `~/.opsxdb/connections.json`(脱敏字段完整、密码仍按现有混淆策略;MCP 与桌面同钥/同解码逻辑,或 MCP 仅经本机已打开的 session——优先**文件同步 + 现有 secrets 解码**,与 DBX「读桌面连接库」同构)。
## 内部会话与 MCP 的关系
```
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Cursor/omp │───▶│ opsxdb-mcp │───▶│ tool runtime │
└─────────────┘ │ (stdio/HTTP) │ │ (db.* API) │
└──────────────────┘ └──────┬──────┘
┌─────────────┐ ┌──────────────────┐ │
│ 侧栏 Agent │───▶│ 同一 tool runtime │◀───────────┘
└─────────────┘ └──────────────────┘
```
侧栏 **不要**再直接拼 prompt 假装执行;Agent 模式只通过 tool runtime。Ask 模式保持现有生成/解释/优化(可不调执行工具)。
## GUI 联动(第 4 步,可薄)
- 工具结果中的 SQL →「插入当前编辑器」
- `execute_query` 结果 → 可选「在结果网格打开」(限行)
- 设置页:MCP 开关说明、白名单、只读/可写、复制 Cursor `mcp.json` 片段
## 刻意首版不做
- MCP 增删连接、Kafka/MQ、桌面 `open_table` 远程遥控(可后置)
- 把 Gin `:8788` 做成公网 Agent 后端
- 两套危险策略(GUI 一套、MCP 一套)
## 验收清单
- [x] `opsxdb-mcp` stdio:`tools/list` 含上表工具(二进制 + 单测注册表)
- [x] 白名单外连接调用失败且有明确错误(空白名单=拒绝全部)
- [x] 只读模式下 `DELETE`/`DROP`/写 SQL 被拒;审计写 `mcp-audit.jsonl`
- [x] 通路代码就绪;单测用 sqlite 覆盖 list/describe/exec;MySQL/PG 真库待桌面验收
- [x] Redis 读白名单 + FLUSH*/KEYS/写拒(单测);真库待验
- [ ] 侧栏 Agent 调同一 runtime(**P1 / 设计阶段 2,本轮不做 UI**)
- [x] 文档:`docs/mcp-cursor.example.json` + 本文件
## 参考路径(本机)
- DBX:`/Users/logan/devops/demo/db-gui/dbx/packages/mcp-server`、`crates/dbx-mcp`
- oh-my-pi:`/Users/logan/devops/demo/ai-agent/oh-my-pi/docs/mcp-*.md`、`docs/custom-tools.md`
- OpsxDB 现有:`server/internal/db/*`、`server/internal/ai/*`、`src/AiPanel.tsx`、`docs/DATABASE-OPERATIONS-AUDIT.md`
## P0 验收方式(命令行优先)
> 产品边界:P0 是 **MCP 工具层**,不是 Web 工作台。验收不走浏览器 `:5174`/官网;Web 只看文档。DeepSeek 侧栏 **Ask 写 SQL** 已可测生成;**Agent 调工具查真库**属阶段 2。
### 环境(本机已有)
| 库 | 端口 | 账号 | 说明 |
|----|------|------|------|
| MySQL 8.4 (`opsxdb-mysql`) | 3306 | root 或 opsx / `Demo@123`,库 `demo` | `tests/dbctl.sh up a` |
| Redis 7 (`opsxdb-redis`) | 6379 | 无密码 | `tests/dbctl.sh up f` |
### A. 单测(无真库也可)
```bash
cd /Users/logan/devops/opsxdb/server
go test ./internal/aitools/ -count=1
```
覆盖:白名单拒绝、只读挡 DROP/DELETE、Redis 危险命令拒绝。
### B. 真库 MCP(推荐主路径)
1. GUI 里保存 MySQL / Redis 连接一次(会双写 `~/.opsxdb/connections.json`),记下 `id`。
2. 写白名单:
```bash
mkdir -p ~/.opsxdb/logs
cat > ~/.opsxdb/mcp.json <<'EOF'
{
"mode": "read_only",
"allowed_connection_ids": ["<mysql-conn-id>", "<redis-conn-id>"]
}
EOF
```
3. 编译并跑:
```bash
cd /Users/logan/devops/opsxdb/server
go build -o ../bin/opsxdb-mcp ./cmd/opsxdb-mcp
# Cursor:mcp.json 指向该二进制;或用临时脚本对 stdio 发 initialize + tools/list + tools/call
```
4. 用例清单:
| # | 工具 | 期望 |
|---|------|------|
| 1 | list_connections | 只见白名单内连接,无密码字段 |
| 2 | list_tables(MySQL demo) | 有表名 |
| 3 | describe_table | 有列 |
| 4 | get_schema_context | 截断文本 |
| 5 | execute_query `SELECT … LIMIT 10` | 有行,≤100 |
| 6 | execute_query `DROP TABLE …` | **拒绝** + 审计 |
| 7 | execute_redis_command `PING` / `GET` | 成功 |
| 8 | execute_redis_command `FLUSHDB` | **拒绝** |
| 9 | 白名单外 connection_id | **拒绝** |
| 10 | 审计文件 | `~/.opsxdb/logs/mcp-audit.jsonl` 有记录 |
### C. DeepSeek(当前能验什么)
- **现在**:设置里选 DeepSeek → Ask「生成/解释」对当前 Tab SQL(不执行工具)。
- **阶段 2**:Agent 模式多轮调同一 MCP tool runtime,再验「让 AI 查 demo 表结构再写 SELECT」。
### D. 验收通过后交付物
在本机 `~/Downloads/` 生成:`AI-Agent接入GUI工具开发实践.md`,供 opsxapi / opsxshell 及其他项目复用(MCP-first、只读默认、连接落盘、Ask|Agent、危险确认)。
## 设计备忘(阶段 2–4,P0 不实现)
来源:设计师 2026-10-15。紧凑桌面、深浅主题;不抄 dbx 整屏工具条。
1. **Ask | Agent**:输入框上方同高同宽小分段;Ask/Agent 不同占位;危险写在执行前确认条(结果区顶或气泡内),Ask 不生成执行条;模式跟连接/Tab,切换不丢草稿。
2. **步骤时间线**:挂在该条 Agent 回复下,可折叠,默认最近 3 步;行内状态点+工具名+一行摘要+耗时;点开才见全文;无独立全高工具面板。
3. **插入/结果**:气泡底「插入当前查询」+「新开查询」;行列结果才给「在结果区打开」;默认不抢焦点。
4. **MCP 状态**:设置 → AI/MCP(开关+白名单);有活跃外部会话时标题旁小点「MCP」,悬停摘要,点开最近调用可断开;无活跃不显示。
落地次序:MCP 开关+白名单 → Ask|Agent Seg → 时间线与插入 → MCP 状态点。