# Proxyman MCP：抓包 / 直调 / Mock（阶段 2、5、6 的调试利器）

Proxyman 桌面端 + `mcp__proxyman__*` 工具（会话内直接可用，缺 schema 时用 ToolSearch
`select:mcp__proxyman__get_flows,...` 加载）。**2026-07-31 已在出港查询页全链路实测**：
抓包核对请求体、Map Local mock 三种卡片形态（含真实数据不存在的「未入库」兜底态）一次跑通。

## 与 api-doc 的分工（先契约后事实）

| | api-doc MCP | Proxyman MCP |
|---|---|---|
| 回答什么 | **契约**：接口该有什么入参/出参、参数名叫什么 | **事实**：App 实际发了什么、后端实际回了什么 |
| 用在何时 | 阶段 2 开工前逐接口核对 | 阶段 5/6 实机验证与 corner case 补测 |

标准配合流程：
api-doc 拿权威参数名 → 前端实现 → Proxyman flow 核对请求体确实带上了 →
compose 改参 A/B 验证后端认不认 → 不认 → 记问题清单（附 `export_flow_curl` 证据）→
map local 造 mock 补 UI corner case 验证。

## 接入（一次性，实测步骤）

```bash
# 1) 确认 Proxyman 在跑（返回 Recording: Active + 端口，默认 9090）
#    mcp__proxyman__get_proxy_status
# 2) 模拟器全局代理指向宿主机（模拟器视角宿主机 = 10.0.2.2）
adb -s <serial> shell settings put global http_proxy 10.0.2.2:9090
# 3) 验证完【必须】清掉，否则 Proxyman 一关模拟器就断网，下次验证莫名全挂
adb -s <serial> shell settings put global http_proxy :0
```

本项目内网服务是**纯 HTTP**（192.168.1.250:8093）→ 不需要装证书，明文直接可见。
（若未来切 HTTPS，才需要 `install_certificate` + `enable_ssl_proxying`。）

## 场景 1：核对请求/响应（替代 `ui_probe req`）

logcat 抓 OkHttp 多行 pretty JSON 脆弱且要人肉拼接；Proxyman 一步到位：

- `filter_flows`（key=url, value="IntExpSearch"）→ 拿 flow ID 列表
- `get_flow_detail`（flow_id）→ 完整请求体 + 响应体 + headers（Authorization 自动脱敏）

**出参无文档定义时（如 `IntExpSearch/detail` 返回裸 Map），用真实 flow 的 responseBody
直接盘点字段清单**——判定「锁定状态/计费重量是否存在」这类问题的最快路径。

## 场景 2：直调后端 A/B 验证（替代 run-as 提 token + 手写 curl）

`create_compose_http_from_flow`（从真实 flow 复制请求，**token 自动带上，不用碰
shared_prefs**）→ `update_compose_http` 改一个参数 → `send_compose_http` 看结果对比。
isFclose 这类「参数是否生效」的 A/B 实验用这条链。给后端提缺口时用
`export_flow_curl` 导出可复现的 curl 附进问题清单。

## 场景 3：Map Local 造 mock 验证 corner case（替代代码注入样例 Bean）

老流程「Activity 临时注入 Bean → 截图 → 删码 → 重构建」彻底淘汰：**零代码改动、零重构建**。

- `create_map_local`：url 精确到接口路径，method=POST，response_body 直接写目标 JSON
  （构造空字段/超长文本/罕见状态，比如出港查询的 fclose+opDate 双空「未入库」兜底态）
- 改真实响应个别字段更省事时用 `create_map_local_from_flow`
- 验证完 `delete_rule`（rule_type=maplocal）+ 清代理，**规则残留会污染后续真实数据验证**

响应结构照抄真实 flow 的顶层结构（如 pageQuery 是裸 PageInfo：`{total, list, pages, ...}`，
不要包 `{status, data}`）。

⚠️ 实测坑（2026-07-31 出港仓库）：mock `BaseResultBean` 包装的接口（pageQueryTotal/detail 等）时，
**`status` 必须写 `"1"`**——`BaseResultBean.verifySuccess()` 判 `status == "1"`，写 "200" 会被当失败
静默丢弃（UI 保持默认值，无任何报错，排查靠 flow 已命中但 UI 不变这一矛盾现象）。

⚠️ 实测坑：mock 响应到达后 UI 渲染可能滞后（冷启动首帧 Davey 卡顿 2s+），
**截图断言前先 `ui_probe texts` 确认数据已上屏**——这次就因截图太早误判过一轮「mock 没生效」，
其实 `get_flow_detail` 里 `matchedTools: ["Map Local"]` 早已证明规则命中，UI 只是还没画完。

## 场景 4：环境模拟（按需）

- `create_network_condition`：弱网/高延迟，验证 loading 弹窗与超时提示
- `create_breakpoint`：单次拦截改包（比 map local 更临时的一次性实验）
- `create_map_remote`：把请求转发到另一环境（如后端修复验证用的测试实例）

## 验证收尾清单

- [ ] `list_rules` 确认无本次遗留规则（maplocal/breakpoint/network_condition）
- [ ] 模拟器代理已清（`settings get global http_proxy` 应为 `:0` 或空）
- [ ] 用真实数据再过一遍被 mock 过的页面，确认无假数据残影
