Appearance
Automation (MCP) API
The /mcp endpoint lets MCP clients - Claude and other assistants that speak the Model Context Protocol - drive your account. Ask in plain language ("clone my staging pod", "how much credit is left?") and the client calls the matching tool.
Authentication
MCP is API key only. A login token will not work here.
http
Authorization: Bearer mck_1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f809Create a key, scope it to exactly what the assistant should be allowed to touch, and optionally IP-bind it - see API keys. The key's permissions decide which tools it can call, and a key only ever sees the tools it is allowed to use.
Protocol
/mcp speaks JSON-RPC 2.0 over plain HTTP POST. It is stateless (no sessions, no streaming), so every call is a self-contained request to:
POST https://cloud-api.microapps.io/mcp| Method | What it does |
|---|---|
initialize | Handshake; the client announces itself and gets server info back |
ping | Liveness check; returns an empty result |
tools/list | List the tools this key may call |
tools/call | Run a tool, with params: { name, arguments } |
Most MCP clients only need the URL and your API key; they handle the JSON-RPC plumbing for you.
A few details that matter if you are writing the client yourself:
GETandDELETEon/mcpreturn 405. There is no SSE stream and no session to terminate.- A notification (a request with no
id) is acknowledged with 202 and an empty body. - The protocol version defaults to
2025-03-26. Send your own ininitializeand it is echoed back. - Everything else answers 200, including failures - the JSON-RPC
errorobject carries the problem, not the HTTP status.
json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": { "tools": {} },
"serverInfo": { "name": "cloud-api", "version": "1.0.0" }
}
}Tools
Each tool is gated by the same permission as its REST equivalent, so a key can never do more through MCP than it could through the API. Tools the key cannot use do not show up in tools/list, and calling one anyway comes back as a tool error rather than a silent no-op.
| Tool | Does | Permission |
|---|---|---|
list_pods | List your pods | pods:read |
get_pod | Describe one pod | pods:read |
pod_action | Start, stop, or restart a pod (action: start / stop / restart) | pods:update |
clone_pod | Clone a pod into a new one | pods:create |
list_snapshots | List a pod's snapshots | snapshots:read |
create_snapshot | Take a snapshot | snapshots:create |
list_backups | List a pod's backups | backups:read |
list_account_backups | List every backup on the account, including ones whose pod was deleted | backups:read |
create_backup | Take a backup | backups:create |
list_domains | List your domains | domains:read |
list_networks | List your networks | networks:read |
get_account | Read credit, limits, and contact details | any key |
create_announcement | Publish a platform-wide notice | operator only |
get_pod, pod_action, clone_pod, list_snapshots, create_snapshot, list_backups and create_backup take a podId; pod_action takes action as well. list_pods, list_account_backups, list_domains, list_networks and get_account take no arguments. create_announcement is an operator tool and never appears in a customer key's tools/list - no API key can hold the account permissions it requires.
Tools that change things (pod_action, clone_pod, create_snapshot, create_backup) obey the same $3 credit minimum as the API and show up in your activity log, just like a console click. Read-only tools do neither.
Example: list tools
bash
curl -X POST https://cloud-api.microapps.io/mcp \
-H "Authorization: Bearer $MICROAPPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Example: call a tool
bash
curl -X POST https://cloud-api.microapps.io/mcp \
-H "Authorization: Bearer $MICROAPPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "pod_action",
"arguments": { "podId": "6a4d5b83b7006ccae6391810", "action": "restart" }
}
}'A tool result is MCP content, with the payload as JSON inside a text block:
json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [{ "type": "text", "text": "{\n \"message\": \"Action restart executed\"\n}" }],
"isError": false
}
}Errors
Two kinds, and they look different.
Tool errors are a normal result with isError: true and the explanation in the text block. This is what you get for a missing permission, a pod that is not yours, or too little credit:
json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [{ "type": "text", "text": "Error: insufficient credit. You need at least $3 on your account to proceed." }],
"isError": true
}
}Protocol errors are a JSON-RPC error object, still over HTTP 200:
| Code | When |
|---|---|
-32700 | The body was not valid JSON |
-32601 | Unknown method |
-32602 | Malformed params, or an unknown tool name |
-32603 | The result could not be encoded |