Open Device Cloud MCP

openDeviceCloud exposes a built-in Model Context Protocol server at:

http://127.0.0.1:8000/mcp

Unlike the REST API, the MCP endpoint is not mounted under /api.

Transport

  • HTTP POST

  • JSON-RPC 2.0 request bodies

  • optional Server-Sent Events responses when the client sends Accept: text/event-stream

Initialize A Session

curl -s http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-03-26",
      "capabilities": {},
      "clientInfo": {
        "name": "example-client",
        "version": "1.0.0"
      }
    }
  }'

List Available Tools

curl -s http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/list",
    "params": {}
  }'

The server exposes tools across five categories:

Category

Tools

Images

image_list, image_update, image_delete, image_create_from_device

Devices

device_list, device_create, device_start, device_stop, device_reboot, device_delete, device_status, device_wait_ready

Apps & files

shell_exec, file_read, file_write, app_list, app_launch, app_install, ipa_upload, syslog_get

Interaction

screenshot, ui_dump_hierarchy, ui_tap, ui_swipe, button_press

Networking

bridge_create, bridge_delete

It also supports MCP resources for screenshot payloads:

  • resources/list — list screenshot resources captured in the current MCP session

  • resources/read — lazily fetch screenshot bytes from a server-owned resource URI

By default, screenshot returns an MCP resource link only, keeping large image blobs out of the tool result. Pass include_inline_image: true to also embed the image bytes directly in the response.

Call A Tool

Example: list devices.

curl -s http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "device_list",
      "arguments": {}
    }
  }'

Example: read a screenshot resource returned by the screenshot tool.

curl -s http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -H 'X-OpenDC-MCP-Session: demo-session' \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "resources/read",
    "params": {
      "uri": "odc-screenshot://example/device/capture"
    }
  }'

Example: request both the resource link and an inline image preview.

curl -s http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "tools/call",
    "params": {
      "name": "screenshot",
      "arguments": {
        "device_id": "device-id",
        "include_inline_image": true
      }
    }
  }'

Example: create a persistent Frida bridge to the default Frida server port on an iOS device.

curl -s http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 5,
    "method": "tools/call",
    "params": {
      "name": "bridge_create",
      "arguments": {
        "device_id": "device-id",
        "device_port": 27042,
        "persistent": true
      }
    }
  }'

When device_port is 27042, the tool returns a Frida usage hint so clients can connect directly with a local frida CLI over the exposed bridge.

Session Header

Requests that need to share state across calls (for example, reading a screenshot resource captured in a previous request) should include a consistent session identifier:

X-OpenDC-MCP-Session: <any-string>

The server scopes screenshot resources to this header value. Without it, resources/list and resources/read will not find resources from prior requests.

Batch Requests

The endpoint accepts a JSON array of JSON-RPC 2.0 objects in a single POST. Each item is processed independently and the response is an array of results in the same order. Notifications (messages without an id) are processed but produce no output entry.

Connect Claude Code

Add the server to ~/.claude/mcp.json so Claude Code discovers it automatically:

{
  "mcpServers": {
    "odc": {
      "type": "http",
      "url": "http://127.0.0.1:8000/mcp"
    }
  }
}

Claude Code will then have access to all ODC tools directly from within any conversation.

Tool Reference

Images

image_list — List managed images and Android SDK images.

Argument

Type

Required

Description

agent_id

string

no

Filter by agent

limit

integer

no

Page size

cursor

string

no

Pagination cursor

include_details

boolean

no

Return full metadata (default: false)

refresh

boolean

no

Bypass cache (default: false)


image_update — Rename or re-describe a managed image without changing its ID.

Argument

Type

Required

Description

image

string

yes

Image ID or exact name

name

string

no

New name

description

string

no

New description

agent_id

string

no

Agent scope


image_delete — Delete a managed image.

Argument

Type

Required

Description

image

string

yes

Image ID or exact name

agent_id

string

no

Agent scope


image_create_from_device — Snapshot a stopped device into a new managed image.

Argument

Type

Required

Description

device_id

string

yes

Source device

name

string

yes

Name for the new image


Devices

device_list — List managed devices with status and metadata.

Argument

Type

Required

Description

limit

integer

no

Page size

cursor

string

no

Pagination cursor

refresh

boolean

no

Bypass cache (default: false)


device_create — Create a device from an image.

Argument

Type

Required

Description

image

string

yes

Image ID or exact name

name

string

no

Device display name

model

string

no

Device model override

os_version

string

no

OS version override


device_start / device_stop / device_reboot / device_delete — Lifecycle controls.

Argument

Type

Required

device_id

string

yes


device_status — Power state plus SSH and runtime readiness.

Argument

Type

Required

device_id

string

yes


device_wait_ready — Block until a device accepts remote connections.

Argument

Type

Required

Description

device_id

string

yes

timeout_seconds

integer

no

Max wait time


Apps & Files

shell_exec — Run a shell command in the device guest environment.

Argument

Type

Required

Description

device_id

string

yes

command

string

yes

Shell command

timeout_seconds

integer

no

env

object

no

Extra environment variables


file_write — Write UTF-8 text to a path on the device.

Argument

Type

Required

Description

device_id

string

yes

path

string

yes

Absolute device path

content

string

yes

Text content

mode

string

no

File permissions (e.g. "0644")


file_read — Read a file from the device.

Argument

Type

Required

Description

device_id

string

yes

path

string

yes

Absolute device path

encoding

string

no

"text" (default) or "base64"


app_install — Install an IPA from a URL reachable by the agent.

Argument

Type

Required

Description

device_id

string

yes

ipa_url

string

yes

Download URL (e.g. presigned S3)

ipa_name

string

no

Display name


ipa_upload — Get presigned upload and install URLs for an IPA. Call this first, upload the bytes yourself, then pass the install URL to app_install.

Argument

Type

Required

Description

filename

string

yes

IPA filename

content_type

string

no

MIME type


app_list — List installed applications on a device.

Argument

Type

Required

Description

device_id

string

yes

limit

integer

no

Page size

cursor

string

no

Pagination cursor

include_details

boolean

no

Full metadata (default: false)


app_launch — Launch an installed application by bundle ID.

Argument

Type

Required

device_id

string

yes

bundle_id

string

yes


syslog_get — Fetch recent syslog entries with optional filtering.

Argument

Type

Required

Description

device_id

string

yes

pattern

string

no

Filter string

since_seconds

integer

no

How far back to look

max_lines

integer

no

Result cap


Interaction

screenshot — Capture the device screen with optional crop and resize.

Argument

Type

Required

Description

device_id

string

yes

detail

string

no

"low" or "high"

crop

object

no

{x, y, width, height} in device pixels

max_width

integer

no

Scale down to fit

max_height

integer

no

Scale down to fit

format

string

no

"png" (default) or "jpeg"

jpeg_quality

integer

no

JPEG quality (1–100)

include_inline_image

boolean

no

Also embed bytes in result (default: false)


ui_dump_hierarchy — Dump the accessibility element tree of the current screen. Returns a paginated flat list with labels, values, and bounding boxes. Use coordinate_width and coordinate_height from the response as coordinate bounds for ui_tap and ui_swipe.

Argument

Type

Required

Description

device_id

string

yes

limit

integer

no

Page size

cursor

string

no

Pagination cursor

include_details

boolean

no

Full element metadata (default: false)


ui_tap — Send a tap gesture at the given coordinates.

Argument

Type

Required

device_id

string

yes

x

number

yes

y

number

yes


ui_swipe — Send a swipe gesture between two points.

Argument

Type

Required

Description

device_id

string

yes

x0, y0

number

yes

Start point

x1, y1

number

yes

End point

duration_ms

integer

no

Swipe duration (default: 180)


button_press — Press a hardware-style device button.

Argument

Type

Required

Description

device_id

string

yes

button

string

yes

"home", "power", "volume_up", or "volume_down"


Networking

bridge_create — Forward a TCP port from the agent host to a device port. Use persistent: true for long-lived clients like Frida.

Argument

Type

Required

Description

device_id

string

yes

device_port

integer

yes

Port inside the device

persistent

boolean

no

Keep alive after the request (default: false)

ttl_seconds

integer

no

Auto-expire after this many seconds

include_usage_hint

boolean

no

Return connection instructions

When device_port is 27042, the response includes a Frida usage hint for connecting with the local frida CLI.


bridge_delete — Remove a TCP bridge created by bridge_create.

Argument

Type

Required

bridge_id

string

yes


Authentication

The endpoint understands:

  • Authorization: Basic ...

  • Authorization: Bearer <token> when OPEN_DEVICE_CLOUD_API_TOKEN is configured

If you deploy the backend behind your own auth layer, keep the MCP route aligned with that policy.

When To Use MCP vs REST

  • Use REST for app integration, backend workflows, and explicit resource management.

  • Use MCP when you want AI tooling or assistant-driven flows to interact with devices through a structured tool catalog.