Connect an AI agent to your phone

Pony MCP server 0.3 · Last updated September 30, 2026

The Pony MCP server gives any MCP-capable agent (Claude Desktop, Claude Code, Cursor, and others) hands on a real Android phone running the Pony Companion app. The agent and the phone meet at an encrypted relay, and you pair them once per session with a QR code or a link.

Before you startClaude DesktopClaude CodeCursorOther clientsPairingToolsSafety model

Before you start

  1. Node.js 22 or newer on the computer that runs your agent.
  2. The Pony source folder (pony-companion). Unpack it anywhere and run npm install in it once. The examples below use /path/to/pony-companion. Replace that with your real absolute path. On Windows, use the tsx.cmd file in node_modules\.bin.
  3. The Pony Companion app on your Android phone (Android 10+), with the consent screens done and Pony control turned on under Accessibility.
  4. A relay. Use ours, https://relay.pony.karlmagendavid.com, or run your own with npm run relay (port 8787) and use a URL your phone can reach. localhost won't work, because on the phone it means the phone itself.

Launch the server with tsx directly, as shown below. Don't wrap the stdio command in npm run, because npm prints a banner to stdout and the MCP client will fail to parse it.

Claude Desktop

Open claude_desktop_config.json (Settings → Developer → Edit Config; on macOS it's in ~/Library/Application Support/Claude/, on Windows in %APPDATA%\Claude\) and add:

{
  "mcpServers": {
    "pony": {
      "command": "/path/to/pony-companion/node_modules/.bin/tsx",
      "args": ["/path/to/pony-companion/packages/mcp/src/cli.ts"],
      "env": {
        "PONY_RELAY": "https://relay.pony.karlmagendavid.com"
      }
    }
  }
}

Quit and reopen Claude Desktop. "pony" should appear in the tools menu.

Claude Code

claude mcp add pony --scope user \
  -e PONY_RELAY=https://relay.pony.karlmagendavid.com \
  -- /path/to/pony-companion/node_modules/.bin/tsx /path/to/pony-companion/packages/mcp/src/cli.ts

Check it with claude mcp list, or /mcp inside a session. Leave out --scope user to add it to the current project only.

Cursor

Put the same block in ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project), then enable "pony" under Settings → MCP:

{
  "mcpServers": {
    "pony": {
      "command": "/path/to/pony-companion/node_modules/.bin/tsx",
      "args": ["/path/to/pony-companion/packages/mcp/src/cli.ts"],
      "env": {
        "PONY_RELAY": "https://relay.pony.karlmagendavid.com"
      }
    }
  }
}

Any other MCP client

Stdio (default)

Command: /path/to/pony-companion/node_modules/.bin/tsx
Args: /path/to/pony-companion/packages/mcp/src/cli.ts (optionally --relay <url>)
Env: PONY_RELAY=https://relay.pony.karlmagendavid.com

Streamable HTTP (localhost)

From the pony-companion folder:

npm run mcp -- --http 43123 --relay https://relay.pony.karlmagendavid.com

The server listens on http://127.0.0.1:43123/mcp and accepts only localhost Host and Origin headers. It has no auth token, so don't expose it to a network. Client config:

{
  "mcpServers": {
    "pony": { "url": "http://127.0.0.1:43123/mcp" }
  }
}

One server process controls one phone. The relay can also be set for a single session with the relay argument of pair.

How pairing works

  1. Ask your agent to "pair my phone". It calls pair, which asks the relay for a one-time token and returns a QR code image plus a pony://pair?… link. The token expires after 5 minutes and works once.
  2. In the Pony app, scan the QR. If the QR is on the phone's own screen, open the link or paste it (or the QR text) into the pair screen.
  3. Accept Android's screen-capture prompt. It's asked every session on purpose.
  4. Your phone and the agent's computer exchange public keys (X25519) through the relay and derive session keys. From here on, every frame is encrypted with ChaCha20-Poly1305, and the relay only forwards ciphertext.
  5. Compare the 6-digit safety code. The app shows it, and the agent reads it from status. If the codes don't match, disconnect.
  6. The session lasts up to 30 minutes, then the phone disconnects itself. Pair again for more time.

Tools the server exposes

ToolWhat it does
pairStart a pairing session. Returns the QR (PNG and data URL), the pony://pair link, the token, and the QR JSON. Optional waitMs (0–60000) and relay.
statusWhether a phone is connected, the safety code, time left in the 30-minute session, and the action log (character counts, not text).
screenshotCapture the current screen as a JPEG image.
ui_treeRead the accessibility tree as text. Password fields appear as [password] with no contents.
tapTap x, y in screen pixels from the top left.
swipeSwipe from x1,y1 to x2,y2, optional durationMs.
typeInsert text at the focused field (Pony keyboard first, then set-text; clipboard paste only if the owner enabled it). Refused for password fields.
keyPress back, home, or recents.
open_appOpen an installed app by package name, such as com.android.settings.
wait_for_requestLong-poll (up to 55 s) for the next thing the owner said or typed to Pony. {"empty": true} means call again.
speakSay a sentence out loud on the phone.
ask_userAsk a question out loud and return the owner's spoken answer.
confirmAsk a yes-or-no question. Returns {"accepted": true|false}. Ambiguous speech is not a yes.
disconnectEnd the session and drop the phone connection.

Errors the phone can return include password_field, not_confirmed (the owner declined a risky tap), locked (Pony won't unlock the phone), stopped (the owner said stop), ime_disabled / ime_required (Pony keyboard not enabled or not chosen), and screenshot_failed (for example, a secure app). If type reports method: "key_events", check the field before continuing.

Safety model

More detail is on the privacy page. Questions: hello@orbitbuild.com.