# MCP tools reference

> Every tool the akaphone-mcp server exposes to Claude Code, Cursor and Codex, with arguments, what each returns, the REST call behind it and example prompts.

Source: https://docs.akaphone.ai/mcp/tools/

`akaphone-mcp` 1.1.1 exposes 15 tools. Your agent picks them from your request. You rarely name them yourself, but knowing what they do helps you ask for the right thing. Setup is in [Claude Code](https://docs.akaphone.ai/quickstart/claude-code/) and [Cursor and Codex](https://docs.akaphone.ai/quickstart/cursor-and-codex/). **AI is included**: `device_run_task` needs no model key.

**Recommended:** the hosted remote connector, `https://app.akaphone.ai/mcp` (also reachable as `https://app.akaphone.ai/mcp`, and set up from **Connect to Claude** in the dashboard). It signs in with OAuth, needs no install and no API key, and has the same tools; its waits are capped at 25 seconds. The stdio package is optional: `npx -y https://akaphone.ai/mcp/akaphone-mcp-1.1.1.tgz` (it is not on the npm registry).

Most tools return JSON text (the API response, pretty-printed); the exceptions are noted. If the API returns an error, the tool result is marked as an error and reads `AkaPhone API <status> <code>: <message>`. For `429` responses it also says how many seconds to wait.

## Summary

| Tool | What it does | REST calls |
|---|---|---|
| [`device_create`](#device-create) | Boot a new Android 14 device | `POST /v1/devices` |
| [`device_list`](#device-list) | List your phones, including stopped (saved) ones | `GET /v1/devices` |
| [`device_terminate`](#device-terminate) | Stop a phone and save its data; billing stops | `POST /v1/devices/:id/stop` |
| [`device_start`](#device-start) | Resume a stopped phone from its last save, on any server | `POST /v1/devices/:id/start` |
| [`device_delete`](#device-delete) | Delete a phone and erase its saved data | `DELETE /v1/devices/:id?wipe=true` |
| [`device_screenshot`](#device-screenshot) | The current screen as an image | `GET /v1/devices/:id/screenshot` |
| [`device_input`](#device-input) | Tap, swipe, type or press a key | `POST /v1/devices/:id/input` |
| [`device_install_apk`](#device-install-apk) | Upload a local APK and install it | `POST /v1/uploads`, `PUT` to storage, `POST /v1/uploads/:id/complete`, `POST /v1/devices/:id/apps`, `GET /v1/devices/:id/apps/:install_id` |
| [`device_snapshot`](#device-snapshot) | Save a device's disk as a portable snapshot | `POST /v1/devices/:id/snapshot` |
| [`device_restore`](#device-restore) | Boot a new device from a snapshot, or list snapshots | `POST /v1/snapshots/:id/restore`, `GET /v1/snapshots` |
| [`device_run_task`](#device-run-task) | Run a plain-English task and wait for the result | `POST /v1/devices/:id/tasks`, then `GET /v1/tasks/:id` |
| [`task_status`](#task-status) | Get a task | `GET /v1/tasks/:id` |
| [`task_artifacts`](#task-artifacts) | List or fetch a task's video, screenshots, trace and log | `GET /v1/tasks/:id/artifacts` |
| [`usage`](#usage) | Device-minutes this month | `GET /v1/usage` |
| [`profiles_list`](#profiles-list) | Device profiles for `device_create` | `GET /v1/profiles` |

## device_create

Boots a fresh Android 14 phone and, by default, waits until it is running.

| Argument | Type | Default | Description |
|---|---|---|---|
| `name` | string | none | Friendly name, up to 64 characters. |
| `profile` | string | `pixel_8` | `pixel_8`, `pixel_tablet` or `small_phone` (see `profiles_list`). |
| `wait` | boolean | `true` | Wait until the device is running, for at most 90 seconds. |

**Returns** the [device object](https://docs.akaphone.ai/api/devices/#the-device-object). If the 90 seconds run out while capacity is busy, the API sends `X-Wait-Timed-Out: 1` and the tool adds a note: the device is still `queued` or `creating`, and the agent should check it again with `device_list`.

> Create a phone called "signup-test".

## device_list

| Argument | Type | Default | Description |
|---|---|---|---|
| `include_terminated` | boolean | `false` | Also list deleted devices (the 200 most recent). |

**Returns** an array of devices: running and starting phones (`queued`, `creating`, `running`), phones being saved (`stopping`, `saving`) and **stopped phones with saved data** (`stopped`, with `data.bytes` and `data.saved_at`). Deleted phones appear only with `include_terminated`.

> Which phones do I have, and which ones are stopped?

## device_terminate

| Argument | Type | Description |
|---|---|---|
Stop the phone and save its data (apps, logins, files); billing stops; resume with `device_start`. The name is kept from earlier versions: it no longer destroys the phone. To erase a phone use [`device_delete`](#device-delete).

| Argument | Type | Description |
|---|---|---|
| `device_id` | string | The device to stop. |

**Returns** the device, now `stopping`; it moves on to `saving` and then `stopped` on its own, and `data.generation` goes up by one. Billing stops at once. A phone that was still queued or booting comes back `stopped` (or `terminated`, if it was new and had never been saved).

> Stop all my running phones.

## device_start

Resumes a stopped phone from its latest save. It can start on any host; the host restores the saved data and boots it.

| Argument | Type | Default | Description |
|---|---|---|---|
| `device_id` | string | required | A phone in status `stopped`. |
| `wait` | boolean | `true` | Wait until it is running, for at most 90 seconds. |

**Returns** the device, normally `running`, with the same timed-out note as `device_create` if the wait ran out. A phone that is not `stopped` (for example still `saving`) gives a `409 conflict` error; so does being over your plan's [saved-phone limit](https://docs.akaphone.ai/concepts/devices/#saved-phones). Credit and concurrency checks are the same as for `device_create`.

> Start checkout-test again and check I'm still signed in.

## device_delete

Deletes a phone permanently: stops it without saving if it is running, and erases all of its saved data. Cannot be undone.

| Argument | Type | Description |
|---|---|---|
| `device_id` | string | The phone to delete. |
| `confirm` | `true` | Required, and must be exactly `true`. Calls without it are rejected before anything is sent. |

**Returns** the device in status `terminated`. Use it to clean up throwaway phones and to make room when you hit your plan's saved-phone limit (Free 3, any pack 20, Scale 50, Enterprise 500).

> Delete the phones I used for yesterday's test runs.

## device_screenshot

| Argument | Type | Description |
|---|---|---|
| `device_id` | string | A running device. |

**Returns** an `image/jpeg` image of the current screen, which the agent can look at directly.

> Show me what's on the screen of signup-test.

## device_input

Sends one input event to a running device. Coordinates are device pixels: 720×1560 on `pixel_8` (`profiles_list` has the others).

| Argument | Type | Used with | Description |
|---|---|---|---|
| `device_id` | string | all | A running device. |
| `type` | `tap`, `swipe`, `text` or `key` | all | The kind of event. |
| `x`, `y` | integer, 0–10000 | `tap` | Where to tap. |
| `x1`, `y1`, `x2`, `y2` | integer, 0–10000 | `swipe` | Start and end points. |
| `ms` | integer, 1–10000 | `swipe` | Duration, default 300. |
| `text` | string, 1–500 characters | `text` | Text to type into the focused field. |
| `key` | `HOME`, `BACK`, `RECENTS`, `ENTER`, `DEL` or `TAB` | `key` | Hardware or navigation key. |

**Returns** a short confirmation. A missing field for the chosen type (for example a `tap` without `y`) is an error before anything is sent. Input does not confirm that the tap had an effect; follow it with `device_screenshot`.

> On signup-test, tap the email field at 360, 640, type test@example.com and press Enter.

## device_install_apk

Uploads a local APK and installs it on a running device, then waits for the result.

| Argument | Type | Description |
|---|---|---|
| `device_id` | string | A running device. |
| `file_path` | string | Path to a local `.apk` file, at most 300 MB. |

The tool creates an upload, `PUT`s the file straight to storage with the presigned URL, completes the upload, starts the install, and polls the install status for up to **5 minutes**.

**Returns** the install: `status` `installed` with the `package` name, or an error result with `status` `failed` and the installer's `error`. If the install is still pending after 5 minutes, the tool says so; the install continues on the device. Runtime permissions are granted on install. `.aab` bundles are refused before any upload; build a universal APK first. See [Install an APK](https://docs.akaphone.ai/guides/install-apk/).

> Install ./app/build/outputs/apk/debug/app-debug.apk on signup-test and open it.

## device_snapshot

| Argument | Type | Description |
|---|---|---|
| `device_id` | string | A running device. |
| `name` | string | Optional label, up to 64 characters. |

**Returns** the [snapshot](https://docs.akaphone.ai/api/snapshots/#the-snapshot-object) in `pending` status. It becomes `ready` after a short while. Snapshots are portable: `device_restore` can boot any number of new phones from one, on any host. Your plan's snapshot quota applies, and you can take at most 5 snapshots per hour. See [Snapshots](https://docs.akaphone.ai/concepts/snapshots/). You do not need a snapshot just to keep a phone's data: `device_terminate` already saves it.

> Snapshot signup-test as "logged-in".

## device_restore

| Argument | Type | Default | Description |
|---|---|---|---|
| `snapshot_id` | string | none | Snapshot to boot from. **Omit it to list your snapshots instead.** |
| `name` | string | none | Name for the new device. |
| `wait` | boolean | `true` | Wait until the new device is running, for at most 90 seconds. |

**Returns** the new device (with the same timed-out note as `device_create`), or the snapshot list when `snapshot_id` is omitted. The original device is not touched.

> Start a new phone from the "logged-in" snapshot.

## device_run_task

Has ARTEMIS carry out a plain-English instruction on a device. It then polls every 3 seconds until the task finishes or `wait_seconds` runs out.

| Argument | Type | Default | Description |
|---|---|---|---|
| `device_id` | string | required | A running device with no active task. |
| `instruction` | string | required | What to do, 1–8,000 characters. |
| `profile` | `"flash"` or `"pro"` | `"pro"` | `flash` for quick, simple actions; `pro` for multi-step work. The REST API's own default is `flash`. |
| `wait_seconds` | integer | `600` | 0–1800. `0` returns at once with the queued task. |

The task runs on the included AI (no key needed; it counts toward your plan's daily AI tasks). Optional: with the stdio package, `MODEL_API_KEY` and `MODEL_PROVIDER` in the server's environment are sent as the `X-Model-Key` and `X-Model-Provider` headers to use [your own key](https://docs.akaphone.ai/guides/model-keys/#byok) instead. To get structured output back, describe it in the instruction, for example *“reply with JSON {version, build}”*.

**Returns** the [task](https://docs.akaphone.ai/api/tasks/#the-task-object) with `steps`, `status` and `result`. If the task is still running when `wait_seconds` runs out, the text ends with *(still running; poll with task_status)*.

> On signup-test, open the app, sign up as test+42@example.com with password Test1234!, and tell me what the first screen after sign-up says.

## task_status

| Argument | Type | Description |
|---|---|---|
| `task_id` | string | The task. |

**Returns** the task with its `steps`. Statuses: `queued`, `running`, `succeeded`, `failed`, `cancelled`.

> Is that task finished yet?

## task_artifacts

| Argument | Type | Description |
|---|---|---|
| `task_id` | string | A finished task. |
| `download` | string | Optional. The `id` (`art_…`) or file name of one artifact to fetch. |

**Without `download`**, the tool returns `{ "files": [...] }`. Each file has its `id`, `kind`, `name`, `size_bytes` and a presigned download `url`. The URLs are valid for 15 minutes. The files are `video.mp4`, `before.png`, `after.png`, `trace.tar.gz` and `stdout.log`. The list is empty for a few seconds after a task ends, while the host uploads the files.

**With `download`**, the tool fetches that file through its presigned URL:

| File | Returned as |
|---|---|
| `before.png`, `after.png` (screenshots) | an image the agent can see |
| `stdout.log` | text (the last 200 KB if it is longer) |
| `video.mp4`, `trace.tar.gz` | a note with the download URL, since binary files cannot be shown inline |

> Show me the after screenshot of the last task, and the end of its log.

## usage

No arguments. **Returns** the [usage report](https://docs.akaphone.ai/api/usage/) for the current month: `total_minutes`, `active_devices`, minutes per day and per device.

> How many device-minutes have I used this month?

## profiles_list

No arguments. **Returns** the device profiles with `id`, `name`, `width`, `height`, `dpi` and `android`:

```json
[
  { "id": "pixel_8", "name": "Pixel 8", "width": 720, "height": 1560, "dpi": 320, "android": "14" },
  { "id": "pixel_tablet", "name": "Pixel Tablet", "width": 1280, "height": 800, "dpi": 240, "android": "14" },
  { "id": "small_phone", "name": "Small phone", "width": 540, "height": 960, "dpi": 240, "android": "14" }
]
```

> Which device sizes can I use? Start a tablet.

## Environment variables

| Variable | Required | Description |
|---|---|---|
| `AKAPHONE_API_KEY` | yes | Your `ak_live_…` key. The server exits at startup without it. |
| `AKAPHONE_API_URL` | no | Defaults to `https://app.akaphone.ai`. |
| `MODEL_API_KEY` | no | Optional: your own Gemini, Anthropic or OpenAI key. Leave it out to use the included AI. |
| `MODEL_PROVIDER` | no | `gemini` (default), `anthropic` or `openai`. Any other value stops the server at startup with `MODEL_PROVIDER must be one of gemini, anthropic, openai`. |

## Tips for prompts

- **Name your devices** and refer to them by name. The agent maps names to ids with `device_list`.
- **Ask for a verdict.** Ending with *“…and tell me PASS or FAIL”* makes results easy to scan.
- **Ask it to clean up.** End with *“then stop the phone”* to keep it for later (stopped phones cost nothing), or *“then delete the phone”* for a throwaway one.
- **Keep secrets out of instructions.** Instructions are stored with the task, so use test accounts.
