clousd-mcp
A real Android phone in the cloud for MCP agents: observe the screen, act, reset to a saved state.
我該用這個嗎
品質與安全性
發現項目(1)
- LOW在 observe 中
根據工具定義與協定合規性的自動化分析。
上下文成本
這是每次將伺服器的工具載入模型上下文時所消耗的約略 token 數量。數量越高,可用於其他工作的注意力就越少。
安裝
一鍵安裝
將以下內容加入你的 `claude_desktop_config.json` 檔案:
{
"mcpServers": {
"clousd-mcp": {
"command": "uvx",
"args": [
"clousd-mcp"
]
}
}
}可執行的套件
0.2.0stdio遠端端點
https://api.clousd.com/mcpstreamable-http它能做什麼
工具清單
工具(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).
輸入結構描述
{
"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"
}輸出結構描述
{
"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.
輸入結構描述
{
"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.
輸入結構描述
{
"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"
}輸出結構描述
{
"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.
輸入結構描述
{
"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"
}輸出結構描述
{
"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.
輸入結構描述
{
"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"
}輸出結構描述
{
"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.
輸入結構描述
{
"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"
}輸出結構描述
{
"type": "object",
"properties": {
"result": {
"additionalProperties": true,
"title": "Result",
"type": "object"
}
},
"required": [
"result"
],
"title": "recipeOutput"
}社群
證據