vault backup: 2026-04-06 16:23:54
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
---
|
||||
created: 2026-03-29
|
||||
updated: 2026-04-06
|
||||
type: project
|
||||
status: 未开始
|
||||
status: COMPLETED (2026-03-30)
|
||||
parent: "[[Smart Support]]"
|
||||
phase: 3
|
||||
timeline: 第 4-6 周
|
||||
@@ -19,177 +20,59 @@ tags:
|
||||
|
||||
# Phase 3:OpenAPI 自动发现
|
||||
|
||||
> Status: COMPLETED (2026-03-30)
|
||||
|
||||
## 目标
|
||||
|
||||
实现 Smart Support 的「10x 差异化功能」:用户粘贴 OpenAPI 规范 URL,系统自动生成 MCP 服务器和 Agent 配置。这个阶段结束时,用户无需写代码,只需提供 API 文档就能让 AI Agent 操作他们的系统。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- [[Smart Support/Phase 2 - 多 Agent + 安全]] 完成
|
||||
- 多 Agent 路由 + interrupt 流程工作正常
|
||||
- YAML agent 注册表可以动态加载新 agent
|
||||
实现 Smart Support 的「10x 差异化功能」:用户粘贴 OpenAPI 规范 URL,系统自动生成 @tool 函数和 Agent 配置。
|
||||
|
||||
## 阶段产出
|
||||
|
||||
- 粘贴 OpenAPI spec URL → 自动解析 + 生成 MCP 服务器 + 注册 Agent
|
||||
- LLM 自动分类端点(读/写、客户参数、Agent 分组)
|
||||
- 运维审核界面确认/修正 LLM 分类结果
|
||||
- SSRF 防护保障 URL 获取安全
|
||||
- 导入过程异步执行,WebSocket 实时推送进度
|
||||
- SSRF 防护模块:私有 IP 拦截、DNS 重绑定防御、重定向链验证
|
||||
- OpenAPI 获取器:SSRF 安全、JSON/YAML 自动检测、10MB 大小限制
|
||||
- 结构化 OpenAPI 验证器:3.0.x 和 3.1.x
|
||||
- 端点解析器:$ref 解析、参数提取、自动生成 operationId
|
||||
- 启发式 + LLM 端点分类器:GET=read, POST/PUT/PATCH/DELETE=write,LLM 失败回退启发式
|
||||
- 审核 API(/api/openapi):导入任务、分类审核、批准生成
|
||||
- @tool 代码生成器:async 函数 + httpx
|
||||
- Agent YAML 生成器:按分类分组端点
|
||||
- 导入编排器:fetch -> validate -> parse -> classify 全流程
|
||||
- 内存任务存储:导入状态追踪
|
||||
|
||||
## 集成检查点
|
||||
## 新增文件
|
||||
|
||||
第 6 周末验证:
|
||||
1. 粘贴一个真实的 OpenAPI 3.0 spec URL → 解析成功
|
||||
2. 生成的 MCP 服务器正确包装每个端点
|
||||
3. LLM 分类结果合理(GET = read,DELETE = write)
|
||||
4. 运维审核后,agent 自动注册到 supervisor
|
||||
5. 在聊天中使用新生成的工具完成操作
|
||||
6. SSRF 攻击被拦截(私有 IP、localhost)
|
||||
| 文件 | 用途 | 行数 |
|
||||
|------|------|------|
|
||||
| `app/openapi/models.py` | 冻结数据类:EndpointInfo, ClassificationResult, ImportJob | 68 |
|
||||
| `app/openapi/ssrf.py` | SSRF 防护(validate_url, safe_fetch, DNS 解析) | 162 |
|
||||
| `app/openapi/fetcher.py` | SSRF 安全规范获取 | 94 |
|
||||
| `app/openapi/validator.py` | 结构化规范验证 | 52 |
|
||||
| `app/openapi/parser.py` | 端点提取 + $ref 解析 | 153 |
|
||||
| `app/openapi/classifier.py` | 启发式 + LLM 分类器 | 164 |
|
||||
| `app/openapi/review_api.py` | 导入/审核 API 路由 | 180 |
|
||||
| `app/openapi/generator.py` | @tool 代码 + YAML 生成 | 157 |
|
||||
| `app/openapi/importer.py` | 异步导入流水线 | 117 |
|
||||
|
||||
---
|
||||
## 测试覆盖
|
||||
|
||||
## 任务清单
|
||||
- 新增测试:125 个(118 单元 + 7 集成)
|
||||
- 总测试:322
|
||||
- 覆盖率:93.23%
|
||||
- SSRF 测试最多:42 个
|
||||
|
||||
### 1. SSRF 防护模块
|
||||
## 与计划的偏差
|
||||
|
||||
> 独立模块 `backend/app/openapi/ssrf.py`,可与 Phase 1-2 并行开发
|
||||
- 未构建自定义工具基类(架构文档明确禁止)
|
||||
- 使用轻量级结构化验证器而非包装外部库
|
||||
- 内存任务存储而非数据库(可后续迁移 PostgreSQL)
|
||||
- 前端审核 UI 推迟到 Phase 5
|
||||
|
||||
- [ ] URL 解析:提取 host,解析 DNS 获取 IP
|
||||
- [ ] 屏蔽私有 IP 范围:
|
||||
- `10.0.0.0/8`
|
||||
- `172.16.0.0/12`
|
||||
- `192.168.0.0/16`
|
||||
- `127.0.0.0/8`(localhost)
|
||||
- `169.254.0.0/16`(link-local,云元数据端点)
|
||||
- `0.0.0.0/8`
|
||||
- `::1`(IPv6 localhost)
|
||||
- [ ] DNS 重绑定防护:解析 DNS → 检查 IP → 使用解析后的 IP 发起请求(不让 DNS 在检查和请求之间变化)
|
||||
- [ ] URL 协议限制:仅允许 `http://` 和 `https://`,拒绝 `file://`, `ftp://`, `gopher://` 等
|
||||
- [ ] 可选 URL 白名单:通过配置限制只允许特定域名
|
||||
- [ ] 单元测试覆盖所有拦截场景
|
||||
## 技术债务
|
||||
|
||||
### 2. OpenAPI 规范解析器
|
||||
|
||||
- [ ] 支持 OpenAPI 3.0+ 规范(JSON 和 YAML 格式)
|
||||
- [ ] 使用 `openapi-spec-validator` 验证规范合法性
|
||||
- [ ] 通过 SSRF 安全模块获取远程 URL 内容
|
||||
- [ ] 解析每个端点提取:
|
||||
- HTTP 方法 + 路径
|
||||
- 描述 / summary
|
||||
- 请求参数(path params, query params, request body schema)
|
||||
- 响应 schema
|
||||
- 认证要求(API key, Bearer token, OAuth)
|
||||
- [ ] 错误处理:
|
||||
- 无效 URL → 「无法访问该地址,请检查 URL 是否正确」
|
||||
- 无效规范格式 → 「该文件不是有效的 OpenAPI 3.0 规范:[具体原因]」
|
||||
- 认证要求无法自动满足 → 提示用户提供 API key
|
||||
- [ ] OpenAPI 2.0 (Swagger) → 返回明确提示:「检测到 Swagger 2.0 格式,请升级到 OpenAPI 3.0」
|
||||
- [ ] 大型规范(100+ 端点)→ 正常处理,不超时
|
||||
|
||||
### 3. MCP 服务器生成器
|
||||
|
||||
- [ ] 为每个解析到的端点生成 MCP tool 定义
|
||||
- [ ] Tool 名称:从路径 + 方法自动生成(如 `GET /orders/{id}` → `get_order_by_id`)
|
||||
- [ ] Tool 描述:使用端点的 summary/description
|
||||
- [ ] Tool 参数:从 path params + query params + request body 提取,保留类型信息
|
||||
- [ ] 生成可运行的 MCP 服务器代码(Python,使用 `mcp` SDK)
|
||||
- [ ] 处理复杂 request body(嵌套对象、数组)→ 扁平化或保留 JSON 结构
|
||||
- [ ] 认证注入:生成的服务器支持在配置中设置 API key / Bearer token,自动添加到请求 header
|
||||
|
||||
### 4. LLM 辅助端点分类
|
||||
|
||||
- [ ] 将解析后的端点信息(方法、路径、描述)发送给 LLM
|
||||
- [ ] LLM 分类任务:
|
||||
1. **读/写分类**:每个端点标记为 `read`(不触发 interrupt)或 `write`(触发 interrupt)
|
||||
2. **客户参数识别**:哪些参数代表客户标识(customer_id, email, phone)
|
||||
3. **Agent 分组建议**:将端点按功能分组为不同 Agent(如「订单管理」「用户管理」「支付操作」)
|
||||
- [ ] 分类提示模板:
|
||||
|
||||
```
|
||||
你是一个 API 安全分析师。分析以下 API 端点列表,为每个端点提供:
|
||||
1. 操作类型:read(查询/获取数据)或 write(创建/修改/删除数据)
|
||||
2. 客户参数:哪些参数代表客户身份标识
|
||||
3. 建议的 Agent 分组名称
|
||||
|
||||
规则:
|
||||
- GET 请求通常是 read,但要看描述(如 GET /export 可能是 write)
|
||||
- POST/PUT/PATCH/DELETE 通常是 write
|
||||
- 涉及金钱、订单状态变更、账号操作的必须标记为 write
|
||||
```
|
||||
|
||||
- [ ] 分类结果缓存:同一规范不重复分类
|
||||
- [ ] 成本控制:使用 prompt caching 减少重复输入成本
|
||||
|
||||
### 5. 运维审核/修正 UI
|
||||
|
||||
- [ ] API 端点:`GET /api/openapi/review/{import_id}` → 返回 LLM 分类结果
|
||||
- [ ] API 端点:`POST /api/openapi/review/{import_id}` → 提交修正后的分类
|
||||
- [ ] 前端审核界面:
|
||||
- 端点列表,每行显示:方法、路径、描述、LLM 分类(read/write)、Agent 分组
|
||||
- 每个分类可以点击修改(下拉选择)
|
||||
- 「全部确认」按钮 → 生成最终 MCP 服务器 + Agent YAML
|
||||
- [ ] 修正后重新生成不需要再次调用 LLM
|
||||
|
||||
### 6. Agent YAML 自动生成
|
||||
|
||||
- [ ] 根据 LLM 分类 + 运维修正结果,生成 Agent YAML 配置
|
||||
- [ ] 每个 Agent 分组 → 一个 agent 条目
|
||||
- [ ] permission 根据分组内端点的最高权限决定(有一个 write 端点就标记为 write)
|
||||
- [ ] 自动生成 agent description(基于分组内端点的描述汇总)
|
||||
- [ ] 生成的 YAML 合并到 agent 注册表,热加载到 supervisor(不需要重启)
|
||||
|
||||
### 7. 异步导入 + 进度更新
|
||||
|
||||
- [ ] 导入流程作为后台任务执行(`asyncio.create_task`)
|
||||
- [ ] 通过 WebSocket 推送进度更新:
|
||||
|
||||
```json
|
||||
{"type": "import_progress", "step": "parsing", "message": "正在解析 OpenAPI 规范..."}
|
||||
{"type": "import_progress", "step": "classifying", "message": "正在分析端点 12/50..."}
|
||||
{"type": "import_progress", "step": "generating", "message": "正在生成 MCP 服务器..."}
|
||||
{"type": "import_progress", "step": "review", "message": "分析完成,请审核分类结果", "review_url": "/review/abc123"}
|
||||
{"type": "import_progress", "step": "done", "message": "导入完成!新增 3 个 Agent,15 个工具"}
|
||||
```
|
||||
|
||||
- [ ] 导入期间聊天功能不受影响
|
||||
- [ ] 导入失败 → 推送错误消息 + 错误详情
|
||||
|
||||
### 8. 测试
|
||||
|
||||
- [ ] **SSRF 测试:** 私有 IP (10.x, 172.16.x, 192.168.x) → 拦截
|
||||
- [ ] **SSRF 测试:** localhost / 127.0.0.1 → 拦截
|
||||
- [ ] **SSRF 测试:** 169.254.169.254(云元数据)→ 拦截
|
||||
- [ ] **SSRF 测试:** 合法公网 URL → 放行
|
||||
- [ ] **SSRF 测试:** file:// 协议 → 拦截
|
||||
- [ ] **解析测试:** 有效 OpenAPI 3.0 JSON → 正确解析端点
|
||||
- [ ] **解析测试:** 有效 OpenAPI 3.0 YAML → 正确解析端点
|
||||
- [ ] **解析测试:** 无效规范 → 明确错误信息
|
||||
- [ ] **解析测试:** 大型规范(100+ 端点)→ 不超时
|
||||
- [ ] **生成测试:** 端点 → MCP tool 定义(名称、参数、描述匹配)
|
||||
- [ ] **分类测试:** mock LLM 响应 → 正确解析分类结果
|
||||
- [ ] **分类测试:** GET 端点 → 默认 read,DELETE 端点 → 默认 write
|
||||
- [ ] **集成测试:** 完整流程:URL → 解析 → 分类 → 生成 → 注册
|
||||
- [ ] **E2E 测试:** 粘贴 spec URL → 进度更新 → 审核 → 新工具在聊天中可用
|
||||
|
||||
## 技术要点
|
||||
|
||||
| 功能 | 技术选型 | 说明 |
|
||||
|------|---------|------|
|
||||
| 规范验证 | openapi-spec-validator | PyPI 包,支持 3.0+ |
|
||||
| URL 获取 | httpx + SSRF 模块 | 异步 HTTP,IP 检查 |
|
||||
| MCP 生成 | mcp SDK (Python) | 生成 stdio MCP 服务器 |
|
||||
| LLM 分类 | ChatAnthropic structured output | JSON mode 确保输出格式 |
|
||||
| 异步任务 | asyncio.create_task | FastAPI 内后台任务 |
|
||||
|
||||
## 风险与缓解
|
||||
|
||||
| 风险 | 影响 | 缓解措施 |
|
||||
|------|------|---------|
|
||||
| LLM 分类不准确 | 读操作被标记为写(多余确认)或反之(危险) | 运维审核 UI 作为安全网,默认偏向标记为 write |
|
||||
| 复杂 request body 无法处理 | 部分端点工具不可用 | 跳过无法处理的端点,在审核 UI 中标注 |
|
||||
| DNS 重绑定绕过 SSRF | 安全漏洞 | 解析后绑定 IP 发请求,不二次解析 |
|
||||
| 大规范生成慢 | 用户等待久 | 异步 + 进度条,分批生成 |
|
||||
- 前端 ReviewPage 推迟(API 就绪)
|
||||
- 代码生成基于字符串模板
|
||||
- LLM 分类提示可用真实案例调优
|
||||
- 审核 API 无速率限制
|
||||
|
||||
## Related
|
||||
|
||||
|
||||
Reference in New Issue
Block a user