appium-robot-mcp
v0.1.0
Published
Advanced Appium MCP server — AI-driven mobile automation for Android & iOS with multi-session support, smart locators, vision-based element finding, and test generation.
Maintainers
Readme
appium-robot-mcp
An advanced Model Context Protocol server for mobile automation — drive Android & iOS apps from any MCP-compatible AI client with natural language.
appium-robot-mcp is an independent, from-scratch MCP server inspired by the use cases of appium/appium-mcp. It gives AI assistants a clean, well-typed tool surface for mobile testing and automation: multi-session management, prioritized smart locators, gestures, opt-in vision-based element finding, locator/test generation, and a small but powerful plugin API.
✨ Features
- Cross-platform — Android (UiAutomator2) and iOS (XCUITest), plus a flexible
generalmode for any driver. - Multi-session core — create, attach, detach, delete, list, and switch between sessions. Owned vs. attached ownership is tracked, so attached remote sessions survive disconnects.
- Smart locators — priority-ordered strategies (accessibility id → id → native predicate → xpath) with built-in waiting/retry.
- Rich gestures — tap, double-tap, long-press, swipe, scroll, drag-and-drop, and
scroll_to_element(scrolls until found or the list stops changing). - AI vision finding (opt-in) — locate elements by description using any OpenAI-compatible vision model. Gated behind
AI_VISION_ENABLEDwith image compression + 5-minute LRU caching. - Server-less Android (adb) mode — pull the UI hierarchy and generate locators straight from
adb(uiautomator dump), with no Appium server or session required. Great for quick inspection and CI. - Codegen —
generate_locatorsmines the live screen for ready-to-use selectors;appium_generate_testsscaffolds Java/TestNG, JUnit, pytest, or WebdriverIO tests. - NO_UI mode — drop heavy base64/HTML payloads for faster, cheaper responses in CI.
- Plugin API — extend the server with custom tools and lifecycle hooks via
appium-robot-mcp/core, no fork required. - Safe by design — argument redaction in logs, remote-URL allowlisting, and configurable session cleanup on disconnect.
📋 Prerequisites
- Node.js 22+ (tested on 26)
- Appium 2 server running (
npm i -g appium) with the relevant drivers:- Android:
appium driver install uiautomator2+ANDROID_HOMEset - iOS (macOS):
appium driver install xcuitest+ Xcode
- Android:
- A booted emulator/simulator or a connected device
🛠️ Install & Build
git clone <your-fork-url> appium-robot
cd appium-robot
npm install
npm run buildStart an Appium server in another terminal:
appium⚙️ Configure your MCP client
Point your client at the built entry (dist/index.js). See examples/mcp-config.json:
{
"mcpServers": {
"appium-robot": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/appium-robot/dist/index.js"],
"env": {
"ANDROID_HOME": "/Users/you/Library/Android/sdk",
"CAPABILITIES_CONFIG": "/absolute/path/to/appium-robot/examples/capabilities.json"
}
}
}
}Environment variables
| Variable | Required | Description |
| --- | --- | --- |
| APPIUM_SERVER_URL | Optional | Appium server URL (default http://127.0.0.1:4723) |
| CAPABILITIES_CONFIG | Optional | Absolute path to a capabilities.json with per-platform presets |
| SCREENSHOTS_DIR | Optional | Where screenshots/recordings are saved (default: cwd) |
| NO_UI | Optional | true/1 to disable rich payloads (faster, cheaper) |
| APPIUM_MCP_ON_CLIENT_DISCONNECT | Optional | delete_all (default) or skip — owned-session cleanup policy |
| REMOTE_SERVER_URL_ALLOW_REGEX | Optional | Regex remote URLs must match (default ^https?://) |
| APPIUM_COMMAND_TIMEOUT_MS | Optional | Driver command timeout (default 120000) |
| APPIUM_ELEMENT_TIMEOUT_MS | Optional | Default element wait (default 10000) |
| AI_VISION_ENABLED | Optional | true to register appium_ai. Requires the two vars below |
| AI_VISION_API_BASE_URL | If AI on | OpenAI-compatible vision API base URL |
| AI_VISION_API_KEY | If AI on | API key |
| AI_VISION_MODEL | Optional | Model name (default Qwen3-VL-235B-A22B-Instruct) |
| AI_VISION_COORD_TYPE | Optional | normalized (default) or absolute |
| AI_VISION_IMAGE_MAX_WIDTH | Optional | Max width before compression (default 1080) |
| AI_VISION_IMAGE_QUALITY | Optional | JPEG quality 1–100 (default 80) |
| LOG_LEVEL | Optional | debug | info | warn | error (default info) |
Capabilities presets
Create a capabilities.json (see examples/capabilities.json) with android, ios, and/or general sections, then set CAPABILITIES_CONFIG. Capabilities passed inline to appium_session_management are merged on top of the preset.
🎯 Tools
| Category | Tool | Description |
| --- | --- | --- |
| Setup | select_device | Discover and select an Android/iOS device (auto-selects if one) |
| Setup | prepare_ios_simulator | Boot a simulator + open Simulator UI; returns a capabilitiesHint |
| Setup | appium_prepare_ios_real_device | List provisioning profiles + build WDA signing capabilitiesHint |
| Session | appium_session_management | create / attach / detach / delete / list / select |
| Element | appium_find_element | Find with prioritized strategies + waiting |
| Element | appium_set_value | Type text (optional clear-first) |
| Element | appium_get_text | Read element text |
| Element | appium_get_element_attribute | Read any attribute/property of an element |
| Element | appium_get_active_element | Element UUID of the focused element |
| Gesture | appium_gesture | back / tap / double_tap / long_press / scroll / swipe / scroll_to_element |
| Gesture | appium_drag_and_drop | Drag between elements/coordinates |
| Gesture | appium_perform_actions | Raw W3C Actions sequences (custom multi-touch) |
| Input | appium_mobile_keyboard | hide / is_shown |
| Input | appium_mobile_press_key | Android keycode / iOS hardware button |
| Screen | appium_screenshot | Save PNG (element or full screen) |
| Screen | appium_get_page_source | UI hierarchy XML |
| Screen | appium_get_window_size | Screen dimensions |
| Screen | appium_orientation | Get/set orientation |
| Screen | appium_mobile_device_info | info / battery / time |
| Screen | appium_screen_recording | start / stop (MP4) |
| Device | appium_geolocation | get / set / reset GPS |
| Device | appium_mobile_file | push / pull / delete files |
| Device | appium_driver_settings | get / update driver settings |
| Device | appium_mobile_clipboard | get / set clipboard text |
| Device | appium_mobile_device_control | lock / unlock / shake / open_notifications |
| App | appium_app_lifecycle | activate / terminate / install / uninstall / is_installed / query_state / background / clear / deep_link |
| App | appium_mobile_permissions | get / update / reset app permissions |
| App | appium_context | list / switch native & webview contexts |
| App | appium_alert | accept / dismiss / get_text |
| Codegen | generate_locators | Mine the screen for prioritized locators |
| Codegen | appium_generate_tests | Scaffold tests (TestNG/JUnit/pytest/WebdriverIO) |
| ADB (no server) | adb_get_page_source | Android UI hierarchy XML via uiautomator dump — no Appium server |
| ADB (no server) | adb_generate_locators | Prioritized locators straight from adb — no Appium server |
| ADB (no server) | adb_current_activity | Foreground package + activity via dumpsys |
| ADB (no server) | adb_tap | Tap absolute coordinates via input tap |
| ADB (no server) | adb_input_text | Type into the focused field via input text |
| ADB (no server) | adb_key_event | Send a keyevent (BACK/HOME/ENTER…) via input keyevent |
| Help | appium_documentation_query | Search the built-in Appium knowledge base |
| Help | appium_skills | Ordered setup/troubleshooting steps (android/ios/general) |
| AI (opt-in) | appium_ai | Vision-based element finding → coordinate UUID |
There is also a Generate Code With Locators MCP prompt that turns a scenario + generate_locators output into a Page Object + test.
📚 Example flow
1. select_device
2. appium_session_management { action: "create", platform: "android" }
3. appium_get_page_source # inspect the screen
4. generate_locators # get ready-to-use selectors
5. appium_find_element { strategy: "accessibility id", selector: "search-button" }
6. appium_gesture { action: "tap", elementUUID: "<from step 5>" }
7. appium_set_value { strategy: "id", selector: "search_src_text", text: "iPhone 15 Pro" }
8. appium_generate_tests { scenario: "search for a product and add to cart", framework: "java-testng" }⚡ Server-less Android (adb) mode
You don't always need a running Appium server. If you just want to inspect a screen and grab locators, the adb_* tools talk to the device directly via adb — no server, no session, no capabilities.
1. select_device # (optional) pick an Android device
2. adb_current_activity # what app/screen am I on?
3. adb_generate_locators # prioritized locators via uiautomator dump
4. adb_tap { x: 540, y: 260 } # drive the UI with input events
5. adb_input_text { text: "hello" }Requirements: adb on your PATH (or ANDROID_HOME/ANDROID_SDK_ROOT set) and a device listed by adb devices. These tools are Android only — iOS has no adb equivalent, so use the Appium-based tools there.
🔌 Plugin API
Import from appium-robot-mcp/core to register custom tools and lifecycle hooks (register, beforeCall, afterCall, destroy) and to filter tools with a policy. Use verifyAppiumMcpNames to catch name collisions before deploying. See examples/plugin-example.ts.
import { createAppiumMcpServer } from "appium-robot-mcp/core";
const server = createAppiumMcpServer({
plugins: [new MyPlugin()],
policy: { allowTools: [/^appium_/, /^my_/] },
});
await server.start({ transportType: "stdio" });🧪 Development
npm run dev # tsc watch
npm run typecheck # type-only check
npm run build # emit dist/📄 License
Apache-2.0. See LICENSE.
