🔗 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.

Top comments (1)
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?