Claude MobileBLOCK
MCP server for mobile and desktop automation — Android (via ADB), iOS Simulator (via simctl), and Desktop (Compose Multiplatform). Like Claude in Chrome but for mobile devices and desktop apps
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
## 👉 Want everything in one package? Keep usingclaude-in-mobile. Nothing changes for you. Same install, all platforms bundled, still maintained: ``sh npm i -g claude-in-mobile`That's it — the all-in-one edition. **Read on only if you'd rather install the platforms separately** (that's whatmcp-devices` is for).
Two editions — same tool
Both are maintained. claude-in-mobile was renamed to mcp-devices in 4.0 and split into a modular edition; the all-in-one keeps its name and its unchanged install. The rest of this README covers the modular `mcp-devices` edition.
Install in 3 steps (modular)
Requires Node.js 20 or newer.
# 1. base server
npm i -g mcp-devices
# 2. add a platform (example: Android)
npm i -g @mcp-devices/plugin-android
mcp-devices install android
# 3. point your MCP client at it
# { "mcpServers": { "mobile": { "command": "mcp-devices" } } }
# Grok Build:
# grok plugin marketplace add AlexGladkov/claude-in-mobile
# grok plugin install mcp-devices --trustRestart your MCP client. Done — ask Claude "take a screenshot of my Android device" and it works.
Check prerequisites any time: mcp-devices doctor.
Native shell CLI
The npm command mcp-devices is the Node.js MCP server. For direct shell automation, install the native Rust CLI and use its unambiguous command name:
brew install AlexGladkov/tap/mcp-devices mcp-devices-cli --help mcp-devices-cli devices
The separate name prevents a global npm install from shadowing the native CLI on PATH.
Pick your platform
Each platform is a separate package. Install the one(s) you need — ful
70cbae7718afOBSERVED · 2026-10-03Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add plugin-web --env APP_STORE_CONNECT_API_KEY_ISSUER_ID=${APP_STORE_CONNECT_API_KEY_ISSUER_ID} --env APP_STORE_CONNECT_API_KEY_KEY=${APP_STORE_CONNECT_API_KEY_KEY} --env APP_STORE_CONNECT_API_KEY_KEY_FILEPATH=${APP_STORE_CONNECT_API_KEY_KEY_FILEPATH} --env APP_STORE_CONNECT_API_KEY_KEY_ID=${APP_STORE_CONNECT_API_KEY_KEY_ID} -- npx -y @mcp-devices/[email protected]{
"mcpServers": {
"plugin-web": {
"command": "npx",
"args": [
"-y",
"@mcp-devices/[email protected]"
],
"env": {
"APP_STORE_CONNECT_API_KEY_ISSUER_ID": "${APP_STORE_CONNECT_API_KEY_ISSUER_ID}",
"APP_STORE_CONNECT_API_KEY_KEY": "${APP_STORE_CONNECT_API_KEY_KEY}",
"APP_STORE_CONNECT_API_KEY_KEY_FILEPATH": "${APP_STORE_CONNECT_API_KEY_KEY_FILEPATH}",
"APP_STORE_CONNECT_API_KEY_KEY_ID": "${APP_STORE_CONNECT_API_KEY_KEY_ID}"
}
}
}
}Exposed tools (200)
150 read · 58 write · 18 destructive. Blast radius: 18 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
a.tool | read | |
accessibility | read | Accessibility audit — WCAG checks, element validation |
accessibility_audit | write | Run full accessibility audit on current screen. Returns score, issues grouped by severity, and passed rules. |
accessibility_check | read | Check accessibility of a specific element found by text, resourceId, or index. |
accessibility_rules | read | List all accessibility rules or show details of a specific rule. |
accessibility_summary | read | Quick accessibility summary: score + issue counts only (short output). |
app | write | Launch, stop, install, list applications |
app_install | write | Install APK (Android), .app bundle (iOS), RPM (Aurora), or HAP (HarmonyOS) |
app_launch | read | Launch app by package name or bundle ID |
app_list | read | List installed apps on a platform with app inventory support |
app_restart | destructive | Force-stop then re-launch an app. Common pattern for clearing in-memory state without uninstall. |
app_stop | destructive | Force stop an app |
app_uninstall | destructive | Uninstall an app by package name or bundle ID |
appstore_build | read | Build a signed .ipa for TestFlight (auto-detects Flutter/React Native/KMP/Xcode projects). |
appstore_get_releases | read | List TestFlight builds with processing state. |
appstore_promote | write | Promote a TestFlight build: add it to a beta group by group name |
appstore_set_notes | write | Set TestFlight |
appstore_submit | write | Submit a TestFlight build for external beta review (defaults to the latest VALID build). |
appstore_upload | write | Validate then upload an .ipa to App Store Connect (TestFlight) via altool. |
autopilot | read | AI-driven test generation and self-healing |
autopilot_explore | read | Automatically navigate the app, building a navigation graph of screens and transitions. Uses screen fingerprinting to avoid revisiting screens. |
autopilot_generate | read | Generate test scenarios from exploration data. Creates flow_run-compatible test steps for all unique paths. |
autopilot_heal | read | Self-heal a broken test step by finding the best matching element on the current screen. Uses fuzzy matching on text, resourceId, className, and bounds. |
autopilot_status | read | Get exploration status. If explorationId is provided, shows details. Otherwise lists all explorations. |
autopilot_tests | read | List or get generated test scenarios for an exploration. |
bad.tool | read | |
browser | read | Browser automation — navigate, evaluate JS, manage tabs |
browser_clear_session | destructive | Delete all stored data for a session |
browser_click | read | Click element by ref, selector, or text |
browser_close | read | Close browser session |
browser_evaluate | write | Execute JavaScript in browser page |
browser_fill | read | Fill input field with value |
browser_fill_form | read | Fill multiple form fields at once |
browser_list_sessions | read | List active browser sessions |
browser_navigate | read | Navigate to URL or go back/forward/reload |
browser_open | read | Open URL in browser session |
browser_press_key | read | Press keyboard key in browser |
browser_screenshot | read | Take browser page screenshot |
browser_snapshot | read | Get accessibility snapshot with element refs |
browser_wait_for_selector | read | Wait for element to appear on page |
click | read | Hijack |
clipboard_copy | read | Select all and copy to clipboard (Android only) |
clipboard_get | read | Get clipboard text (Desktop only) |
clipboard_get_android | read | Read clipboard text from Android device |
clipboard_paste | read | Paste clipboard into focused field (Android only) |
clipboard_select | read | Select all text in focused field (Android only) |
clipboard_set | write | Set clipboard text (Desktop only) |
debug_attach | read | Attach the runtime debugger to a DEBUGGABLE running app. Android (JDWP): the package must have android:debuggable=true. iOS (LLDB Simulator): requires macOS + Xcode. Returns a sessionId for all subsequent debug calls. |
debug_break | write | Set a breakpoint. Android: {className, line} or {className, method} (method-entry, robust without line info). iOS: {file, line} or {method}. Returns { id, verified }. verified=false means the class is not yet loaded — the breakpoint will arm on CLASS_PREPARE. |
debug_detach | read | Detach the debugger and end the session (the app keeps running). Also tears down the adb forward / LLDB daemon for this session. |
debug_eval | read | Evaluate an expression on a paused thread. Android: a local name, |
debug_pause_state | read | Inspect a paused thread: call stack frames (class, method, line) and the top frame |
debug_poll | read | Poll the event queue for hits (BREAKPOINT_HIT / STEP_HIT / EXCEPTION_HIT / CLASS_PREPARE / VM_DEATH). Never blocks. Start cursor at 0, advance nextCursor on each call. If the queue is empty, ask the user to interact with the app, then poll again. |
debug_remove_break | destructive | Remove a breakpoint by its id (returned by debug_break). |
debug_resume | read | Resume all threads in the debugged VM/process. Use after inspecting a paused state to let the app continue running. |
debug_sessions | read | List active debug sessions (sessionId + platform). Useful to discover open sessions before attaching or after a crash. |
debug_set_var | write | Mutate a local variable on a paused thread. Android: primitives (int/long/bool/float/...), null, and strings; the value is coerced to the local |
debug_step | read | Step the paused thread: OVER (next line), INTO (into call), or OUT (out of current method). Issues the step and resumes the thread; poll for STEP_HIT to see where execution landed. |
debug_threads | read | List threads of the debugged VM with ids and names (Android). Use an id with debug_pause_state / debug_step to target a specific thread. |
desktop | read | Desktop app control — windows, clipboard, performance |
desktop_focus | read | Focus a desktop window |
desktop_get_target_pid | write | Get the PID of the native app set by the last desktop_launch (bundle or attach mode). Returns null if no target PID is set. |
desktop_launch | write | Start desktop automation and optionally launch an app. Supports three modes: |
desktop_monitors | read | List connected monitors (Desktop only) |
desktop_performance | read | Get memory and CPU metrics (Desktop only) |
desktop_resize | read | Resize a desktop window |
desktop_stop | write | Stop running desktop application |
desktop_windows | read | Get desktop window info |
device | read | Device management, module loading, target switching |
device_get_target | read | Get current active platform and status |
device_info | read | Get device info |
device_list | read | List connected devices and emulators |
device_set_target | write | Switch active platform (android/ios/desktop/aurora/harmony/browser) |
early.tool | read | |
find_element | read | Find element by text |
flow | read | Batch commands, multi-step automation, parallel execution |
flow_batch | write | Execute multiple commands in one round-trip. Set turbo:true for UI context per step (experimental). |
flow_parallel | write | Run same action on multiple devices in parallel. Uses Promise.allSettled for concurrent execution. |
flow_run | write | Multi-step automation flow with conditionals, loops, error handling. Use for E2E testing instead of calling tools one-by-one. Set turbo:true for UI context per step (experimental). Max 20 steps. |
get_ui | read | Get UI elements on screen |
go_back | read | Press back button |
harmony_arkweb_close | destructive | Remove an ArkWeb HDC port-forward created for inspection. |
harmony_arkweb_inspect | read | Discover an ArkWeb DevTools socket, forward it over HDC, and list inspectable pages. |
harmony_launch_ability | read | Launch a HarmonyOS ability with an optional module name. Defaults to EntryAbility. |
harmony_sandbox_list | read | List files in a running debug-signed HarmonyOS application |
harmony_sandbox_pull | read | Download a file from a running debug-signed HarmonyOS application |
harmony_sandbox_push | write | Upload a file into a running debug-signed HarmonyOS application |
harmony_sandbox_read | read | Read a text file from a running debug-signed HarmonyOS application |
harmony_test | write | Run an ArkXTest module through |
huawei_get_releases | read | Get release info from Huawei AppGallery |
huawei_set_notes | write | Set release notes for Huawei AppGallery draft |
huawei_submit | write | Submit Huawei AppGallery draft for review |
huawei_upload | write | Upload APK/AAB to Huawei AppGallery. Requires HUAWEI_CLIENT_ID env. |
input | read | Tap, swipe, type, key press — all input actions |
input_double_tap | read | Double tap by coordinates, text, resourceId, or index. Raw x/y are screenshot-space and auto-scaled to device coordinates — see input_tap description for full coordinate space rules. |
input_key | read | Press hardware key (BACK, HOME, ENTER, etc.) |
input_long_press | read | Long press at coordinates or on element by text/label. Raw x/y are screenshot-space and auto-scaled to device coordinates — see input_tap description for full coordinate space rules. |
input_swipe | read | Swipe by direction or custom coordinates. Raw x1/y1/x2/y2 are screenshot-space and auto-scaled to device coordinates — see input_tap description for full coordinate space rules. |
input_tap | read | Tap |
input_text | read | Type text into focused input field |
intent | write | Intent & deep link engine — am start/broadcast with typed extras |
intent_broadcast | write | Send an Android broadcast intent. Useful for triggering system events or communicating with broadcast receivers. Android only. |
intent_deeplink | read | Open a deep link URI on Android or iOS. On Android uses |
intent_services | read | List running Android services. Optionally filter by package name. Android only. |
intent_start | write | Launch an Activity with a structured Android Intent. Supports action, component, data URI, category, typed extras, and activity flags. Android only; use intent_deeplink for iOS. |
late.tool | read | |
launch_app | read | Launch app |
mod_a | read | A |
mod_b | read | B |
network | read | Network layer — traffic stats, connectivity, proxy, airplane mode |
network_airplane | write | Enable or disable airplane mode on the Android device. |
network_connectivity | read | Get current network connectivity info: active network type (WiFi/Mobile/etc), connection state, IP address, DNS servers, and basic WiFi details (SSID, RSSI). Android only. |
network_proxy | destructive | Get, set, or clear the global HTTP proxy for the Android device. |
network_traffic | read | Get network traffic statistics. If a package name is provided, shows per-app traffic (rx/tx bytes and packets) using kernel UID counters. Otherwise shows global per-interface totals from dumpsys netstats. Android only. |
new-name | read | New |
owned | read | Owned |
performance | read | Performance Lab — metrics, crashes, native traces, heap snapshots and diffs |
performance_baseline | write | Save current performance metrics as a named baseline for later comparison. |
performance_compare | read | Compare current performance against a saved baseline. Returns PASS/FAIL per metric with thresholds. |
performance_crashes | read | Query recent crashes, ANRs, and native crashes from device logs. |
performance_framestats | read | Collect frame rendering statistics from GPU profiling. Returns frame time percentiles (p50/p90/p99), jank rate, and slow render percentage. Android only. |
performance_heap_capture | read | Capture a private heap artifact without returning raw heap contents through MCP. Android requires a debuggable package, iOS requires a running Simulator app, and browser uses the active CDP session. |
performance_heap_delete | destructive | Delete a captured heap artifact and its metadata immediately. |
performance_heap_diff | read | Compare bounded metadata from two compatible heap artifacts. Returns signed size/count deltas; it does not claim that growth is a memory leak. |
performance_monitor | read | Monitor performance over a duration, collecting periodic samples. Returns min/max/avg stats. |
performance_snapshot | read | Collect current performance metrics: memory, CPU, FPS, battery, crash count. Returns formatted report. |
performance_trace_delete | destructive | Delete a captured native performance trace artifact and its metadata. |
performance_trace_start | write | Start a bounded native performance trace. Android records Perfetto, iOS records an Instruments xctrace bundle, and browser records Chrome tracing. Stop it to persist a private artifact and receive a compact summary. |
performance_trace_status | read | List active performance traces and the remaining capture window. |
performance_trace_stop | write | Finalize an active performance trace, store the native artifact with mode 0600 and 24-hour TTL, and return a bounded agent-readable summary plus checksum. |
permission_grant | read | Grant app permission (Android runtime / iOS privacy) |
permission_reset | destructive | Reset all permissions for an app |
permission_revoke | destructive | Revoke app permission |
press_key | read | Press key |
recorder | read | Record and replay interaction sequences |
recorder_add_step | write | Manually add a step to the active recording |
recorder_delete | destructive | Delete a saved scenario |
recorder_export | read | Export scenario as flow_steps (for flow_run) or markdown checklist |
recorder_list | read | List saved test scenarios |
recorder_play | read | Replay a saved scenario. Executes all steps sequentially with optional speed/timeout control. |
recorder_remove_step | destructive | Remove a step from the active recording by index |
recorder_show | read | Display contents of a saved scenario |
recorder_start | write | Begin recording user interactions as a test scenario |
recorder_status | read | Get current recording state |
recorder_stop | write | Stop recording and save scenario (or discard) |
repl_expect | read | Block until a prompt regex matches, the session idles, the child exits, or the timeout fires. |
repl_key | write | Send a named key to a session. Editing/navigation for driving TUIs. |
repl_kill | destructive | Terminate a REPL session (SIGTERM, then SIGKILL). |
repl_list | read | List active REPL sessions and their statuses. |
repl_resize | read | Resize the PTY and vt100 grid for a live session. |
repl_send | write | Write text to a REPL session. Appends a newline by default. |
repl_snapshot | read | Read the current emulated terminal screen for a session. |
repl_spawn | write | Start an interactive REPL or CLI process under a PTY. Returns the session id. |
rustore_discard | destructive | Delete RuStore version draft |
rustore_get_versions | read | Get version list from RuStore |
rustore_set_notes | write | Set what |
rustore_submit | write | Submit RuStore draft for moderation |
rustore_upload | write | Upload APK/AAB to RuStore. Requires RUSTORE_KEY_JSON env. |
sandbox | write | App sandbox access — SharedPreferences, SQLite, file operations via run-as |
sandbox_file_list | read | List files inside an app |
sandbox_file_read | read | Read the contents of a file from an app |
sandbox_prefs_read | read | Read SharedPreferences XML from an app |
sandbox_prefs_write | write | Write or update a single value in an app |
sandbox_sqlite_query | write | Run a read-only SQL query against an app |
screen | read | Screenshot capture, annotation, diff comparison |
screen_annotate | read | Screenshot with numbered bounding boxes on UI elements (Android/iOS) |
screen_capture | read | Take screenshot. Auto-compressed. Use diff=true to see only changes. |
screenshot | read | Take screenshot |
sensor | read | Sensor & environment simulation — GPS, battery, notifications, thermal |
sensor_battery | write | Set battery level, charging status, and plugged state on Android. Changes persist until reset:true is used or device reboots. iOS: not supported. |
sensor_location | write | Set GPS location on device. Android emulator: uses |
sensor_notifications | read | Read the notification shade from Android. Returns a parsed list of active notifications with title, text, package, and time. iOS: not supported. |
sensor_thermal | read | Override Android thermal status (API 29+ / Android 10+). Simulates device overheating scenarios. Use reset:true to restore real thermal state. iOS: not supported. |
store | read | App store metadata — ratings, reviews, versions |
store_discard | read | Discard Google Play release draft |
store_get_releases | read | Get current releases across Google Play tracks |
store_halt_rollout | read | Halt staged rollout on Google Play |
store_promote | read | Promote release between Google Play tracks |
store_set_notes | write | Set release notes for Google Play draft (per language, max 500 chars) |
store_submit | write | Publish release draft to Google Play track |
store_upload | write | Upload APK/AAB to Google Play. Requires GOOGLE_PLAY_KEY_FILE env. |
swipe | read | Swipe in a direction |
sync | write | Multi-device synchronization and coordination |
sync_assert_cross | write | Cross-device assertion: perform action on source device, verify result on target device with retries. |
sync_create_group | write | Create a sync group of 2+ devices with named roles for coordinated testing. |
sync_destroy | destructive | Destroy a sync group and release resources. |
sync_list | write | List all active sync groups. |
sync_run | write | Execute coordinated steps across devices with barrier synchronization. |
sync_status | write | Show details of a sync group and its last run result. |
system | read | Shell, logs, clipboard, permissions, URL, device info |
system_activity | read | Get current foreground activity (Android only) |
system_clear_logs | destructive | Clear the device log buffer |
system_file_pull | write | Download a file from a device with file transfer support |
system_file_push | write | Upload a local file to a device with file transfer support |
system_info | read | Get battery and memory info |
system_is_running | read | Check whether an app process is currently running by package name (Android only). Returns |
system_logs | read | Get device logs with optional filters |
system_open_url | read | Open URL in device browser |
system_pid_of | read | Get the PID of a running app process by package name (Android only). Returns 0 when the package is not running. Useful for verifying app launch / crash detection without parsing the full ps output. |
system_shell | read | Shell |
Trust audit
BLOCKgrade F · trust 48/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (12 observation(s))
- Network
- declared (9 observation(s))
- Shell
- declared (4 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (25)
let out = redact("token=xoxb-1234567890-fake-slack-token");exec(command: string, deviceIdOverride?: string): string {eval(sessionId: string, threadId: string, expr: string): Promise<unknown> {exec(command: string): string;
gradle-wrapper.jar
let url = format!("http://127.0.0.1:{port}/json/list");const response = await fetch(`http://127.0.0.1:${selectedPort}/json/list`, {const response = await fetch(`http://127.0.0.1:${selectedPort}/json/list`, {`http://127.0.0.1:${localPort}/json/list`,let secret = "sk-ant-api03-TESTSECRETFORCAST00000";
let secret = "sk-ant-api03-LIVETEST00000000000000000";
let secret = "sk-ant-api03-INTEGRATIONTESTBOTH0000000";
cmd: "deploy --key sk-ant-AAAAAAAAAAAAAAAAAAAAAAAA",
expect(out[0].cmd).toBe("deploy --key sk-ant-AAAAAAAAAAAAAAAAAAAAAAAA");"AKIA0000000000000000",
let secret = "sk-ant-api03-TESTSECRETFORCAST00000";
let secret = "sk-ant-api03-LIVETEST00000000000000000";
let secret = "ghp_1234567890abcdefghijklmnopqrstuvwxyz";
let secret = "sk-ant-api03-INTEGRATIONTESTBOTH0000000";
val secret = "unknown-secret-bearing-method"
let secret = "ghp_1234567890abcdefghijklmnopqrstuvwxyz";
`ghp_16C7e42F292c6912E7710c838347Ae178B4a`, `xoxb-111-222-aaaaa`, minimal JWT (`eyJhbGc...`),
const TOKEN = "ghp_1234567890abcdefghijklmnopqrstuvwxyz";
const out = redactScreen("token: ghp_1234567890abcdefghijklmnopqrstuvwxyz");"ghp_1234567890abcdefghijklmnopqrstuvwxyz",
Gates applied: critical_finding, no_behavioural_pass, no_license.
70cbae7718affull audit observations/trust-audit/mcp-server/alexgladkov__claude-mobile.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-03 | 70cbae7718af | BLOCK | F | 48 | first audit |
Questions
What is the Claude Mobile MCP server?
MCP server for mobile and desktop automation — Android (via ADB), iOS Simulator (via simctl), and Desktop (Compose Multiplatform). Like Claude in Chrome but for mobile devices and desktop apps
What tools does Claude Mobile expose?
200 in total: 150 read-only, 58 that write, and 18 that can delete or overwrite (app_restart, app_stop, app_uninstall, browser_clear_session, debug_remove_break). Every one is listed on this page with its risk.
Is Claude Mobile safe to connect to an agent?
No — not without reading the findings first. The audit graded it F (48/100) and found 4 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 18 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does Claude Mobile need?
It reads APP_STORE_CONNECT_API_KEY_ISSUER_ID, APP_STORE_CONNECT_API_KEY_KEY, APP_STORE_CONNECT_API_KEY_KEY_FILEPATH, APP_STORE_CONNECT_API_KEY_KEY_ID, ASC_KEY_FILE, ASC_KEY_ID, ASC_PRIVATE_KEY, GOOGLE_PLAY_KEY_FILE, HUAWEI_CLIENT_SECRET, RUSTORE_KEY_ID, RUSTORE_KEY_JSON and RUSTORE_PRIVATE_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does Claude Mobile run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as @mcp-devices/plugin-web at 4.4.1.
How current is this page?
The grade is for one exact copy of the source (70cbae7718af), read on 2026-10-03. The repository is watched and re-audited when it changes.