About/Developers

For developers & AI agents

Put an AI on the same live board.

cnvs.app speaks the Model Context Protocol and a plain REST API. Claude Desktop, Claude Code and any MCP-capable client can read and edit the same whiteboard or kanban board your teammates are looking at — in real time, with no API key.

No API key JSON-RPC 2.0 REST + MCP Live subscribe

01 — Protocol

One endpoint, JSON-RPC 2.0.

Strokes and text nodes an AI adds appear instantly for everyone connected, tagged with an ai:<name> author label. The MCP server is a single HTTPS endpoint that accepts JSON-RPC 2.0 over POST:

https://cnvs.app/mcp

No API key, no OAuth. The board ID is the key — anyone who knows the board ID (the bit after the # in the URL) can read and write to that board, just like any human visitor. Keep your board URLs private if the content is sensitive.

Add to Claude Desktop

Open Settings → Developer → Edit Config and add a streamable HTTP server entry:

{
  "mcpServers": {
    "cnvs": {
      "type": "http",
      "url": "https://cnvs.app/mcp"
    }
  }
}

Restart Claude Desktop. Ask the model to “open the cnvs board at https://cnvs.app/#<your-id> and add a sticky with today's agenda” and the note will land on the live canvas.

Add to Claude Code

claude mcp add --transport http cnvs https://cnvs.app/mcp

02 — Tools & resources

What an agent can do.

Tools exposed

open_board

Resolve a cnvs URL or ID; creates the board if it doesn't exist yet.

get_board

Full structured snapshot — ids, coordinates, text content — for precise edits.

get_preview

Schematic SVG render (a few kB) so the model can see the layout without blowing up context.

add_text

Create or update a text node. Supports Markdown, Mermaid diagrams, sticky-note style.

add_link

Drop a URL capsule onto the canvas.

add_image

Place a raster or SVG image from a data URL (capped at ~900 kB).

draw_stroke

Freehand stroke from a list of world-coordinate points.

move

Reposition an existing text node by id.

erase

Delete a text, stroke or image by id.

wait_for_update

Long-poll: block until the next edit lands (debounced ~3 s), then return — for turn-based loops on clients that don't surface resources/subscribe pushes to the model.

set_board_mode

Switch an empty board to draw or todo (kanban). Immutable once the board has content.

create_column / update_column / delete_column

Manage kanban columns — title, sort, lane and colour.

create_task / update_task / move_task / delete_task

Manage kanban cards — name, description, due date, priority, assignee — across columns.

list_tasks

Read a whole todo board in one call → { mode, columns, tasks }.

Resources exposed

cnvs://board/{id}/state.json

Full JSON snapshot — best for editing. Image base64 payloads are elided. Supports resources/subscribe.

cnvs://board/{id}/preview.svg

Compact SVG preview — best for visual orientation. Tiny pixelated image thumbnails embedded when available.

cnvs://board/{id}/tasks.json

Kanban state of a todo board — { mode, columns, tasks }. Subscribable, so AI agents react to card moves and edits in real time.

03 — Realtime

Live notifications & push-to-model.

Live notifications

Standard MCP Streamable-HTTP session flow: initialize returns an Mcp-Session-Id header, the client opens GET /mcp with Accept: text/event-stream to hold the notification stream, and resources/subscribe returns a plain JSON result. The server then emits notifications/resources/updated onto the GET stream whenever anyone (human or AI) edits a subscribed board — aggregated into a single event ~3 seconds after activity settles, so a burst of strokes or typing produces one wake-up rather than dozens. Claude Desktop and Claude Code pick this up automatically once the capabilities.resources.subscribe capability is advertised. Same live sync humans see in the browser — see real-time collaboration.

Push-to-model — cnvs-whiteboard + mcp-listen

Most chat-UI MCP clients consume the push inside their session cache but never re-invoke the model on it — so the AI stays blind to edits until the user prompts again. Two Agent Skills close this loop: /cnvs-whiteboard/SKILL.md (primary skill that owns the cnvs.app read/write workflow) and /mcp-listen/SKILL.md (generic listener — runs a tiny @modelcontextprotocol/sdk client under Claude Code's Monitor tool, so each push becomes a real in-chat notification that triggers a fresh model turn). No polling, and an optional author filter (--ignore-author-prefix "ai:") stops the AI from waking itself on its own writes. Install both:

mkdir -p ~/.claude/skills/mcp-listen && cd ~/.claude/skills/mcp-listen
curl -O https://cnvs.app/mcp-listen/SKILL.md \
     -O https://cnvs.app/mcp-listen/package.json \
     --create-dirs -o scripts/listen.mjs https://cnvs.app/mcp-listen/scripts/listen.mjs
npm install

mkdir -p ~/.claude/skills/cnvs-whiteboard && cd ~/.claude/skills/cnvs-whiteboard
curl -O https://cnvs.app/cnvs-whiteboard/SKILL.md

Skill sources: cnvs-whiteboard/SKILL.md · mcp-listen/SKILL.md · listen.mjs · package.json. mcp-listen works against any Streamable-HTTP MCP server with resources/subscribe, not just cnvs.app.

Example call

curl -X POST https://cnvs.app/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "add_text",
      "arguments": {
        "board_id": "<your-board-id>",
        "x": 200, "y": 160,
        "content": "Hello from MCP!",
        "postit": true
      }
    }
  }'

04 — Limits & safety

Quotas, the same for everyone.

Quotas are applied equally to browser, REST and MCP clients — an AI agent gets exactly the same surface and the same ceilings as a human in a tab.

  • Rate limited to 60 requests per 10 seconds per board, enforced on all transports. REST and MCP share a Worker-isolate-local bucket; browser WebSockets are rate-limited independently inside the per-board Durable Object — see /quotas.json for live values.
  • Single-request body cap: 5 MiB (REST and MCP), enforced both via Content-Length and during the streaming read.
  • CORS: Access-Control-Allow-Origin: * on every public HTTP endpoint so browser-based clients can GET snapshots and POST mutations cross-origin without a proxy.
  • Per-board quotas: 500 text nodes (max 100 000 chars each), 50 images (total ≤ 10 MB), 2000 strokes. Exceeding returns HTTP 413 / MCP -32000 with a human-readable message.
  • Every mutation is attributed with an author tag (ai:<label> for AI, user:<uuid> for humans) so the origin of each item is preserved.
  • Non-existent board IDs return a JSON-RPC error — only open_board creates new boards.