qwen-code 仓库中 mobile-mcp 演进全解析:从移动设备 MCP 服务器到 0-1000 相对坐标能力
【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code
本篇技术指南以本仓库 packages/mobile-mcp/CHANGELOG.md 为骨架,结合 packages/mobile-mcp/src 下的 TypeScript 源码与测试,系统梳理@qwen-code/mobile-mcp这个移动设备 MCP 服务器从 v0.0.11 到 v0.0.61 的完整演进脉络,以及 fork 到 qwen-code 后新增的相对坐标归一化、Android 专属工具等本地化能力。读完本文,你将掌握该 MCP 服务器的工具集全貌、底层驱动架构(mobilecli / mobilewright)、安全加固历史,以及如何在 MCP 客户端中配置并启用 0-1000 相对坐标模式以对接 Qwen VL 模型的mobile_use坐标约定。
一、mobile-mcp 是什么
@qwen-code/mobile-mcp是一个基于 Model Context Protocol 的 MCP 服务器,它让 LLM Agent 能够通过截图、无障碍元素树、坐标触控三种通道与 iOS / Android 移动设备(模拟器、仿真器、真机)交互。本仓库中的实现是上游 mobile-next/mobile-mcp),通过git subtree方式跟踪上游,本地修改记录与同步脚本见 packages/mobile-mcp/scripts/sync-from-upstream.sh。
从包配置 packages/mobile-mcp/package.json 可以看到它的技术栈:
- 运行时要求 Node.js >= 18;
- 核心依赖
@modelcontextprotocol/sdk(1.26.0)、express(5.1.0,SSE 传输)、commander(CLI 参数)、fast-xml-parser(Android UI 树解析)、mobilewright(iOS 模拟器驱动)、zod(工具参数校验); - 提供了
mcp-server-mobile这个 bin 入口,即 packages/mobile-mcp/src/index.ts; - 测试基于 Playwright(
c8 playwright test)。
二、版本演进总览:一条清晰的能力成长线
CHANGELOG 覆盖了 2025-04 至 2026-07 的 0.0.11 ~ 0.0.61 共 50 余个版本,可以归纳为几个阶段:
| 阶段 | 版本区间 | 核心主题 |
|---|---|---|
| 起步期 | 0.0.11 ~ 0.0.19 | 多设备支持、iOS 真机(go-ios)、方向切换、元素识别增强 |
| 工具丰富期 | 0.0.20 ~ 0.0.30 | save_screenshot、use_default_device、长按、app 安装卸载、mobilecli 引入 |
| 稳定性与兼容期 | 0.0.31 ~ 0.0.43 | libc 兼容、多屏设备(折叠屏)截图、远程设备、超大截图 buffer |
| 安全加固期 | 0.0.44 ~ 0.0.52 | URL 协议限制、路径遍历修复、SSE 认证、跨域/并发防护、依赖安全升级 |
| 架构升级期 | 0.0.53 ~ 0.0.61 | 崩溃报告工具、iOS Device Kit 替换 WebDriverAgent、mobilewright SDK 化、信号处理 |
从版本频率看,该项目保持着约每 1~2 周一个版本的迭代节奏,且大量版本包含安全依赖升级(fast-xml-parser、path-to-regexp、hono、@modelcontextprotocol/sdk 等),这是其工程纪律的一个显著特征。
三、底层驱动架构的两次大迁移
CHANGELOG 揭示了 mobile-mcp 后端驱动能力的两次关键架构迁移,这是理解整个项目的钥匙。
1. mobilecli 统一二进制(0.0.30 引入)
在 0.0.30(2025-10-06)中,项目明确宣告"introduction of mobilecli tool, will replace imagemagick, sips, go-ios and adb in the future"——即用统一的mobilecli二进制逐步替代四类外部依赖:
- ImageMagick(图像缩放)
- sips(macOS 图像缩放)
- go-ios(iOS 真机通信)
- adb(Android 通信)
在 packages/mobile-mcp/src/server.ts 中可以看到这一架构的落地:ensureMobilecliAvailable()在每次获取设备 Robot 前都会校验 mobilecli 是否可用,随后getRobotFromDevice()依次探测 iOS 真机(IosManager)、Android 设备(AndroidDeviceManager)、iOS 模拟器(mobilecli.getDevices),最终返回对应的IosRobot/AndroidRobot/MobileDevice实例。这一"抽象 Robot + 平台实现"的模式定义在 packages/mobile-mcp/src/robot.ts 的Robot接口中:getScreenSize、swipe、tap、longPress、listApps、installApp、sendKeys、pressButton、getElementsOnScreen、setOrientation等一应俱全。
2. mobilewright SDK 化(0.0.55 ~ 0.0.61)
0.0.55 用 mobilewright SDK 替换了 mobilecli("Replace mobilecli with mobilewright SDK"),后续 0.0.56、0.0.57、0.0.60 持续升级 mobilewright 版本(0.0.38 → 0.0.41 → 0.0.53)。mobilewright 承担了 iOS 模拟器的管理、WebDriverAgent 的自动下载安装(0.0.38:无需手动安装 WDA,数秒内即可开始在模拟器上开发)以及后续的 Device Kit 集成。
从源码看,iOS 模拟器的 agent 生命周期管理位于 packages/mobile-mcp/src/server.ts 的getRobotFromDevice()中:通过agentVerifiedSimulators集合做去重,对每个首次使用的模拟器执行mobilecli.agentStatus()检查,失败则调用mobilecli.agentInstall()自动安装。
3. iOS Device Kit 替换 WebDriverAgent(0.0.53)
0.0.53 是一个重要的架构节点:iOS 侧从 WebDriverAgent 切换到开源的 iOS Device Kit(Apache License),同时修复了 testmanagerd 导致 Device Kit 卡死黑屏的问题,并在视图树响应中新增placeholder字段。加上 0.0.58 的getRobot设备类型/平台识别、0.0.61 对通过 npm 安装的 go-ios(bare semver 版本号)的检测修复,iOS 真机链路的健壮性逐步完善。
四、工具集全貌:从 CHANGELOG 到源码逐一对位
CHANGELOG 中散落的工具新增记录,最终都收敛为 packages/mobile-mcp/src/server.ts 中注册的具体 MCP 工具。完整工具清单如下(与 packages/mobile-mcp/README.md 一致):
设备管理
mobile_list_available_devices:列出全部可用设备(Android 仿真器 + iOS 真机 + iOS 模拟器)。0.0.48 修复了getDeviceType错误导致设备列表为空的问题;0.0.46 优化了工具描述,便于 LLM 理解。mobile_get_screen_size/mobile_get_orientation/mobile_set_orientation:屏幕尺寸与方向。0.0.13 开始支持方向切换。
App 管理
mobile_list_apps:列出已安装应用(Android 侧通过cmd package query-activities过滤出带 launcher activity 的应用,见 packages/mobile-mcp/src/android.ts)。mobile_launch_app/mobile_terminate_app:启动/终止应用。0.0.47 起支持locale参数(BCP 47 标签),Android 侧在 Android 13+ 上通过cmd locale set-app-locales实现,老版本静默忽略。mobile_install_app/mobile_uninstall_app:安装/卸载。0.0.30 加入 app 安装卸载能力;fork 版扩展了 Android 专属参数(见下文第六节)。
屏幕交互
mobile_take_screenshot/mobile_save_screenshot:截图。0.0.20 引入save_screenshot(供其他 MCP 服务器落盘复用);0.0.43 增大了截图 buffer,修复 >4MB 截图的 bug;0.0.23/0.0.24 修复了折叠屏等多屏设备的截图;0.0.21 起 iOS 统一用 WDA 截屏。mobile_list_elements_on_screen:列出带坐标的 UI 元素(跨平台)。Android 侧底层是uiautomator dumpXML 解析(packages/mobile-mcp/src/android.ts 的collectElements:仅保留有 text / content-desc / hint / resource-id / checkable 属性的节点,并剔除宽高为 0 的节点);iOS 侧 0.0.16 起支持 StaticText、Image 元素识别。mobile_click_on_screen_at_coordinates、mobile_double_tap_on_screen(0.0.32 加入 Android/iOS 双击)、mobile_long_press_on_screen_at_coordinates(0.0.24 加入长按,0.0.39 加入duration参数,默认 500ms,范围 1~10000ms)、mobile_swipe_on_screen:全部坐标类触控工具。
输入与导航
mobile_type_keys:向聚焦元素输入文本,submit参数控制是否回车提交(0.0.11 起支持)。Android 非 ASCII 文本通过 mobilenext devicekit 的剪贴板广播注入(packages/mobile-mcp/src/android.ts 的sendKeys)。mobile_press_button:HOME / BACK / VOLUME_UP / VOLUME_DOWN / ENTER 以及 Android TV 的 DPAD 系列按键(0.0.14 加入 Android TV dpad 导航支持)。mobile_open_url:打开 URL。
录制与调试
mobile_start_screen_recording/mobile_stop_screen_recording:屏幕录制(0.0.46 加入,真机与模拟器/仿真器均支持)。实现上通过mobilecli spawnCommand启动后台录制进程,用activeRecordingsMap 管理生命周期,停止时先 SIGINT、超时 5 分钟兜底 SIGKILL(packages/mobile-mcp/src/server.ts)。mobile_list_crashes/mobile_get_crash:崩溃报告(0.0.53 加入)。
Android 专属(fork 新增)
mobile_ui_dump、mobile_adb_pull、mobile_adb_push:见第六节。
远程设备(可选)
- 当
MOBILEFLEET_ENABLE=1时注册mobile_list_remote_devices、mobile_allocate_remote_device、mobile_release_remote_device(0.0.44 引入远程设备支持,可在 Mobile Fleet 上分配 Android/iOS 设备)。
五、安全加固历程:一个值得借鉴的演进样本
CHANGELOG 是观察该项目安全意识的最佳窗口,安全相关修复贯穿始终:
| 版本 | 安全问题 | 修复方式 |
|---|---|---|
| 0.0.50 | open_url可打开任意 scheme | 默认仅允许 http/https,需显式设置MOBILEMCP_ALLOW_UNSAFE_URLS=1放开(社区报告漏洞) |
| 0.0.49 | 截图/录屏保存路径穿越 | 修复路径遍历(社区报告漏洞) |
| 0.0.52 | SSE 传输无认证 | 新增MOBILEMCP_AUTHBearer token 认证;未设置时启动告警 |
| 0.0.52 | SSE 跨域/并发连接 | 阻断跨域请求、拒绝并发连接而非静默替换、断开时清理 transport 以便重连 |
| 0.0.51 | 默认监听 0.0.0.0 | --port改为--listen [host:]port,默认 localhost |
| 0.0.45 | Android shell 注入 | 修复launchAppshell 转义、openUrlURL 转义 |
| 0.0.25 | 文本输入注入 | 改进文本输入转义 |
| 0.0.52 | CI 脚本注入 | 通过环境变量传递github.ref_name |
| 多版本 | 依赖漏洞 | fast-xml-parser、path-to-regexp、hono、@modelcontextprotocol/sdk 等持续升级 |
上述策略大多能在源码中直接印证:
- URL 协议校验:
mobile_open_url在 packages/mobile-mcp/src/server.ts 中检查url.startsWith('http://') || url.startsWith('https://'),否则抛出ActionableError; - SSE 防护:
startSseServer在 packages/mobile-mcp/src/index.ts 中实现 Bearer 校验(req.headers.authorization !== 'Bearer ' + token返回 401)、跨域请求返回 403、重复连接返回 409; - shell 注入防护:
escapeShellText在 packages/mobile-mcp/src/android.ts 中转义\'"` 空格、管道、重定向符等全部 shell 特殊字符; --listen参数解析:支持[host:]port,端口必须在 1~65535 整数范围内,默认 host 为localhost。
这些修复的共同特点是:默认安全(secure by default)——新特性默认关闭或默认收紧,需要用户显式 opt-in 才放开,且对外部报告者致谢(0.0.50、0.0.49 均致谢漏洞报告者)。
六、qwen-code fork 的本地化增强
本仓库的 fork 在保持与上游同步的同时(当前版本 0.20.1),新增了几项面向 Qwen 系 Agent 的定制能力,全部记载于 packages/mobile-mcp/README.md。
1. 可选的 0-1000 相对坐标模式
这是 fork 最核心的增强,镜像了 cua-driver 的相对坐标 shim 设计。启用后,所有坐标输入/输出归一化到 0-1000 刻度,与 Qwen VL 模型computer_use/mobile_use的坐标约定对齐。
环境变量:
| 变量 | 取值 | 默认 | 说明 |
|---|---|---|---|
MOBILE_MCP_COORDINATE_SPACE | 0(关)/1(开) | 0 | 启用 0-1000 归一化坐标 |
MOBILE_MCP_COORDINATE_SCALE | 任意正整数 | 1000 | 满刻度值(mobile_use约定可设999) |
工作原理(实现见 packages/mobile-mcp/src/coord-norm.ts):
- 输入反归一化:
mobile_click_on_screen_at_coordinates、mobile_double_tap_on_screen、mobile_long_press_on_screen_at_coordinates、mobile_swipe_on_screen四个工具在真正执行前,将 0-scale 输入换算回设备像素/逻辑点。换算函数normToPx为Math.round((norm / scale) * dim),并有越界校验(超出[0, scale]直接报错提示"请用归一化坐标");swipe 的distance按滑动方向对应的轴(上下按高度、左右按宽度)换算。 - 输出归一化:
mobile_list_elements_on_screen的元素坐标从像素换算到 0-1000;mobile_get_screen_size报告为 1000x1000。屏幕尺寸在mobile_get_screen_size返回后被ingestScreenSizeFromResult解析并缓存到screenSizeCache,坐标工具优先用缓存,未命中时通过ensureScreenSize实时获取;方向变更会触发invalidateScreenSize失效缓存。 - 描述重写:启用后工具描述中的 "in pixels" 自动替换为 "in 0-scale normalized coordinates",
server的instructions也会追加归一化坐标使用说明,引导模型先调用mobile_get_screen_size理解设备尺寸。 - 默认关闭:未配置时行为零变化,完全向后兼容。归一化基准为
getScreenSize()——iOS 是逻辑点,Android 是物理像素;shim 完全运行在 packages/mobile-mcp/src/server.ts,底层android.ts/ios.ts等后端文件不被触碰。
测试用例见 packages/mobile-mcp/test/coord-norm.test.ts,例如normToPx(500, 800, 1000) === 400(中点映射)、normToPx(333, 800, 1000) === 266(就近取整)、hasCoordFields对四个坐标工具返回 true 而对mobile_take_screenshot返回 false。
2. 扩展的 Android 安装选项
mobile_install_app新增四个 Android 专属布尔参数,映射到adb install标志(实现见 packages/mobile-mcp/src/android.ts 的installApp,选项类型定义在 packages/mobile-mcp/src/robot.ts 的InstallOptions):
| 参数 | 标志 | 说明 | 默认值 |
|---|---|---|---|
replace | -r | 替换已存在的应用 | true |
grant_permissions | -g | 授予全部运行时权限 | false |
allow_downgrade | -d | 允许版本号降级 | false |
allow_test | -t | 允许安装测试 APK | false |
iOS / 模拟器侧会静默忽略这些选项。
3. Android 专属调试工具
mobile_ui_dump:通过uiautomator dump输出完整未过滤的 XML 视图树(保留父子层级与全部节点属性),区别于mobile_list_elements_on_screen的扁平 JSON;支持--compressed缩减输出,可指定output_path落盘。实现会重试最多 10 次以应对null root node returned by UiTestAutomationBridge的不稳定状态。mobile_adb_pull:从设备拉取文件到本地。mobile_adb_push:推送文件到设备,默认仅允许推送到/sdcard/(force=true才可越界),且会校验本地文件存在。
4. 遥测默认关闭
上游的 PostHog 遥测在本 fork 中默认关闭,需显式设置MOBILEMCP_ENABLE_TELEMETRY=1才会上报(packages/mobile-mcp/src/server.ts 的posthog函数先检查该开关)。同时保留了MOBILEMCP_DISABLE_TELEMETRY环境变量以兼容上游约定。
5. MCP 模型 Payload 过滤
部分模型 API 路由会拒绝对话历史中包含特定厂商关键词的请求。fork 提供了MCP_MODEL_PAYLOAD_FILTER=1开关,在 mobile-mcp 边界启用可逆别名过滤(packages/mobile-mcp/src/payload-filter.ts):匹配文本被替换为__mcp_ref_<hex>__形式的引用令牌,回传同一服务器时解码还原;该过滤器默认关闭。注意:被过滤的别名如果传给 shell 或其他 MCP 服务器,不会在那里被解码。
七、部署与配置实践
1. MCP 客户端配置
在 MCP 客户端(如 Claude Code / VSCode / qwen-code 等支持 MCP 的 Agent 环境)中,标准配置方式(详见 packages/mobile-mcp/README.md):
{ "mcpServers": { "mobile-mcp": { "command": "npx", "args": ["@qwen-code/mobile-mcp"] } } }启用相对坐标模式:
{ "mcpServers": { "mobile-mcp": { "command": "npx", "args": ["@qwen-code/mobile-mcp"], "env": { "MOBILE_MCP_COORDINATE_SPACE": "1" } } } }对特定路由启用 Payload 过滤:
{ "mcpServers": { "mobile-mcp": { "command": "npx", "args": ["@qwen-code/mobile-mcp"], "env": { "MCP_MODEL_PAYLOAD_FILTER": "1" } } } }2. 完整环境变量参考
综合 CHANGELOG 与源码,可用的环境变量汇总如下:
| 环境变量 | 作用 |
|---|---|
MOBILE_MCP_COORDINATE_SPACE | 启用 0-1000 相对坐标(fork 新增) |
MOBILE_MCP_COORDINATE_SCALE | 归一化满刻度,默认 1000(fork 新增) |
MCP_MODEL_PAYLOAD_FILTER | 启用 MCP 响应厂商词过滤(fork 新增,默认关) |
MOBILEMCP_ENABLE_TELEMETRY | 启用遥测上报(fork 默认关) |
MOBILEMCP_DISABLE_TELEMETRY | 禁用遥测(上游变量) |
MOBILEMCP_AUTH | SSE 传输的 Bearer token 认证 |
MOBILEMCP_ALLOW_UNSAFE_URLS | 允许open_url打开非 http/https 协议 |
MOBILEFLEET_ENABLE | 启用远程设备池相关工具 |
ANDROID_HOME | adb 所在目录($ANDROID_HOME/platform-tools) |
GO_IOS_PATH | 指定 go-ios 可执行文件路径 |
3. 运行模式与前置条件
CLI 入口(packages/mobile-mcp/src/index.ts)支持两种运行模式:
- stdio(默认):
mcp-server-mobile直接以标准输入输出与 MCP 客户端通信; - SSE:
--listen [host:]port启动 HTTP 服务(GET /mcp建立 SSE 连接、POST /mcp提交消息),默认 host 为localhost,建议生产环境务必设置MOBILEMCP_AUTH。
前置条件(README 明确列出):
- Android:需 Android SDK Platform Tools,
adb在 PATH 上或通过ANDROID_HOME定位(packages/mobile-mcp/src/android.ts 的getAdbPath还会回退检查 macOS 的~/Library/Android/sdk与 Windows 的%LOCALAPPDATA%\Android\Sdk默认路径,Windows 上始终使用adb.exe); - iOS 真机:需 go-ios;
- iOS 模拟器:Xcode + 模拟器运行时 + mobilecli(经 mobilewright 依赖自动安装,首次使用会自动安装 agent)。
八、工程质量与发布实践
CHANGELOG 还透露出值得借鉴的工程习惯:
- 可复现构建(0.0.52):CI 使用
npm ci而非npm install,tag 发布时移除npm update以保持 lockfile 完整性,生产依赖锁定到精确版本; - 测试框架迁移(0.0.58):从 mocha/nyc 迁移到 Playwright,以减少依赖漏洞面;本 fork 的测试同样基于 Playwright 运行(见 packages/mobile-mcp/test 下的
coord-norm.test.ts、payload-filter.test.ts、mobile-ui-dump.test.ts等); - 优雅退出(0.0.61):捕获系统信号做干净的 v8 退出,确保
NODE_V8_COVERAGE输出被完整落盘(stdio 模式在SIGINT/SIGTERM时process.exit(0)); - CI 最小权限(0.0.53):
contents权限收窄为read,并移除不必要的 Java 构建步骤; - 依赖安全常态化:几乎每个版本都伴随安全相关依赖升级,形成了一种"发布即安全检查"的节奏。
九、总结
从 0.0.11 到 0.0.61,mobile-mcp 走完了一条从"能用"到"好用地用"的路径:统一了移动设备驱动(mobilecli / mobilewright / Device Kit)、补全了交互工具矩阵(点按、双击、长按、滑动、方向、文本、按键)、持续强化了安全边界(认证、跨域、协议白名单、路径校验、注入转义),并沉淀了可复现构建与 Playwright 测试的工程底座。而 qwen-code fork 在完全兼容上游的基础上,通过 0-1000 相对坐标 shim 将移动端工具与 Qwen VL 的mobile_use坐标约定打通,让模型可以稳定地在截图与坐标空间之间完成"看图—定位—操作"的闭环。对于任何希望让 LLM Agent 真正"上手"移动设备的开发者,这个包既是一个可直接使用的 MCP 服务器,也是一份研究移动端 Agent 工具设计的高质量参考实现。
【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考