DEV Community

Cover image for Give Your AI Agent Hands: Android Automation via MCP
Mostafa Dekmak
Mostafa Dekmak

Posted on

Give Your AI Agent Hands: Android Automation via MCP

🔗 github.com/dkmostafa/app-automating

What it is

app-automating is an open-source MCP server that gives an AI agent real
control over Android — emulators and physical devices alike.

It does three things:

  • Manages the AVD environment. Create, boot, rename, stop and delete emulators. Download system images. List what's attached. No Android Studio, no clicking through a GUI — the agent owns the device lifecycle.
  • Drives the screen. Tap, type, swipe, scroll, press keys, take screenshots, read the view hierarchy. Anything a finger can do, through Appium.
  • Remembers how it got there. Every interaction records itself automatically, so the agent can ask "how do I get from the home screen to checkout?" instead of rediscovering the route on every run.

That third one is the part that doesn't exist elsewhere. Most tooling in this
space is a thin wrapper over adb — it gives a model hands but no memory, so
every session starts from zero.

28 tools, three modules: android_ (10) for the device lifecycle,
appium_ (13) for the screen, navigation_memory_ (5) for the map.

Where it fits

It's deliberately not a testing framework. It's a capability layer — the
agent decides what the job is.

You want to The agent does
Test an app Boots a clean emulator, installs the build, walks the flows, screenshots what broke
Scrape a mobile-only app Navigates to the data, reads the view hierarchy, pages through results
Reproduce a bug Replays a recorded route to the exact screen, every time
Explore an unfamiliar app Maps the screens it finds and builds a navigation graph as it goes
Automate a repetitive chore Anything you'd otherwise do by hand, thirty times

If the task involves an Android screen and you'd rather describe it than script
it, this is the layer underneath.

Built with

Pure Python at the core — the server itself is a remote control for other
people's tools, and it stays out of their way.

Layer Stack
MCP server FastMCP over STDIO — no sockets, deliberately
Device control Appium + the uiautomator2 driver
Emulator control The Android SDK directly: adb, emulator, avdmanager, sdkmanager
Navigation memory SQLAlchemy + aiosqlite — one local SQLite file, no service to run
Schemas & config Pydantic v2 + pydantic-settings
Tooling Python 3.12+, uv, pytest, ruff

Under that, the codebase is four-layer Clean Architecture — one vertical slice
per module, dependencies pointing inward, and an architecture test in every
module that walks the AST and fails the build on a layer violation. More on
that later in the post.

How it works

Top comments (1)

Collapse
 
raknaos profile image
Raknaos

Nice layering. The navigation_memory piece is the one that actually differentiates this from a thin adb wrapper - I run a headless-browser bridge myself and the 'every session starts from zero' problem is exactly what eats agents on repetitive UI flows.

Curious how you keep the view-hierarchy snapshots stable across app updates though. In my experience the moment a dev renames a resource-id the cached route breaks silently and you think the agent is 'lost' when really your graph is stale. Do you fingerprint nodes by structure or by id, and how does the memory self-correct?