1. 移动端自动化的痛点与 mobile-mcp 的破局思路
做过移动端自动化的人都有一个共同的感受:环境搭建比写用例还累。Appium 要装 Node、配 JDK、下 Android SDK、搞 WebDriverAgent 签名,一套流程走下来半天没了,换台机器还得重来。更别提 iOS 真机调试时那些证书和开发者模式的坑,每一步都能卡住人。而 mobile-mcp 这个项目,本质上就是冲着这些痛点来的——它把移动端设备的能力封装成 MCP 协议的标准工具接口,让 AI 助手或者自动化脚本可以直接调用,不用再关心底层是 Appium 还是 WebDriverAgent 在干活。
MCP 全称 Model Context Protocol,是一种让 AI 模型与外部工具、数据源进行标准化交互的协议。你可以把它理解成“AI 世界的 USB 接口”——不管背后接的是数据库、浏览器还是手机,只要遵循这套协议,AI 就能统一调用。mobile-mcp 做的事情,就是给 iOS 和 Android 设备做了一个 MCP Server,把点击、滑动、输入、截图、获取页面结构这些移动端操作暴露成标准工具。这样一来,任何支持 MCP 的客户端(比如各种 AI 编程助手、自动化平台)都能直接操控手机,而不需要为每个平台单独写适配层。
这个项目适合谁?如果你是自动化测试工程师,正在被 Appium 的环境问题折磨,mobile-mcp 提供了一条更轻的路;如果你是 AI 应用开发者,想让自己的 Agent 具备操控手机的能力,mobile-mcp 就是现成的桥梁;如果你只是对移动端自动化感兴趣,想快速跑通一个 Demo 感受一下,它的上手门槛也比传统方案低不少。核心关键词就三个:MCP 协议、iOS/Android 自动化、设备控制。接下来我会从设计思路、核心实现、实操流程到踩坑经验,把这块内容完整拆一遍。
2. 核心架构拆解:mobile-mcp 到底怎么把手机变成 AI 工具
2.1 为什么选 MCP 而不是直接写 Appium 脚本
传统移动端自动化方案通常是这样的:你写 Python 脚本,调 Appium 客户端库,Appium Server 再通过 WebDriverAgent(iOS)或 UiAutomator(Android)去操控设备。这条链路很长,每一层都可能出问题。而且脚本是“死”的——你写死了点哪个坐标、找哪个元素,页面一变就得改。
mobile-mcp 的思路不一样。它把设备操作抽象成一组原子化的工具,比如mobile_click、mobile_swipe、mobile_type、mobile_screenshot、mobile_get_page_source。这些工具通过 MCP 协议暴露出去,AI 模型可以根据当前屏幕内容动态决定下一步做什么。这就从“预设脚本”变成了“实时决策”,灵活性完全不是一个量级。
选 MCP 还有一个现实考量:生态兼容性。现在越来越多的 AI 工具开始支持 MCP,比如各种 IDE 插件、桌面助手、自动化平台。mobile-mcp 只要实现一次 MCP Server,就能被所有这些客户端复用。反过来,如果每个客户端都自己写一套移动端控制逻辑,那就是重复造轮子。MCP 在这里扮演的是“标准化中间层”的角色,把设备控制的复杂度收敛到一个地方。
2.2 整体架构分层与数据流
mobile-mcp 的架构可以分成四层来理解。最底层是设备通信层,iOS 走的是 WebDriverAgent 的 HTTP 接口,Android 走的是 ADB 和 UiAutomator 的桥接。这一层负责跟真机或模拟器建立连接,发送底层指令。
往上是操作抽象层,把“点击屏幕某个位置”这种动作封装成统一的函数签名,抹平 iOS 和 Android 的差异。比如 iOS 的点击需要传坐标,Android 的点击可以通过 ADB shell input tap 实现,这一层会把它们统一成click(x, y)这样的接口。
再往上是MCP 协议层,负责把操作抽象层的能力注册成 MCP 工具,处理请求解析、参数校验、结果序列化。这一层是整个项目的核心,决定了外部客户端怎么调用、能调用什么。
最上面是客户端层,也就是各种支持 MCP 的 AI 助手或自动化平台。它们通过标准输入输出或者网络连接跟 mobile-mcp 通信,发送工具调用请求,接收执行结果。
数据流是这样的:客户端发送一个 MCP 请求,比如“点击坐标 (100, 200)”,协议层解析后调用操作抽象层的 click 方法,抽象层根据当前设备类型分发到对应的设备通信层,通信层通过 WebDriverAgent 或 ADB 执行实际操作,然后把结果逐层返回。整个过程对客户端来说是透明的,它不需要知道背后是 iOS 还是 Android。
2.3 支持的核心能力清单
mobile-mcp 目前覆盖的能力基本能满足日常自动化和测试需求。设备管理方面,支持列出已连接设备、获取设备信息、启动和关闭应用。交互操作方面,支持点击、长按、滑动、输入文本、按键事件(返回、Home、音量等)。信息获取方面,支持截图、获取页面 XML 结构、获取当前 Activity 或 Bundle ID。还有一些辅助能力,比如等待元素出现、滚动到指定位置、处理弹窗等。
这些能力看起来简单,但组合起来就能完成很复杂的任务。比如“打开某 App,搜索关键词,截图结果,返回首页”这一串操作,在 MCP 客户端里就是几次工具调用的编排。AI 模型可以根据截图内容判断当前页面状态,决定下一步是点击还是滑动,这就实现了动态的自动化流程。
注意:mobile-mcp 的能力边界取决于底层 WebDriverAgent 和 ADB 的支持范围。有些系统级操作(比如修改系统设置、模拟指纹)可能不在覆盖范围内,具体要看项目的最新文档。
3. 环境搭建实操:从零把 mobile-mcp 跑起来
3.1 前置依赖与版本选择
在动手之前,先把依赖理清楚。Node.js 是必须的,建议用 18 LTS 或 20 LTS,太新的版本有时候会有兼容性问题。Python 环境主要用于某些辅助脚本,不是核心依赖,但建议装一个 3.10 以上的版本备用。
Android 这边,需要装 Android SDK Platform Tools,确保adb命令在终端里能直接用。如果要连真机,需要在手机开发者选项里打开 USB 调试,插上电脑后用adb devices确认设备能被识别。模拟器的话,Android Studio 自带的 AVD 就可以,启动后同样用adb devices验证。
iOS 这边麻烦一些。你需要一台 Mac(这是硬性要求),装好 Xcode 和 Command Line Tools。真机调试需要配置开发者证书,并且在 iPhone 的设置里开启开发者模式(设置 → 隐私与安全性 → 开发者模式)。WebDriverAgent 需要签名后才能跑在真机上,这一步是 iOS 自动化最容易卡住的地方。
| 依赖项 | 版本建议 | 用途说明 |
|---|---|---|
| Node.js | 18 LTS / 20 LTS | 运行 mobile-mcp 服务 |
| Android SDK Platform Tools | 最新版 | adb 设备通信 |
| Xcode | 15+ | iOS 设备通信与 WDA 编译 |
| Python | 3.10+ | 辅助脚本(可选) |
| Appium | 2.x(可选) | 部分场景下的备选方案 |
3.2 安装 mobile-mcp 与初始化配置
安装方式通常有两种:通过 npm 全局安装,或者从源码克隆后本地构建。推荐先用 npm 安装,省事。命令大概是npm install -g mobile-mcp这样的形式,具体包名以项目实际发布为准。安装完成后,运行mobile-mcp --help看看命令是否可用。
初始化配置主要涉及设备连接方式。Android 默认走 adb,一般不需要额外配置,只要adb devices能看到设备就行。iOS 需要指定 WebDriverAgent 的地址和端口,通常是http://localhost:8100,因为 WDA 默认跑在这个端口。如果 WDA 跑在别的机器上,需要改成对应的 IP。
配置文件一般是一个 JSON 或 YAML 文件,放在项目目录或者用户主目录下。里面可以配默认设备、超时时间、截图保存路径等。超时时间建议设长一点,比如 30 秒,因为移动端操作有时候响应比较慢,设太短容易误报失败。
提示:第一次跑 iOS 的时候,建议先用 Xcode 手动把 WebDriverAgent 跑起来,确认能在手机上正常执行测试,然后再让 mobile-mcp 去连。这样出问题的时候好定位是 WDA 的问题还是 mobile-mcp 的问题。
3.3 连接真机与模拟器的差异处理
Android 真机和模拟器在 mobile-mcp 看来差别不大,都是通过 adb 通信。但真机有时候会有权限弹窗,比如“允许 USB 调试吗”,需要手动点一下。模拟器一般没这个问题。另外,模拟器的性能取决于电脑配置,跑复杂操作可能会卡,真机通常更流畅。
iOS 真机和模拟器的差异就大了。模拟器不需要签名,WDA 可以直接跑;真机必须签名,而且证书过期后需要重新签。模拟器的触摸事件和真机也有细微差别,有些在模拟器上能跑的用例,到真机上可能因为渲染时序问题失败。所以如果目标是真机自动化,尽量早点在真机上测,别等到最后才发现问题。
还有一个坑是 iOS 版本兼容性。不同 iOS 版本对 WDA 的支持不一样,新版本 iOS 刚出来的时候,WDA 往往需要更新才能适配。如果你用的是最新版 iOS,建议先确认 mobile-mcp 和 WDA 是否已经支持,否则可能连不上。
4. 核心操作实战:用 MCP 工具操控手机完成自动化任务
4.1 设备发现与连接建立
启动 mobile-mcp 服务后,第一件事是让客户端知道有哪些设备可用。通常会有一个list_devices工具,调用后返回当前连接的设备列表,包括设备 ID、平台类型、系统版本等信息。Android 设备 ID 就是adb devices里显示的那串序列号,iOS 设备 ID 是 UDID。
拿到设备 ID 后,需要显式连接或者指定目标设备。有些实现是自动连接第一个可用设备,有些需要手动指定。建议在配置里写死设备 ID,避免多设备时连错。连接建立后,可以调一个get_device_info之类的工具确认连接状态,返回的信息里应该包含屏幕分辨率、当前前台应用等。
这一步的常见问题是设备显示为“unauthorized”。Android 上通常是手机上没有点“允许调试”,重新插拔 USB 或者重启 adb 服务(adb kill-server && adb start-server)一般能解决。iOS 上可能是 WDA 没跑起来,或者证书失效了,需要重新编译部署 WDA。
4.2 页面元素定位与交互操作
mobile-mcp 获取页面结构的方式是调get_page_source,返回的是 XML 格式的层级树。Android 上这个 XML 来自 UiAutomator,iOS 上来自 WDA 的 accessibility 树。你可以从这个 XML 里找到元素的坐标、文本、资源 ID 等信息,然后决定点哪里。
点击操作有两种方式:按坐标点,或者按元素找。按坐标点简单直接,但页面一滚动坐标就失效了。按元素找更稳,但需要解析 XML,而且有些元素可能没有唯一的标识符。实际用的时候,我一般先用get_page_source拿到 XML,找到目标元素的 bounds 属性,算出中心坐标,再调click。这样比纯写死坐标灵活,又比复杂的元素查找逻辑简单。
输入文本用type工具,需要先点击输入框获取焦点,再发送文本。有些输入框有特殊行为,比如自动补全、输入法拦截,这时候可能需要先清空再输入,或者用 ADB 的input text命令绕过输入法。滑动用swipe,传起始坐标和结束坐标,可以控制滑动方向和距离。
| 操作类型 | 工具名 | 关键参数 | 适用场景 |
|---|---|---|---|
| 点击 | mobile_click | x, y | 按钮、链接、图标 |
| 长按 | mobile_long_press | x, y, duration | 上下文菜单、拖拽 |
| 滑动 | mobile_swipe | x1, y1, x2, y2 | 翻页、滚动列表 |
| 输入 | mobile_type | text | 搜索框、表单 |
| 截图 | mobile_screenshot | 无 | 结果验证、调试 |
| 获取页面 | mobile_get_page_source | 无 | 元素定位、状态判断 |
4.3 截图与页面结构获取的实战技巧
截图看起来简单,但实际用的时候有几个细节要注意。首先是截图时机,页面还在加载的时候截图可能拿到白屏或者半成品,最好等页面稳定后再截。可以配合wait_for_element或者固定延时来确保页面加载完成。其次是截图格式,PNG 体积大但清晰,JPEG 体积小但可能有压缩伪影,根据用途选。
页面结构获取的坑更多。Android 的 UiAutomator XML 有时候会包含大量无用节点,解析起来很慢。可以先用get_page_source拿到完整 XML,然后用 XPath 或者正则提取需要的部分。iOS 的 accessibility 树相对干净一些,但有些自定义控件可能没有正确的 accessibility 标签,导致找不到元素。
我自己的做法是:先用截图看页面长什么样,再用页面结构找元素坐标,两者结合。截图给人看,页面结构给程序看。如果页面结构里找不到目标元素,就退回用截图加坐标估算,虽然不够精确,但至少能跑通流程。
注意:频繁调用
get_page_source会明显拖慢执行速度,因为每次都要序列化整个页面树。建议在关键节点调用,不要每一步都调。
5. 常见问题与排查技巧实录
5.1 连接类问题速查
连接问题是最常见的,尤其是 iOS。下面这个表整理了我遇到过的大部分情况。
| 现象 | 可能原因 | 排查步骤 |
|---|---|---|
| adb devices 无设备 | USB 调试未开、驱动问题 | 检查开发者选项、换线换口 |
| 设备显示 unauthorized | 手机未授权 | 手机上点允许、重启 adb |
| iOS 连接超时 | WDA 未启动或端口不对 | 检查 WDA 进程、确认端口 |
| WDA 签名失败 | 证书过期或配置错误 | 重新签名、检查 Bundle ID |
| 操作无响应 | 页面未加载完、坐标错误 | 加等待、重新获取页面结构 |
Android 这边还有一个坑是“设备离线”。有时候 adb 显示设备在线,但执行命令没反应,这时候adb reconnect或者重启 adb 服务通常能解决。如果还不行,可能是 USB 线接触不良,换根线试试。
iOS 的 WDA 签名问题值得单独说。免费开发者账号签的 WDA 只有 7 天有效期,过期后需要重新签。如果用的是付费账号,有效期会长一些。建议把 WDA 的编译和签名流程脚本化,过期了一键重签,不然每次手动搞很烦。
5.2 操作失效与元素定位失败
元素定位失败的原因很多,最常见的是页面还没加载完就去点。解决办法是加等待,可以用固定延时,也可以用wait_for_element轮询。固定延时简单但不够优雅,轮询更可靠但需要知道元素的特征。
另一个原因是元素被遮挡。比如弹窗覆盖了按钮,这时候直接点按钮的坐标可能点到弹窗上。解决办法是先检测有没有弹窗,有的话先关掉再操作。或者用页面结构找到弹窗的关闭按钮,先点关闭。
还有一种情况是元素在可滚动区域外。比如列表里的某一项在屏幕下方,需要先滑动才能看到。这时候直接点坐标会点到屏幕外,无效。解决办法是先滑动到元素可见,再点击。可以用scroll_to或者手动计算滑动距离。
5.3 性能优化与稳定性提升
mobile-mcp 跑久了可能会变慢,尤其是频繁截图和获取页面结构的时候。优化思路有几个:减少不必要的截图,只在需要验证的时候截;缓存页面结构,同一页面多次操作时不用每次都重新获取;用更精确的坐标代替大范围滑动,减少操作次数。
稳定性方面,建议给每个操作加重试机制。移动端环境不稳定,偶尔失败很正常,重试一两次往往就能成功。但重试次数不要太多,否则失败的时候会卡很久。一般重试 2 到 3 次,每次间隔 1 秒左右比较合适。
还有一个经验是:尽量用元素的文本或 ID 来定位,少用绝对坐标。绝对坐标在不同分辨率、不同系统版本上可能不一样,换台设备就失效了。用元素特征定位虽然写起来麻烦一点,但可移植性好很多。
6. 进阶玩法:mobile-mcp 与 AI Agent 的结合
6.1 让 AI 自主决策操作步骤
mobile-mcp 最大的想象空间在于跟 AI Agent 结合。传统自动化是“人写步骤,机器执行”,AI Agent 模式下是“人给目标,AI 决定步骤”。比如你说“帮我在购物 App 里搜一下蓝牙耳机,截图前三个结果”,AI 会自己打开 App、找到搜索框、输入关键词、截图、返回结果。整个过程不需要你写任何定位逻辑。
实现方式是:AI Agent 通过 MCP 协议调用 mobile-mcp 的工具,每次操作后获取截图或页面结构,根据当前状态决定下一步。这其实就是一个闭环控制:感知 → 决策 → 执行 → 再感知。mobile-mcp 提供感知和执行能力,AI 模型负责决策。
这种模式的优势是适应性强。页面改版了、按钮位置变了,AI 可以根据截图重新识别,不需要改代码。缺点是速度和稳定性不如写死的脚本,因为每次决策都要调模型,有延迟。所以适合场景相对固定但页面多变的场景,比如跨多个 App 的流程测试。
6.2 多设备并行与批量任务
mobile-mcp 支持多设备连接,可以同时操控多台手机。这在批量任务场景下很有用,比如同时在 10 台设备上安装 App、跑冒烟测试、收集日志。实现方式一般是启动多个 mobile-mcp 实例,每个实例绑定一台设备,然后由上层调度器分发任务。
多设备并行要注意资源竞争。比如多台设备同时截图,如果都存到同一个目录,文件名可能冲突。解决办法是给每个设备分配独立的目录或文件名前缀。另外,USB 带宽有限,同时连太多设备可能导致 adb 响应变慢,一般建议单台电脑不超过 8 台设备。
批量任务还有一个坑是设备状态不一致。有的设备可能锁屏了、有的可能弹了系统更新提示。执行前最好统一检查设备状态,该解锁的解锁,该关弹窗的关弹窗。可以写一个预处理脚本,把所有设备恢复到干净状态再开始任务。
6.3 与 CI/CD 流水线的集成思路
把 mobile-mcp 集成到 CI/CD 里,可以实现自动化的移动端回归测试。思路是:代码提交后触发流水线,流水线启动 mobile-mcp 服务,连接测试设备,执行预设的 MCP 工具调用序列,收集结果和截图,最后生成报告。
跟 Jenkins、GitLab CI 这些工具集成时,关键是把 mobile-mcp 的启动和停止做成脚本,方便流水线调用。设备连接建议用固定的测试机,不要用开发同学的手机,避免被人拔线。测试结果可以输出成 JUnit XML 格式,这样 CI 工具能直接解析展示。
需要注意的是,CI 环境下的设备稳定性比本地差。建议加健康检查,执行前先确认设备在线、WDA 正常、屏幕解锁。如果设备有问题,自动重试或者切换到备用设备,避免整个流水线因为一台设备挂掉而失败。
7. 我踩过的坑与实操心得
先说 iOS 的开发者模式。iOS 16 以后,开发者模式藏得比较深,在“设置 → 隐私与安全性”最下面。而且开启后需要重启手机才生效。我第一次搞的时候找了半天,还以为是证书问题。另外,开发者模式有时候会自己关掉,尤其是系统更新后,需要重新开。如果突然连不上 WDA,先检查开发者模式是不是关了。
Android 的坑主要在权限上。有些 App 会检测 USB 调试状态,发现开了调试就拒绝运行。这种一般需要用模拟器或者改包名绕过,比较麻烦。还有就是 Android 13 以后的通知权限,如果 App 需要通知权限但没给,可能会弹窗拦截,影响自动化流程。建议在测试前手动把权限都授好。
还有一个通用经验是:截图和页面结构要配合使用。光看页面结构有时候判断不了页面状态,比如加载中还是加载完了,结构可能差不多。光看截图又没法精确定位元素。两者结合,截图判断状态,结构定位元素,效率最高。
最后说一个性能相关的:mobile-mcp 的响应速度受设备影响很大。旗舰机操作很流畅,低端机可能每个操作都要等一两秒。如果做批量任务,建议用配置差不多的设备,避免因为个别慢设备拖累整体进度。另外,USB 2.0 和 3.0 的接口速度也有差别,能用 3.0 就用 3.0。
这个项目后续还可以往几个方向扩展:一是支持更多平台,比如鸿蒙;二是增加更复杂的操作,比如多点触控、手势密码;三是跟更多 AI 工具集成,降低使用门槛。如果你也在做移动端自动化,不妨试试 mobile-mcp,说不定能省下不少折腾环境的时间。