Multi-device MCP server for Android automation, built in Python with adbutils and uiautomator2.
- Exposes Android automation capabilities as MCP tools.
- Supports multiple connected devices in parallel.
- Uses per-device session caching and UI locks to avoid conflicting actions on the same device.
- Works with
stdio,streamable-http, andssetransports.
- Python
>=3.11 uvfor dependency and environment managementmcp(FastMCP)adbutilsuiautomator2Pillow
adbinstalled and available inPATH- One or more Android devices/emulators connected and authorized (
adb devices) uvinstalled
uv syncIf you use an existing virtual environment:
source .venv/bin/activate
uv syncuv run mcp-android-server --mode stdiouv run mcp-android-server --mode streamable-http --port 3001MCP endpoint URL:
http://127.0.0.1:3001/mcp
uv run mcp-android-server --mode sse --port 3001--mode {stdio,streamable-http,sse}
--port PORT
--default-serial SERIAL
--max-workers N
--session-ttl-s SECONDS
--healthcheck-interval-s SECONDS
--connect-retries N
--connect-backoff-s SECONDS
Environment variables (equivalent to CLI defaults):
MCP_TRANSPORTMCP_PORTMCP_DEFAULT_SERIALMCP_MAX_WORKERSMCP_SESSION_TTL_SMCP_HEALTHCHECK_INTERVAL_SMCP_CONNECT_RETRIESMCP_CONNECT_BACKOFF_S
Add this to ~/.codex/config.toml:
[mcp_servers.android]
url = "http://127.0.0.1:3001/mcp"[mcp_servers.android]
command = "uv"
args = ["run", "mcp-android-server", "--mode", "stdio"]
cwd = "/absolute/path/to/mcp_android"
[mcp_servers.android.env]
PYTHONPATH = "src"All device-specific tools accept serial.
If serial is omitted, resolution order is:
--default-serial/MCP_DEFAULT_SERIAL- The only connected device
- Error if multiple devices are connected
list_devices()get_device_status(serial)clear_device_session(serial)list_active_sessions()
get_logcat_output(serial?, app_package, log_level="DEBUG", max_lines=100)
log_level values:
DEBUGINFOWARNINGERROR
get_screenshot(serial?, scale_factor=0.4)get_ui_dump(serial?, returned_attributes)
Allowed returned_attributes values:
index,text,resource-id,class,package,content-desccheckable,checked,clickable,enabled,focusable,focusedscrollable,long-clickable,password,selected,boundsdrawing-order,hint
click_ui_element(serial?, text?, resource_id?, content_desc?, timeout_s=10.0)
For click_ui_element, provide exactly one selector among:
textresource_idcontent_desc
tap_screen(serial?, x, y)swipe_screen(serial?, x1, y1, x2, y2, duration_ms=300)send_text(serial?, text_to_send, clear_existing=false)perform_system_action(serial?, action)whereactionis:BACKHOMERECENT_APPS
- Call
list_devices. - Call
get_screenshotto inspect current state. - Call
get_ui_dumpto find selectors. - Call
click_ui_elementortap_screen. - Call
get_logcat_outputfor app diagnostics.
Run unit tests:
uv run python -m unittest discover -s tests/unit -vDevice not found:- Check serial from
list_devices.
- Check serial from
Multiple devices connected. Please specify serial:- Pass
serialexplicitly or set--default-serial.
- Pass
- UI element not found:
- Use
get_ui_dumpand verify the exact selector text/resource id/content description.
- Use
- No logs returned for
get_logcat_output:- Ensure the app process is running and
app_packageis correct.
- Ensure the app process is running and
- ADB authorization issues:
- Reconnect device and accept RSA authorization prompt.