android-mcp
Provides full control of Android devices and emulators through ADB, enabling screen observation, UI interaction, app management, system controls, and device management for Android.
Click on "Install 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., "@android-mcpTake a screenshot of the current screen"
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.
android-mcp
An MCP (Model Context Protocol) server that gives AI agents full control of Android devices and emulators through plain ADB — no companion APK, no extra daemon, no telemetry.
With this server, agents like Claude Code, Claude Desktop, or Cursor can see the screen (screenshots + UI hierarchy) and act on it (tap, swipe, type, launch apps, read logs, record video) on any device that adb can reach.
You: "Open Settings, turn on dark mode, and show me a screenshot"
Agent: launches the app, navigates by reading the UI hierarchy,
taps the right elements, and returns a screenshot — hands-free.Why another Android MCP?
This project merges the best ideas of two excellent servers into one dependency-light TypeScript implementation:
Inspiration | What was adopted |
App management, uiautomator-based element listing, screenshots, screen recording, orientation control | |
WiFi ADB + mDNS auto-discovery, selector-based taps, wait-for-element, smart default-device selection |
Differences by design:
ADB only. No uiautomator2 server APK on the device, no
mobileclibinary on the host.Zero telemetry. Nothing is phoned home, ever.
Android-first. No iOS code paths to carry around.
Agent-friendly errors. Failures return actionable messages that tell the agent what to try next.
Related MCP server: airi-android
Requirements
Node.js 18+
Android platform-tools (
adb) — auto-detected fromANDROID_HOME,~/Library/Android/sdk(macOS), or%LOCALAPPDATA%\Android\Sdk(Windows), withPATHas fallbackAn Android device with USB debugging or wireless debugging enabled, or a running emulator
Installation
git clone https://github.com/qalvinahmad/android-mcp.git
cd android-mcp
npm install
npm run buildClaude Code
claude mcp add android -- node /path/to/android-mcp/dist/index.jsClaude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"android": {
"command": "node",
"args": ["/path/to/android-mcp/dist/index.js"]
}
}
}Cursor / other MCP clients
Any client that speaks MCP over stdio works the same way: run node /path/to/android-mcp/dist/index.js as the server command.
Environment variables (all optional)
Variable | Purpose |
| Default device id used when a tool call omits |
| Set to |
| Android SDK location, used to locate |
Device selection
Every tool accepts an optional device parameter. When omitted, the server resolves the target in this order:
ANDROID_MCP_DEVICEenvironment variableThe only online device, if exactly one is connected
The first physical device (USB or WiFi preferred over emulators)
android_list_devices also auto-connects wireless-debugging peers advertised via mDNS (adb mdns services) when the device list is empty — devices on the same network appear without any manual adb connect.
Capabilities — 26 tools
Device management
Tool | Description | Key parameters |
| List connected devices with name, Android version, connection type (usb/wifi/emulator), and state. Auto-discovers mDNS wireless peers. | — |
| Connect over WiFi ADB. Port defaults to 5555. |
|
| Model, Android version, SDK level, screen size, orientation, battery level, foreground app. |
|
App management
Tool | Description | Key parameters |
| List installed apps that have a launcher activity. |
|
| Launch an app by package name. |
|
| Force-stop a running app. |
|
| Install an APK, optionally granting all runtime permissions. |
|
| Uninstall an app. |
|
Screen observation
Tool | Description | Key parameters |
| Screenshot returned inline as an image the agent can see. |
|
| Screenshot saved to a local |
|
| UI hierarchy: element type, text, accessibility label, resource id, focus/clickable state, and center tap coordinates. |
|
| Poll until an element appears — use instead of fixed sleeps for dynamic content. | selector, |
Interaction
Tool | Description | Key parameters |
| Tap at pixel coordinates. |
|
| Find an element by selector and tap its center. Waits up to | selector, |
| Double-tap at coordinates. |
|
| Long-press at coordinates. |
|
| Directional swipe from screen center or from given coordinates. |
|
| Drag and drop between two points. |
|
| Type into the focused field (ASCII), optionally clearing it first and/or submitting with ENTER. |
|
| Press a key: |
|
| Open an http(s) URL in the default browser. |
|
| Expand the notification shade. |
|
System
Tool | Description | Key parameters |
| Force portrait/landscape (disables auto-rotate). |
|
| Start background screen recording (max 180 s, Android limit). |
|
| Stop recording, pull the |
|
| Read recent logs with buffer selection ( |
|
Element selectors
android_tap_element and android_wait_for_element accept any combination of:
Selector | Matching |
| Exact visible text |
| Substring of visible text, case-insensitive |
| Full id ( |
| Substring of accessibility label, case-insensitive |
| Full class ( |
Usage examples
Prompts you can give an agent once the server is connected:
"List my devices and take a screenshot of the current screen."
"Open the Settings app and toggle dark mode."
"Install ~/Downloads/app-release.apk with all permissions granted, launch it, and check logcat for errors."
"Fill in the login form: tap the field with resource id
email, typeuser@example.com, then tap the Login button.""Record the screen while you walk through the onboarding flow, then save the video to my desktop."
"My Flutter app crashed — read the crash buffer and tell me why."
How it works (spec)
┌──────────────┐ stdio (JSON-RPC / MCP) ┌─────────────┐ adb CLI ┌─────────────┐
│ MCP client │ ◄────────────────────────► │ android-mcp │ ◄─────────► │ device / │
│ (Claude, ...) │ │ (Node.js) │ │ emulator │
└──────────────┘ └─────────────┘ └─────────────┘Transport: stdio, stateless — one server process per client session.
Screenshots:
adb exec-out screencap -p, returned as PNG (inline base64 image or file).UI hierarchy:
adb exec-out uiautomator dump /dev/tty, parsed withfast-xml-parser, retried up to 10× when the bridge returns a null root. Elements with no size or no useful text/id are filtered out.Input:
adb shell input(tap/swipe/text/keyevent/draganddrop). Text is shell-escaped; only ASCII is supported byinput text, and non-ASCII input returns an actionable error instead of typing garbage.Recording:
adb shell screenrecordspawned in the background; stop sendsSIGINTto the on-device process (killall -2 screenrecord), waits for the file to finalize, thenadb pulls it.Foreground app detection:
dumpsys activity activities(ResumedActivity, covering both pre- and post-Android-13 formats) withdumpsys window(mFocusedApp) as fallback.Safety rails: package names validated against
[a-zA-Z0-9_.], output paths must be absolute with allowed extensions, URLs restricted to http(s) unless explicitly overridden.
Project layout
src/
├── index.ts entry point — stdio transport
├── server.ts MCP server + 26 tool registrations
├── adb.ts adb discovery/execution, device resolution, WiFi + mDNS connect
└── ui.ts uiautomator dump parsing, selector matching, wait-for-elementDevelopment
npm run watch # rebuild on change
npm run inspector # test tools interactively with MCP InspectorTroubleshooting
Symptom | Fix |
| Install Android platform-tools and/or set |
| Enable USB debugging (or wireless debugging), accept the RSA prompt on the device, check |
Screenshot is black | The screen is off — send |
| The foreground screen is secure (password field, DRM). Use |
Non-ASCII text fails |
|
WiFi connect fails | Ensure wireless debugging or |
Contributing
Issues and pull requests are welcome. Keep changes small and focused:
Fork and create a feature branch.
npm run buildmust pass with no TypeScript errors.Verify against a real device or emulator where possible (MCP Inspector makes this easy).
Describe the behavior change in the PR.
License
MIT © Alvin Ahmad (@qalvinahmad)
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/qalvinahmad/android-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server