clousd-mcp: a real Android phone for your AI agent
Clousd MCP server gives any MCP-capable agent a real Android phone in the cloud. Not an emulator: each device is built as a specific handset (Pixel, Galaxy, Xiaomi, Motorola, OnePlus, realme, OPPO, vivo, Sony, TECNO, Infinix and 150+ more, Android 12 to 17) with the same build, sensors, cameras, codecs and GPU strings as the real hardware, Google Play inside, and its own network exit in the country you choose. Apps see a phone, so your agent sees the same screens a person sees: no "unusual activity" walls, no emulator detection, no captcha loops.
Six tools cover the whole loop: observe the screen (screenshot with numbered elements plus the UI tree), act
on it (tap by element number, swipe, type in any language, open apps and links), inspect the phone without
touching the screen (notifications, clipboard, app versions, crashes), snapshots to reset every run to the same
state or clone a prepared phone into many, recipe to replay a recorded flow without a model, and devices to
manage the fleet. Works with Cursor, Windsurf, Zed, desktop assistants, LangChain-style agents and anything else that
speaks MCP, locally or through the hosted endpoint at https://api.clousd.com/mcp.
Early access: keys on request at clousd.com/agents. Docs: clousd.com/docs. Source: github.com/Clousd-Android/clousd-sdk.
Why a real cloud phone instead of an emulator
| Emulator on your machine | Clousd phone | |
|---|---|---|
| What apps see | Goldfish/ranchu hardware, emulator build, no SIM | A specific real model: build fingerprint, sensors, cameras, codecs, GPU, SIM and carrier |
| Google Play | Needs Google APIs images, often blocked | Play Store and Play services on every device |
| Network | Your IP, your country | Residential, mobile, ISP or datacenter exit in the country you choose; SIM, time zone and locale follow it |
| Reset between runs | Snapshots, slow to restore | Saved state restored in seconds; clone one prepared phone into ten or a hundred |
| Scale | One per CPU core | Start with one, run hundreds, stopped phones cost nothing |
| Setup | SDK, images, ADB, host resources | One API key |
That is why agents built for social apps, marketplaces, banking flows, app testing and research run here: the phone behaves like the device in a user's pocket, and every episode starts from the same state.
Install
pip install clousd-mcp
Any MCP client, local (stdio) server, one environment variable:
{
"mcpServers": {
"clousd": {
"command": "clousd-mcp",
"env": { "CLOUSD_API_KEY": "cl_live_..." }
}
}
}
Clients that take a command line instead of JSON: run clousd-mcp with CLOUSD_API_KEY in the environment.
Remote server, no install
The same server runs at https://api.clousd.com/mcp (streamable HTTP). Point any MCP client at it with your key in
the Authorization header; clients that cannot set headers can pass ?api_key=cl_live_... in the URL.
{
"mcpServers": {
"clousd": {
"url": "https://api.clousd.com/mcp",
"headers": { "Authorization": "Bearer cl_live_..." }
}
}
}
Self-hosting the remote mode: CLOUSD_MCP_HTTP=127.0.0.1:8790 clousd-mcp serves /mcp over HTTP; every request
must carry a key, nothing is read from the environment. The hosted endpoint is also listed in the
MCP registry as io.github.Clousd-Android/clousd-mcp.
Tools
Nine tools: a few large tools are easier for a model to choose from than dozens of small ones. Every tool has parameter descriptions, a result schema and hints (read-only, destructive, idempotent), so clients and models pick the right one.
| Tool | What it does |
|---|---|
devices |
list the phones this key can use (name, number, model, Android, state, network, linked accounts); start, stop or rename one. Every tool takes the phone's API name, its name from the dashboard ("Anna IG", "Pixel 7 #3") or its number |
observe |
a fresh screenshot with a number drawn on every element, the app in front, and the elements as text with their positions |
act |
tap / long_press (by element number or point), swipe, scroll, tap_text, wait_text, type, key, open_app, close_app, open_url, intent, settings, clipboard_set, notifications_open / _close / _clear, installed; waits until the screen settles and refuses an action taken on a stale screen |
inspect |
read without touching the screen: notifications, clipboard, app (version, install time, running), crashes (app crashes, native crashes, ANRs), health, installed |
snapshots |
list, save, restore (reset between runs) or clone a phone with its own identity |
recipe |
run an app recipe on one phone (built-in flows such as login, warm-up, publish, or your own steps); record a new one from what is done on the phone and replay it without a model |
network |
where phones go online: exit types and countries on sale, the account's proxies and the devices on each, add your own proxy or a Clousd exit, bind devices, new IP, check |
resources |
saved app accounts (never with passwords), texts, the media library; add accounts and link them to phones, add Facebook / Threads that sign in through an Instagram account, upload files, copy them into phones' galleries |
fleet |
many phones in one call: recipes lists the built-in recipes with their inputs, run starts a recipe or your steps on up to 32 phones in parallel (each with its own login via vars_by_device, starts spread with stagger) and returns a job, status shows per-phone progress |
Screenshots come back 540 px wide (CLOUSD_SHOT_WIDTH to change). Act on an element by its number from the last
observe: the most reliable way to press a button. Coordinates, when needed, are in that image and the server scales
them to the phone. Typing goes through the input method and works in any language and in password fields.
Automate, do not tap
Tapping through observe -> act is for exploring and for screens no recipe covers. For a known app task the agent
should run a recipe, and for several phones one fleet call, not a loop:
fleet op=recipes app=instagram -> login, warm, publish_post, publish_story, delete_last_post
fleet op=run devices=all package=com.instagram.android action=warm
vars={"seconds":"900","comment_chance":"0.1"} stagger=20,90
-> {"job": "j_8a1c", "devices": [10 phones]}
fleet op=status job=j_8a1c -> {"counts": {"running": 7, "done": 3}, "devices": {...}}
Signing ten accounts in at once from the saved accounts (resources op=accounts), the password never passes through the
agent: fleet op=run devices=all steps=[{"op":"login","package":"com.instagram.android","account":"linked"}] signs every
phone into the account linked to it. Or with logins given right there: fleet op=run devices=["dev_01","dev_02",...] package=com.instagram.android action=login vars_by_device={"dev_01":{"login":"anna.k","password":"..."}, ...}. Passwords never appear in the output.
What a session looks like
observe dev_04f2 -> screenshot, "On screen: com.android.chrome", elements 1..34
act dev_04f2 tap element=12 -> "ok" (settled in 0.6 s)
act dev_04f2 type text="weather in Berlin"
act dev_04f2 key text=enter
act dev_04f2 wait_text text=Berlin -> "found after 1.9 s"
inspect dev_04f2 crashes -> []
snapshots dev_04f2 restore snapshot_id=snap_7f3 -> "restored" (next episode starts clean)
What teams use it for
- Agent evaluation and training: restore a snapshot, run the agent for N steps, check the screen, repeat. One phone, hundreds of identical episodes. Run AndroidWorld-style task sets on real device models.
- App testing on real models: the same test on a Galaxy A35, a Pixel 9 and a moto g05, Android 14 to 16, without
a device farm. Crashes, ANRs and the logcat are one
inspectaway. - Account and content operations: each phone keeps its own identity, network and app state; clone a prepared phone instead of setting up the next one by hand; recipes replay a flow on many phones.
- Anything that needs a phone in a specific country: the exit, SIM, time zone and locale match.
Security and scope
- Keys are issued per account with a scope (
readorcontrol) and an explicit list of phones; a read key can observe and inspect but never acts. - Over HTTP the key travels in the
Authorizationheader of every request; the hosted server keeps nothing between requests. - Phones never leak traffic outside their configured exit: a kill-switch below Android drops anything that is not going through the exit.
- ADB is available on request per phone, with an IP allow-list and a one-time code, for checks that need to go deeper than the screen.
FAQ
Is this an emulator? No. Each phone is a full Android system built as a specific real model; apps read the same hardware identity the real handset reports. Emulator detection does not trigger.
Which MCP clients work? Anything that speaks MCP over stdio or streamable HTTP: Cursor, Windsurf, Zed, desktop
assistants, agent frameworks with MCP support, and your own code through the Python client
(clousd).
How fast is a step? observe with the UI tree takes about 1 to 3 seconds; act with settle 0.3 to 1 second.
A typical agent step including the model is 5 to 10 seconds.
What does it cost? Per minute while the phone runs, or a monthly plan; stopped phones cost nothing. Network traffic by the gigabyte. See clousd.com/pricing.
Can I run my own flows without a model? Yes: record a flow once (recipe with record_start / record_stop, or
by hand in the dashboard) and replay it with recipe run on any number of phones.
Links
- Phones for AI agents: https://clousd.com/agents/
- Documentation and API reference: https://clousd.com/docs/ and https://clousd.com/docs/reference/
- Device catalog (150+ models): https://clousd.com/devices/
- Networks: https://clousd.com/network/
- Snapshots and clones: https://clousd.com/snapshots/
- Python client: https://pypi.org/project/clousd/
- Source, OpenAPI description, issues: https://github.com/Clousd-Android/clousd-sdk
Built on the clousd Python client. MIT license.
mcp-name: io.github.Clousd-Android/clousd-mcp
Metadata
Release files for clousd-mcp 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| clousd_mcp-0.3.1.tar.gz | 22.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| clousd_mcp-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 41.4 kB
Release files / clousd_mcp-0.3.1.tar.gz
| Download URL | clousd_mcp-0.3.1.tar.gz |
|---|---|
| Size | 22.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
85a47310f25d9dba1c35710e0b53540e17c86a52e23e54a10efa106b1999a576
|
|
BLAKE2b-256 checksum How to use checksums |
6e37dc2daf0bab85769f86d60075f3fe4939c282b28917ee2e659f7caecb3780
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / clousd_mcp-0.3.1-py3-none-any.whl
| Download URL | clousd_mcp-0.3.1-py3-none-any.whl |
|---|---|
| Size | 19.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0fd62176ee42ffb4db0dd11f32a849ee9639dc6b6700bfa5aed47e3267d7b743
|
|
BLAKE2b-256 checksum How to use checksums |
1afcacc825a9af9b68e9c92b30250bc173f8188577bba59df76523ba134b256b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log