Skip to main content
Glama
liam798
by liam798
README.md
# testclaw-mcp

给 TestClaw 提供远程 HTTP MCP 工具层。

当前仓库的 AI 主架构已经调整为 `API + CLI + SKILL`。`testclaw-mcp` 继续保留,但定位改为:

- 面向外部 MCP 客户端的兼容层
- 远程 HTTP MCP 暴露层
- 无法直接运行 `testclaw-cli` 时的替代接入方式

如果当前运行环境可直接安装并执行 `testclaw-cli`,业务主路径应优先走 `testclaw-cli`,而不是继续把 `testclaw-mcp` 当作唯一执行面。

OAuth 登录主路径已经收敛到 `sonic-server`。`testclaw-mcp` 仅保留自身兼容 OAuth/HTTP 接入能力,用于已有 MCP 客户端接入;业务主路径仍优先走 `testclaw-cli`。

## 能力

- OAuth 登录 Sonic MCP
- 无鉴权 `GET /healthz`
- 获取当前用户
- 查询项目 / 模块 / 用例 / 元素 / 步骤 / 安装包 / Agent / 设备 / 测试结果 / 测试套件
- 创建模块 / 测试用例 / 步骤 / 测试套件
- 连接 Agent websocket 查询已安装应用
- 远程安装 / 打开 / 关闭 / 卸载应用
- 运行 / 停止测试套件
- 通用 Sonic API 请求

## 默认目标

默认会连到:

- `SONIC_BASE_URL=http://192.168.31.121:3001`
- `SONIC_API_PREFIX=/api/controller`

也可以通过环境变量覆盖。

## 环境变量

- `SONIC_BASE_URL`:Sonic 站点地址,例如 `http://192.168.31.121:3001`
- `SONIC_API_PREFIX`:API 前缀,默认 `/api/controller`
- `SONIC_MCP_HOST`:MCP 对外可访问的主机名或 IP,默认 `127.0.0.1`
- `SONIC_MCP_PORT`:HTTP MCP 监听端口,默认 `39040`
- `SONIC_MCP_DATA_DIR`:SQLite 数据目录,默认 `./.data`
- `MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL`:允许 `http://` issuer,仅测试/内网使用

## 安装依赖

```bash
cd testclaw-mcp
npm install
```

要求 Node `>=22.5.0`。

## 本地运行

```bash
SONIC_BASE_URL=http://192.168.31.121:3001 \
SONIC_MCP_HOST=127.0.0.1 \
SONIC_MCP_PORT=39040 \
MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL=true \
node index.js
```

注意:

- OAuth 地址会直接由 `SONIC_MCP_HOST` 和 `SONIC_MCP_PORT` 推导
- 服务端本地监听固定绑定 `0.0.0.0`
- `SONIC_MCP_HOST` 必须填写客户端可访问的真实地址,例如 `127.0.0.1` 或 `192.168.31.121`
- 若要使用 `http://`,必须显式开启 `MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL=true`
- 部署端不再需要写死 `SONIC_USERNAME` / `SONIC_PASSWORD`

服务器部署示例:

```bash
SONIC_BASE_URL=http://127.0.0.1:3001 \
SONIC_MCP_HOST=192.168.31.121 \
SONIC_MCP_PORT=39040 \
MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL=true \
node index.js
```

## 在 MCP 客户端中接入

当前版本只提供 HTTP `/mcp` 接入,不再支持 `stdio`。

示例(Codex):

```toml
[mcp_servers.sonic]
url = "http://127.0.0.1:39040/mcp"
```

首次登录:

```bash
codex mcp login sonic
```

如果你把 `testclaw-mcp` 部署到服务器上,再把地址改成服务器 URL,例如:

```toml
[mcp_servers.sonic]
url = "http://192.168.31.121:39040/mcp"
```

通用 MCP 客户端示例:

```json
{
  "mcpServers": {
    "sonic": {
      "url": "http://127.0.0.1:39040/mcp"
    }
  }
}
```

## 登录方式

当前版本的登录方式是:

1. Codex 连接 `/mcp`
2. 用户执行 `codex mcp login sonic`
3. 浏览器打开 `testclaw-mcp` 的 `/authorize`
4. 用户输入 Sonic 用户名密码
5. `testclaw-mcp` 向 Sonic 换取 `SonicToken`
6. 后续 MCP 工具调用自动附带当前登录用户对应的 `SonicToken`

部署端不保存 Sonic 明文账号密码。

## 第一版工具

- `sonic_login`
- `sonic_get_current_user`
- `sonic_list_projects`
- `sonic_list_modules`
- `sonic_get_module`
- `sonic_create_module`
- `sonic_list_test_cases`
- `sonic_get_test_case`
- `sonic_create_test_case`
- `sonic_list_elements`
- `sonic_get_element`
- `sonic_list_steps`
- `sonic_get_step`
- `sonic_create_step`
- `sonic_list_packages`
- `sonic_create_package`
- `sonic_upload_package`
- `sonic_list_agents`
- `sonic_list_installed_apps`
- `sonic_get_agent`
- `sonic_list_devices`
- `sonic_get_device`
- `sonic_prepare_android_debug`
- `sonic_release_device`
- `sonic_install_package`
- `sonic_open_app`
- `sonic_kill_app`
- `sonic_uninstall_app`
- `sonic_list_results`
- `sonic_get_result`
- `sonic_list_suites`
- `sonic_get_suite`
- `sonic_create_suite`
- `sonic_run_suite`
- `sonic_force_stop_suite`
- `sonic_api_request`

## AI Agent 全自动流程

当前 `testclaw-mcp` 已经可以覆盖一条完整的 AI Agent 自动化链路:

1. `sonic_list_projects`
2. `sonic_list_modules` / `sonic_create_module`
3. `sonic_list_test_cases` / `sonic_create_test_case`
4. `sonic_list_elements` / `sonic_create_step`
5. `sonic_create_suite`
6. `sonic_prepare_android_debug`
7. `sonic_install_package` / `sonic_open_app` / `sonic_kill_app` / `sonic_uninstall_app`
8. `sonic_run_suite`
9. `sonic_get_result` / `sonic_force_stop_suite`
10. `sonic_release_device`

也就是说,AI Agent 现在可以:

- 自动创建测试模块、测试用例、步骤和测试套件
- 自动占用 Android 设备并获取 `adb` / `uiautomator2` 调试地址
- 自动在本地 `adb` 模式下安装应用、启动应用、停止应用、卸载应用
- 自动触发 Sonic 测试套件执行并轮询结果
- 在流程结束后自动释放设备

推荐编排顺序:

1. 先通过 `sonic_prepare_android_debug` 绑定设备
2. 再通过 `sonic_create_*` 系列工具生成测试资产
3. 如需直接做设备前置动作,优先走默认 `executionMode=local`
4. 再调用 `sonic_run_suite`
5. 最后无论成功失败都执行 `sonic_release_device`

当前默认设计适合:

- `Codex/Claude Desktop/Cursor -> testclaw-mcp -> Sonic Server`
- 如果 `testclaw-mcp` 跑在 AI Agent 本机,则设备应用操作默认走本机 `adb`

## 健康检查

可直接用无鉴权接口做部署探活:

```bash
curl http://127.0.0.1:39040/healthz
```

返回会包含:

- `status`
- `version`
- `time`
- `checks.sqlite`
- `checks.sonic`

## 设备选择

以下设备操作工具现在都支持 3 种设备选择方式:

- `deviceId`
- `udId`
- `adbAddress`

适用工具:

- `sonic_prepare_android_debug`
- `sonic_release_device`
- `sonic_list_installed_apps`
- `sonic_install_package`
- `sonic_open_app`
- `sonic_kill_app`
- `sonic_uninstall_app`

其中 `adbAddress` 支持直接传页面上展示的字符串,例如:

```text
adb connect 192.168.31.52:52892
```

当前解析规则是:

- 先按 `adbAddress` 的 host 找到对应 Agent
- 再查找该 Agent 下当前登录用户唯一一台 `DEBUGGING` 状态的 Android 设备
- 若匹配到多台或 0 台,会直接报错,要求改传 `deviceId` 或 `udId`

## 设备执行模式

设备相关工具现在支持两种执行模式:

- 默认 `executionMode=local`
- 可选 `executionMode=server`

默认 `local` 的含义是:

- `testclaw-mcp` 仍然通过 Sonic Server 占用设备并获取调试端口
- 但真正的 `adb` 操作在 **运行 `testclaw-mcp` 的这台机器本地执行**
- 因此如果你希望 `Codex -> 本机 adb -> Sonic 设备调试端口`,就应该把 `testclaw-mcp` 跑在 Codex 本机

兼容模式 `server` 的含义是:

- 继续沿用旧逻辑
- 由 `testclaw-mcp` 通过 Agent WebSocket 在服务端侧执行应用安装、启动、停止、卸载与应用列表查询

支持 `executionMode` 的工具:

- `sonic_list_installed_apps`
- `sonic_install_package`
- `sonic_open_app`
- `sonic_kill_app`
- `sonic_uninstall_app`

`sonic_prepare_android_debug` 的默认行为:

- 支持 `deviceId` 或 `udId`
- 默认给 Android 设备分配一组确定性的调试端口:
  - `sasRemotePort = 45000 + (deviceId % 1000) * 2`
  - `uia2RemotePort = sasRemotePort + 1`
- 返回结果里会额外带上:
  - `resolvedDevice`
  - `adbAddress`
  - `localCommands.connectAdb`
  - `localCommands.uia2ServerUrl`

## 本地运行示例

如果你要让 Codex 本地直连设备,请在 Codex 本机运行 `testclaw-mcp`:

```bash
SONIC_BASE_URL=http://192.168.31.121:3001 \
SONIC_MCP_HOST=127.0.0.1 \
SONIC_MCP_PORT=39040 \
SONIC_MCP_ADB_BIN=adb \
node index.js
```

可选环境变量:

- `SONIC_MCP_ADB_BIN`
  - 指定本地 `adb` 可执行文件路径,默认 `adb`
- `SONIC_MCP_ADB_ENV_JSON`
  - 以 JSON 形式附加本地执行 `adb` 时需要的环境变量

## 安全说明

- 推荐生产环境给 `SONIC_MCP_HOST` 配置可访问的 `HTTPS` 域名
- `HTTP` 模式属于显式不安全模式,仅建议内网或测试环境使用
- SQLite 会保存 OAuth client、授权码、access token / refresh token 以及 Sonic session token
- 不会长期保存 Sonic 明文密码

## 说明

返回结果尽量保留 Sonic 原始响应结构(`code` / `message` / `data`),方便后续扩展。后面如果你要,我可以继续补:

- 测试用例 tools
- 模块 / 公共步骤 tools
- 设备占用 / 释放 tools
- 更细的资源级权限控制