# io.github.Clousd-Android/clousd-mcp

> A real Android phone in the cloud for MCP agents: observe the screen, act, reset to a saved state.

- name: io.github.Clousd-Android/clousd-mcp
- version: 0.3.2
- connection class: R1 (autonomous)
- trust: 96/100
- quality: 73/100 (needs work)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/io.github.Clousd-Android%2Fclousd-mcp
- tools: https://api.protogrid.dev/v1/servers/io.github.Clousd-Android%2Fclousd-mcp/tools

**An agent can connect on its own if it already holds `CLOUSD_MCP_TOKEN`.** Remote endpoint behind a static API key or header. The registry never sees the value; the agent fills the placeholder.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "clousd-mcp": {
      "type": "http",
      "url": "https://api.clousd.com/mcp",
      "headers": {
        "Authorization": "Bearer ${CLOUSD_MCP_TOKEN}"
      }
    }
  }
}
```

Placeholders to fill: `${CLOUSD_MCP_TOKEN}`.

## Trust

- hygiene: 100
- liveness: 96
- freshness: 100
- provenance: 90
- drivers: +repository +namespace-matches-repo +website +reachable +uptime-91% +updated-7d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 73/100 (needs work)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 86 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 1 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 10 of 10 tools declare readOnlyHint or destructiveHint
- warn `tools.directory_hints`: 7 of 10 tools declare all four hints; missing: observe (destructiveHint, idempotentHint); inspect (destructiveHint, idempotentHint); account (destructiveHint, idempotentHint)
- pass `tools.token_cost`: about 4,298 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 25 (weight 15)

- warn `stability.changes`: 16 tool changes in 30 days
- fail `stability.rug_pull`: 1 tools kept their name but changed most of their description in 30 days; review before trusting them

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: deps.dev does not know clousd-mcp@0.3.2

- tools: 10, about 4,298 tokens to load them all
- tool set hash: fe59afa9a51bb1723c20d5d539cfea5e
- tools last changed: 2026-10-16T21:25:55.105Z
- badge: [![protogrid quality](https://protogrid.dev/badge/io.github.Clousd-Android/clousd-mcp.svg)](https://protogrid.dev/servers/io.github.Clousd-Android/clousd-mcp)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-16 `fleet` added
  - Work with many phones in one call - the way to automate, instead of tapping each phone step by step. op=recipes lists the built-in app recipes (sign in, warm up an account, publish, delete the last post...) with their inputs; prefer a recipe over act whenever one fits the task. op=run starts a recipe (package + action) or your own steps on up to 32 phones at once (they may live on different servers) and returns a job id right away - the phones work in parallel, minutes to an hour for a warm-up. op=status with job shows per-phone progress: call it every 30-60 s until state is done or failed. Steps for op=run: recipe (package, action, vars), open_app / close_app (package), url (url), tap_text / wait_text (text, seconds), wait (seconds, seconds_max), scroll (text=down|up), browse (seconds 10-600: scroll like a person), install_app (package from the catalog), key (key), screenshot, rotate (new IP), if_text / unless_text (text, skip), login (package, account: an id from resources op=accounts or "linked" for the account linked to each phone - the server fills the password), publish (package, text: post|story|reel, media_id from resources op=media, caption). vars_by_device gives each phone its own account or media_id too, e.g. {"dev_1": {"account": "12"}, "dev_2": {"account": "13"}}.
- 2026-10-16 `resources` added
  - The account's resources, the same as Resources in the dashboard. accounts: saved app accounts (login, status, the phone it is linked to; parent_id = it signs in through that Instagram) - passwords and 2FA secrets are never shown; add_via_instagram (account_id = an Instagram account, platform = com.facebook.katana or com.instagram.barcelona): a Facebook / Threads that signs in through that Instagram, on the same phone, no password. To sign a phone in, run fleet with the step {"op":"login","package":...,"account":<id> or "linked"} and the server fills the password itself. add_accounts / link_account: save accounts and link one to a phone. texts / add_texts: captions, comments, bios, names. media / upload_media: the photo and video library; publish one with fleet step {"op":"publish","package":...,"text":"post", "media_id":<id>,"caption":...}. send_media: copy files into phones' galleries as if taken by that phone.
- 2026-10-16 `network` added
  - Where phones go online. Every phone uses one proxy of the account: your own proxy, or a Clousd exit (residential, mobile, ISP, datacenter in a country, paid per GB); time zone, locale and SIM follow it. op=options: exit types on sale and countries. op=status: the exit a device uses now (IP, country, carrier). op=proxies: the account's proxies and which devices use each. op=add: save your proxy (it is checked at once) or a Clousd exit. op=bind: put devices on a proxy. op=unbind: take them off (no internet until bound again). op=rotate: new IP for every running device on the proxy. op=check: test your proxy. op=delete: remove an unused proxy.
- 2026-10-16 `account` added
  - The account's money - check it before starting phones, creating them or launching long runs, and tell the user what it says. op=balance: balance, spend_per_day (running per-minute phones + paid proxy traffic of the last 24 hours), runs_out_in_hours, phones running per minute with their price, monthly renewals within 7 days, prices per hour / day cap / month / GB by exit type, the top_up link, and warnings: show every warning to the user in plain words (e.g. "about 6 hours left; at zero the phones stop and go to storage", "proxy traffic cost $3.40 today") with the top_up link. When the balance is low, say so before spending more - do not silently start phones.
- 2026-10-16 `recipe` changed (description, inputSchema)
  - before: App recipes: scripted flows that wait for the right screen at each step, deal with popups and report what they did. op=run runs a built-in recipe (package + action) or your own JSON and returns when it is finished. op=record_start begins recording what is done on the phone (through act, or by a person in the live view); record_status shows progress; record_stop returns the recorded draft recipe, ready for op=run.
  - after: App recipes on one phone: scripted flows that wait for the right screen at each step, deal with popups and report what they did. op=run runs a built-in recipe (package + action - the list with inputs is fleet op=recipes) or your own JSON and returns when it is finished; for several phones use fleet op=run instead. op=record_start begins recording what is done on the phone (through act, or by a person in the live view); record_status shows progress; record_stop returns the recorded draft recipe, ready for op=run.
- 2026-10-16 `snapshots` changed (inputSchema)
- 2026-10-16 `inspect` changed (inputSchema)
- 2026-10-16 `act` changed (inputSchema)
- 2026-10-16 `observe` changed (inputSchema)
- 2026-10-16 `devices` changed (description, inputSchema)
  - before: Phones this API key can use. op=list: name, state (running / stopped / starting), model, Android version and network exit of each phone. op=start / op=stop with `device`: start a stopped phone (waits until it has booted, one to three minutes) or stop one (a stopped phone keeps its state and costs nothing).
  - after: Phones this API key can use. op=list: name, label (the name people see in the dashboard, e.g. "Anna IG" or "Pixel 7 #3"), number, state (running / stopped / starting), model, Android version, network exit, the app accounts linked to it and its proxy_id. Every tool takes the name, the label or the number. op=rename with device and label: give a phone a name (empty = back to "Model #N"); name phones after their accounts to keep a fleet readable. op=start / op=stop with `device`: start a stopped phone (waits until it has booted, one to three minutes) or stop one (a stopped phone keeps its state and costs nothing).

Full history: https://api.protogrid.dev/v1/servers/io.github.Clousd-Android%2Fclousd-mcp/changes

## Dependencies

- pypi clousd-mcp@0.3.2: unknown

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0.

## Remotes

- https://api.clousd.com/mcp (streamable-http, auth api_key ${CLOUSD_MCP_TOKEN}, reachable true, uptime30d 0.90625)

## Packages

- pypi clousd-mcp@0.3.2 secrets: CLOUSD_API_KEY

## Tools (10)

- `account`: The account's money - check it before starting phones, creating them or launching long runs, and tell the user
    what it says. op=balance: balance, spend_per_day (running per-minute phones + paid proxy traffic of the last 24 hours),
    runs_out_in_hours, phones running per minute with their price, monthly renewals within 7 days, prices per hour / day
    cap / month / GB by exit type, the top_up link, and warnings: show every warning to the user in plain words (e.g.
    "about 6 hours left; at zero the phones stop and go to storage", "proxy traffic cost $3.40 today") with the top_up
    link. When the balance is low, say so before spending more - do not silently start phones.
- `act`: Do one thing on the phone, then wait until the screen settles. Prefer element numbers from observe over
    coordinates; tap_text taps the element whose text contains `text`. Typing goes into the focused field (tap it
    first) and works in any language. Returns what happened; "the screen did not change" means the action probably
    missed - observe again.
- `devices`: Phones this API key can use.
    op=list: name, label (the name people see in the dashboard, e.g. "Anna IG" or "Pixel 7 #3"), number, state (running /
    stopped / starting), model, Android version, network exit, the app accounts linked to it and its proxy_id. Every
    tool takes the name, the label or the number. op=rename with device and label: give a phone a name (empty = back to
    "Model #N"); name phones after their accounts to keep a fleet readable.
    op=start / op=stop with `device`: start a stopped phone (waits until it has booted, one to three minutes) or stop
    one (a stopped phone keeps its state and costs nothing).
- `fleet`: Work with many phones in one call - the way to automate, instead of tapping each phone step by step.
    op=recipes lists the built-in app recipes (sign in, warm up an account, publish, delete the last post...) with their
    inputs; prefer a recipe over act whenever one fits the task. op=run starts a recipe (package + action) or your own
    steps on up to 32 phones at once (they may live on different servers) and returns a job id right away - the phones
    work in parallel, minutes to an hour for a warm-up. op=status with job shows per-phone progress: call it every
    30-60 s until state is done or failed. Steps for op=run: recipe (package, action, vars), open_app / close_app
    (package), url (url), tap_text / wait_text (text, seconds), wait (seconds, seconds_max), scroll (text=down|up),
    browse (seconds 10-600: scroll like a person), install_app (package from the catalog), key (key), screenshot,
    rotate (new IP), if_text / unless_text (text, skip), login (package, account: an id from resources op=accounts or
    "linked" for the account linked to each phone - the server fills the password), publish (package, text: post|story|reel,
    media_id from resources op=media, caption). vars_by_device gives each phone its own account or media_id too, e.g.
    {"dev_1": {"account": "12"}, "dev_2": {"account": "13"}}.
- `inspect`: Read the phone without touching the screen.
    notifications: the shade as a list (app, title, text, time). clipboard: the clipboard text.
    app: installed version, install/update time, installer, whether it runs or is on screen.
    crashes: recent app crashes, native crashes and ANRs with the first lines of the stack.
    health: running, booted, network exit and the latest automatic check of the phone.
    installed: packages of apps that can be opened.
- `network`: Where phones go online. Every phone uses one proxy of the account: your own proxy, or a Clousd exit (residential,
    mobile, ISP, datacenter in a country, paid per GB); time zone, locale and SIM follow it. op=options: exit types on
    sale and countries. op=status: the exit a device uses now (IP, country, carrier). op=proxies: the account's proxies
    and which devices use each. op=add: save your proxy (it is checked at once) or a Clousd exit. op=bind: put devices on
    a proxy. op=unbind: take them off (no internet until bound again). op=rotate: new IP for every running device on the
    proxy. op=check: test your proxy. op=delete: remove an unused proxy.
- `observe`: Look at the phone: a fresh screenshot, the app on screen and (with_text) every labelled or tappable element with
    a number. Act on an element by its number (act element=N); coordinates, when needed, are in this image's pixels.
- `recipe`: App recipes on one phone: scripted flows that wait for the right screen at each step, deal with popups and report
    what they did. op=run runs a built-in recipe (package + action - the list with inputs is fleet op=recipes) or your own
    JSON and returns when it is finished; for several phones use fleet op=run instead.
    op=record_start begins recording what is done on the phone (through act, or by a person in the live view);
    record_status shows progress; record_stop returns the recorded draft recipe, ready for op=run.
- `resources`: The account's resources, the same as Resources in the dashboard. accounts: saved app accounts (login, status, the
    phone it is linked to; parent_id = it signs in through that Instagram) - passwords and 2FA secrets are never shown;
    add_via_instagram (account_id = an Instagram account, platform = com.facebook.katana or com.instagram.barcelona): a
    Facebook / Threads that signs in through that Instagram, on the same phone, no password. To sign a phone in, run fleet with the step
    {"op":"login","package":...,"account":<id> or "linked"} and the server fills the password itself. add_accounts /
    link_account: save accounts and link one to a phone. texts / add_texts: captions, comments, bios, names. media /
    upload_media: the photo and video library; publish one with fleet step {"op":"publish","package":...,"text":"post",
    "media_id":<id>,"caption":...}. send_media: copy files into phones' galleries as if taken by that phone.
- `snapshots`: Saved states of a phone, for starting every run from the same point.
    op=list: id, created, android, current, restorable. op=save: save the current state.
    op=restore with snapshot_id: reset the phone to that state (what happened since is lost).
    op=clone with snapshot_id and new_name: a new phone from that state.
