clousd-mcp
A real Android phone in the cloud for MCP agents: observe the screen, act, reset to a saved state.
¿Debería usar esto?
Calidad y seguridad
Hallazgos (1)
- LOWen observe
Basado en el análisis automatizado de las definiciones de herramientas y el cumplimiento del protocolo.
Costo de contexto
Este es el número aproximado de tokens que se consumen cada vez que las herramientas del servidor se cargan en el contexto de un modelo. Los recuentos más altos reducen la atención disponible para otras tareas.
Instalar
Instalación con un clic
Agrega esto a tu archivo `claude_desktop_config.json`:
{
"mcpServers": {
"clousd-mcp": {
"command": "uvx",
"args": [
"clousd-mcp"
]
}
}
}Paquetes ejecutables
0.2.0stdioPuntos de conexión remotos
https://api.clousd.com/mcpstreamable-httpQué puede hacer
Inventario de herramientas
Herramientas (6)
⚪devices(op, device)
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).
Esquema de entrada
{
"type": "object",
"properties": {
"op": {
"default": "list",
"description": "list (default) | start | stop",
"title": "Op",
"type": "string"
},
"device": {
"default": "",
"description": "device name, for start/stop",
"title": "Device",
"type": "string"
}
},
"title": "devicesArguments"
}Esquema de salida
{
"type": "object",
"properties": {
"result": {
"additionalProperties": true,
"title": "Result",
"type": "object"
}
},
"required": [
"result"
],
"title": "devicesOutput"
}🟢observe(device, with_text, numbers)
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.
Esquema de entrada
{
"type": "object",
"properties": {
"device": {
"description": "Device name from devices (op=list), e.g. dev_04f2",
"title": "Device",
"type": "string"
},
"with_text": {
"default": true,
"description": "also list the elements (numbered, centres in image pixels)",
"title": "With Text",
"type": "boolean"
},
"numbers": {
"default": true,
"description": "draw the element numbers on the screenshot",
"title": "Numbers",
"type": "boolean"
}
},
"required": [
"device"
],
"title": "observeArguments"
}🔴act(device, action, element, x, y, ...)
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.
Esquema de entrada
{
"type": "object",
"properties": {
"device": {
"description": "Device name from devices (op=list), e.g. dev_04f2",
"title": "Device",
"type": "string"
},
"action": {
"description": "one of: tap long_press swipe scroll tap_text wait_text type key open_app close_app open_url installed intent settings clipboard_set notifications_open notifications_close notifications_clear",
"title": "Action",
"type": "string"
},
"element": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "element number from the last observe (tap, long_press)",
"title": "Element"
},
"x": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "x in screenshot pixels (tap, long_press, swipe start)",
"title": "X"
},
"y": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "y in screenshot pixels",
"title": "Y"
},
"x2": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "swipe end x",
"title": "X2"
},
"y2": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "swipe end y",
"title": "Y2"
},
"text": {
"default": "",
"description": "type: the text; key: home|back|recents|enter|tab|del|menu; scroll: down|up; open_app/close_app: package; open_url: https://...; tap_text/wait_text: text on screen; settings: wifi|bluetooth|display|sound|apps|location|about|battery|...; intent: a URI to view (geo:, tel:, https:...) or JSON {action,data,package,component,extras}; clipboard_set: the text",
"title": "Text",
"type": "string"
},
"ms": {
"default": 300,
"description": "swipe / long_press duration in ms",
"title": "Ms",
"type": "integer"
},
"timeout": {
"default": 30,
"description": "wait_text: seconds to wait, up to 120",
"title": "Timeout",
"type": "integer"
}
},
"required": [
"device",
"action"
],
"title": "actArguments"
}Esquema de salida
{
"type": "object",
"properties": {
"result": {
"title": "Result",
"type": "string"
}
},
"required": [
"result"
],
"title": "actOutput"
}🟢inspect(device, what, package)
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.
Esquema de entrada
{
"type": "object",
"properties": {
"device": {
"description": "Device name from devices (op=list), e.g. dev_04f2",
"title": "Device",
"type": "string"
},
"what": {
"description": "notifications | clipboard | app | crashes | health | installed",
"title": "What",
"type": "string"
},
"package": {
"default": "",
"description": "app: the package to describe; crashes: only this package",
"title": "Package",
"type": "string"
}
},
"required": [
"device",
"what"
],
"title": "inspectArguments"
}Esquema de salida
{
"type": "object",
"properties": {
"result": {
"additionalProperties": true,
"title": "Result",
"type": "object"
}
},
"required": [
"result"
],
"title": "inspectOutput"
}🔴snapshots(device, op, snapshot_id, new_name)
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.
Esquema de entrada
{
"type": "object",
"properties": {
"device": {
"description": "Device name from devices (op=list), e.g. dev_04f2",
"title": "Device",
"type": "string"
},
"op": {
"default": "list",
"description": "list (default) | save | restore | clone",
"title": "Op",
"type": "string"
},
"snapshot_id": {
"default": "",
"description": "restore / clone: id from op=list",
"title": "Snapshot Id",
"type": "string"
},
"new_name": {
"default": "",
"description": "clone: name of the new phone (letters and digits, up to 16)",
"title": "New Name",
"type": "string"
}
},
"required": [
"device"
],
"title": "snapshotsArguments"
}Esquema de salida
{
"type": "object",
"properties": {
"result": {
"additionalProperties": true,
"title": "Result",
"type": "object"
}
},
"required": [
"result"
],
"title": "snapshotsOutput"
}🔴recipe(device, op, package, action, steps, ...)
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.
Esquema de entrada
{
"type": "object",
"properties": {
"device": {
"description": "Device name from devices (op=list), e.g. dev_04f2",
"title": "Device",
"type": "string"
},
"op": {
"description": "run | record_start | record_status | record_stop",
"title": "Op",
"type": "string"
},
"package": {
"default": "",
"description": "run: app package of a built-in recipe (e.g. com.instagram.android)",
"title": "Package",
"type": "string"
},
"action": {
"default": "",
"description": "run: built-in recipe name (e.g. warm, login, publish_post)",
"title": "Action",
"type": "string"
},
"steps": {
"default": "",
"description": "run: your own recipe as JSON {app, steps:[...]} (e.g. a recorded draft)",
"title": "Steps",
"type": "string"
},
"vars": {
"default": "",
"description": "run: variables as JSON, e.g. {\"seconds\": \"300\"}",
"title": "Vars",
"type": "string"
}
},
"required": [
"device",
"op"
],
"title": "recipeArguments"
}Esquema de salida
{
"type": "object",
"properties": {
"result": {
"additionalProperties": true,
"title": "Result",
"type": "object"
}
},
"required": [
"result"
],
"title": "recipeOutput"
}Comunidad
Evidencia