☰
AI听见Android反馈:nl2sh+MCP+A2A打造设备端开发闭环
2026/10/22 19:59:58 网站建设 项目流程

让写代码的 AI 听见 Android 的反馈,这个想法是我在一次连续调试了六个小时 Android 崩溃问题之后冒出来的。当时某模型已经把代码写出来了,业务逻辑看起来也没毛病,可真扔到模拟器上一跑,不到三秒就抛异常。我一边翻 Logcat 一边把堆栈喂回去,让它改,它改了,再跑,又崩。如此反复,一晚上就在“复制报错、粘贴回给 AI、等它改、再编译再装”这个循环里耗掉了。那之后我开始认真琢磨一件事:既然 AI 已经能写代码了,为什么不能直接让它自己看见设备返回的结果?于是就有了基于 nl2sh 的这套小工具链,核心就两件事:让 MCP 把 Android 设备的实时状态投射到大模型上下文里,再用 A2A 协议让不同分工的 Agent 互相配合,形成一个“写代码—跑构建—看反馈—改代码”的设备端开发闭环。

这篇文章不会讲什么高深理论,就是把我折腾这套闭环过程中的设计思路、踩过的坑、以及可以直接拿走的实操方案完整写出来。适合那些正在尝试把大模型引入 Android 日常开发、但受困于“AI 只会写代码却对设备一无所知”的团队和个人开发者。

1. 项目缘起:为什么我会想做一个“AI 反馈闭环”

1.1 从“AI 写出代码”到“代码在 Android 上跑通”

先说说问题的根源。市面上各类 AI 编程工具已经非常能打了,你给它一句“写一个从相册选图然后做圆形裁剪的页面”,它很快能给你一段像模像样的 Kotlin 代码。但这只是第一步,而且是整个开发流程里最“虚假繁荣”的一步。真正消耗时间的是接下来这段:这段代码能不能编过?编过之后能不能装上?装上了之后运行会不会崩?崩了之后日志里在抱怨什么?这些反馈信息全部存在于本地环境、adb 通道、Gradle 输出和那一串串 Logcat 日志里,而写代码的 AI 默认是看不见它们的。传统工作流里,这些信息靠人眼去看,再靠人手动转换成自然语言喂给 AI。一个崩溃堆栈,复制粘贴的时候还要挑关键行,去掉冗余信息,这个预处理过程本身就是经验活。

我想做的东西说穿了就是把“人肉搬运反馈信息”这一步去掉。nl2sh 这个名字是我自己起的,意思是 Natural Language 2 Shell,能让 AI 直接把一句自然语言需求翻译成可以在开发机上执行的命令行操作,比如“重新编译并安装到第一台设备上”“把当前应用进程杀掉重启”“抓取最近 300 行日志并过滤掉 Noise 级别”。但这些命令只是手段,真正的价值在于把它们和 AI 的代码生成能力接在一起,让 AI 不仅会写代码,还能自己执行代码、自己看到执行结果。

1.2 项目的三个关键词:nl2sh、MCP、A2A

这套体系里三个关键词各管一段。nl2sh 负责的是“把意图变成命令”。它像是一个翻译层,接收大模型输出的结构化意图,转化成 shell 命令在开发机上执行,再把执行结果标准化后返回给 AI。你可以把它理解成 AI 的“手”,让 AI 不只是动嘴输出代码文本,还能实际碰一碰 Android SDK、Gradle 和 adb。

MCP 全称是 Model Context Protocol,它负责的是“把设备的实时状态变成 AI 能读懂的上下文”。MCP Server 在开发机上跑起来之后,可以把设备列表、构建结果、Logcat 日志等资源,按照协议的格式暴露给接入的大模型。MCP 的价值在于把这些设备信息变成了标准化的、可重用的上下文资源,而不是每次都要用提示词硬塞给模型的零散字符串。比如说“当前有哪些在线设备”这种问题,模型可以直接调用 MCP 工具获取,而不是靠人在 prompt 里手动填写。

A2A 则是 Agent 与 Agent 之间的通信协议。我在这套闭环里拆出了三个 Agent,一个负责写代码,一个负责执行构建与安装,一个负责分析运行日志。它们各有各的职责,互相之间通过 A2A 消息传递任务和结果。没有 A2A 的时候,我要把所有职责塞进一个系统提示词里,让同一个模型既当程序员又当测试又当运维,结果就是上下文乱成一锅粥,错误相互干扰。拆开之后每个 Agent 的上下文更干净,单个任务的准确率高了一大截。

1.3 这个闭环能解决什么问题,适合谁

这套闭环解决的核心问题,就是减少“人类作为 AI 与设备之间传话筒”的次数。写代码时,AI 负责生成和修改;构建时,AI 自己执行 Gradle 命令并读取失败原因;运行时,AI 自己装 App、自己拉日志、自己看堆栈。人只需要在关键节点确认方向,剩下的循环让它自己转。

适合谁来用?首先是那些已经有 CI 经验、对 adb 和 Gradle 命令不陌生的 Android 开发者,因为这套东西的原理不过就是把原来人手敲的命令交给 AI 去编排。其次是一个团队里负责搭基础设施的工程师,你完全可以把它做成内部工具,让团队里其他普通开发者在 IDE 之外也能对设备做更细粒度的调试。再就是那些在折腾 MCP 和 A2A 但找不到真实业务场景的人,Android 设备调试其实是个非常好的试验场,因为它反馈链路短、反馈信号明确、出错可观测性强。

我实际用下来的感受是,这套闭环对于“编译报错”“运行时崩溃”“布局不符合预期”这三类问题效果最显著。对于那种需要跨模块长期重构的大任务,AI 的上下文窗口还是会受限,这是当前阶段的客观限制,后面我会专门说。

2. MCP:给写代码的 AI 装上 Android 的“感知神经”

2.1 MCP 在闭环中的角色:把设备状态变成模型可读的上下文

MCP 的理念核心,是把“工具”变成“上下文资源”。你不用把设备列表硬塞进系统提示词里,而是让模型在你需要的时候自己通过 MCP 去取。就像人写代码时不会时刻盯着任务管理器,但一旦程序卡住了,会打开任务管理器看一眼——MCP 给 AI 提供的就是这种“按需感知”的能力。

在这套闭环里,MCP Server 跑在开发机上,通过 adb 与本地 Android 设备通信,通过协议接口与大模型侧通信。模型侧发起一次 MCP 工具调用,本质上就是一次远程过程调用,参数是自然语言描述,返回值是标准化的结构化数据。我们的 MCP Server 做了四件事:枚举在线设备、返回构建状态、读取 Logcat 日志、执行 shell 命令。这四件事覆盖了 Android 开发调试里 90% 的反馈需求。

为什么不直接在系统提示词里把所有设备信息写死?因为设备信息是动态的。一台设备可能在调试中途断连,一份日志可能每一秒都在刷新,构建状态会随代码变化而改变。系统提示词是静态的,MCP 是动态的。这是我选 MCP 而不是“prompt 搬运”的根本原因。

2.2 我暴露的 4 个 MCP 工具与它们的调用流程

实际实现时,我暴露了四个核心工具。第一个是获取设备列表,返回所有通过 adb 连接的设备及其状态。第二个是获取构建状态,接收一个项目路径参数,返回最近一次 Gradle 构建的结果、耗时和错误摘要。第三个是读取 Logcat,接收包名、日志级别、行数上限和时间范围,返回过滤后的日志片段。第四个是执行 shell 命令,接收命令字符串、超时时间和执行目录,返回标准输出与退出码。

这四个工具的调用流程有一个共同点:所有参数都经过白名单校验。比如执行 shell 命令这个工具,底层虽然是透传 adb shell,但命令前缀必须匹配预设的允许列表,否则直接拒绝。这个设计在后面安全边界那部分我会展开讲。从协议角度看,每个工具都实现了 MCP 的 tools/call 接口,输入输出用 JSON 结构化定义,模型可以基于这些定义自动生成调用参数,不需要人写任何胶水代码。

实际跑下来,调用频率最高的是读取 Logcat 和获取构建状态。前者一天要被调用几百次,因为 AI 每次改完代码都要看一次日志确认效果;后者则在自动修复循环里频繁触发。设备列表的调用频率反而低,但它的意义在于让 AI 知道“我在跟谁说话”,没有这个前置感知,后续所有操作都可能是对着一台离线设备空转。

2.3 MCP Server 的工程落地细节:传输、会话与上下文裁剪

落地 MCP Server 时有几个工程细节值得单独拿出来说。传输层方面,我采用了两个通道:stdio 通道供本地 CLI 工具直接挂载调用,SSE(Server-Sent Events)通道供远程 IDE 插件或另一台机器上的服务调用。本地开发用 stdio 最简单,零配置,进程起来就能连;远程场景则必须用 SSE,但需要注意断线重连的问题,MCP 客户端大多有自动重试机制,但服务端最好保证会话是可恢复的。

会话管理上,我做了 30 分钟空闲自动断开的策略。Android 开发中经常出现开发机休眠或者模拟器重启的情况,一个长时间挂着的 MCP 连接不仅浪费资源,而且会在设备状态变化后返回过期数据,误导模型的判断。断开后模型侧下次调用会自动重连,感知不到这个过程。

上下文裁剪是我觉得最值得讲的一点。Logcat 日志可能非常长,一次崩溃涉及的堆栈可能上千行,如果没有裁剪就全部塞给模型,上下文窗口会迅速被占满,模型会变得“短视”,只盯着最新几行看。我在 MCP Server 内部做了三层裁减:按级别过滤(只保留 Error 和 Warning 级别)、按包名过滤(只保留目标应用的日志)、按关键词提取(遇到 FATAL EXCEPTION 和 AndroidRuntime 时自动截取整个崩溃块)。这三层裁减做完,一次崩溃分析的日志量能从几千行压缩到十几行,模型的分析质量反而提升了。

提示:如果你自己实现 MCP Server,务必在“原始日志完整”和“模型上下文有限”之间做一个缓冲层。直接无脑灌日志会让模型输出质量断崖式下跌,这不是模型变笨了,而是有效信号被海量噪声淹没了。

3. A2A:让多个 Agent 协作,而不是一个 Agent 硬扛

3.1 为什么单 Agent 不够用:角色拆分

最开始我尝试过只用一个大模型 Agent,让它既理解自然语言需求、又生成代码、又执行 shell 命令、又分析日志。结果很惨烈:它经常在执行命令失败后陷入自我怀疑,把“分析日志”和“修改代码”这两件事搅在一起,一会说代码有问题,一会说设备有问题,上下文里全是相互矛盾的中间推理。核心问题是单个 Agent 的上下文窗口是共享的,职责混杂导致推理链条互相污染。

A2A 的思路是把一个大而全的 Agent 拆成三个小而专的 Agent,它们各自有独立的系统提示词、独立的上下文窗口,只通过 A2A 消息交换必要的信息。写代码的 Agent 永远不接触原始的 Logcat 堆栈,它只接收分析 Agent 整理好的、已经定位到具体文件和行号的修复建议;执行命令的 Agent 永远不碰业务代码,它只负责把命令跑好并返回退出码和关键输出。

这个拆分的直接收益是单 Agent 的上下文变干净了。写代码 Agent 的上下文里全是 Kotlin 代码和编译错误信息,分析 Agent 的上下文里全是日志摘要和堆栈切片。每种信息都流向了最需要它的 Agent,不再互相干扰。

3.2 Agent 之间的消息流设计

A2A 协议的消息本质上是 JSON-RPC 风格的请求与响应,定义里有任务的创建、派发、状态更新和结果回传等动作。我在这套系统里设计了一个很精简的消息流转逻辑。

一个典型的自动修复流程是这样的:调度器(我写的一个本地进程)收到一条来自用户的自然语言指令,比如“写一个带缓存功能的网络图片加载器,并在模拟器上验证”。调度器创建任务后,首先发给写代码 Agent,它生成代码并返回带有文件路径和修改点描述的消息。调度器再把这条消息连同项目路径一起发给执行 Agent,执行 Agent 调用 MCP 工具完成构建和安装。如果构建失败,执行 Agent 返回退出码和编译错误摘要,调度器将这条消息转发给写代码 Agent,同时附上修改建议,写代码 Agent 进行第二轮修改。如果构建成功并安装运行,执行 Agent 会通过 MCP 拉取 Logcat,将日志原始内容发送给分析 Agent,分析 Agent 判断是否存在崩溃或异常,若存在则提取关键堆栈并生成“问题定位报告”,回传给写代码 Agent 触发新一轮修复。

这个设计的精妙之处在于:每个 Agent 都不需要知道全貌。写代码 Agent 不知道设备具体型号,它只看到“修复建议:MainActivity.kt 第 88 行有空指针风险”;分析 Agent 不知道代码改动内容,它只看到日志和堆栈。这种“按需暴露”的信息流设计,让整个系统在行为上像一个整体,但内部又是解耦的。

3.3 A2A 协议落地时要注意的事

A2A 在落地时有一个非常现实的问题:协议很新,工具链远没有 MCP 成熟。我建议不要一上来就去追求完整的协议实现,先把最小可用闭环跑通。我在最开始的时候只实现了三个消息动作:任务创建、任务状态查询、结果消息回传。这三个动作加上 JSON-RPC 的格式约束,已经能满足绝大多数 Agent 协作需求。

另一个要注意的是消息的超时与重试。Agent 之间的通信不是即时的,一个写代码 Agent 可能需要在本地加载上下文、调用模型、生成代码,这个过程可能要十几秒甚至更久。调度器必须给每个子任务设置合理的超时时间,并且要在超时后能进行有限度的重试。我给写代码 Agent 设的是 120 秒超时,执行 Agent 设的是 60 秒超时,分析 Agent 设的是 30 秒超时。这些数值是不断调出来的,一开始太保守导致频繁误判超时,后来放宽了一个数量级才稳定下来。

A2A 消息体里还有一个容易被忽略的字段:任务的优先级。当你的系统里同时跑着多个调试任务时,没有优先级就会出现低价值任务把执行 Agent 占满、高价值任务排不上队的问题。我在任务创建时加了一个 0 到 9 的优先级字段,默认值是 5,紧急修复任务设为 9,批量回归任务设为 2。调度器按优先级从高到低派发,同优先级按先来后到。

4. 端到端闭环实操:从一句需求到一次自动修复

4.1 闭环运转的完整流程

整理一下整个闭环的运转流程,用我们最常用的场景来举例:开发者对着终端说了一句“新写一个页面,展示设备当前的电池健康度,并且跑起来验证不崩溃”。

第一步,nl2sh 的解析层拿到这句自然语言,提取出意图(新建页面、功能是显示电池健康度、目标动作是运行验证)。第二步,调度器创建 A2A 主任务,把意图下发给写代码 Agent,要求它生成一段可以独立编译的 Compose 页面代码。第三步,写代码 Agent 完成代码,返回修改文件清单。第四步,调度器把项目路径和代码变更信息打包给执行 Agent,执行 Agent 调用 MCP 构建工具,触发 Gradle 编译。第五步,构建通过后,执行 Agent 继续调用 MCP 的安装工具,把 APK 装到指定设备上,再调用启动命令拉起应用。第六步,应用启动三秒后,执行 Agent 调用 MCP 日志工具抓取 Logcat。第七步,日志原始数据被发送给分析 Agent,分析 Agent 判断是否有 FATAL EXCEPTION,没有异常则输出“验证通过”,有异常则输出定位报告。第八步,调度器把定位报告回传给写代码 Agent,触发修复循环。

这个流程看起来环节不少,但每一步都是自动的,整个“从需求到验证通过”的耗时平均在三到五分钟,其中大部分时间花在 Gradle 编译上。如果是增量编译,耗时能压缩到两分钟以内。对比人工处理同样任务通常需要的半小时以上,效率提升非常明显。

4.2 核心代码片段:nl2sh 的解析与派发

nl2sh 是整个闭环里最贴近用户的一层。它的核心逻辑是把自然语言指令拆解成结构化的任务描述。我并没有自己做复杂的 NLP 解析,而是借用了大模型的 Function Calling 能力:把“新建页面”“执行构建”“分析崩溃”“重新安装”“拉取日志”这些动作定义成 JSON Schema,让模型直接把用户输入映射成结构化输出。

下面这段是经过大量精简后的伪代码,展示了 nl2sh 从收到用户输入到派发 A2A 任务的完整路径:

import json from dataclasses import dataclass @dataclass class ParsedIntent: action: str # 例如: create_page / run_verify / fix_crash target: str # 例如: BatteryHealthPage.kt device_id: str # 例如: emulator-5554 priority: int # 0-9 def parse_user_input(text: str, llm_func) -> ParsedIntent: # 核心:把文本输入交给大模型,要求按 JSON Schema 返回结构化结果 schema = { "action": ["create_page", "run_verify", "fix_crash", "read_log"], "target": "string", "device_id": "string", "priority": "integer" } response_json = llm_func(text, schema) return ParsedIntent(**json.loads(response_json)) def dispatch_to_agents(intent: ParsedIntent): # 创建 A2A 任务,按动作类型决定先派发给哪个 Agent if intent.action == "create_page": a2a_client.create_task( agent="code_agent", payload={"request": intent.target}, priority=intent.priority ) elif intent.action == "run_verify": a2a_client.create_task( agent="executor_agent", payload={"project_dir": PROJECT_DIR, "device_id": intent.device_id}, priority=intent.priority )

实际的实现里还会有更多的防御逻辑,比如 Schema 校验失败时的 fallback 提示、设备 ID 为空时自动选择第一个在线设备等。但从这段代码可以看到,nl2sh 并没有多么高深的技术,它做的是任务理解和任务分发,真正的执行闭环是依靠 MCP 和 A2A 在背后撑起来的。

4.3 一个真实的调试会话实录

讲一个实际的调试会话过程,方便大家直观感受这套闭环是怎么工作的。有一次测试里,我让系统开发一个用 RecycleView 展示内容列表的页面,跑在像素模拟器上。第一轮,写代码 Agent 生成了一段标准的 Adapter 代码,执行 Agent 调用 MCP 构建工具,Gradle 增量编译大概用了五十多秒,构建失败。编译错误摘要显示是布局文件里一个 TextView 的 id 引用不存在。执行 Agent 把这段错误摘要打包,由调度器发给写代码 Agent。写代码 Agent 收到后,很快定位到问题,补上了缺失的 id,并返回了修改点描述。第二轮构建就通过了,APK 安装到模拟器,应用启动三秒后,执行 Agent 抓取 Logcat。

这一轮日志里出现了 FATAL EXCEPTION,一个空指针异常,堆栈指向 Adapter 里某个 ViewHolder 的 onCreateViewHolder 方法。执行 Agent 把日志发给分析 Agent,分析 Agent 过滤后得出了简洁的定位报告:“空指针发生在第 64 行,context 参数在传入时为 null,建议检查 Activity 中调用 Adapter 的位置是否传入了有效 context。”调度器把这个报告回传给写代码 Agent,于是它开始第三轮修改:在 Activity 初始化 Adapter 的地方补上正确的 context 传递。第三轮构建通过,安装启动,Logcat 持续观察三十秒无异常,闭环任务结束,系统输出“验证通过”。

整个过程里我只参与了一件事:在最初的提示词里说清楚需求。后面所有的编译、报错、分析、修改,全部由这个 MCP 与 A2A 组合成的闭环自动完成了。这种体验在过去是不可想象的。

4.4 安全边界:命令权限、超时控制、人工确认

写代码的 AI 一旦能够直接操作本地环境,安全边界就是必须认真对待的事情。我在这个闭环里做了三道防线。

第一道防线是命令白名单。nl2sh 的 shell 工具底层只允许执行预先定义好的命令模板,例如gradle :app:assembleDebug、adb install -r、adb shell am start、adb logcat -d。不允许执行任意拼接的复杂 shell 指令,尤其不允许出现管道符、重定向符和 eval 类操作。这样即使模型产生了恶意或者错误的意图,也无法越权执行超出范围的命令。

第二道防线是超时熔断。执行 Agent 的每一次 MCP 调用都要有超时上限,默认 60 秒,如果超时就自动终止对应进程并返回超时错误。这个机制防止了 Gradle 挂死、adb 卡住这类问题把整个闭环拖死。有一点需要注意:超时不等于报错,超时信息也要回传给调度器和写代码 Agent,让它们知道“刚才的操作没有成功完成,换一种方式再试”。

第三道防线是危险操作人工确认。凡是涉及卸载应用、清除数据、格式化、重启设备这一类不可逆的操作,nl2sh 不会直接执行,而是先把命令挂起,给用户终端弹一个确认提示。这个设计很笨但很管用,有一次模型真的建议用adb uninstall清掉某个基础应用,如果不是有人工确认这道关卡,团队里那位同事的测试机可能就惨了。

注意:模型生成的命令再“合理”,也要先过白名单再执行。你永远不知道它在推理过程中会把哪个前一步的失败归因到环境上,然后产生一个你完全没设想过的大胆操作。

5. 常见问题与排查技巧实录

5.1 问题速查表

在实际搭建和运行这套闭环的过程中,我整理了下面这些高频问题,基本覆盖了从协议联调到日常使用的大部分故障场景:

症状可能原因排查与解决方案
MCP 工具调用超时adb 服务状态异常,或设备休眠先执行adb kill-server再执行adb start-server;确保宿主机休眠策略关闭
Logcat 抓回来是空的目标应用进程已死,或包名过滤错误先查adb shell ps确认应用进程存在;改用adb logcat -d --pid=<pid>按进程而非包名过滤
Gradle 构建默认走了全量编译增量编译失效,构建缓存被污染删除build目录下的缓存文件,但保留 Gradle 的用户级缓存;检查是否改了 Kotlin 脚本本身
写代码 Agent 反复修改同一处代码分析 Agent 的定位报告不够精确检查日志裁剪级别是否过严,把关键堆栈里“at 包名.类名.方法名(文件.kt:行号)”格式的行完整保留
A2A 消息丢失导致任务挂起任务状态查询没有设置超时与重试给调度器增加心跳机制,超过 N 秒无状态更新自动重新查询一次任务状态
多设备在线时操作到错误的设备设备 ID 没有显式传递到底层 MCP 工具强制在任务创建时就确定 device_id,不允许执行 Agent 绕过参数自行选择设备
模型上下文被日志占满,回答质量下降原始日志直接透传,没有做上下文裁剪在 MCP Server 内部强制开启三级过滤,并且把裁剪后的日志字节数限制在 4KB 以内

这张表里的每一条都是我真实遇到过的问题。印象最深的是日志抓取为空那一次,排查了半天发现应用是在启动三秒后才崩溃,而日志抓取发生在启动后一秒,等于什么都还没发生就去抓了。后来把抓取时机调整到“启动后等三秒再执行”,问题直接消失。

5.2 几条有味道的避坑经验

聊几条常规文档里不太会写的实战心得。

第一,MCP 工具返回结构一定要扁平且带明确的 success 字段。模型是靠着 JSON 结构来理解返回内容的,如果返回里嵌套了三层字典,模型在推理过程中很容易丢失关键信息。我后来的统一返回格式是{success: true/false, code: 0/非0, message: 摘要, data: 具体内容},模型对这个结构的理解准确率明显高于自由格式。

第二,A2A 的 Agent 消息里必须带“意图摘要”,不能只扔原始数据。比如执行 Agent 返回给分析 Agent 的消息,不能只是一大段 Logcat,要在前面加一句“这是应用启动三秒后的日志,重点查看有无 FATAL EXCEPTION”。Model 跟人一样,有提示和没提示的处理质量差别很大。

第三,日志分析 Agent 不要用体系太复杂的模型。分析日志任务的特点是输入短、逻辑单一、对推理深度要求不高,但对吞吐量有要求。把分析日志的任务交给轻量模型,把写代码的任务交给重量模型,能让整个系统在成本和速度上取得更好的平衡。

第四,一定要给每个 Agent 加独立的 token 用量监控。Agent 化了之后,原来的“一次对话用了多少 token”变成“系统一轮调试用了多少 token”,如果不管控,一天调试个几十轮,token 消耗会非常惊人。我在调度器里加了简单的统计:每轮调试结束后输出各 Agent 的 token 开销,超过预设阈值自动触发人类确认。

6. 项目效果、局限与下一步

6.1 实测效果与适用边界

这套 nl2sh + MCP + A2A 闭环搭建完成之后,我让它在模拟器和一台老旧的实体测试机上跑了两个星期,覆盖了页面开发、崩溃修复、布局调整三类典型任务。从数据上看,简单功能从需求到验证通过的平均耗时从人工调试的四十分钟左右,降到了系统自动闭环的五分钟以内。崩溃修复类任务的自动成功率大约在七成,剩下三成失败的原因大多是涉及多文件联动的逻辑问题,AI 单靠 Logcat 堆栈不足以推断出完整业务上下文。

但适用边界必须说清楚。这套闭环适合的是“在当前项目结构下、以当前依赖为基础的开发调试”,它不适合做跨模块的大型重构,也不适合在 CI 上完全替代人工 Code Review。模型生成的代码风格稳定性和组织性也有天花板,我目前还是会让核心代码变更经过人眼确认。设备和依赖管理越复杂,闭环的出错率就越高,但即便如此,这套体系也比“人肉搬运报错”的老路要高效得多。

6.2 后续可扩展的方向

后续有一个方向我特别想继续推进:把设备端 UI 状态也纳入 MCP 的反馈源。目前 Logcat 和构建状态这种“文本化反馈”已经做得很顺了,但界面的实际渲染效果——按钮位置对不对、布局有没有溢出、颜色有没有偏——这些视觉信息还是靠人看截图。如果能在 MCP Server 里接一条截屏路径,让 AI 定期拉取设备屏幕截图并做视觉理解,闭环就能从“不崩溃”升级到“看起来对”,这是质的飞跃。

另一个明显的扩展方向是把这个闭环接入到现有 IDE 工作流里。目前我的使用方式还是偏向命令行交互,但对很多开发者来说,他们希望直接在编辑器里看到 AI 的修改和设备的反馈。MCP 天然支持这种集成方式,理论上只要在 IDE 插件里挂一个 MCP 客户端,就能把设备状态、构建结果和日志流都变成编辑器里的实时上下文,这个方向值得再做一版。

最后说说我个人的体会。这套东西从有了想法到跑通第一个完整修复循环,用了大概一周的业余时间,过程中最大的障碍不是协议有多难,而是“让 AI 相信设备返回的信息是真实的”。前几次调试时,模型收到崩溃堆栈后经常倾向于认为“堆栈可能是旧的”“日志可能被截断了”,然后开始瞎猜原因。后来我在 MCP 返回信息里显式加了一个captured_at时间戳字段,并且让调度器在消息里强调“这是刚刚抓取的最新日志”,模型才开始认真对待数据。这个细节让我印象深刻:AI 的连接性,不仅是协议层面的连接,也是信任层面的连接。当它能确信自己“听见”的就是设备的真实声音时,它才敢真正开始动手解决问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询