# MCP server

> Connect any MCP client to Distilled's server over Streamable HTTP with your API key. Your agent gets the tools its key's scopes allow.

The server is at `https://mcp.distilled.cx/mcp` and speaks Streamable HTTP without sessions. It offers only the tools its caller's scopes allow, and tells your agent how to use them when it connects.

## Connect with OAuth

Claude, ChatGPT, Claude Code and Codex sign in with OAuth: add the address as a connector, sign in to Distilled when asked, and allow a workspace. The connection shows under API keys with the app's name, and revoking that key disconnects it.

- In Claude, open Settings, then Connectors, and add a custom connector.
- In ChatGPT, turn on developer mode under Apps and Connectors and create one with OAuth.

The Distilled plugin adds the server together with a skill for driving phones. Add the marketplace `distilledcx/plugins` in Claude (Customize, then Plugins), Claude Code or Codex, and install `distilled`.

## Connect with an API key

Scripts and clients that can't open a browser send an API key as a bearer token instead:

mcp.json:

```json
{
  "mcpServers": {
    "distilled": {
      "type": "http",
      "url": "https://mcp.distilled.cx/mcp",
      "headers": {
        "Authorization": "Bearer dk_live_..."
      }
    }
  }
}
```

## Tools

The actions can return a screenshot of the result in the same call, so an agent sees what it did without asking again. Allocating and managing phones, billing, secrets and usage are REST only.

| Phones | Does |
| --- | --- |
| `list_phones` | Lists the workspace's phones |
| `get_phone` | Reads phones |
| `start_phones` | Starts stopped phones on their own data |
| `stop_phones` | Stops phones, keeping their apps and data |
| `watch_phone` | Shows a phone's screen live in the chat, in apps that draw MCP Apps |
| `set_phone_details` | Names phones and keeps notes on them |
| `list_accounts` | Lists the app accounts signed in on phones |
| `save_account` | Records which app account is signed in on a phone |
| `batch` | Runs up to 50 calls at once |

| Driving a phone | Does |
| --- | --- |
| `acquire_phone` | Holds a phone for the agent |
| `release_phone` | Lets it go |
| `screenshot` | Returns the screen as an image |
| `ui_tree` | Returns the elements on screen |
| `tap` | Taps a point |
| `long_press` | Holds a point |
| `swipe` | Swipes between two points |
| `type_text` | Types text |
| `press_key` | Presses a key such as back or home |
| `launch_app` | Opens an app |
| `open_url` | Opens a link in Chrome |
| `wait_for_idle` | Waits for the screen to settle |

| Network and location | Does |
| --- | --- |
| `get_egress` | Reads a month's traffic |
| `list_proxies` | Lists the workspace's proxies |
| `save_proxies` | Saves one or many proxies |
| `set_egress` | Routes phones through a proxy or Distilled's network |
| `rotate_exit` | Moves phones to fresh Distilled exits |
| `get_phone_location` | Reads where phones' GPS says they are |
| `set_phone_location` | Pins phones' GPS to a point, or puts it back near their exit |

| Apps | Does |
| --- | --- |
| `search_apps` | Searches the app catalog |
| `get_app` | Reads one app |
| `install_app` | Installs or updates apps on one phone or many |
| `uninstall_app` | Uninstalls apps from one phone or many |
| `wait_for_installs` | Waits for installs and uninstalls to end |
| `list_app_updates` | Lists installed apps with a newer build |
| `list_phone_apps` | Lists a phone's installs |

| Files | Does |
| --- | --- |
| `put_file` | Puts a picture, video or file from a link on phones; media lands in the camera roll |
| `upload_file` | Shows a panel where the person drops a file from their computer; it goes straight to the phone |
| `file_upload_start` | Starts an upload an agent that can run commands sends itself with curl, straight to the file store |
| `file_upload_finish` | Finishes that upload and puts the file on the phone |
| `file_upload_cancel` | Drops an upload that won't be finished |

| Runs and skills | Does |
| --- | --- |
| `send_order` | Starts a run from a saved skill or from steps |
| `list_runs` | Lists recent runs |
| `get_run` | Reads a run, with its last steps if asked |
| `stop_run` | Stops a run |
| `resume_run` | Carries on with a phone waiting for a person, letting go of it if you hold it |
| `create_skill` | Saves a skill |
| `list_skills` | Lists saved skills |
| `set_skill_enabled` | Turns a skill on or off |
| `delete_skill` | Deletes a skill |

## Many phones at once

Tools that drive, check or set up phones take `phone_ids`, or `all_phones` for every phone of the workspace, as well as `phone_id`, and do them all at once in one call. Tools for one phone's view, file uploads or debugging, and `resume_run`, take one `phone_id`. In an app that can't show it, `watch_phone` answers a console link that opens the phone to watch without taking it. `batch` runs up to 50 different calls at once and answers with each in order.

## Getting files onto a phone

There are three ways to get a video or picture onto a phone for an app to post. However it arrives, the file is the newest item in the phone's gallery.

- An agent that can run commands and reach the file, such as Claude Code or Codex, calls `file_upload_start`, sends the parts with curl as its answer says, and calls `file_upload_finish`. The file goes straight to storage and the agent only ever holds that upload's token.
- When the file is on the person's computer, `upload_file` shows a panel in the Claude and ChatGPT apps where they drop it, and tells the agent when it lands.
- `put_file` fetches a public link, for up to 100 MB in one call counting every phone's copy; past that it sends nothing and points to an upload.

Source: https://distilled.cx/docs/mcp/
