Skip to main content

ScreenMCP Python SDK

A Python library for controlling phones and desktops programmatically through ScreenMCP. Fully async, built on websockets and httpx.

Installation

pip install screenmcp

Or install from source:

cd sdk/python
pip install -e .

Quick Start

import asyncio
from screenmcp import ScreenMCPClient

async def main():
    # 1. Create API client with your API key
    client = ScreenMCPClient(api_key="pk_your_key_here")

    # 2. List available devices
    devices = await client.list_devices()
    print(f"Found {len(devices)} devices")

    # 3. Connect to a device — returns a DeviceConnection
    phone = await client.connect(device_id="a1b2c3d4e5f67890abcdef1234567890")
    print(f"Connected to worker: {phone.worker_url}")
    print(f"Phone online: {phone.phone_connected}")

    # 4. Send commands on the connection
    result = await phone.screenshot()
    print(f"Got image: {len(result['image'])} bytes base64")

    await phone.click(540, 960)
    await phone.type_text("Hello from Python!")
    await phone.scroll("down", amount=800)

    tree = await phone.ui_tree()
    print(tree)

    # 5. Disconnect
    await phone.disconnect()

asyncio.run(main())

The connection flow is:

  1. Create client with API key (no device ID yet)
  2. list_devices() to see available devices
  3. connect(device_id=...) discovers a worker, opens a WebSocket, and returns a DeviceConnection
  4. Send commands on the connection — each command goes through the WebSocket to the device and back
  5. disconnect() closes the WebSocket

You can also use async with for automatic disconnect:

async with await client.connect(device_id="...") as phone:
    await phone.screenshot()

Configuration

client = ScreenMCPClient(
    api_key="pk_...",                                # required
    api_url="https://api.screenmcp.com",             # cloud mode (default)
    command_timeout=30.0,                            # seconds (default 30)
    auto_reconnect=True,                             # default True
)

Open Source Mode

For self-hosted ScreenMCP (no cloud account needed):

client = ScreenMCPClient(
    api_key="pk_your_local_key",
    api_url="http://localhost:3000",     # your MCP server URL
)

Available Commands

All command methods are on the DeviceConnection object returned by client.connect().

Screen & UI

Method Description
screenshot() Capture the screen (returns base64 PNG)
ui_tree() Get the accessibility tree
click(x, y) Tap at coordinates
long_click(x, y) Long-press at coordinates
drag(start_x, start_y, end_x, end_y) Drag gesture
scroll(direction, amount) Scroll up/down/left/right

Text Input

Method Description
type_text(text) Type into focused input
get_text() Read text from focused element
select_all() Select all text
copy(return_text=False) Copy selection (optionally return copied text)
paste(text=None) Paste from clipboard (or paste given text)
get_clipboard() Read clipboard contents
set_clipboard(text) Set clipboard contents

Navigation

Method Description
back() Press Back
home() Press Home
recents() Open app switcher

Keyboard (Desktop)

Method Description
press_key(key) Press and release a key (e.g. "Enter", "Tab")
hold_key(key) Hold a key down (e.g. "Shift")
release_key(key) Release a held key

Camera

Method Description
list_cameras() List available cameras
camera(camera_id) Take a photo with a specific camera

All methods are async and return a dict with the command result.

Selector Engine

Find UI elements by text, role, description, or resource ID:

from screenmcp import find_elements

# Get the UI tree first
result = await phone.ui_tree()
tree = result["tree"]

# Find by text
elements = find_elements(tree, "text:Settings")

# Find by role/class
elements = find_elements(tree, "role:EditText")

# Find by content description
elements = find_elements(tree, "desc:Home button")

# Find by resource ID
elements = find_elements(tree, "id:com.android.chrome:id/search_box")

# Combine with AND
elements = find_elements(tree, "role:TextView&&text:Settings")

# Negate
elements = find_elements(tree, "!text:Settings&&role:TextView")

Each returned FoundElement has: x, y (center coordinates), text, class_name, content_description, resource_id, bounds.

Fluent API

# Find an element and get its info
element = await phone.find("text:Settings", timeout=2.0).element()
print(f"Settings is at ({element.x}, {element.y})")

# Find and click in one step
await phone.find("text:Settings").click()

# Check if an element exists
if await phone.exists("text:Settings", timeout=1.0):
    print("Settings button is visible")

# Wait for an element to appear
await phone.wait_for("text:Loading complete", timeout=10.0)

# Wait for an element to disappear
await phone.wait_for_gone("text:Loading...", timeout=10.0)

Generic Commands

Use send_command() for any command, including future ones:

resp = await phone.send_command("screenshot", {"quality": 50})
print(resp.result)

Error Handling

from screenmcp import ScreenMCPClient, AuthError, CommandError, ConnectionError

client = ScreenMCPClient(api_key="pk_...")
try:
    async with await client.connect(device_id="...") as phone:
        await phone.click(100, 200)
except AuthError:
    print("Invalid API key")
except ConnectionError:
    print("Could not connect to worker")
except CommandError as e:
    print(f"Command failed: {e}")

Manual Lifecycle

If you prefer not to use the context manager:

client = ScreenMCPClient(api_key="pk_...")
phone = await client.connect(device_id="...")
try:
    await phone.screenshot()
finally:
    await phone.disconnect()

Requirements

  • Python 3.10+
  • websockets >= 12.0
  • httpx >= 0.25.0

Metadata

Release files for screenmcp 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for screenmcp 1.2.0
File Size Uploaded Provenance
screenmcp-1.2.0.tar.gz 12.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for screenmcp 1.2.0
File Interpreter ABI Platform
screenmcp-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 26.3 kB

Release files / screenmcp-1.2.0.tar.gz

Download URL screenmcp-1.2.0.tar.gz
Size 12.5 kB
Tags Source
SHA-256 checksum
How to use checksums
4b0495121f5be88f68569cd4436a9b417115c5dd207ee787f4b672ae5af16c4f
BLAKE2b-256 checksum
How to use checksums
2888eee823ce461647bae1e5c48ab2398255f728f6e671d26b5bf4a01475e46b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / screenmcp-1.2.0-py3-none-any.whl

Download URL screenmcp-1.2.0-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
485901e3f9514c80b28bf6212abbe29e0748adde0c4af3a9ae3afc179cd9838e
BLAKE2b-256 checksum
How to use checksums
d46e21dd824011746db24b1edde3d074c185ffe76eb58d7e8678e7aa0157e43f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Security for screenmcp 1.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page