digitomancy-mcp
Provides Android automation capabilities, including reading the screen, tapping and typing, remembering UI elements as named anchors, verifying screen state with checkpoints, and running resumable multi-step routines on connected Android devices, emulators, or BlueStacks.
Click on "Deploy 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., "@digitomancy-mcprun my morning routine on the Pixel and resume if it fails"
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.
Digitomancy
Divination by fingers. Android automation for people and agents: read the screen, tap and type, remember buttons as named anchors, check where you are with checkpoints, and run multi-step routines that resume after a failure. Works with a USB phone, an emulator or BlueStacks, from a CLI, from Python, or from Claude as an MCP server and plugin.
Status: early but working. Tested on a Pixel 9 (Android 16) plus unit tests against a fake device. The Tasker bridge has unit tests but hasn't yet been verified end to end on a device.
Why not just use X
Tool | Good for | Why it isn't the whole answer |
Ad-hoc agent poking via the accessibility tree | No memory: every session finds the same buttons again | |
A full LLM agent framework | Heavy and opinionated if you already have agents | |
Fast Android-only driver, no Appium server | Digitomancy builds on this | |
Appium | Cross-platform QA | Needs a server; overkill for Android-only |
Mirroring the screen | Use |
What Digitomancy adds: named devices, anchor maps (selector first, normalized coordinates as fallback), checkpoints with failure snapshots, resumable routines, and a Tasker bridge. What an agent finds once gets written down; the next run looks it up.
Related MCP server: duet
Install
As a Claude plugin: build it with scripts/build_plugin.sh and install dist/digitomancy.plugin. You need adb and uv on your PATH. See plugin/README.md.
As a CLI or library:
git clone https://github.com/MadnessEngineering/digitomancy-plugin && cd digitomancy-plugin
uv sync --group dev # add --extra vision for image-template checkpoints
uv run dgm doctor # tools, workspace, which devices are onlineAs an MCP server in any MCP client:
{"mcpServers": {"digitomancy": {"command": "uv", "args": ["run", "--project", "/path/to/digitomancy-plugin", "digitomancy-mcp"]}}}Connect a device
Phone: enable Developer options (tap Build number 7 times), turn on USB debugging, plug in, and accept the prompt. On first connect uiautomator2 installs its helper on the device.
BlueStacks: go to Settings → Advanced and enable ADB, then
uv run dgm -d bluestacks connect. Check the port it shows; editdevices.yamlto match.
Workspace
Your devices, maps and routines live in a workspace: $DGM_HOME, or ~/.digitomancy by default, created on first run with starter maps and routines. Existing files are never overwritten.
devices.yaml: names → serials. Pick one with-d NAME,$DGM_DEVICEordefault:. Unknown names are used as raw serials.maps/<app>.yaml:anchors(things to tap),screens(checkpoint specs) andhazards(things never to tap). Refer to them asmap:name.routines/*.py: routines built from stages. A stage canrequirea screen, and a failed run canresume_fromthat stage..runs/: evidence from failed checkpoints (screenshot, UI dump, foreground activities).catalog/(optional, fromdgm catalog): a redacted index of your Tasker projects and tasks.hazards_manual.txtandhazard_patterns.txtthere tell the Tasker bridge which tasks it must never fire.
Concepts
Coordinates: a float in
[0,1]is a fraction of the screen, and an int is a pixel. Maps store fractions so they work at any resolution. They still depend on orientation.Checkpoints: a screen spec combines conditions with
allorany:selector,gone,app,activity,anchor,image. A failedexpectsaves a snapshot to.runs/.Tasker:
dgm tasker "Task Name" -p par1=xfires a task througham broadcast. It needs a one-time profile on the phone; see docs/TASKER.md.
CLI
dgm doctor | connect | look [--all] | tap map:anchor|x,y | check map:screen
dgm routines | run NAME [-p k=v] [--resume-from STAGE]
dgm tasker TASK [-p k=v] [-w SEC] | catalog [SOURCES…]
dgm mirror [-- scrcpy args] | mcpKnown conflicts
Accessibility suppression. While uiautomator2's on-device server runs, Android suppresses every accessibility service: Tasker, AutoInput, Join, screen readers. The CLI stops the server when each command exits; the MCP server stops it after 60s idle or on
release.scrcpy
--new-display. Apps on virtual displays don't count as foreground. Detection reads Display #0 only.Launching apps.
Device.launch()resolves the default launcher activity. uiautomator2'sapp_startcan pick a random one, and some apps (Tasker) run a task from their second launcher activity.
Development
uv run pytest -q # no device needed: tests use a fake device
./scripts/build_plugin.sh # dist/digitomancy/ and dist/digitomancy.plugin
claude plugin validate dist/digitomancyLicense
MIT. Copyright (c) 2026 Madness Engineering. The Tasker action code table in the plugin comes from Taskomater/Tasker-XML-Info (MIT).
Available Tools
20 toolscheckCheckC
Evaluate a mapped screen 'map:screen' (optionally waiting). Returns ok + per-condition detail.
Inputs: screen (required), device, timeout. Returns: object
devicesDevicesB
Registered devices (devices.yaml), the default, and which serials adb sees right now.
Inputs: no named parameters. Returns: object
keyKeyB
Press a key: home, back, enter, recent, power, volume_up, volume_down, delete…
Inputs: name (required), device. Returns: result
launchLaunchC
Start an app by package name.
Inputs: package (required), device, stop_first. Returns: result
list_mapsList MapsC
All maps with their anchors and screens.
Inputs: no named parameters. Returns: object
list_routinesList RoutinesC
Known routines with params and stage names (stages are resume points).
Inputs: no named parameters. Returns: result
lookLookC
Current app + compact UI node list. Lines: #idx class 'text' id=res @(x,y normalized) [tap].
Inputs: limit, device, everything. Returns: result
releaseReleaseC
Stop uiautomator on the device so Tasker/AutoInput accessibility comes back.
Inputs: device. Returns: result
run_routineRun RoutineC
Run a routine. On failure returns the failed stage, snapshot dir, and a resume hint.
Inputs: name (required), device, params, resume_from. Returns: object
save_anchorSave AnchorC
Remember a tap target. From a look node (stores selector + point) or raw normalized x,y.
Inputs: name (required), map_name (required), x, y, +3 more. Returns: result
screenshotScreenshotA
PNG of the screen (downscaled to save tokens). Use when look can't see it (games, canvases).
Inputs: scale, device.
shellShellC
Raw adb shell escape hatch.
Inputs: cmd (required), device. Returns: result
swipeSwipeB
Swipe between two points (fractions or pixels). Scroll down = swipe(0.5,0.75,0.5,0.25).
Inputs: x1 (required), x2 (required), y1 (required), y2 (required), +2 more. Returns: result
tapTapC
Tap. Floats in [0,1] are screen fractions (preferred); otherwise pixels.
Inputs: x (required), y (required), device. Returns: result
tap_anchorTap AnchorC
Tap a mapped anchor 'map:name' (selector first, saved point as fallback).
Inputs: ref (required), device, timeout. Returns: result
tap_nodeTap NodeC
Tap node #index from the last look on this device.
Inputs: index (required), device. Returns: result
tasker_lookupTasker LookupA
Search the Tasker catalog (built by dgm catalog) by task/profile name substring.
Returns matching tasks with their actions and calls, plus hazard flags. Never fire a task marked hazard; tasker_run refuses them anyway.
Inputs: limit, query, project. Returns: object
tasker_runTasker RunB
Fire a Tasker task via broadcast (needs the DGM Dispatch profile, docs/TASKER.md).
Inputs: task (required), device, params, wait_result. Returns: object
type_textType TextC
Type into the focused field.
Inputs: text (required), clear, device. Returns: result
workspaceWorkspaceB
Where devices.yaml, maps/ and routines/ live (created and seeded if missing). Edit devices.yaml there.
Inputs: no named parameters. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
TDQS
Scored across 20 tools
Most tools have clearly distinct purposes, but tap, tap_node, and tap_anchor overlap as three tap variants, and tasker_run versus run_routine could be confused without careful reading. The descriptions generally clarify when to use each tool, so ambiguity is limited.
There is a mix of snake_case multiword names and bare nouns/single verbs such as shell, workspace, look, tap, and swipe. The convention is readable but not consistent across the set.
20 tools is on the heavy side for a device-automation server, though most correspond to real primitives rather than duplicates. It sits in the borderline-heavy 16–25 range.
The set covers device inspection, interaction, maps/anchors, routines, Tasker, and raw adb shell. It lacks structured CRUD for maps and routines and some UI actions like long-press, but the shell escape hatch prevents hard dead ends.
Maintenance
Related MCP Connectors
Drive cloud Android phones on US mobile IPs. Read the screen, tap, type, install apps and run tasks.
Cloud Android phones for AI agents: read the screen, tap, type, install APKs, park and resume.
Give your AI agent a real cloud Android phone: push APKs, drive it, get screenshots and logs.
Let AI agents control Android and iOS devices on Mobilerun Cloud: screen, input, apps, workflows.
Related MCP Servers
- AlicenseCqualityBmaintenanceEnables AI agents to control Android phones, emulators, redroid containers, iOS devices, and cloud-hosted devices through a perceive-act-verify loop of screen reading, taps, gestures, typing, and app launching. Exposes 138 tools for driving screens, elements, and files over adb, Portal APIs, and ios-portal without running ARM-only code on the device.9415 npm1MIT
- AlicenseNot gradedqualityBmaintenanceEnables an AI coding agent to drive a real Android phone over adb and one or more visible Chrome windows in the same test run, with safe guarded commands, screenshots returned as images, per-step logs, reports, and recordings. It lets agents act, inspect the screen and device log, fix code, and rerun a scenario until the feature passes.21 npm3MIT
- AlicenseAqualityBmaintenanceEnables AI agents to see and drive a real Android phone over plain ADB: screenshots and numbered UI trees, gestures, typing with accents and emoji, SMS/RCS reading and prepared replies, notifications, files, and settings, with no root and no app installed on the phone. Safeguards mask security codes and require explicit confirmation before sending, paying, deleting or confirming anything.182MIT
- AlicenseAqualityAmaintenanceLets AI agents use an Android phone: read the screen, tap, type, scroll, open apps, take screenshots and reply to notifications, with approval cards before anything is sent, posted, bought or deleted. Runs inside the Buddy app on the phone; no root, adb or PC.1048207Apache 2.0