内容
# 开放移动MCP服务器 📱
一个用于移动自动化的开源**模型上下文协议(MCP)**服务器。给任何LLM在真正的Android或iOS设备上赋予视觉和操作能力 — 截图、点击、滑动、读取日志和验证应用程序,无需编写测试代码。
与**Claude Code**、**Claude Desktop**、**Cursor**以及其他任何MCP兼容的客户端一起使用。
## 功能
- **感知**: 截图、语义UI层次结构、OCR、元素查找器、布局健康分析。
- **交互**: 点击、滑动、输入、缩放、旋转、长按、硬件按键操作。
- **日志**: 每个应用程序的Android日志过滤,过滤系统噪音。后台日志监视。
- **环境**: Metro捆绑器管理、应用程序生命周期、深链接、屏幕录制、语言切换。
- **文本输入**: 通过[ADB Keyboard](https://github.com/senzhk/ADBKeyBoard)支持Unicode/西里尔字母/CJK/Emoji,并自动恢复键盘。
## 先决条件
1. **Node.js** (v18+)
2. **ADB** 已安装并在PATH中(适用于Android)。
3. **Maestro** (适用于iOS;适用于Android输入的备用方案)。
- **Mac/Linux**: `curl -Ls "https://get.maestro.mobile.dev" | bash`
- **Windows**:
```powershell
powershell -Command "iwr -useb https://get.maestro.mobile.dev | iex"
```
4. **(可选)ADB Keyboard** — 仅在需要非ASCII输入时需要(Unicode、西里尔字母、Emoji)。
- 从[GitHub](https://github.com/senzhk/ADBKeyBoard)下载并安装:`adb install ADBKeyboard.apk`。
## 配置
### macOS / Linux
```json
{
"mcpServers": {
"open-mobile-mcp": {
"command": "npx",
"args": ["open-mobile-mcp"]
}
}
}
```
### Windows
```json
{
"mcpServers": {
"open-mobile-mcp": {
"command": "npx",
"args": ["open-mobile-mcp"],
"env": {
"MAESTRO_HOME": "C:\\Users\\YOUR_USER\\.maestro",
"PATH": "C:\\Users\\YOUR_USER\\.maestro\\maestro\\bin;C:\\Windows\\system32;C:\\Windows;..."
}
}
}
}
```
> **注意**: 在Windows上,显式设置`MAESTRO_HOME`和`PATH`通常是必需的,以便找到`maestro`。
<details>
<summary>从源代码运行</summary>
```bash
git clone https://github.com/xzaleksey/open-mobile-mcp.git
cd open-mobile-mcp
npm install && npm run build
```
然后在MCP配置中使用`"command": "node", "args": ["/path/to/open-mobile-mcp/build/index.js"]`。
</details>
## 工具
### 感知
| 工具 | 平台 | 描述 |
| :--- | :--- | :--- |
| `device_list` | Android/iOS | 列出连接的模拟器和模拟器 |
| `get_viewport` | Android/iOS | 截图(约800px宽)。 **使用`originalWidth`/`originalHeight`获取点击坐标** — 图片已缩放,点击图片像素将失败。 |
| `get_semantic_hierarchy` | Android/iOS | 作为JSON的修剪UI树 |
| `get_screen_text` | Android/iOS | 通过Tesseract.js进行OCR(默认`eng`) |
| `configure_ocr` | Android/iOS | 设置默认OCR语言(例如`eng+fra`) |
| `find_element` | Android/iOS | 通过`testId`、`text`或`contentDescription`查找元素 |
| `wait_for_element` | Android/iOS | 轮询直到元素出现(默认20s) |
| `get_element_image` | Android/iOS | 特定元素的截图 |
| `capture_diff` | — | 比较两个base64截图,返回差异% |
| `analyze_layout_health` | Android/iOS | 检测深嵌套和布局性能问题 |
### 交互
| 工具 | 平台 | 描述 |
| :--- | :--- | :--- |
| `tap_on_element` | Android/iOS | **推荐** — 通过选择器查找+点击。注意:文本匹配是精确的;表情前缀(例如`🇫🇷 French A2`)会破坏文本匹配 — 首先检查`get_semantic_hierarchy`以获取精确文本。 |
| `device_tap` | Android/iOS | 原始坐标点击。必须使用原始设备像素,而不是截图像素。 |
| `device_swipe` | Android/iOS | 通过坐标滑动 |
| `device_type` | Android/iOS | 输入文本(处理Unicode) |
| `device_pinch` | Android | 两指缩放/放大 |
| `device_rotate_gesture` | Android | 两指旋转 |
| `device_press_key` | Android/iOS | 硬件按键:`back`、`home`、`recents`、`enter`、`delete`、`volume_up`、`volume_down`、`power`、`tab`、`search`、`space`、`menu`、`dpad_*`。还接受原始Android按键代码。 |
### 环境和日志
| 工具 | 平台 | 描述 |
| :--- | :--- | :--- |
| `manage_bundler` | Android/iOS | 启动/停止/重启Metro。传递`deviceId` + `packageId`进行基于PID的Android日志过滤。 |
| `manage_platform_logs` | Android/iOS | 手动控制`adb logcat` / `xcrun`捕获。传递`deviceId` + `packageId`进行每个应用程序的过滤。 |
| `get_bundler_logs` | Android/iOS | 最近的Metro/Android/iOS日志。返回`[status]`行 — 如果缓冲区为空,捕获可能未运行。 |
| `stream_errors` | Android/iOS | 跨所有源的最近错误/异常行 |
| `get_network_logs` | Android/iOS | 网络日志行。对于iOS,过滤内部日志捕获缓冲区(通过`manage_platform_logs`启用)。 |
| `wait_for_log` | Android/iOS | 阻塞直到日志模式匹配。参见下面的子代理模式。 |
| `manage_app_lifecycle` | Android/iOS | 启动、停止、安装或卸载应用程序 |
| `open_deep_link` | Android/iOS | 打开URL或深链接 |
| `clear_app_data` | Android/iOS | 重置应用程序到全新安装状态 |
| `get_app_info` | Android | 版本、权限、安装日期 |
| `start_recording` / `stop_recording` | Android/iOS | 屏幕录制到`.mp4`(Android使用`screenrecord`,iOS使用`simctl io`)。 |
| `run_maestro_flow` | Android/iOS | 运行Maestro YAML流程 |
| `run_doctor` | — | 运行`npx expo-doctor` |
| `install_deps` | — | 运行`npx expo install <packages>` |
### wait_for_log — 后台子代理模式
`wait_for_log`阻塞直到日志缓冲区中出现模式。直接在主代理中调用它会冻结对话。始终在Claude Code中将其委托给后台子代理:
```typescript
// 步骤1 — 在触发日志的操作之前启动监视器
// (在Claude Code中,使用带有run_in_background: true的Agent工具)
// 子代理提示:“调用wait_for_log,模式为'route: /home',超时为60000。报告结果。”
// 步骤2 — 在主代理中执行操作
tap_on_element({ selector: "Home", strategy: "text" });
// 步骤3 — 主代理继续自由;当子代理完成时收到通知
```
## 许可证
MIT