Open source · MIT · v0.2 · in active development
Think of it as the Playwright for mobile

Let your AI agent
drive real mobile apps

maestro-mcp is an MCP server with 32 tools to automate iOS & Android apps — tap, type, swipe, assert, screenshot, deep-link — built on Maestro. Like Playwright for the web, it gives mobile one reliable, code-aware API, native to AI agents through the Model Context Protocol.

32
MCP tools
180
passing tests
2
platforms (iOS + Android)
1
API for both platforms
What it is

Automate mobile apps, not just test them

Like Playwright, it's a reliable automation layer for real apps — tap, type, swipe, assert, navigate, set permissions, deep-link, mock location. Use it to drive flows, reproduce bugs, capture screenshots, or build agents that operate your app. One API for iOS and Android, code-aware and agent-native.

📱

Cross-platform by design

One unified API for iOS simulators and Android emulators. The server auto-detects the platform from the device ID and adapts each step (e.g. iOS has no back button → swipe-from-edge gesture).

🔍

Code-aware selectors

Static analysis of Swift (SwiftUI/UIKit), Kotlin (Jetpack Compose), and Android layout XML maps your screens, buttons, and navigation — so automation targets real elements, not brittle guesses.

⚙️

Code, not YAML boilerplate

Describe a flow as steps; the server compiles it to Maestro, runs it, and returns the result. Like Playwright's API over raw browser commands — built-in templates for login, navigation, search, and forms.

🩺

Rich failure diagnostics

When a flow fails you get the UI hierarchy, failure screenshots inline, and pattern-based diagnostics (Metro, element-not-found, crash, timeout, network) with concrete fix suggestions.

How it works

From source code to a driven app

01 · scan

Scan project

Detect platform, app IDs, screens and UI elements from native source.

02 · target

Map selectors

Turn discovered screens into reliable element targets for automation.

03 · drive

Run the flow

Compile steps to Maestro, execute on a real device or emulator.

04 · observe

Inspect

Screenshots, UI hierarchy, and diagnostics on every step.

Add it to any MCP client

// .mcp.json
{
  "mcpServers": {
    "maestro-mcp": {
      "command": "node",
      "args": ["dist/index.js"]
    }
  }
}
Install

One command, every client

No clone, no build. Runs from npm via npx — point any MCP client at the same command. Works in Claude Code, Cursor, Windsurf, Claude Desktop, VS Code, and Codex CLI.

⌨️ Claude Code

claude mcp add maestro -- \
  npx -y @luxurylabs/maestro-mcp

🖱️ Cursor

~/.cursor/mcp.json
{ "mcpServers": { "maestro": {
  "command": "npx",
  "args": ["-y", "@luxurylabs/maestro-mcp"] } } }

🌊 Windsurf

~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "maestro": {
  "command": "npx",
  "args": ["-y", "@luxurylabs/maestro-mcp"] } } }

🖥️ Codex CLI · TOML

~/.codex/config.toml
[mcp_servers.maestro]
command = "npx"
args = ["-y", "@luxurylabs/maestro-mcp"]

Also: Claude Desktop & VS Code (Copilot) — see the full install guide. Host needs Maestro CLI + Android/iOS SDKs; the built-in setup tool checks and installs them.

Ways to use it

One toolkit, many modes

Automation, not only test execution. The same 32 tools cover autonomous QA, scripted flows, interactive driving, and clean screenshot capture.

🤖 Autonomous QA

Describe a goal in plain English; the agent plans, drives, and self-corrects.

scan_projectsuggest_flowsgenerate_and_run_flow

📜 Scripted flows

Pass an explicit step array for a deterministic, repeatable flow.

generate_and_run_flowrun_flow

🕹️ Interactive driving

Issue one action at a time and inspect between steps.

tapinput_textswipetake_screenshot

🔍 Code-aware test gen

Generate flows from your real Swift/Kotlin/XML, targeting exact labels & IDs.

analyze_source_filescan_project

📸 Screenshot studio

Boot a device, fix the status bar to 9:41, capture clean App Store shots.

boot_deviceoverride_status_bar

🐞 Bug reproduction

Replay a flow, set permissions/location/deep-links, capture failure artifacts.

set_permissionsset_locationopen_url

Example: log in and open Settings

"Open com.example.app, log in with test@mail.com / secret123, then go to Settings."
// the agent calls generate_and_run_flow
{
  "appId": "com.example.app",
  "name": "login-and-settings",
  "steps": [
    { "action": "launchApp", "params": { "appId": "com.example.app" } },
    { "action": "tapOn",     "params": { "text": "Email" } },
    { "action": "inputText", "params": { "text": "test@mail.com" } },
    { "action": "tapOn",     "params": { "text": "Log in" } },
    { "action": "tapOn",     "params": { "text": "Settings" } },
    { "action": "assertVisible", "params": { "text": "Settings" } }
  ]
}

More walkthroughs — code-aware test gen, App Store screenshots, permission & deep-link testing — in the README usage guide.

Under the hood

Built with

TypeScript @modelcontextprotocol/sdk Maestro CLI tree-sitter sharp zod vitest · 180 tests ADB · xcrun simctl
Status: v0.2 — functional beta, in active development. Solid tested core (180 unit tests, CI on every push). Pre-1.0: the tool API may still change. Contributions and feedback welcome.