lksrz avatar

cnvs.app

lksrz/cnvs-whiteboard-skills

Zero-auth collaborative whiteboard that lets AI agents and humans draw on the same canvas in real time. Exposes ten MCP tools for creating boards, adding text, links, images, strokes, and Mermaid diagrams, plus moving and erasing elements. Supports resource subscriptions over SSE so agents get notified when humans edit the board, with debounced updates after activity settles. Ships with two Agent Skills: one that teaches Claude how to diagram and react to changes, another that pumps MCP push notifications into Claude Code's Monitor tool. Falls back to REST for runtimes without MCP support. Each board ID is the access key, no signup required.

tools
25
transport
HTTP
last updated
Jun 15, 2026

Install

From registry metadata
$ npx add-mcp https://cnvs.app/mcp --name whiteboard

Run in your terminal. add-mcp asks which agents to add it to (Claude Code, Codex, Cursor and more). Add -g to install it for every project.

Review the command, arguments and environment values before installing. MCP servers run with your local permissions.

Other ways

Claude Code

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

Run in your terminal. Add --scope user to make it available in every project.

Tools

Verified live · 25 tools

Verified live against the running server on Nov 6, 2026.

open_boardALWAYS call this first when given a board URL or ID. Resolves the canonical board id and auto-creates the board row if it does not exist yet. Returns a summary (item counts, authors). After this, call BOTH `get_preview` and `get_board` before editing so you can see the layout...2 params

ALWAYS call this first when given a board URL or ID. Resolves the canonical board id and auto-creates the board row if it does not exist yet. Returns a summary (item counts, authors). After this, call BOTH `get_preview` and `get_board` before editing so you can see the layout...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
url_or_id*string
Full board URL (https://cnvs.app/#<id>) or bare UUID.
create_boardCreate a fresh board in ONE call — optionally pre-filled with content, auto-laid-out, and/or PIN-locked at create time. Mirrors the extended `POST /api/boards` REST body exactly (same server-side implementation). With no arguments it returns a blank draw board; `mode: 'todo'`...6 params

Create a fresh board in ONE call — optionally pre-filled with content, auto-laid-out, and/or PIN-locked at create time. Mirrors the extended `POST /api/boards` REST body exactly (same server-side implementation). With no arguments it returns a blank draw board; `mode: 'todo'`...

Parameters* required
authorstring
Author tag stamped on every created item (e.g. 'ai:plai'). Defaults to 'ai:import'.
autolayoutboolean
Draw mode only: fill x/y for texts/images that omit them (deterministic masonry). Without it, items missing coordinates are rejected. No-op in todo mode.
contentobject
Initial board content, applied atomically at create time. Draw mode: `texts` [{x?, y?, content, color?, width?, postit?, diagram?, kind?, author?, sourceId?}], `lines` [{points, color?, anchors?, a...
lockstring
PIN-lock the board atomically at create time; the plaintext key is returned ONCE as `access_key`.one of write · all
modestring
Board mode. Defaults to 'draw'.one of draw · todo
templatestring
Starter column set when mode is 'todo' and content.columns is empty/absent. Defaults to 'kanban'.one of kanban · sprint · bugs
get_boardFull structured JSON state of a board: texts (id, x, y, content, color, width, postit, author), strokes (id, points, color, author), images (id, x, y, width, height, dataUrl, thumbDataUrl, author; heavy base64 >8 kB elided to dataUrl:null, tiny images inlined). Use this for EX...2 params

Full structured JSON state of a board: texts (id, x, y, content, color, width, postit, author), strokes (id, points, color, author), images (id, x, y, width, height, dataUrl, thumbDataUrl, author; heavy base64 >8 kB elided to dataUrl:null, tiny images inlined). Use this for EX...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
get_previewCompact schematic SVG render of the board (typically a few kB even for dense boards). Returns both an image/svg+xml content block (you can SEE it) and the raw SVG text. CALL THIS any time you need to understand where things are — before placing new items, before deciding wheth...2 params

Compact schematic SVG render of the board (typically a few kB even for dense boards). Returns both an image/svg+xml content block (you can SEE it) and the raw SVG text. CALL THIS any time you need to understand where things are — before placing new items, before deciding wheth...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
add_textCreate a NEW text node, or update an existing one (pass the same `id` to overwrite content/position in place — preferred over creating a duplicate). Supports cnvs markup (Markdown-ish) and Mermaid diagrams in the content. When using Mermaid, the ENTIRE content of this text nod...11 params

Create a NEW text node, or update an existing one (pass the same `id` to overwrite content/position in place — preferred over creating a duplicate). Supports cnvs markup (Markdown-ish) and Mermaid diagrams in the content. When using Mermaid, the ENTIRE content of this text nod...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
authorstring
Author tag, defaults to ai:claude.
board_id*string
colorstring
Named ink only (no hex). Accepted (case-insensitive): 'auto'/''/'black'/omitted for theme-aware ink, or 'red', 'blue', 'green', 'orange', 'yellow', 'pink', 'purple', 'maroon', 'brown', 'gray', 'lig...
content*string
diagramboolean
Render as a framed diagram box (2px border in the text colour, centred text). Mutually exclusive with postit.
idstring
Optional stable id; generated when omitted.
postitboolean
widthnumber
Explicit width in px (160–4096).
x*number
y*number
add_linkDrop a URL capsule onto the board — rendered as a clickable pill showing the hostname. Use this instead of `add_text` when the node is just a link; the capsule styling signals clickability to humans. Same coordinate rules as `add_text` (+x right, +y down).6 params

Drop a URL capsule onto the board — rendered as a clickable pill showing the hostname. Use this instead of `add_text` when the node is just a link; the capsule styling signals clickability to humans. Same coordinate rules as `add_text` (+x right, +y down).

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
authorstring
board_id*string
url*string
x*number
y*number
add_imagePlace a raster or SVG image on the board at (x, y) with explicit width/height in board pixels. `data_url` MUST be a `data:image/(png|jpeg|gif|webp|svg+xml);base64,...` string ≤ ~900 kB; hosted URLs are not accepted. The bytes are header-checked (the leading bytes must be PNG/J...10 params

Place a raster or SVG image on the board at (x, y) with explicit width/height in board pixels. `data_url` MUST be a `data:image/(png|jpeg|gif|webp|svg+xml);base64,...` string ≤ ~900 kB; hosted URLs are not accepted. The bytes are header-checked (the leading bytes must be PNG/J...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
authorstring
board_id*string
data_url*string
height*number
idstring
thumb_data_urlstring
width*number
x*number
y*number
draw_strokeDraw a freehand stroke on the board. Use for arrows, underlines, connector lines, annotations, or simple shapes — a straight line needs two points, a rough circle wants ~20. Stroke width is fixed at 3 px; `color` is a NAME, not hex (case-insensitive): 'auto'/''/'black'/omitted...6 params

Draw a freehand stroke on the board. Use for arrows, underlines, connector lines, annotations, or simple shapes — a straight line needs two points, a rough circle wants ~20. Stroke width is fixed at 3 px; `color` is a NAME, not hex (case-insensitive): 'auto'/''/'black'/omitted...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
authorstring
board_id*string
colorstring
idstring
points*value
Points as [[x,y],...], flat [x1,y1,x2,y2,...], or a JSON string of either.
moveReposition an existing item to a new (x, y) without retyping its content. Works for every item kind: `text` and `link` set the top-left to (x, y); `line` translates every point so the stroke's bounding box top-left lands at (x, y); `image` sets the top-left like text. `kind` d...6 params

Reposition an existing item to a new (x, y) without retyping its content. Works for every item kind: `text` and `link` set the top-left to (x, y); `line` translates every point so the stroke's bounding box top-left lands at (x, y); `image` sets the top-left like text. `kind` d...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
id*string
kindstring
Item kind. Defaults to `text`.one of text · link · line · image
x*number
y*number
eraseDelete a single item by id. `kind` MUST match the item type: 'text' for text nodes, 'line' for freehand strokes, 'image' for images — the wrong kind silently targets the wrong table and is a common mistake. Get the id + type from `get_board` (texts[], lines[], images[]). There...4 params

Delete a single item by id. `kind` MUST match the item type: 'text' for text nodes, 'line' for freehand strokes, 'image' for images — the wrong kind silently targets the wrong table and is a common mistake. Get the id + type from `get_board` (texts[], lines[], images[]). There...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
id*string
kind*string
one of text · line · image
wait_for_updateLong-poll: blocks until the next edit lands on this board, then returns. WHEN TO CALL THIS: if your MCP client does NOT surface `notifications/resources/updated` events from `resources/subscribe` back to the model (most chat clients do not — they receive the SSE event but don'...3 params

Long-poll: blocks until the next edit lands on this board, then returns. WHEN TO CALL THIS: if your MCP client does NOT surface `notifications/resources/updated` events from `resources/subscribe` back to the model (most chat clients do not — they receive the SSE event but don'...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
timeout_msnumber
set_board_modeChoose whether this board is a freeform whiteboard ('draw', the default) or a kanban task board ('todo'). Mode is switchable WHENEVER the board is empty of real content: drawings (text/strokes/images) and tasks. Empty or seeded columns DON'T count (switching to 'draw' clears t...4 params

Choose whether this board is a freeform whiteboard ('draw', the default) or a kanban task board ('todo'). Mode is switchable WHENEVER the board is empty of real content: drawings (text/strokes/images) and tasks. Empty or seeded columns DON'T count (switching to 'draw' clears t...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
mode*string
Board mode.one of draw · todo
templatestring
Optional starter column template when mode is 'todo': 'kanban' (To do / In progress / Done, the default), 'sprint' (Backlog / Sprint / Review / Done), or 'bugs' (Triage / Confirmed / In progress /...
create_columnAdd a kanban column (swimlane) to a 'todo' board. Generates and returns a stable column id. `sort` is a float ordering key (ascending); omit to default to 0. `lane` is an integer row index for multi-row layouts (defaults to 0). `color` is an optional title color ('red' / 'blue...7 params

Add a kanban column (swimlane) to a 'todo' board. Generates and returns a stable column id. `sort` is a float ordering key (ascending); omit to default to 0. `lane` is an integer row index for multi-row layouts (defaults to 0). `color` is an optional title color ('red' / 'blue...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
authorstring
Author tag, defaults to ai:claude.
board_id*string
colorstring
Title color: 'red', 'blue', 'green', or 'auto' (default).
laneinteger
Row index for multi-row layouts. Defaults to 0.
sortnumber
Float ordering key (ascending). Defaults to 0.
title*string
update_columnRename, reorder, recolor or move an existing kanban column. Requires the column `id` (from `list_tasks`). Pass `title`, `sort`, `lane` and/or `color` to change them.8 params

Rename, reorder, recolor or move an existing kanban column. Requires the column `id` (from `list_tasks`). Pass `title`, `sort`, `lane` and/or `color` to change them.

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
authorstring
Author tag, defaults to ai:claude.
board_id*string
colorstring
Title color: 'red', 'blue', 'green', or 'auto' (default).
id*string
laneinteger
Row index for multi-row layouts.
sortnumber
Float ordering key (ascending).
titlestring
delete_columnDelete a kanban column by id. Tasks in the column are removed with it. Get the id from `list_tasks`.3 params

Delete a kanban column by id. Tasks in the column are removed with it. Get the id from `list_tasks`.

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
id*string
create_taskCreate a task (card) in a column on a 'todo' board. Generates and returns a stable task id. `column_id` must reference an existing column (see `list_tasks`). `description` is free-form prose stored on the card; `priority` is one of 'H' | 'M' | 'L' (omit for none); `due_date` i...11 params

Create a task (card) in a column on a 'todo' board. Generates and returns a stable task id. `column_id` must reference an existing column (see `list_tasks`). `description` is free-form prose stored on the card; `priority` is one of 'H' | 'M' | 'L' (omit for none); `due_date` i...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
assigneestring
authorstring
Author tag, defaults to ai:claude.
board_id*string
column_id*string
descriptionstring
doneboolean
Whether the task is completed (checked off). Defaults to false.
due_datestring
ISO 8601 date.
name*string
prioritystring
High / Medium / Low. Omit for none.one of H · M · L
sortnumber
Float ordering key within the column. Defaults to 0.
update_taskUpdate an existing task by `id` (from `list_tasks`). Pass only the fields you want to change: `name`, `description`, `due_date`, `priority` ('H'|'M'|'L'), `assignee`, `done` (true once completed), `column_id` (to reassign), `sort`. To move a card between columns while setting...12 params

Update an existing task by `id` (from `list_tasks`). Pass only the fields you want to change: `name`, `description`, `due_date`, `priority` ('H'|'M'|'L'), `assignee`, `done` (true once completed), `column_id` (to reassign), `sort`. To move a card between columns while setting...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
assigneestring
authorstring
Author tag, defaults to ai:claude.
board_id*string
column_idstring
descriptionstring
doneboolean
Whether the task is completed (checked off).
due_datestring
ISO 8601 date.
id*string
namestring
prioritystring
one of H · M · L
sortnumber
move_taskMove a task to a column at a given sort position — the kanban drag-and-drop primitive. `column_id` is the destination column and `sort` its float order key (ascending) within that column.5 params

Move a task to a column at a given sort position — the kanban drag-and-drop primitive. `column_id` is the destination column and `sort` its float order key (ascending) within that column.

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
column_id*string
id*string
sort*number
delete_taskDelete a task (card) by id. Get the id from `list_tasks`.3 params

Delete a task (card) by id. Get the id from `list_tasks`.

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
id*string
list_tasksRead the full kanban state of a 'todo' board: `{ mode, columns, tasks }`, both ordered by their `sort` key (ascending). Each task carries its hot fields (name, due_date, priority, assignee, done, column_id, sort) plus an opaque `content` JSON string (holds the description). Us...2 params

Read the full kanban state of a 'todo' board: `{ mode, columns, tasks }`, both ordered by their `sort` key (ascending). Each task carries its hot fields (name, due_date, priority, assignee, done, column_id, sort) plus an opaque `content` JSON string (holds the description). Us...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
set_laneSet (or clear) the title of a kanban row (lane). Lanes group columns into horizontal swimlanes; a lane is identified by its integer `lane` index (the same index columns carry). Pass a `title` to name the row, or an empty string to clear it. Read current lane titles + the share...5 params

Set (or clear) the title of a kanban row (lane). Lanes group columns into horizontal swimlanes; a lane is identified by its integer `lane` index (the same index columns carry). Pass a `title` to name the row, or an empty string to clear it. Read current lane titles + the share...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
authorstring
Author tag, defaults to ai:claude.
board_id*string
lane*integer
Row index (>= 0).
titlestring
Row title; empty string clears it.
set_column_widthSet the shared kanban column width in pixels for a 'todo' board (all columns share one width). Clamped to [200, 480]. Read the current value as `colWidth` from `list_tasks`.3 params

Set the shared kanban column width in pixels for a 'todo' board (all columns share one width). Clamped to [200, 480]. Read the current value as `colWidth` from `list_tasks`.

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
width*number
Column width in px, clamped to [200, 480].
create_tasksBulk-create multiple task cards in one call — far cheaper than calling `create_task` N times. Pass `tasks`: an array of task objects, each with `column_id` (required) + the same fields `create_task` accepts (`name`, `description`, `due_date`, `priority`, `assignee`, `done`, `s...4 params

Bulk-create multiple task cards in one call — far cheaper than calling `create_task` N times. Pass `tasks`: an array of task objects, each with `column_id` (required) + the same fields `create_task` accepts (`name`, `description`, `due_date`, `priority`, `assignee`, `done`, `s...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
authorstring
Author tag applied to every task, defaults to ai:claude.
board_id*string
tasks*array
Array of task objects to create.
query_tasksRead tasks from a 'todo' board with server-side filtering — handy for 'what's overdue?' / 'what's assigned to X?' without pulling the whole board. All filters are optional and AND together: `assignee` (exact match), `priority` ('H'|'M'|'L'), `done` (boolean), `overdue` (true →...8 params

Read tasks from a 'todo' board with server-side filtering — handy for 'what's overdue?' / 'what's assigned to X?' without pulling the whole board. All filters are optional and AND together: `assignee` (exact match), `priority` ('H'|'M'|'L'), `done` (boolean), `overdue` (true →...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
assigneestring
Exact-match assignee filter.
board_id*string
doneboolean
due_afterstring
ISO date; due_date > this.
due_beforestring
ISO date; due_date < this.
overdueboolean
Only tasks past due and not done.
prioritystring
one of H · M · L
export_tasksExport a 'todo' board's columns + tasks as a single text document. `format` is 'markdown' (a checklist grouped by column, the default) or 'csv' (one row per task with column/name/priority/assignee/due_date/done). Returns the rendered text. Same data as the GET /api/boards/<id>...3 params

Export a 'todo' board's columns + tasks as a single text document. `format` is 'markdown' (a checklist grouped by column, the default) or 'csv' (one row per task with column/name/priority/assignee/due_date/done). Returns the rendered text. Same data as the GET /api/boards/<id>...

Parameters* required
access_keystring
8-character lowercase alphanumeric board access key when the board is locked (legacy 6-character lowercase alphanumeric keys are also accepted). Equivalent to setting the `X-Board-Key` HTTP header...
board_id*string
formatstring
Output format. Defaults to 'markdown'.one of markdown · csv

Sponsors

Readme

cnvs-whiteboard-skills

Agent Skills + MCP server discovery for cnvs.app — the free, no-signup real-time collaborative whiteboard. Any AI agent can read, write, draw, diagram, and subscribe to live human edits on a shared canvas, either through the hosted MCP server or the REST fallback.

Works with Claude Code, Claude Desktop, Cursor, OpenCode / OpenAI Codex, Aider (with MCP plugin), any other MCP-speaking client, and Hermes-family agents.

MCP Server

Endpoint: https://cnvs.app/mcp (Streamable HTTP, protocol 2025-06-18, no auth — the board ID is the access key).

Registered in the official MCP Registry as app.cnvs/whiteboard.

Capabilities


View the full README on GitHub

Details

Repository
github.com/lksrz/cnvs-whiteboard-skills
Website
cnvs.app
Transport
HTTP
Registry
MCP registry, active
Resources
3
Tools verified
Nov 6, 2026