mobilerun-mcp
Summary: Mobilerun MCP is a host-side MCP server that lets AI clients see, control, and automate Android devices (and iOS via ios-portal) over ADB — 94 tools for perception, gestures, apps, media, notifications, system intents, and verification.
Screen perception —
perceive_screen(annotated screenshot with numberedsom_idmarks),read_screen(ASCII grid),get_ui_tree,get_screenshot,screenshot,screenshot_path.Gestures & input — tap/double-tap/long-press by coordinates or
som_id, swipe, directional scrolling (scroll_*,scroll_to), type text (with WPM/clear/submit), clear input, home/back/enter, recent apps, raw key codes.Apps & deep links — launch/start/stop apps, fuzzy app lookup, list installed apps, discover and open deep links, resolve URI handlers.
System intents, contacts, files, media — set alarms/timers, dial, compose SMS, calendar events, share text, navigate, resolve contacts, search/open device files, control media playback and volume, mute.
Notifications — read, dismiss, and trigger notification action buttons or inline replies.
Node-level automation (mobilerun-core) — find nodes (on/off screen), tap text/node, scroll until visible, asserts, waits (idle, text, app, screen change), clipboard get/set, browser JS execution, install/uninstall/grant permissions.
Device management — list/ping/connect/disconnect devices, device status, screen size, current app, doctor diagnostics, Portal setup, echo, raw ADB (opt-in).
Planning & verification — set plan, mark steps, record findings, end session, validate/verify actions, watch device events, configurable waits, web search for app guidance.
Safety & config — policy levels (
off/standard/strict), read/write scope restriction, HTTP or stdio transports, env-driven device/Portal/API-key configuration.
Allows controlling Android devices (physical, emulator, redroid; ARM or x86_64) over adb, providing tools for screen perception, gestures, app launching, text input, and device management.
Provides tools for interacting with iOS devices through ios-portal, including screen perception, gestures, app launching, and device control.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mobilerun-mcpopen the Settings app and turn on Wi-Fi"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Mobilerun MCP
English · Tiếng Việt
A host-side Model Context Protocol (MCP) server that connects AI clients to Android (physical phones, emulators, redroid) over ADB and iOS through ios-portal. It focuses on device automation, screen perception, gestures, app management, and system intents — with all heavy lifting executed on the host, so nothing ARM-only has to run on the device.
This repo contains two cooperating pieces:
an MCP server providing 94 tools exposed over stdio or HTTP
the Mobilerun Portal accessibility service running on the Android device
Highlights
Host-side architecture: zero ARM-only dependency on device; runs seamlessly on physical devices, x86_64 emulators, and redroid containers
Zero-setup runner via
npxwith automatic Python runtime, virtual environment, and dependency provisioning94 exposed tools covering screen perception, gestures, apps, intents, notifications, media, and device control
Set-of-Mark (SoM) visual perception with numbered labels (
som_id), accessibility tree, and OCR (Tesseract / OmniParser v2)Built-in verification loop: every state-changing tool waits for the screen to settle and returns a
post_action_observationDirect compatibility with droidrun's
mobilerun-coreDevice API for programmatic automationWorks over any network reachability supported by ADB (USB, Wi-Fi, LAN, VPN,
adb connect)Built-in configurable safety policies (
off,standard,strict) protecting sensitive personal and financial data
Related MCP server: Karagöz
Requirements
Node.js
>=18(for zero-setup execution vianpx)adb(Android Debug Bridge, via platform-tools)An Android device or emulator with USB debugging enabled
Python
3.10+(optional, only needed for local source development)Tesseract OCR (optional, for OCR on screens with sparse accessibility trees)
Installation and setup
1. Configure your AI client
Claude Code / Claude Desktop / VS Code / Cursor / Antigravity
Same server entry for all of them; only the file differs:
Claude Code —
.mcp.jsonin your project rootClaude Desktop —
claude_desktop_config.jsonCursor —
.cursor/mcp.jsonVS Code —
.vscode/mcp.json(VS Code names the top-level keyservers, notmcpServers)Antigravity — MCP settings panel (MCP Store -> View raw config), backed by
~/.gemini/config/mcp_config.json, or.agents/mcp_config.jsonfor a single workspace
{
"mcpServers": {
"mobilerun": {
"command": "npx",
"args": ["-y", "@impeterwayne/mobilerun-mcp@latest"],
"env": {
"MOBILERUN_DEVICE": "<serial>"
}
}
}
}Or via Claude Code CLI:
claude mcp add --scope user mobilerun -e MOBILERUN_DEVICE=<serial> -- npx -y @impeterwayne/mobilerun-mcp@latestNote:
MOBILERUN_DEVICEis optional if only one device is connected via ADB.
Codex CLI
~/.codex/config.toml:
[mcp_servers.mobilerun]
command = "npx"
args = ["-y", "@impeterwayne/mobilerun-mcp@latest"]
env = { MOBILERUN_DEVICE = "<serial>" }OpenCode
opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"mobilerun": {
"type": "local",
"command": [
"npx",
"-y",
"@impeterwayne/mobilerun-mcp@latest"
],
"environment": {
"MOBILERUN_DEVICE": "<serial>"
},
"enabled": true
}
}
}2. Device setup and Portal install
Download and install the Mobilerun Portal APK on your Android device:
adb install -r <portal.apk>Then enable the Mobilerun Portal accessibility service under Settings > Accessibility.
git clone https://github.com/Hi-im-Connect/mobilerun-mcp.git && cd mobilerun-mcp
uv venv --python 3.13 .venv && uv pip install -e .On Windows, use .venv\Scripts\python.exe in place of .venv/bin/python.
In your MCP client configuration:
{
"mcpServers": {
"mobilerun": {
"command": "/path/to/mobilerun-mcp/.venv/bin/python",
"args": ["-m", "mobilerun_mcp"],
"env": { "MOBILERUN_DEVICE": "<serial>" }
}
}
}Available tools
94 tools covering screen perception, gestures, system control, notifications, media, and automation.
Screen perception and reading
Tool | What it does |
| Captures an annotated screenshot with numbered marks ( |
| ASCII/text grid representation of the screen and elements (settles screen before reading). |
| Compact accessibility hierarchy tree (classes, resource IDs, labels, flags, bounds). |
| Returns current screenshot as base64 image data. |
| Plain screenshot with optional overlay suppression. |
| Takes a screenshot, saves it to a PNG file on disk, and returns the path. |
Gestures, typing and input
Tool | What it does |
| Tap at coordinates |
| Double-tap at |
| Press and hold at |
| Long press at precise |
| Swipe between two coordinates |
| Scroll content downward (revealing content below). |
| Scroll content upward (revealing content above). |
| Scroll content to the left. |
| Scroll content to the right. |
| Directional scroll by custom fraction of the screen. |
| Scroll until target text or coordinates become visible. |
| Type text into the currently focused input field or target |
| Types text with optional typing speed (WPM) and clear options. |
| Clears text from the currently focused input field. |
| Simulates pressing the physical/virtual Home button. |
| Simulates pressing the Back button (closes keyboards and popups). |
| Simulates pressing Enter / Search / Submit. |
| Opens the recent applications overview switcher. |
| Dispatches hardware key codes or named keys ( |
| Legacy button press helper ( |
Apps and deep links
Tool | What it does |
| Launch an application by fuzzy name or exact package name, waiting for foreground. |
| Starts an app by package ID and optional specific activity. |
| Search installed apps by name or package; returns ranked candidates with scores. |
| Lists installed applications (user-installed and optional system apps). |
| Discovers available deep links and shortcuts for an app. |
| Resolves which application handles a given URI or intent action. |
| Opens a screen directly via URI, app shortcut, or intent action. |
System intents, contacts, files and media
Tool | What it does |
| Executes common Android intents (set alarm, navigate, dial phone, open browser). |
| Finds contacts by partial name and returns phone numbers. |
| Searches the device media store (downloads, pictures, documents, videos). |
| Opens a file on device in its default application. |
| Retrieves active media playback sessions, track metadata, and volume. |
| Controls media playback (play, pause, next, previous, stop, rewind, fast forward). |
| Increases media volume. |
| Decreases media volume. |
| Toggles media mute state. |
Notifications
Tool | What it does |
| Reads active status-bar notifications with titles, text, and action buttons. |
| Dismisses a specific notification or clears all dismissible ones. |
| Triggers a notification action button or sends an inline reply. |
mobilerun-core Device API
Tool | What it does |
| Full UI state snapshot ( |
| Serialized JSON string of the device UI hierarchy. |
| UI snapshot with automatic retry logic for transient/reloading view hierarchies. |
| Queries supported backend capabilities, actions, and platform information. |
| Checks whether a specific action is supported on the target device. |
| Returns device screen width and height in pixels. |
| Package name of the current foreground application. |
| Current device system time. |
| Finds nodes matching filters (text, ID, class, substring), including off-screen. |
| Finds nodes matching filters strictly within visible screen bounds. |
| Finds and taps the first visible node containing specific text. |
| Taps the center of a node object returned from |
| Taps target element and waits for UI to become idle. |
| Continuously scrolls until an element matching criteria appears on screen. |
| Asserts that a specific app package is currently in the foreground. |
| Asserts that expected text is visible within a timeout. |
| Waits until the specified app package reaches the foreground. |
| Waits for screen animations and UI updates to finish settling. |
| Waits until UI changes from its current state. |
| Waits until an element containing the specified text appears. |
| Polls until nodes matching filters are detected. |
| Launches an app and waits until it is fully loaded and idle. |
| Force-stops an application with optional data clearing. |
| Installs an APK file from host storage onto the device. |
| Uninstalls an application package. |
| Grants runtime permission ( |
| Dispatches a deep link or view intent pinned to a package. |
| Executes JavaScript within the foreground browser page. |
| Reads current clipboard text content. |
| Writes text content to the device clipboard. |
Device management and connection
Tool | What it does |
| Comprehensive status: battery, screen state, foreground app, storage, IP. |
| Lists available connected ADB devices and emulators. |
| Verifies low-latency reachability of the device and Portal service. |
| Re-establishes ADB and Portal connection for a target device. |
| Disconnects a network/TCP ADB device and cleans up session state. |
| Installs and initializes the Mobilerun Portal service on the device. |
| Runs health diagnostics across ADB, device authorization, and the Portal. |
| Compatibility check for screenshot capture permissions. |
| Simple round-trip ping verifying MCP transport responsiveness. |
| Executes raw ADB commands (disabled by default; requires |
Planning, verification and research
Tool | What it does |
| Verifies post-action outcomes against expected text or UI element state. |
| Pre-validates planned actions against safety policy before execution. |
| Configurable wait for long-running operations (downloads, uploads, page loads). |
| Listens to device events (foreground app changes, notifications, keyboard). |
| Searches the web for application UI instructions and workflows. |
| Initializes an execution plan checklist with goals and deliverables. |
| Updates the status of a plan step ( |
| Records key data points and evidence extracted during device interaction. |
| Concludes automation session and reports summary results. |
| Returns best practice instructions and tips for controlling devices. |
Configuration
Variable | Default | Description |
| First connected device | Target ADB serial, network address ( |
|
| Safety policy: |
|
| Tool scope restriction ( |
|
| Set to |
| unset | API key for Brave search via |
| unset | API key for Tavily search via |
| Auto-downloaded | Local path override for OmniParser icon detection ONNX model |
|
| Host address for HTTP MCP mode ( |
|
| Port for HTTP MCP mode ( |
|
| Custom path to |
Troubleshooting
Symptom | Fix |
| Run |
| Unlock the phone and tap Allow on the USB debugging authorization prompt |
| Reconnect USB cable or run |
| Install platform-tools or specify binary location with |
| Enable in Settings > Accessibility > Mobilerun Portal, or run |
| The screen changed after the last action; call |
Client lists no | Check client config file syntax and paths; restart the AI client |
License
Available Tools
94 toolsassert_onAssert OnC
Fail unless app_id is in the foreground.
Inputs: app_id (required), device. Returns: object
assert_text_visibleAssert Text VisibleB
Fail unless text becomes visible on screen within timeout seconds.
Inputs: text (required), device, timeout. Returns: object
capabilitiesCapabilitiesC
Backend, platform and the actions this device supports.
Inputs: device. Returns: object
clear_inputClear InputC
Clear the focused text field.
Inputs: device. Returns: object
connect_deviceConnect DeviceB
(Re)connect adb and the Portal for a device; use after the network path came back.
Inputs: device. Returns: object
current_app_idCurrent App IdC
Package / bundle id of the foreground app.
Inputs: device. Returns: result
disconnect_deviceDisconnect DeviceB
Disconnect a TCP/IP adb device (adb disconnect host:port) and drop its session.
Inputs: device. Returns: object
dismiss_notificationDismiss NotificationC
Dismiss one notification (by key, or package/title) or every clearable one.
Inputs: key, title, device, package, +1 more. Returns: object
doctorDoctorC
Health check of adb, the Portal and the device (mobilerun doctor).
Inputs: device. Returns: object
double_tapDouble TapC
Double-tap at (x, y) or a mark.
Inputs: x, y, device, som_id. Returns: object
echoEchoA
Returns text verbatim: a check that the MCP transport is alive (no device access).
Inputs: text, message. Returns: object
end_sessionEnd SessionA
Mark the end of the task (the server keeps listening; the next call starts fresh). reason: short summary of what was done. outcome: success (goal state verified) | partial | failure. goal_type: play_media | send_message | send_email | purchase | post | open_app | search | navigate | other. For send_message, send_email, purchase and post, success is refused unless you looked at the screen (read_screen / perceive_screen) after your last action. Success is also refused while fewer findings than the plan's target_count are recorded. failure is never refused.
Inputs: device, reason, outcome, summary, +1 more. Returns: object
execute_scriptExecute ScriptC
Run JavaScript in the foreground browser page and return its JSON result.
Inputs: js (required), device.
find_filesFind FilesA
Search the device's media index by name, newest first: images, videos, audio and documents (downloads included). kind: image | video | audio | document | any. Returns content:// URIs for open_file (limit default 10, cap 25). With path, searches that shared-storage folder by file name instead (any file type).
Inputs: kind, path, limit, query, +2 more. Returns: object
find_nodesFind NodesA
Nodes matching every given filter (exact text/desc/resource_id/class_name, or *_contains substrings), including off-screen ones.
Inputs: desc, text, tree, device, +5 more. Returns: result
find_nodes_on_screenFind Nodes On ScreenC
Like find_nodes, limited to nodes inside the visible screen.
Inputs: desc, text, tree, device, +5 more. Returns: result
get_clipboardGet ClipboardC
The clipboard's text (Android needs the Mobilerun Keyboard as the active IME).
Inputs: device. Returns: result
get_device_statusGet Device StatusB
Battery, screen power, foreground app, size, storage, network addresses, volume.
Inputs: device. Returns: object
get_media_sessionsGet Media SessionsC
Active media sessions (app, playback state, title/artist) and the music volume.
Inputs: device, include_system. Returns: object
get_screenshotGet ScreenshotC
Plain screenshot as an image.
Inputs: device.
get_ui_treeGet Ui TreeC
Compact accessibility tree (class, id, label, flags C/L/E/S/K/P, bounds).
Inputs: device, max_depth. Returns: object
get_usage_guideGet Usage GuideB
How to use this server well. Topics: overview, shortcuts, text_entry, failures, ledger, safety, stop, efficiency, full.
Inputs: topic. Returns: object
grant_permissionGrant PermissionC
Grant a runtime permission (android.permission.*) to an app.
Inputs: package (required), permission (required), device. Returns: object
install_appInstall AppC
Install an APK (host path) on the device.
Inputs: path (required), device, replace, grant_permissions. Returns: object
keyKeyC
Press a key by mobilerun-core name (back, home, menu, enter, delete, escape, tab, space, search, page_up, page_down, volume_up, volume_down, wakeup, media_play_pause, ...) or by Android keycode number.
Inputs: name_or_code (required), device. Returns: object
launch_appLaunch AppA
Open an app by name (fuzzy) or exact package_name. An ambiguous name returns ranked candidates instead of guessing. If the app is already in the foreground it is left as is (already_foreground=true) unless force=true.
Inputs: force, device, package, app_name, +1 more. Returns: object
list_app_deeplinksList App DeeplinksB
Deep links into an app, best first. source: shortcut (launcher shortcut, app-shortcut://pkg/id, open with open_deeplink) > resolved (curated and verified on this device) > catalog (curated) > discovered (declared by the app's intent filters).
Inputs: device, package, app_name, package_name. Returns: object
list_appsList AppsA
List installed apps (user apps only unless include_system_apps=true). include_protected_apps is honoured on Mobilerun Cloud devices only (as in mobilerun-core).
Inputs: device, system, include_system_apps, include_protected_apps. Returns: object
list_devicesList DevicesA
Devices you can control. scope: local (adb devices) | cloud (Mobilerun Cloud, needs MOBILERUN_CLOUD_API_KEY) | all. Cloud filters: state (creating, assigned, ready, terminated, ...), type, name, country, page, pageSize (or a filters dict). Any listed id works as the device argument of every tool.
Inputs: name, page, type, scope, +4 more. Returns: object
long_pressLong PressB
Press and hold at (x, y), a mark (som_id) or a get_state element (index). Hold time: duration_ms or ms (default 1000).
Inputs: x, y, ms, index, +3 more. Returns: object
long_press_atLong Press AtC
Long press at (x, y) (mobilerun agent action).
Inputs: x (required), y (required), device. Returns: object
lookup_appLookup AppC
Search installed apps by name or package; returns ranked candidates with scores.
Inputs: limit, query, device, app_name. Returns: object
mark_stepMark StepA
Update a plan step: pending | in_progress | done | skipped | failed. Put facts you read off the screen in note; the pixels are gone next turn.
Inputs: index (required), status (required), note, device. Returns: object
media_controlMedia ControlB
Control playback in any app without touching the screen: play, pause, play_pause, next, previous, stop, rewind, fast_forward. Goes to the active media session; package_name (from get_media_sessions) is checked against it and reported.
Inputs: action, device, command, package_name. Returns: object
muteMuteB
Toggle mute on the media stream (muted=true/false forces a state). Muting remembers the previous level for unmute.
Inputs: muted, device. Returns: object
notification_actionNotification ActionB
Tap one of a notification's own buttons (reply, archive, stop...); reply_text fills an inline reply field and sends it. Best-effort: it drives the notification shade.
Inputs: action (required), key, title, device, +2 more. Returns: object
open_and_settleOpen And SettleB
Start an app and wait until it is in front and idle.
Inputs: app_id (required), idle, device, timeout. Returns: object
open_deep_linkOpen Deep LinkC
Dispatch a deep link / intent (default action VIEW), optionally pinned to a package.
Inputs: deep_link (required), action, device, package_name. Returns: object
open_deeplinkOpen DeeplinkA
Jump straight to a screen via a URI, an app-shortcut://pkg/id from list_app_deeplinks, or an intent action. package_name / app_name pin the target app. intent:, file:, content: and javascript: URIs are refused.
Inputs: uri (required), device, package, app_name, +1 more. Returns: object
open_fileOpen FileB
Open a file in its default viewer. uri: a content://media/... URI from find_files (never build one by hand); path: a file under shared storage.
Inputs: uri, path, device. Returns: object
open_recent_appsOpen Recent AppsC
Open the recent-apps overview.
Inputs: device. Returns: object
perceive_screenPerceive ScreenB
LOOK at the screen: an annotated screenshot plus every element and its tap point.
e is an array whose INDEX is the som_id (first entry = som_id 1): [center_x, center_y,
name, flags] (name/flags omitted when empty). elements is the same list as text.
Box colours: BLUE tappable, GREEN text input (type_text), MAGENTA scrollable, AMBER
toggle, GREY nothing declared, RED on-host vision (detector/OCR; a good guess, not a fact).
Flags (only when true): e editable, c checked, o unchecked, d disabled, f focused,
l long-pressable, ? low-confidence vision box, w scroll host (aim inside it).
offscreen: text that exists but is not on screen (cannot be tapped).
detail="full" adds the visual pass (OmniParser YOLOv8 icon detector + OCR) for icons the
tree does not describe; perception_tier reports tree_only or full. description is
logged only. ids go stale after any action.
Inputs: ocr, lang, detail, device, +3 more.
ping_devicePing DeviceC
Is the device reachable? For adb devices, reports the Portal transport (http or content_provider).
Inputs: device. Returns: object
pressPressA
Press home, back or enter (kept for old clients; prefer press_home/back/enter).
Inputs: button (required), device. Returns: object
press_backPress BackB
Press Back (also closes the keyboard without leaving the screen).
Inputs: device. Returns: object
press_enterPress EnterA
Press Enter (submits search bars and forms).
Inputs: device. Returns: object
press_homePress HomeC
Press the Home button.
Inputs: device. Returns: object
read_notificationsRead NotificationsA
Current status-bar notifications, newest first, without touching the screen: key, app, title, text, action labels. Ongoing ones (music, navigation, downloads) only with include_ongoing=true; package_name filters to one app; limit default 20, cap 30. With the safety policy on, banking and authenticator notifications are withheld.
Inputs: limit, device, package, package_name, +1 more. Returns: object
read_screenRead ScreenA
Read the screen now (waits for it to stop moving first): the screen drawn as a character grid, each element a box with its som_id and label, then a table of what can be acted on: som (tap by this), in (som_id of the smallest box containing it), flg, label (only when it did not fit on the grid). Flags: * tappable, e text input (type_text, not tap), S scrollable, c toggle ON, o toggle OFF, l long-pressable, d disabled, - nothing declared (usually still tappable). N+k = som_id N plus k more elements with exactly those bounds; tap N. Header IDLE/BUSY: BUSY means it was still moving when the wait expired. Use perceive_screen instead for how something looks, when this ends with ESCALATE, or when what you need is missing.
Inputs: device. Returns: result
record_findingRecord FindingB
Record one item you found. quote must be copied exactly from the CURRENT screen.
Inputs: item (required), quote (required), device. Returns: object
request_screen_capture_permissionRequest Screen Capture PermissionA
Compatibility no-op: screenshots use the Portal / adb screencap, no prompt is needed.
Inputs: device. Returns: object
resolve_contactResolve ContactA
Find contacts by (partial) name and return their phone numbers.
Inputs: name (required), limit, device. Returns: object
resolve_deeplinkResolve DeeplinkC
Which app would open this URI (or intent action such as android.settings.WIFI_SETTINGS)? handler_kind: app | browser_only | none.
Inputs: uri (required), device. Returns: object
screenshotScreenshotC
Plain screenshot. hide_overlay hides the Portal's element overlay first.
Inputs: device, hide_overlay.
screenshot_pathScreenshot PathC
Take a screenshot, save it as a PNG file and return the path.
Inputs: device. Returns: object
screen_sizeScreen SizeD
[width, height] in pixels.
Inputs: device. Returns: result
scrollScrollC
Scroll the content in direction (up | down | left | right) by distance (fraction of the screen). verify=true reports whether the screen actually moved (mobilerun-core).
Inputs: direction (required), ms, device, verify, +1 more. Returns: object
scroll_downScroll DownB
Scroll the content down (reveal what is below): a centered swipe over half the screen (amount), or inside a scrollable mark (som_id).
Inputs: amount, device, som_id. Returns: object
scroll_leftScroll LeftC
Scroll the content left (reveal what is to the left).
Inputs: amount, device, som_id. Returns: object
scroll_rightScroll RightB
Scroll the content right (reveal what is to the right).
Inputs: amount, device, som_id. Returns: object
scroll_toScroll ToA
Two modes. With x1, y1, x2, y2: drag the content from one point to the other (precise scroll). With text: scroll in direction until an element containing text is visible and return its mark.
Inputs: x1, x2, y1, y2, +5 more. Returns: object
scroll_untilScroll UntilC
Scroll until a matching node is on screen; result is the node (or null).
Inputs: text, device, settle, distance, +5 more. Returns: object
scroll_upScroll UpC
Scroll the content up (reveal what is above).
Inputs: amount, device, som_id. Returns: object
set_clipboardSet ClipboardC
Put text on the clipboard.
Inputs: value (required), device. Returns: object
set_planSet PlanC
Start a plan checklist. target_count > 0 means 'N items must be recorded' before end_session(success) is allowed. With 3+ steps and a search_query, the first web search rides along in the reply.
Inputs: steps (required), goal, device, deliverable, +2 more. Returns: object
setup_portalSetup PortalC
Install and enable the Mobilerun Portal on the device (mobilerun setup); path installs a specific Portal APK.
Inputs: path, device. Returns: object
start_appStart AppC
Start an app by id (Android package / iOS bundle id), optionally a specific activity.
Inputs: app_id, device, package, activity. Returns: object
stop_appStop AppB
Force-stop an app; clear_data also wipes its data.
Inputs: app_id (required), device, clear_data. Returns: object
supportsSupportsC
Whether this device supports a Device action (e.g. execute_script, get_clipboard).
Inputs: action (required), device. Returns: result
swipeSwipeB
Swipe from (x1, y1) to (x2, y2) over duration_ms / ms (default 300). mobilerun agent form: coordinate=[x, y], coordinate2=[x, y], duration in seconds.
Inputs: ms, x1, x2, y1, +6 more. Returns: object
system_intentSystem IntentA
One-call Android actions (action = the verb; verb= is accepted too). Verbs: set_alarm(hour, minute, label), set_timer(seconds, label), dial(phone_number), compose_sms(phone_number, body), add_calendar_event(title, start, end, location, notes; ISO datetimes), share_text(text, subject), navigate( destination, mode drive|walk|bike|transit). dial/compose_sms only prefill; the user sends.
Inputs: end, body, hour, mode, +15 more. Returns: object
tapTapC
Tap at (x, y) or at the center of a numbered mark (som_id from perceive_screen / read_screen). stealth=true uses mobilerun-core's humanized tap.
Inputs: x, y, device, som_id, +1 more. Returns: object
tap_and_waitTap And WaitB
Tap a text (or node) and wait until the UI has been idle for idle seconds.
Inputs: target (required), idle, device. Returns: object
tap_nodeTap NodeB
Tap the center of a node returned by find_nodes / find_nodes_on_screen.
Inputs: node (required), device, stealth. Returns: object
tap_textTap TextC
Tap the first on-screen node whose text/description contains text.
Inputs: text (required), device. Returns: object
timeTimeD
The device clock.
Inputs: device. Returns: result
typeTypeC
Type text (mobilerun). index taps that get_state element first; stealth=true types key by key like a person (mobilerun-core), at wpm words per minute.
Inputs: text (required), wpm, clear, index, +2 more. Returns: object
type_textType TextA
Type into the focused field (tap it first, or pass som_id). submit presses Enter after.
Inputs: text (required), clear, device, som_id, +1 more. Returns: object
uiUiC
Raw UI snapshot (a11y_tree, phone_state, device_context, ...), as Device.ui().
Inputs: device, filter. Returns: object
ui_jsonUi JsonC
The UI snapshot serialized as JSON text.
Inputs: device, filter, indent. Returns: result
ui_with_recoveryUi With RecoveryC
UI snapshot that retries past a dead or empty accessibility tree.
Inputs: device, filter. Returns: object
uninstall_appUninstall AppD
Uninstall an app.
Inputs: app_id (required), device. Returns: object
validate_actionValidate ActionB
Pre-check a planned action against the safety policy (and, for our action set, that its target exists) without doing it. gesture_type is the action (tap, type_text, launch_app, open_deeplink, ...); target is the app name/package, deep-link URI or text you plan to use. Returns allowed=false with a category for blocked apps and text.
Inputs: x, y, uri, text, +7 more. Returns: object
verify_actionVerify ActionC
Check an outcome against the live screen. kind: text (visible), gone (not visible), app (foreground package or name), activity, changed (the last action changed the screen).
Inputs: expected (required), kind, device, timeout, +1 more. Returns: object
volume_downVolume DownC
Lower the music volume by steps.
Inputs: steps, device. Returns: object
volume_upVolume UpC
Raise the music volume by steps.
Inputs: steps, device. Returns: object
wait_forWait ForA
LONG waits only (downloads, uploads, processing, status changes); gestures already settle. With text / package / activity: wait until that is on screen (gone=true: until it disappears). Otherwise wait until loading finishes (no progress bar or "Loading" text) and the screen is still; condition is echoed back, you judge the returned state. Timeouts: timeout_ms (default 5000, max 30000) / poll_interval_ms (default 500, min 100), or timeout / interval in seconds.
Inputs: gone, text, device, package, +6 more. Returns: object
wait_for_appWait For AppC
Wait until app_id is in the foreground.
Inputs: app_id (required), poll, device, timeout. Returns: result
wait_for_idleWait For IdleC
Wait until the UI stops changing.
Inputs: poll, device, timeout. Returns: result
wait_for_nodesWait For NodesC
Poll find_nodes until something matches (or timeout, returning []).
Inputs: desc, poll, text, device, +7 more. Returns: result
wait_for_screen_changeWait For Screen ChangeC
Wait until the UI differs from now.
Inputs: poll, device, timeout. Returns: result
wait_for_textWait For TextC
Wait until a node containing text exists (off-screen nodes count).
Inputs: text (required), poll, device, timeout. Returns: result
watch_device_eventsWatch Device EventsA
Collect device events for up to timeout_seconds (default 10, max 30), returning early once max_events (default 50) arrive: foreground app, keyboard, screen content, notifications posted/removed. kinds filters: foreground, keyboard, screen, notifications.
Inputs: kinds, device, duration, interval, +2 more. Returns: object
web_searchWeb SearchA
Search the web for how to do something in an app ('how to in android'). Returns ranked sources (title, url, snippet) and, with TAVILY_API_KEY set, a synthesized answer. max_results 1-10 (default 5); topic general | news. The screen overrules results.
Inputs: query (required), limit, topic, max_results. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
TDQS
Scored across 94 tools
Many tools overlap heavily: ui/ui_json/ui_with_recovery/get_ui_tree/perceive_screen/read_screen all return screen state, screenshot/screenshot_path/get_screenshot are near-duplicates, and tap/tap_text/tap_node/tap_and_wait plus press/press_home/press_back/press_enter/key blur action boundaries. The descriptions do hint at distinctions (raw vs annotated, coordinate vs text), but the sheer number of near-synonyms with legacy aliases ('kept for old clients', 'prefer ...') makes misselection likely.
Almost everything follows a snake_case verb_noun convention (get_screenshot, launch_app, list_devices, press_home). Deviations are minor: bare nouns (ui, capabilities, time, echo), a single-word verb 'press' vs compound 'press_home', and a few legacy synonyms. Overall predictable and readable.
94 tools is far beyond what a device-control surface needs, and much of the count comes from redundant aliases and overlapping variants (multiple screenshot tools, multiple screen-read tools, multiple tap/wait/key variants). This is an extreme mismatch that burdens selection.
Coverage is exhaustive: input gestures, UI perception, app lifecycle (install/uninstall/stop/grant), files, notifications, media, clipboard, device management, deep links, safety validation, and a task-planning/verification loop. Nearly every lifecycle operation for the domain is present with no obvious dead ends.
Maintenance
Related MCP Connectors
Give your AI agent a real cloud Android phone: push APKs, drive it, get screenshots and logs.
Let AI agents control Android and iOS devices on Mobilerun Cloud: screen, input, apps, workflows.
Cloud Android phones for AI agents: create a phone, read the screen, tap, type, install APKs, park.
Cloud Android phones for AI agents: read the screen, tap, type, install APKs, park and resume.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI agents to control, inspect, and automate Android devices, Waydroid containers, and AVD emulators over ADB. Provides tools for screenshots, UI-hierarchy text-based tapping, gestures, key presses, text input, app management, and raw shell commands.12MIT
- AlicenseBqualityBmaintenanceEnables AI agents to automate Android and iOS devices, including emulators and physical devices, by capturing screenshots, reading UI accessibility trees, performing touch and text input, and managing app lifecycle and logs.184MIT
- AlicenseCqualityCmaintenanceEnables an AI agent to see and control Android devices, including x86_64 emulators and redroid, through 68 tools covering gestures, typing, apps, notifications, files, browser control, and more.681MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to visually perceive and directly control Android devices via ADB and screen-control tooling, including screenshots, taps, swipes, typing, app management, UI inspection, file transfer, shell commands, and audio/video streaming.374 npmMIT