news 2026/10/16 3:27:07

airi 开发日志解读:用 FastMCP 与 ADB 搭建 Android MCP 服务器,让 LLM 操作手机

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
airi 开发日志解读:用 FastMCP 与 ADB 搭建 Android MCP 服务器,让 LLM 操作手机
  • 人工智能
  • AI Agent
  • MCP 服务
  • 工具调用
  • GUI 自动化
  • 语音
  • 数字人
  • 交互助手

【免费下载链接】airi

💖🧸 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器,目标是接近 Neuro-sama 的高度;支持实时语音聊天、Minecraft 和 Factorio 游玩,支持 Web / macOS / Windows。

项目地址:https://gitcode.com/moeru-ai/airi
点击查看免费下载

导读:本文是对 airi 项目 2025.04.22 开发日志(原始文档)的技术解读。日志记录了开发者 LemonNeko 用一个周末时间实现airi-android的过程——这是一个基于 MCP(Model Context Protocol)与 ADB 交互的服务器,为 AIRI 以及任何 LLM 提供了操作 Android 手机的能力。读完本文,你将理解 MCP 的 Resources / Prompts / Tools 三大核心概念、如何用 Python 的FastMCP快速搭建一个 ADB MCP 服务器、LLM 通过「截图 + UI 自动化 + 点击滑动」操作手机的四步工作流,以及图形渲染类 App、响应长度限制、动画与安全四个实战难点;最后结合当前仓库源码,你会看到这套思路最终在 airi 桌面端演化成了完整的 MCP 服务器接入体系。

背景:从桌宠到「让 AIRI 用手机」

在正式展开之前,需要交代这个 DevLog 的上下文。日志作者是 airi 的开发者之一 LemonNeko。两个月前,团队把 AIRI 的 Web 界面移植到了 Electron(当时对应 PR #7),使 AIRI 能以桌面宠物的形式悬浮在屏幕上;尽管后来该项目又用 Tauri 做了重构(对应 PR #90),「让 AI 拥有可以操作的外部设备」这个方向被保留了下来。而在 2025.04.20 那个周末,作者花时间做出了一个能与ADB(Android Debug Bridge)交互的 MCP 服务器 Demoairi-android,迈出了「让 AIRI 使用手机」的第一步。

作者最初的想法其实更简单:写一点 Tool Calling 代码、改一改提示词,告诉 LLM「这些工具可以操作手机」就够了。但当时 MCP 太流行,抱着尝试的心态,最终选择用 MCP 实现,并把服务器打包成了 Docker 镜像,发布到了公开的 MCP 服务器列表上,供其他 LLM 工具直接接入。

仓库佐证:如今 airi 主仓库中,MCP 接入已经是一等公民。桌宠客户端 stage-tamagotchi 内置了完整的 MCP 服务器管理、连接测试与工具桥接能力;仓库还维护着一个面向 macOS 桌面编排的专用服务 computer-use-mcp。这正是本文末尾要展开的「后续演化」内容。

MCP 是什么:标准化「应用如何给 LLM 提供上下文」

要编写 MCP 服务器,首先需要理解 MCP 本身。日志给出了非常通俗的定义:

MCP(Model Context Protocol,模型上下文协议)是一个尝试标准化「应用如何为 LLM 提供上下文」的协议。

它提出了三个核心概念:

  1. Resources(资源):服务器可以把数据与内容作为上下文提供给 LLM。
  2. Prompts(提示词):创建可复用的提示词模板与工作流。
  3. Tools(工具):允许 LLM 通过你的服务器执行一些动作。

日志里有个非常生动的小插曲:作者看到「资源」这个词,联想到 Ruby on Rails 中「用户就是一种资源」,于是想当然地认为「ADB 设备应该也是资源」,写出了第一版代码:

from mcp.server.fastmcp import FastMCP from ppadb.client import Client mcp = FastMCP("airi-android") adb_client = Client() @mcp.resource("adb://devices") def get_devices(): return adb_client.devices()

结果错了。当作者让 Cursor 去获取设备列表时,它不知道该怎么操作——因为「主动去查看当前有哪些设备连接」本质上是一次主动性行为,应该是一个工具(Tool)而非资源。这个例子很好地说明了 MCP 中三个概念的边界:

  • 资源是被动提供的:适合「你问我答」式的数据读取;
  • 工具是主动执行的:适合「帮我做一件事」式的动作调用(例如查询设备列表、点击屏幕、滑动页面);
  • 提示词是模板化引导:适合把常用的指令组织成可复用的工作流。

源码佐证:在 airi 桌面端的 LLM 工具层,MCP 能力正是通过两个内置工具暴露给模型的:builtIn_mcpListTools(先列出所有可用 MCP 工具)与builtIn_mcpCallTool(按<serverName>::<toolName>格式调用某个工具)。其中arguments以 JSON 字符串传入,由模型在运行时自行组装——这与日志里「让 LLM 主动决定调用哪个工具、传什么参数」的设计意图完全一致。

LLM 操作手机的四步工作流(Cursor 的做法)

作者在日志中坦承,自己还没完全想清楚「具体怎么让 LLM 操作手机」,于是采用「直接上手、让 Cursor 来用」的实践路线。观察 Cursor 的实际行为后,总结出了 LLM 操作手机的标准套路:

  1. 使用截屏功能,大略了解手机屏幕上的内容;
  2. 使用 UI 自动化工具,获取想要操作的元素的精确位置;
  3. 点击或滑动该元素;
  4. 重复以上步骤,直到任务完成。

这个「观察 → 定位 → 操作 → 再观察」的闭环,本质上就是今天各类 computer-use / GUI Agent 的共同范式:视觉模型负责理解界面,UI 自动化负责把语义目标换算成坐标,点击与滑动负责执行。日志作者评价「目前看来运行良好」。

四个待讨论的实战难点

日志没有停留在「能跑」的层面,而是提出了四个非常实际的工程问题,这也正是 MCP + 手机操作类项目普遍会遇到的坎:

难点 1:图形 API 直绘内容无法被 UI 自动化定位。如果屏幕上是一个用图形 API(如 OpenGL / Vulkan / 游戏引擎)直接绘制的游戏画面,而不是标准 UI 组件,UI 自动化工具拿不到任何元素的位置信息,自然也就无法操作它。这提示了一个方向:在纯视觉内容面前,坐标级的点击与滑动可能需要升级为「基于视觉理解 + 坐标推断」的方案。

难点 2:LLM 响应长度有限,复杂操作需要分步触发。一个 LLM 响应能承载的内容是有上限的,复杂的多步操作往往放不进一次响应。作者提出的设想是:像 airi-factorio 那样,每一步操作完成之后,自动告诉 LLM 结果并触发它规划下一步,从而把长任务拆解成「执行一步 → 回报一步 → 再规划一步」的循环,绕开单次响应的长度限制。

难点 3:动画会干扰「操作后立刻截屏」的判断。部分 App 有酷炫的过渡动画:操作完成后立刻截屏,画面可能还没渲染到位,导致模型误判操作失败。作者提出两个候选方案——操作完成后等待一段时间再截屏,或者直接改用屏幕录制来获取连续的视觉反馈。

难点 4:让 AI 直接操作手机的安全风险。把操作系统级权限交给 LLM 意味着什么?误操作、不可逆的破坏性动作(如删数据、转账)、隐私泄露等风险都需要认真评估。日志在此只是提出了问题、抛给大家讨论,并未给出定论——这也是「AI 操作真实设备」类项目至今仍在演进的安全课题。

仓库佐证:安全与审批机制正是 airi 当前 MCP 体系的重点之一。在 computer-use-mcp 中可以看到:终端命令、App 打开/聚焦、点击/输入等动作默认都需要审批;denyApps会屏蔽敏感应用(如密码管理器、系统设置、Activity Monitor),AIRI 自身也在默认拒绝列表中以避免自我操作;审批状态通过approval_required回传,Electron 桌面端弹出原生审批对话框,AIRI 再代表用户自动调用 approve/reject。这些设计正是对日志中「安全风险」问题的工程化回应。

开发小技巧:命令行启动 Android 模拟器

日志还分享了一个对日常开发很实用的技巧:完全可以用命令行直接启动 Android 模拟器,而不必打开笨重的 Android Studio,能显著降低内存压力:

emulator -avd Pixel_6_Pro_API_34

-avd参数指定要启动的 AVD(Android Virtual Device)名称,示例中的Pixel_6_Pro_API_34是一个 Pixel 6 Pro、API 级别 34 的虚拟设备配置。对需要反复调试 ADB 交互逻辑(截图、UI 自动化、点击滑动)的开发者来说,这个命令让「起一个干净的测试环境」变成一行命令的事。

从一篇 DevLog 到仓库里的 MCP 接入体系

日志末尾,作者预告了下一步:给 AIRI 桌面宠物接上 MCP 服务器,看看它自己想做什么——也许它会像现在的 ReLU 一样点开 Telegram 和人聊天,只不过不通过 Telegram 的官方 API,而是直接模拟真实操作。这个预告后来真的在仓库里落地了,我们可以从当前源码中看到它的完整形态:

① mcp.json 配置文件(用户数据目录)桌面端把 MCP 服务器配置持久化在 Electron 的userData目录下的mcp.json中(见 MCP 管理器的 getConfigPath),首次启动自动写入{ "mcpServers": {} }骨架。配置格式是标准的 MCP 服务器描述,支持两种传输方式。

② 配置 Schema 与校验(shared/mcp-config.ts)仓库把配置校验集中在了 shared/mcp-config.ts:

  • stdio 服务器:command(必填,非空字符串)+ 可选的args、env、cwd、enabled;
  • HTTP 服务器:url(必须是绝对 http/https 地址)+ 可选的headers、enabled。

url被刻意限制为 http/https,是因为主进程会代替用户去请求该地址,若允许file:或data:这类 scheme,一份粘贴来的配置就会变成本地文件读取的原语——这是一个非常值得借鉴的安全细节。校验失败时,错误信息会保留字段路径(如mcpServers.fs.command: ...)并做「union 分支最接近解释」,方便用户在设置页直接定位问题。

③ Electron 主进程的 MCP ManagerMCP 管理器 承担了完整的生命周期管理:

  • 基于官方@modelcontextprotocol/sdk的Client,对 stdio 服务器通过StdioClientTransport拉起子进程(记录 pid、接管 stderr),对 HTTP 服务器通过StreamableHTTPClientTransport连接并逐请求附带 headers;
  • 提供listTools(列出每个会话暴露的工具,命名为serverName::toolName)与callTool(支持对工具名做stdio::等前缀归一化的重试);
  • 提供testServer:真实拉起/连接服务器并调用listTools,带 10 秒请求超时、15 秒总超时的双重保护,失败时只保留 stderr 尾部 16000 字符,防止噪音淹没设置界面;
  • 应用启动时执行applyAndRestart,逐项报告每个服务器是started / failed / skipped(被enabled: false禁用的记为 skipped),并展示每个服务器的运行状态(running / stopped / error 及其 pid 或 url、最后错误)。

④ 设置界面与连接测试设置页(mcp.vue)提供可视化表单编辑:每个服务器条目支持 stdio/http 切换、启用开关、运行状态徽标、JSON 编辑器(可格式化、从表单同步草稿、校验后应用),以及逐条目的连接测试——测试会真实建立连接并列出工具,返回ok / tools / durationMs。保存并应用后主进程重启全部会话,界面会汇总started / failed / skipped数量。

⑤ 工具桥接(stage-ui / mcp.ts)共享 UI 层 createMcpTools 把 MCP 能力包装成两个 LLM 可见的代理工具:builtIn_mcpListTools与builtIn_mcpCallTool。桌宠渲染进程通过 tamagotchi-mcp-tools store 把 Electron 侧的listTools / callTool注入进来,以mcp:前缀注册进 LLM 工具存储,从而让模型可以「先列出、再调用」任意 MCP 服务器上的工具——这与日志中让 LLM 主动获取工具列表、主动决定操作方式的目标一脉相承。

⑥ 从手机到桌面:computer-use-mcp更进一步,仓库中的 computer-use-mcp 把同样的思路扩展到了桌面端:通过desktop_screenshot、desktop_click、desktop_type_text、desktop_open_app等 MCP 工具,让 AIRI 观察并操作 macOS 桌面;提供terminal_exec后台终端执行、browser_dom_*浏览器 DOM 桥接、workflow_*工作流编排,以及审批队列与审计日志。它在mcp.json中通过pnpm -F @proj-airi/computer-use-mcp start以 stdio 方式接入 AIRI,并支持dry-run(不注入任何输入)、macos-local(macOS 本地执行)、linux-x11(遗留实验后端)三种执行模式。可以说,日志里「下一步给桌宠接上 MCP」的预告,最终演化为了一整套「AIRI 作为控制面、本地执行层作为手脚」的 agent 体系。

结语

这篇 DevLog 的价值在于记录了一次真实的「从零到一」:一个开发者如何因为 FOMO 开始研究 MCP、如何用错误的类比(把设备当 Resources)加深了对 Tools 的理解、如何用「让 Cursor 自己用」的办法快速验证思路,并沉淀出「截图 + UI 自动化 + 点击滑动 + 迭代循环」的手机操作范式。日志末尾留下的四个问题——纯图形内容、响应长度、动画时序、安全边界——在今天仓库的 MCP 体系里都能看到对应的工程答案。如果你也想给自己的 LLM 应用接入真实设备操作能力,从FastMCP + ADB起步、再参考 airi 的 mcp.json 配置与审批机制逐步加固,是一条非常值得复刻的路线。

  • 人工智能
  • AI Agent
  • MCP 服务
  • 工具调用
  • GUI 自动化
  • 语音
  • 数字人
  • 交互助手

【免费下载链接】airi

💖🧸 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器,目标是接近 Neuro-sama 的高度;支持实时语音聊天、Minecraft 和 Factorio 游玩,支持 Web / macOS / Windows。

项目地址:https://gitcode.com/moeru-ai/airi
点击查看免费下载

相关推荐

上一篇:如何在5分钟内开始使用afl.rs进行Rust代码模糊测试
下一篇:CodeGPT高级代理系统:10个实用工具助你高效编程的完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 3:26:08

反序列化漏洞原理与攻击面:从POP链到代码审计实战

反序列化漏洞&#xff0c;是我做代码审计时最常被问到的类型之一。早年有一次接到应急任务&#xff0c;某业务系统在Cookie里存了用户信息&#xff0c;入口处一行unserialize($_COOKIE[user])&#xff0c;当时我第一眼觉得“这不就是明显的反序列化点吗”&#xff0c;可真要构造…

作者头像 李华
网站建设 2026/10/16 3:25:51

UE5增强输入系统触发器详解:从引脚特征到参数配置实战

UE5的增强输入系统&#xff08;Enhanced Input System&#xff09;从推出以来&#xff0c;基本成了各类游戏项目做键位绑定、动作触发的事实标准。相比老的Input系统&#xff0c;它把“按键被按下”、“按住几秒”、“快速双击”这些行为全都抽象成了输入动作资产上的触发器&am…

作者头像 李华
网站建设 2026/10/16 3:25:46

pyq量化实战教程:从环境搭建到多策略组合的完整避坑指南

简介&#xff1a;这份课程资源面向希望用Python构建桌面多媒体应用的开发者&#xff0c;以PyQt为核心&#xff0c;带你完成一个功能完整的视频监控系统实战项目。内容覆盖PyQt基础组件与布局管理、QMediaPlayer与QVideoWidget视频播放、OpenCV摄像头接入、多线程处理避免界面卡…

作者头像 李华
网站建设 2026/10/16 3:24:58

高速高精EtherCAT运动控制方案:从展会demo到产线落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/16 3:24:48

2026跨平台开发选型:uni-app、uni-app x与Flutter深度对比

做跨平台开发的同学&#xff0c;最近两年应该没少刷到这几个名字&#xff1a;uni-app、uni-app x、Flutter。真要坐下来对比&#xff0c;又会发现网上的测评多半停留在“XX很牛、XX很坑”的情绪层面&#xff0c;参数对不上&#xff0c;场景也对不上。这篇文章我想尽量用工程视角…

作者头像 李华
网站建设 2026/10/16 3:24:46

AI视觉人数统计与智能门禁联动:构建本地化超员监管系统

这次我们看的不是某个开源框架&#xff0c;而是一个很现实的场景&#xff1a;托管房/公寓一次住了多少人&#xff0c;真的数得清吗&#xff1f;1818黄金眼的相关报道里出现过“89平方托管房住了20多个人”的案例。这类问题靠人工巡查很难根治&#xff0c;因为租客上下班时间不固…

作者头像 李华