# Cloud Computer AI > Cloud Computer AI is a console for cloud computers. People use the human canvas at /app. Agents and screen readers use /agent when the server is started with AGENT_VIEW_ENABLED=1. Programmatic control is the JSON API under /api, a legacy MCP endpoint at /api/mcp, and a streamable HTTP MCP server at /mcp when MCP_ENABLED=1. The agent view is semantic HTML with hash routes. It does not replace the human canvas. Delete is destructive: confirm with the user before calling it. ## Views - [Human canvas](/app): Visual workspace, desktop stream, and settings where API keys are created. - [Agent view](/agent): Tables, forms, and live regions for computers, launch, templates, backups, billing, settings, API notes, activity, and help. Open a desktop at /agent#desktop/{id}. - [API reference](/agent-api.html): Human-readable shapes for the same endpoints. - [Full notes](/llms-full.txt): Request and response bodies derived from the server. - [Action catalog](/.well-known/ccai-actions.json): Selectors and endpoints for agent-view controls. - [OpenAPI](/openapi.json): OpenAPI 3.1 for the REST endpoints the MCP tools call. ## Auth - Send `Authorization: Bearer` with the Clerk session token. The console reads it from `window.OpenPCAuth.getToken()`. - Public reads: [GET /api/flags](/api/flags) returns `{ "agentView", "a11yFocusSafe", "mcp", "ownerLock", "desktopFrameA11y", "a11yP2CanvasAlt", "desktopOcr", "canvasListView", "composeServices" }`, [GET /api/config](/api/config), and [GET /api/health](/api/health). Each flag is true only when its env var is `1`: AGENT_VIEW_ENABLED, A11Y_P3_FOCUS_SAFE, MCP_ENABLED, OWNER_LOCK_ENABLED, DESKTOP_FRAME_A11Y, A11Y_P2_CANVAS_ALT, DESKTOP_OCR_ENABLED, CANVAS_LIST_VIEW, COMPOSE_SERVICES_ENABLED. `mcp` is true only when MCP_ENABLED=1. `composeServices` is true only when COMPOSE_SERVICES_ENABLED=1. - Create an API key while signed in with [POST /api/api-keys](/api/api-keys). The secret is returned once. [GET /api/workspace](/api/workspace) lists key id, name, prefix, and created date, and omits the secret. - Preferred view is stored in the browser as `ccai.view` (`human` or `agent`). `?view=human` opens the canvas without changing that preference. ## Computers - [List computers](/api/computers): GET `{ computers }`. - [Create computer](/api/computers): POST `{ name, templateId, provider, size, vcpu, memoryMb, diskGb, ttlHours, x, y, disclosureAck, services? }`. Railway templates require `disclosureAck: true`. Optional `services` is a list of catalog service ids, queued after the computer is running when COMPOSE_SERVICES_ENABLED=1, and ignored when the flag is off. Response 201 `{ computer }`. - [Get computer](/api/computers/{id}): GET `{ computer }`. - [Start](/api/computers/{id}/start): POST `{ computer }`. - [Stop](/api/computers/{id}/stop): POST `{ computer }`. - [Delete](/api/computers/{id}): DELETE `{ ok, id }`. Destructive. Confirm with the user first. The agent view asks in a dialog and returns focus to the triggering button on Cancel. - [Screenshot](/api/computers/{id}/screenshot): GET `{ pngBase64 }` (raw base64 PNG). Shared computers stay screenshot-able. - [Screen text](/api/computers/{id}/screen-text): GET `{ text, cachedAt, engine: "tesseract" }` when DESKTOP_OCR_ENABLED=1. Same visibility as screenshot. 501 `{ code: "ocr_unavailable" }` when tesseract is missing. 404 when the flag is off. - [Service catalog](/api/services): GET `{ services }` when COMPOSE_SERVICES_ENABLED=1. 404 `{ error: "services disabled" }` when the flag is unset or `0`. Catalog entries are docker, wordpress (depends on docker, port 8080), n8n (depends on docker, port 5678), and grok_cli (Grok Build CLI, no dependencies, signed out, no tokens). - [Computer services](/api/computers/{id}/services): GET `{ services }`. POST `{ serviceId }` queues that service and its dependencies and returns 202 `{ computer, services }`. 400 `{ error: "unknown service" }`. 409 `{ error: "computer not running" }` when the computer is not running. - [Service health](/api/computers/{id}/services/{sid}/health): POST re-checks one added service and returns `{ services }`. - Template id `t_docker` is a fresh Ubuntu desktop with Docker Engine, Docker Compose plugin (v2.24+), git, curl, jq and a terminal. Docker starts at boot. Minimum size is 2 vCPU and 4096 MB. - [Update](/api/computers/{id}): PATCH `{ name?, x?, y? }`. Card positions are stored on the computer record (the same fields drag writes). There is no separate layout store and no `move_computer` MCP tool. When OWNER_LOCK_ENABLED=1, a non-owner gets 403 `{ error: "Only the owner or an admin can control this computer", code: "not_owner" }` for PATCH, including layout-only `{ x, y }`. - [Click](/api/computers/{id}/click): POST `{ x, y, button }` where button is `left`, `middle`, or `right`. Optional `nx`, `ny`, `double`, `move`. - [Type](/api/computers/{id}/type): POST `{ text }`. - [Key](/api/computers/{id}/key): POST `{ key }` such as `ctrl+c` or `Return`. - [Scroll](/api/computers/{id}/scroll): POST `{ direction, amount }`. `direction` is `up` or `down`. `amount` is 1 to 20. The agent view form collects dx and dy and sends direction from the sign of dy. - [Bash](/api/computers/{id}/bash): POST `{ command, timeoutMs? }`. `cmd` is accepted as an alias. Response `{ exitCode, stdout, stderr }`. - [Backup status](/api/computers/{id}/backup-status): GET `{ id, name, host, backup }` for Backup Cloudflare computers. - [Stream](/api/computers/{id}/stream): POST starts or returns the desktop stream `{ streamUrl, password? }`. ## Templates, usage, MCP - [Workspace](/api/workspace): GET `templates`, `usage`, and `apiKeys` (no secrets). Template ids in that list are the source for `templateId`. - [Credit balance](/api/credits/balance): GET `{ usd, updatedAt, packs }`. - [Legacy MCP](/api/mcp): GET advertises tools. POST `{ tool, arguments }` runs `list_computers`, `get_computer`, `exec`, or `create_computer`. `name` is an alias of `tool`. This endpoint is unchanged. ## MCP server Streamable HTTP MCP at [POST /mcp](/mcp) (`https://app.cloudcomputerai.com/mcp`) when MCP_ENABLED=1. Protocol versions: 2025-06-18, 2025-03-26, 2024-11-05. POST is JSON-RPC (`application/json`, one message or a batch). GET and DELETE return 405. Stateless. Create a token while signed in with Clerk: Settings → Personal access tokens, or [/agent → API & tokens](/agent#api). POST /api/tokens `{ name, expiresDays }` returns the plaintext `ccai_pat_…` token once. GET /api/tokens lists tokens. DELETE /api/tokens/{id} revokes. Managing tokens with a personal access token returns 403. The server stores only the sha256 hash. Auth header: `Authorization: Bearer ccai_pat_…`. A Clerk session JWT is also accepted. Missing or invalid auth is HTTP 401 with `WWW-Authenticate: Bearer realm="cloudcomputerai", resource_metadata="https://app.cloudcomputerai.com/.well-known/oauth-protected-resource"`. Tools call the existing REST routes: `list_computers`, `get_computer`, `list_templates` (GET /api/workspace), `launch_computer`, `start_computer`, `stop_computer`, `screenshot_computer`, `delete_computer`, `click_computer`, `type_text`, `press_key`, `scroll`. When DESKTOP_OCR_ENABLED=1, `screen_text` `{ id }` (readOnlyHint) calls GET /api/computers/{id}/screen-text. When COMPOSE_SERVICES_ENABLED=1, `list_services` `{ id? }` (readOnlyHint) calls GET /api/services or GET /api/computers/{id}/services, and `add_service` `{ id, serviceId }` calls POST /api/computers/{id}/services. Both are omitted from tools/list when the flag is off. `delete_computer` runs only when `confirm` equals exactly `DELETE `. Any other confirm is an error and does not call DELETE. A REST 403 is returned as MCP `isError` text (for example `not_owner`). When OWNER_LOCK_ENABLED=1, stop, start, click, type, key, scroll, exec, bash, ensure-template, railway, backup-restore, PATCH, and DELETE require the owner, a platform admin, or auth bypass. Shared Grok Bot, Ask Grok, and pinned computers stay visible. A non-owner gets 403 `{ code: "not_owner" }`. HTTP 429 responses include a `Retry-After` header in seconds and `retryAfter` in the JSON. Railway daily cap is 3600, Railway active cap is 300, and any other 429 is 60. Claude Code: `claude mcp add --transport http cloudcomputerai https://app.cloudcomputerai.com/mcp --header "Authorization: Bearer ccai_pat_..."` Claude Desktop `claude_desktop_config.json`: `{"mcpServers":{"cloudcomputerai":{"command":"npx","args":["-y","mcp-remote","https://app.cloudcomputerai.com/mcp","--header","Authorization:${CCAI_TOKEN}"],"env":{"CCAI_TOKEN":"Bearer ccai_pat_..."}}}}` Cursor `~/.cursor/mcp.json`: `{"mcpServers":{"cloudcomputerai":{"url":"https://app.cloudcomputerai.com/mcp","headers":{"Authorization":"Bearer ccai_pat_..."}}}}` Grok and any other streamable HTTP MCP client use the same URL and Authorization header. OpenAPI for those REST routes: [openapi.json](/openapi.json). ## Supabase - Template id `t_supabase` is "Supabase: Self-Hosted Postgres Database and Backend". It is in the Templates canvas, the Docker template filter, and MCP `create_computer`. - The guest recipe pins `v1.26.08`, writes keys to `/opt/supabase/.env` (mode 600), and is ready only when `GET http://127.0.0.1:8000/auth/v1/health` returns 200 with the anon key from that file sent as the `apikey` header. A 401 or a 404 is not ready. Do not print that env file. - The computer's Postgres stays on the VM disk when the computer is stopped. Nightly restic file backups do not include VM disks. - The console's own Supabase is a separate stack on gex44-apps, not a customer VM. Studio for a signed-in operator is [https://app.cloudcomputerai.com/supabase/](/supabase/). API on the server is `http://127.0.0.1:8000`. Postgres data is the bind mount `/opt/supabase-platform/volumes/db/data`, not a named data volume. Named volumes `supabase-platform_db-config` and `supabase-platform_deno-cache` are config and cache only. Status without secrets: [GET /api/integrations/supabase](/api/integrations/supabase) returns `health` `ok` or `down`, the pin, and where the keys file lives. It does not return key values. Snapshot `64cfddc4` (2026-10-24) does not contain this data directory. - The service-role key is server-only. The publishable key is also kept in `/opt/supabase-platform/.env`. - The console still reads `store.json` and `cloudai-db`. Supabase is available for the app. It is not the only database. - There is no `/aiagent` route. Use `/agent#help` and `/agent#api`. ## Community Grok Bot MCPs - Template id `t_grok_bot_mcp` is "Community Grok Bot MCPs". It is in the Templates canvas, the Docker template filter, and MCP `create_computer`. - The guest recipe clones quabug/grok-bot-mcp, rthomas24/grok-bot-mcp, Kargatharaakash/grok-bot-mcp, and TheSethRose/grokbot-bridge into `/opt/grok-bot-mcps` and starts Docker Compose. quabug listens on `127.0.0.1:3851`. The other three are stdio servers with dependencies installed in the `stdio` service. No secrets are included. ## Safety - DELETE /api/computers/{id} removes the computer. Do not call it unless the user has confirmed that exact computer. - The agent view will not send DELETE until the confirm dialog is accepted. Cancel returns focus to the button that opened the dialog. - Shell commands and pointer actions change the guest. Do not run destructive commands unless the user asked for them. - Do not copy API key secrets, session tokens, or passwords into logs, pages, or prompts.