phone-harness
Provides tools for controlling Android devices via ADB and UIAutomator, including observing the UI hierarchy, tapping, typing, swiping, navigating, opening apps, and verifying device state.
Provides tools for controlling iOS devices through WebDriverAgent, enabling UI observation, interaction, navigation, and state verification on iOS.
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., "@phone-harnessOpen Settings, tap Wi-Fi, and tell me the current status"
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.
Universal Phone Harness
Universal Phone Harness is a Python MCP server, CLI, and library for controlling Android and iOS devices from AI agents. It turns accessibility hierarchies into bounded indexed DOMs, grounds actions to observed generations, verifies postconditions, and blocks unconfirmed destructive targets.
Android uses ADB and UIAutomator. The iOS backend uses WebDriverAgent. A deterministic mock backend supports local development and CI.
This project can control a real phone. Review agent actions, keep destructive-action confirmation enabled, and never expose the MCP server to untrusted clients.
Features
16 MCP tools for observation, taps, typing, gestures, navigation, waits, assertions, dialogs, clipboard access, and health checks
Indexed UI elements with stale-observation rejection
Accessibility-first grounding with local OCR fallback for canvas and WebView surfaces
Explicit post-action assertions and one re-grounded retry
Destructive-action gates, step budgets, loop detection, and PII masking
Hard output budgets: 600 estimated tokens for observations and 200 for post-action DOMs by default
Compact JSON and native MCP image content
Android, WebDriverAgent-based iOS, and deterministic mock backends
CLI and Python APIs for direct automation
Related MCP server: Mobile Device MCP
Measured results
Tests on a Huawei JLN-LX1 running Android 12 used one warm-up and five measured samples:
Operation | Baseline median | Current median | Change |
Text clear | 321.183 ms | 73.176 ms | 77.22% faster |
Type 32 characters | 892.845 ms | 873.101 ms | 2.21% faster |
Screen hierarchy observation | 2621.626 ms | 2615.850 ms | 0.22% faster |
The clear baseline reproduces the earlier incomplete delete sequence. The comparison measures the cost and speed of the corrected implementation, not an overall system speedup. Full samples and assertions live in artifacts/android-hardening-benchmark.json.
Live MCP measurement reduced one Settings post-action DOM from 2,313 to 751 characters, a 67.53% reduction. Image requests now use MCP image blocks instead of embedding base64 inside JSON text.
Requirements
Python 3.10 or newer
Android: USB debugging or wireless ADB authorization
iOS: a reachable WebDriverAgent server
Optional OCR:
rapidocr-onnxruntimeand OpenCV
Installation
git clone https://github.com/ZachDreamZ/universal-phone-harness.git
cd universal-phone-harness
python -m pip install -e ".[dev]"Install OCR support when needed:
python -m pip install -e ".[ocr]"Android setup
Enable Developer options and USB debugging.
Connect and authorize the phone.
Confirm ADB sees it:
adb devices -l
phone-harness doctorThe default backend is Android and fails closed. It will not silently substitute the mock backend when no device is connected.
MCP setup
After installation, register this stdio server in any MCP client:
{
"mcpServers": {
"phone-harness": {
"command": "python",
"args": ["-m", "phone_harness.mcp_server"]
}
}
}Call phone_observe before indexed actions. Pass its observation_generation with the index:
{
"index": 3,
"observation_generation": 12
}Text and coordinate selectors do not require a generation. Typed text is not echoed in MCP responses.
CLI
phone-harness doctor
phone-harness observe
phone-harness tap Settings
phone-harness settings wifi
phone-harness swipe up --distance medium
phone-harness press HOME
phone-harness wait --text Connected --timeout 5000
phone-harness servePython API
from phone_harness import ActionRequest, ActionType, PhoneHarness, VerificationSpec
harness = PhoneHarness()
state = harness.observe()
settings = next(element for element in state.elements if element.text == "Settings")
result = harness.execute_action(
ActionRequest(
action=ActionType.TAP,
target_index=settings.id,
observation_generation=state.generation,
verify=VerificationSpec(assert_app_package="com.android.settings"),
)
)
print(result.new_state.current_app_package)Use the mock backend explicitly in tests:
from phone_harness.backends.mock import MockPhoneDevice
from phone_harness.harness import PhoneHarness
harness = PhoneHarness(device=MockPhoneDevice())Other explicit backend choices:
from phone_harness.core.config import HarnessConfig
android_config = HarnessConfig(default_platform="android")
ios_config = HarnessConfig(default_platform="ios")
mock_config = HarnessConfig(default_platform="mock")allow_mock_fallback=True is opt-in because silent fallback can make an agent believe it controls a real device when it does not.
MCP tools
Tool | Purpose |
| Return indexed DOM and optional native MCP images |
| Tap by index, text, or coordinates |
| Type into a focused or indexed field |
| Swipe directionally or by coordinates |
| Press system keys such as HOME and BACK |
| Launch an Android package identifier |
| Verify text and foreground-package conditions |
| Poll locally until conditions pass or time out |
| Open a validated HTTP or HTTPS URL |
| Open a system Settings section |
| Set and verify clipboard content |
| Respond to detected dialogs; defaults to deny |
| Long-press a target |
| Double-tap a target |
| Return step and latency metrics |
| Return backend and device health |
Architecture
phone_harness/
backends/ Android, iOS, and mock device adapters
core/ Models, configuration, device interface, exceptions
engine/ Verification, safety, dialogs, sessions, trajectories
perception/ Tree compaction, OCR matching, visual detection, SoM
plugins/ Example MCP client configurations
cli.py Command-line interface
harness.py Action and observation orchestration
mcp_server.py MCP JSON-RPC stdio server
tests/ Unit and integration tests
benchmarks/ Reproducible connected-device benchmarkDevelopment
python -m pip install -e ".[dev]"
python -m pytest -q
python -m compileall -q phone_harness benchmarks
python -m build
python -m twine check dist/*The test suite contains 108 tests and does not require connected hardware. verify_all.py adds optional live-device checks.
Security
Report vulnerabilities privately. See SECURITY.md. Do not include credentials, phone contents, screenshots, or private device identifiers in reports.
Contributing
See CONTRIBUTING.md. Contributions require tests and must pass CI.
License
MIT. See LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA MCP server that enables LLMs to control Android devices via ADB, supporting input, UI hierarchy, device management, and shell commands.14MIT
- AlicenseNot gradedqualityAmaintenanceAn MCP server that lets AI agents control iOS and Android devices (tap, scroll, type, take screenshots, read UI trees, and run code). Works with multiple devices at the same time.12344MIT
- AlicenseNot gradedqualityAmaintenanceAn MCP server that enables AI agents to control Android and iOS devices via natural language, using platform tools like adb and simctl.6,61345Apache 2.0
- AlicenseBqualityAmaintenanceGive any LLM agent a real Android or iPhone. 62 MCP tools: tap, swipe, type, screenshot, screen-tree reading, app launch, camera, TTS, crash reports, batched execution. Android via ADB, iPhone via WebDriverAgent, on-device inference, Docker+KVM emulators. Works with Claude Code, Cursor, LangChain, LlamaIndex, and any MCP client. MIT.66310MIT
Related MCP Connectors
Phone, SMS & email for AI agents — one remote MCP endpoint, OAuth login, zero install.
A paid remote MCP for AI agent browser approval MCP, built to return verdicts, receipts, usage logs,
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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/ZachDreamZ/universal-phone-harness'
If you have feedback or need assistance with the MCP directory API, please join our Discord server