MCP 手机控制 Server(mcp_server/)
多模态 AI(DeepSeek/Claude 等)通过 MCP(Model Context Protocol) 实时操作 Android 手机的统一出口。AI 控制台(mcp_agent/)与外部 MCP 客户端都经它控制设备池中的手机。
本文档 = 使用手册(工具清单/用法)。架构与演进设计见 MCP_DESIGN.md。
架构
- 轻量通道直连(adb monkey 开 App、u2 输入、本地 OCR)不绕平台,省时省 token
- 坐标换算、UI 吸附、剪贴板注入等细节全部在 Server 层消化,模型只需给意图
运行与配置
服务跑在 220 的 python-app 容器内(scripts/start.sh 自动拉起,端口 8033)。
生产访问方式:http://192.168.20.220:8033/mcp;本机调试 python3 -m mcp_server.mcp_server。
| 环境变量 |
默认 |
说明 |
MCP_PLATFORM_URL |
http://127.0.0.1:18050 |
平台地址(Agent 与平台同机时用本机) |
MCP_PLATFORM_USER / MCP_PLATFORM_PASS |
admin / 空 |
平台登录账号 |
MCP_ALLOW_WRITE |
0 |
写门控:=1 才允许点击/输入/开关 App 等写操作(只读工具不受限) |
MCP_ALLOWED_SERIALS |
空=不限 |
设备白名单(逗号分隔),非空时只允许列出的 serial |
MCP_HTTP_HOST / MCP_HTTP_PORT |
0.0.0.0 / 8033 |
监听地址 |
MCP_SCREENSHOT_WIDTH |
540 |
截图返回宽度上限(px),模型看到的图即该坐标系 |
MCP_JPEG_QUALITY |
70 |
截图 JPEG 质量 |
MCP_AUDIT_FILE |
/var/log/mcp/audit.log |
审计日志(每次工具调用一行) |
MCP_PLATFORM_TIMEOUT |
30 |
平台请求超时(秒) |
生产(220 容器)已设 MCP_ALLOW_WRITE=1;MCP_ALLOWED_SERIALS 未设(= 平台设备池内可操作)。
坐标空间(重要约定)
de_screenshot 返回 ≤540px 宽的 JPEG(display 空间),并附 native_size(设备原生分辨率)
de_tap / de_swipe 的坐标一律使用 de_screenshot 返回图像的坐标系,Server 按比例换算为原生坐标
- 先截图、后点击:Server 需要最近一次截图才能建立坐标空间(未截图就点击会报「请先执行 de_screenshot」)
de_tap 带自动吸附:点击点若落在某个可点击元素内,实际会点该元素中心——坐标只需大致对准,偏十几像素也能点准;点空白处则按原坐标
- 返回的
snapped/label 可核对吸附结果(snapped=true 表示已吸到元素,label 为该元素文案)
工具清单(19 个)
设备与状态
| 工具 |
用途 |
de_list_devices |
列出可控制设备:serial / 型号 / 在线 / 任务状态 / 前台 App。开局第一步 |
de_foreground_app(serial) |
当前前台 App 包名(dumpsys,MIUI 焦点为空时自动兜底) |
观察屏幕(感知)
| 工具 |
用途 |
de_screenshot(serial) |
截图并返回图像(≤540px JPEG)+ 尺寸 + 亮/熄屏状态。多模态模型直接看图 |
de_ui_tree(serial, limit=150) |
当前界面元素树(text/id/desc/class/bounds)。可点击元素排前;limit 1-300 控制条数防 token 膨胀。用于确认界面上有什么 |
de_ocr(serial) |
OCR 识别当前屏幕文字(UI 树没有的图片/WebView 文字也能识别),返回 [{text, score}] |
点击与滑动(操作)
| 工具 |
用途 |
de_tap_text(serial, text) |
按屏幕文字点击(推荐):给一个屏幕上可见的文字(子串匹配)即找到并点其中心。原生控件走 UI 树,WebView/图片文字自动 OCR 兜底。找不到返回明确错误 |
de_tap_element(serial, by, value, index=1) |
按元素点击:by = text / id / desc(精确)或 text_contains / desc_contains(模糊)。多命中用 index 取第几个 |
de_tap(serial, x, y) |
坐标点击(截图坐标系,自动吸附,见上)。纯图形目标(视频画面/无文字图标)才用它 |
de_swipe(serial, x1,y1,x2,y2, duration=0.2) |
滑动(截图坐标系;长按=同点起止 + duration≥1) |
de_press_key(serial, key) |
按键:back / home / recent / menu / power / volume_up / volume_down / enter / delete / search / camera |
输入与剪贴板
| 工具 |
用途 |
de_type_text(serial, text) |
向当前界面输入框输入文字(支持中文,直设 EditText 不依赖剪贴板/粘贴) |
de_set_clipboard(serial, text) |
写入设备剪贴板(ClipInject 通道注入 + 读回验证) |
de_read_clipboard(serial) |
读取设备当前剪贴板内容 |
App 管理(轻量 adb 直连,不建 u2 会话)
| 工具 |
用途 |
de_open_app(serial, package) |
打开 App(adb monkey 直启,无需知道 activity——最快的打开路径) |
de_stop_app(serial, package) |
强制停止 App(am force-stop) |
de_list_apps(serial, keyword="") |
列出第三方已装应用(pm list packages -3),keyword 可过滤(如 "douyin") |
de_sleep(serial) |
熄屏(运行中任务会中断,慎用) |
de_wake(serial) |
亮屏并解锁(熄屏时先调它再截图) |
平台联动
| 工具 |
用途 |
de_list_tasks() |
列出平台任务计划(名称/类型/启用/调度),了解已自动化的工作 |
推荐使用模式(操作手机的正确姿势)
de_list_devices 确认目标设备在线
de_screenshot 看图理解当前界面(图像会在下一次模型回合送达)
- 点击定位优先级(从高到低):
- 目标有可见文字 →
de_tap_text(一次调用完成「找到并点击」,最可靠)
- 文字有歧义/多候选 →
de_ui_tree 确认后 de_tap_element(text_contains 模糊匹配)
- 纯图形目标 →
de_tap 坐标(无需精算,Server 自动吸附到可点元素中心)
- 输入文字:先点中输入框(de_tap_text / de_tap),再
de_type_text
- 每次关键操作后
de_screenshot 验证:界面变化 = 成功;无变化 = 未命中,换 de_tap_text / de_tap_element 重新定位,不要重复点同一坐标
- 完成/失败时用中文总结:做了什么、当前状态、注意事项
- 效率约束:界面未变不重复截图/点同位置;连续 6 步无进展停止并总结
安全与审计
- 写门控:
MCP_ALLOW_WRITE=0(默认)时点击/输入/开关 App 全部拒绝,只读工具可用
- 设备白名单:
MCP_ALLOWED_SERIALS 非空时限制可操作的 serial
- 审计日志:每次调用记录
{ts, tool, serial, args, result} 到 MCP_AUDIT_FILE(220 上 /tmp/mcp_audit.log)
- 操作对象限定平台设备池;
adb kill-server / adb disconnect 属项目红线,任何工具不触碰
客户端接入示例
AI 控制台(内置 Agent)
Web 端「AI 控制台」Tab 内建的 Agent(mcp_agent/,OpenAI 兼容协议:DeepSeek 等)也通过本 Server 的同一批工具跑任务:
- 流式输出 + 每步 MCP 工具调用实时展示(含截图缩略)
- 多轮会话记忆(同会话上下文保留,新建会话清空)
- 自进化经验记忆:一轮成功操作会被提炼成「配方」存入
agent_experience 表,下次相似任务自动注入参考(命中/写入均有 🧠 提示卡)
- 模型与 API Key 在 AI 控制台右上角 ⚙ 配置,存平台
app_meta