One endpoint carries the whole site lifecycle: generate, read, write, deploy, bind. No SDK to adopt, no build pipeline to wrap — a newline-delimited JSON-RPC bridge on one side, an HTTPS tool server on the other.
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "ops-agent",
"version": "1.0"
}
}
}
Your MCP client writes newline-delimited JSON-RPC to the bridge's stdin. The bridge forwards each message to POST {CLOUDSITE_URL}/api/mcp with the bearer token, and prints the response back on stdout. That is the entire contract.
# both values come from your CloudSite workspace export CLOUDSITE_URL="https://cloudsite.editorapi.com" export CLOUDSITE_TOKEN="$CLOUDSITE_TOKEN" # the stdio bridge ships with the MCP setup node ./stdio-bridge.js
POST /api/mcp Authorization: Bearer $CLOUDSITE_TOKEN Content-Type: application/json {"jsonrpc":"2.0","id":2,"method":"tools/list"}
Token scope decides the toolset in practice. A read token can enumerate sites and read files; write tools are refused server-side, not hidden on the client.
Client and server exchange protocol version, capabilities and client info.
A notification with no id. The server stops waiting and accepts tool traffic.
Returns the 75 tools with their input schemas. Cache it for the session.
Name plus arguments. The response carries content blocks and, on failure, an error.
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{
"name":"generate_site",
"arguments":{"prompt":"..."}
}}Tools that return work rather than a finished result — deploys, uploads, domain binding — give you a task back. Poll get_task until it settles instead of sleeping on the socket.
Argument names differ per tool. Read the schema from tools/list; the payloads on this page are shape, not a fixed contract.
| Tool | Does | Scope |
|---|---|---|
whoami | Returns the identity behind the token and its scope. | read |
capabilities | Lists what this deployment exposes to the caller. | read |
list_sites / get_site | Enumerate properties and inspect one, including deploy state. | read |
list_site_files / read_site_file | Walk the file tree and pull a single file as UTF-8 text. | read |
generate_site | Builds a full site from one sentence in one to three minutes. | write |
write_site_file / delete_site_file | Create, overwrite or remove one file. Two megabytes per file. | write |
deploy_site / bind_domain | Ship to Pages or Firebase; write the Cloudflare CNAME on bind. | write |
upload_site / create_upload_link | Replace the whole site from files or a zip. | write |
A write replaces the file wholesale. If you care about what is already there — a hand-tuned header, a legal line — fetch it first and edit the text you received. This is also the cheapest way to avoid clobbering another agent's work.
index.html must exist.{"jsonrpc":"2.0","id":7,"method":"tools/call",
"params":{
"name":"write_site_file",
"arguments":{
"site_id":"...",
"path":"index.html",
"content":"..."
}
}}Point a read token at whoami first. It costs one call and tells you exactly what the rest of the session can do.