# 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 | Ask\|Agent + SSE 时间线 + 插入/结果区 + MCP 状态点已落地;P1 确认条已接 | | 冲突 | 与未推「补偿包」冲突先停报,勿 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/写拒(单测);真库待验 - [x] 侧栏 Agent 调同一 runtime(Ask|Agent + `/api/ai/agent` SSE + 步骤时间线 + 结果区/确认) - [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": ["", ""] } 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 状态点。 ### 阶段 2(内部 Ask | Agent)2026-10-15 | 项 | 说明 | |----|------| | Ask | 侧栏分段 **Ask**:走既有 `/api/ai/chat`,不调工具(生成/解释/优化) | | Agent | 分段 **Agent**:`POST /api/ai/agent` → `ai.RunAgent` → 进程内 `aitools.Runtime.Call`(与 MCP 同源) | | 协议 | Agent tool calling 目前仅 **openai-chat**(DeepSeek / OpenAI 兼容) | | 安全 | P0 只读;ConfirmDanger 永不 true;白名单 / 审计同 MCP | | UI | 输入框上 Ask\|Agent;回复下可折叠步骤时间线(默认最近 3 步) | | 单测 | `go test ./internal/ai/ ./internal/aitools/`(含 mock tool loop) | | 真库冒烟 | `cd server && go run ./cmd/opsxdb-agent-accept/`(需 `~/.opsxdb/ai.json` 真 key) | 手动测:打开侧栏 → Agent →「列出 demo 有哪些表并查 users 几行」→ 步骤应出现 `list_tables` / `execute_query`。 ### 真库验收 2026-10-15 MySQL 3306 demo + Redis 6379:`go run ./cmd/opsxdb-mcp-accept/` 全过。实践文档:`~/Downloads/AI-Agent接入GUI工具开发实践.md`。 ## 阶段 3–4 完成记录(2026-10-15) | 项 | 状态 | |----|------| | Agent SSE | ✅ `stream=true` / `Accept: text/event-stream`;步骤边推 + 正文分块;非流式 JSON fallback;停止=Abort | | Anthropic / responses tool calling | ✅ 解析与回灌单测;DeepSeek 仍走 openai-chat | | 在结果区打开 / 插入编辑器 | ✅ 气泡步骤与代码块动作;不抢编辑器 focus | | MCP 状态点 | ✅ 仅 `source=mcp` 近 5 分钟活跃时显示;`GET /api/ai/mcp-status` | | P1 可写+确认 | ✅ 默认只读;`mode=read_write` + 确认条 / `confirm_danger`;Agent 剥离模型自带令牌;`POST /api/ai/agent/confirm` | | 官网/文档 | ✅ intro / AI / FAQ + homepage AI/MCP 文案;**未**宣传默认可写 | 手动测: ```bash cd server && go test ./internal/ai/ ./internal/aitools/ ./internal/server/ -count=1 # 侧栏 Agent:发问看步骤流式出现;有行列结果点「在结果区打开」 # 写:mcp.json mode=read_write 后让 Agent 尝试写 → 气泡确认条 → 执行/取消 # MCP:npx @rlwj-lab/opsxdb-mcp 调工具后侧栏应出现 MCP 点 ```