Manos MCP

Manos MCP

A Model Context Protocol server for ad-hoc UI testing of Android and iOS apps, enabling LLM agents to interact with mobile app UIs and react to observations.

Category
访问服务器

README

Manos

A CLI Model Context Protocol server for ad-hoc UI testing of Android & iOS apps — purpose-built for the exploratory, test-free loop where an LLM agent pokes at an app and reacts to what it sees.

It controls Android emulators/devices (adb) and iOS simulators (xcrun simctl, with idb for native UI interaction) and exposes 39 tools over stdio.

manos gives an agent a tight act → observe loop, device-condition control, crash/log capture, network capture for debug builds, OCR targeting for off-tree elements, an accessibility audit, and session recording that promotes an ad-hoc exploration into a replayable regression test in one call. See IMPROVEMENTS.md for the design rationale and roadmap.

Install

npm install -g manos     # install the CLI, or run on demand with: npx -y manos
manos doctor             # check toolchain + list devices & capabilities

Requires Node 20+. Most MCP clients can launch manos on demand with npx — no global install needed; see Register with an MCP client. Working on manos itself? See From source.

Backend Used for Install
adb all Android control Android platform-tools (auto-detected from $ANDROID_HOME or the default SDK path)
xcrun simctl iOS lifecycle, conditions, logs, screenshots, push xcode-select --install
idb fast native iOS UI inspect/tap/type brew install idb-companion && pipx install fb-idb
maestro under the hood: run_flow, the warm hierarchy engine, and the cross-platform inspect/interaction fallback https://maestro.dev

iOS UI interaction works without idb by falling back to Maestro (slower; call launch_app first). Android UI inspection falls back from uiautomator dump to maestro hierarchy automatically when the on-device UiAutomation connection is contended.

Register with an MCP client

Each tab launches manos with npx -y manos serve, which fetches and runs the published package on demand — no clone or global install required. (If you installed globally with npm install -g manos, use a bare manos serve instead.)

<details open> <summary><b>Claude Code</b></summary>

claude mcp add manos -- npx -y manos serve
claude mcp list            # verify

</details>

<details> <summary><b>Claude Desktop</b></summary>

Edit claude_desktop_config.json (macOS ~/Library/Application Support/Claude/, Windows %APPDATA%\Claude\) and restart the app:

{
  "mcpServers": {
    "manos": { "command": "npx", "args": ["-y", "manos", "serve"] }
  }
}

</details>

<details> <summary><b>Cursor</b></summary>

.cursor/mcp.json (project) or ~/.cursor/mcp.json (global), then enable manos under Settings → MCP:

{
  "mcpServers": {
    "manos": { "command": "npx", "args": ["-y", "manos", "serve"] }
  }
}

</details>

<details> <summary><b>VS Code (GitHub Copilot agent mode)</b></summary>

.vscode/mcp.json — note the servers key and explicit type:

{
  "servers": {
    "manos": { "type": "stdio", "command": "npx", "args": ["-y", "manos", "serve"] }
  }
}

</details>

<details> <summary><b>Windsurf</b></summary>

~/.codeium/windsurf/mcp_config.json, then hit Refresh in the Windsurf MCP panel:

{
  "mcpServers": {
    "manos": { "command": "npx", "args": ["-y", "manos", "serve"] }
  }
}

</details>

<details> <summary><b>Other / generic MCP client</b></summary>

Any MCP-capable client speaks the same stdio protocol. Configure a server that runs:

command: npx
args:    ["-y", "manos", "serve"]
transport: stdio

</details>

From source

For working on manos itself, or to pin a local build instead of the published package:

git clone https://github.com/ryanperkins/Manos-MCP.git && cd Manos-MCP
npm install            # also builds via the prepare script
npm run build          # or rebuild after changes
node dist/cli.js doctor

Register the local build by pointing your client's command/args at node /ABS/PATH/to/Manos-MCP/dist/cli.js serve instead of the npx form above.

CLI

manos serve      Start the MCP server on stdio (default)
manos doctor     Toolchain + connected devices + per-device capabilities
manos devices    List connected devices (tab-separated)
manos --help

The tools

Full reference and the Android vs iOS comparison matrix are in docs/index.html. Highlights:

  • Core: list_devices, device_capabilities, inspect_screen, take_screenshot.
  • Authored flows: run_flow runs a declarative flow locally; cheat_sheet gives the syntax. export_flow (below) turns a recorded session into one.
  • Act + observe: tap, long_press, input_text, press_key, swipe — each takes a selector (id/text/resource_id/accessibility) or coordinates and returns the resulting screen (observe: screen | diff | screenshot | none).
  • Smart waits / assertions / search: wait_for, assert, find_elements, and find_text (OCR the screenshot to locate text the accessibility tree misses — styled buttons, canvas/Flutter/game UIs, WebViews). Targeting falls back to OCR automatically when a text selector finds nothing in the tree, or force it with tap{text, ocr:true}.
  • App state: launch_app, stop_app, clear_app_state, open_deeplink, set_permission.
  • Device conditions: set_appearance, set_orientation, set_locale, set_network, set_location, set_font_scale, set_status_bar, push_notification, and set_conditions (apply many at once / named presets like offline, accessibility, screenshot).
  • Diagnostics: get_logs (with crash/ANR detection), a11y_audit.
  • Network capture (debug apps): network_start/network_requests/network_clear/network_stop — capture decrypted HTTP filtered to specific endpoints. Android hooks OkHttp via Frida (works through HTTP/2, pinning, proxy-bypass); iOS Simulator uses mitmproxy + a simctl-trusted CA. See NETWORK.md.
  • Recording: start_recording → act → export_flow (replayable Maestro flow) or export_report (self-contained HTML report: screenshot timeline + flow + logs + captured network).

A typical loop:

list_devices → inspect_screen → tap{text:"Login", observe:"diff"} → input_text{...} → wait_for{text:"Welcome"}

How element targeting works

inspect_screen returns a compact tree where every node has a stable id derived from its semantic identity (resource-id / accessibility / class + digit-normalized text), not its position. So a counter ticking from 5 to 6 keeps its id and shows up as a changed node in a diff, while a newly-appeared element is added. Act tools accept that id, a text/resource-id selector, or raw coordinates; when you use a selector, the recorded flow stores the selector (resilient replay) rather than brittle coordinates.

Performance

Hierarchy reads use a three-tier backend, chosen per device:

  1. adb uiautomator dump (~2.5s, no extra process) — the default on Android. Tried first.
  2. Warm hierarchy engine — when uiautomator can't reach UI-idle (e.g. apps with constant animations/watermarks, where uiautomator dump errors with could not get idle state), manos keeps one long-lived maestro mcp child resident (used under the hood) and reuses its connected driver. First call pays a one-time warm-up; subsequent inspects are ~150–300ms — the payoff of reusing a resident engine instead of cold-starting the JVM per call.
  3. Cold maestro hierarchy CLI — last resort if the warm session can't start.

Once a device needs the warm session, manos remembers it (per-device) so it doesn't re-pay the uiautomator timeout on every inspect. Screen size/density are cached. The warm child (and its simulator-server) are killed via a process-tree cleanup on exit.

Measured on a hard case (an app that never idles, so everything routes through the warm session):

First inspect (one-time) Steady-state inspect (median) Full tap+observe loop
manos ~11s ~175ms ~3s (was ~35s with cold per-call CLI)

So: on apps where uiautomator works, the adb path is fast with no extra process; on apps that force the fallback, the resident warm engine keeps steady-state inspect in the ~175ms range, and the act+observe loop avoids the per-action JVM cold-start that made it slow before. The remaining first-call cost is the one-time uiautomator probe before switching to warm.

Architecture

src/
  cli.ts                 serve / doctor / devices
  server.ts              McpServer wiring (stdio)
  tools/
    register.ts          all 39 tools
    context.ts           shared state: resolveTarget + act/observe + last-screen cache
  drivers/
    types.ts             Driver contract + Capability model
    android.ts           adb
    ios.ts               simctl + idb (+ maestro fallback)
    registry.ts          device → driver routing
  core/
    hierarchy.ts         compact JSON, stable ids, screen diff, search
    a11y.ts              accessibility heuristics
    waits.ts             condition polling
    session.ts           action journal
    flow.ts              Maestro-flow emitter
    maestro.ts           maestro CLI passthrough (run_flow, cheat sheet)
    maestroDriver.ts     cold maestro hierarchy + one-shot action fallbacks
    maestroSession.ts    warm long-lived `maestro mcp` backend (fast hierarchy/actions)
    netcapture.ts        network capture (Frida OkHttp / mitmproxy) — see NETWORK.md
    ocr.ts               OCR fallback (Apple Vision / Tesseract) for off-tree elements
  assets/frida/          okhttp-capture.js + sidecar.py (injected by netcapture)
  util/                  exec + toolchain discovery

Each driver method may throw a CapabilityError; tools surface it as an actionable message instead of an opaque subprocess failure. The capability model is reported live so an agent can check support before relying on a platform-specific action.

Test

npm test    # unit tests for hierarchy/diff/a11y/flow (no device needed)

The hierarchy parsing, stable-id diffing, accessibility math, screenshot capture, log/crash scan, and the recording→export_flowmaestro check-syntax pipeline have also been verified end-to-end against a live Android emulator.

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选