Claude Code can test an Android app once it has a phone it can see and touch. The shortest route that needs no local emulator: add Mobilebox as a remote MCP server, host your APK at a direct download URL, and ask Claude to create a phone, install the build, open it, read the screen, check what you expect and delete the phone. Claude does the reasoning; the phone is an Android 14 arm64 virtual sandbox in the cloud.

Connect once

Add https://mobilebox.dev/mcp as an HTTP MCP server with the header Authorization: Bearer plus your API key. The MCP setup guide has the Claude Code command, a shareable .mcp.json that keeps the key out of the file, and the Cursor variant. Codex reads a server url and a bearer_token_env_var from its config.toml. Client documentation reviewed on November 4, 2026.

Keys come from sign-up with GitHub. New accounts start with $2 of credit, which is 200 phone-minutes.

Ask for a bounded test

Give Claude the build, the expected screen and the cleanup rule in one prompt. Ask: “Use Mobilebox. Create a phone named app-check. Install https://example.com/builds/app-release.apk. Open the app and report the first screen. If a permission dialog appears, answer it the way a new user would and report the next screen. Check that the text "Welcome" is visible. Delete the phone at the end, even if a step fails.”

Swap in your own URL and expected label. The URL must be a direct download the service can reach, not a page with a Download button.

The calls Claude makes

These are the same tool calls, sent by hand with curl on November 4, 2026 against production. The test APK was a small editor app from F-Droid.

bash
#!/usr/bin/env bash
# The same tool calls an MCP client (Claude Code, Cursor, Codex) makes, sent by hand.
set -euo pipefail
MCP=${MOBILESANDBOX_URL:-https://mobilebox.dev}/mcp
AUTH="Authorization: Bearer ${MOBILESANDBOX_API_KEY:?set MOBILESANDBOX_API_KEY}"
tool() {  # tool NAME JSON_ARGS -> prints the tool's text result
  curl -sS --fail-with-body "$MCP" -H "$AUTH" -H 'Content-Type: application/json' \
    -H 'Accept: application/json, text/event-stream' \
    -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"$1\",\"arguments\":$2}}" \
    | jq -r '.result | if .isError then ("ERROR: " + (.content[0].text)) else (.content[] | select(.type=="text") | .text) end'
}
OUT=$(tool create_phone '{"name":"mcp-check","idle_timeout":120,"max_duration":300}')
echo "$OUT" | head -3
ID=$(grep -o 'ph_[a-z0-9]*' <<<"$OUT" | head -1)
trap 'tool delete_phone "{\"phone_id\":\"$ID\"}"' EXIT
tool install_app "{\"phone_id\":\"$ID\",\"url\":\"https://f-droid.org/repo/org.billthefarmer.editor_198.apk\"}"
tool act "{\"phone_id\":\"$ID\",\"actions\":[{\"type\":\"open_app\",\"package\":\"org.billthefarmer.editor\"},{\"type\":\"tap\",\"target\":{\"text\":\"CANCEL\"}},{\"type\":\"wait\",\"ms\":1000}]}"

It finished in 25 seconds. The output, shortened:

text
ph_ykcnpxsjcv67 "mcp-check" ready
Installed org.billthefarmer.editor 1.98 (versionCode 198).
1. open_app ok
2. tap ok
3. wait ok

app: org.billthefarmer.editor
[1] Text "Untitled.txt" (174,108)
[2] Button desc="Edit" (786,136)
[7] TextField #org.billthefarmer.editor:id/text (540,1231)
ph_ykcnpxsjcv67 deleted

The app opened on a file-access dialog, so the batch tapped CANCEL to reach the editor. Claude would see that dialog in the observe result and decide the same way. Every act result lists each action as ok or failed and then shows the new screen, so Claude checks the outcome, not just the tap.

What it can and can’t test

It can install APKs and arm64 split bundles, drive the UI by visible text, resource id or coordinates, take screenshots, and set locale, timezone, GPS and a proxy. Parking a phone keeps installed apps and logins for the next run.

It can’t reach ADB, logcat or a shell. It has no Google Play, SMS or iOS, and it is not a physical device. For instrumented Espresso tests or ADB access, run a local emulator with a local MCP server; hosted or local compares the options. For a test that runs in CI without Claude, use the no-KVM script.

A ready phone costs $0.01 per minute, billed per second with a one-minute minimum per session. Parked phones are free.

Put it to work.

Open the quickstartRead the API reference