Unpaged
What is Unpaged?
What it can do
- Document Create: Start a new whiteboard — for a plan the team should review, an architecture to show in a design review, research to map, decisions to keep. Returns the document with `rootNodeId` (the
- Document Get: Read a whole whiteboard — every canvas (node) and every element on it — to understand or extend it before editing, or to answer questions about what is on it.
- Document List: Find the user's whiteboards by title — the first call when they mention 'the roadmap board', 'the architecture board' or 'that plan we made': lists documents you own or that were shared
What data it sees
Do you need an account
No: the server works without sign-in
What is Unpaged?
Unpaged is a whiteboard where any shape can open into another canvas, so a document goes from overview to detail without clutter. This hosted MCP server lets your AI agent create and edit those documents as you, over per-user OAuth. What it draws appears live for anyone viewing the canvas.
See a document Claude made through this server, no signup: demo
What your agent can do
- Documents: create, list, read, update, delete; make public or invite people by email; file into folders
- Canvases: create nested canvases (empty or with content), read, update, delete
- Elements: rectangles, ellipses, triangles, diamonds, hexagons, lines, connectors, curves, block arrows, freehand pen strokes, tables, checklists, UML shapes, and Markdown text with code blocks and Mermaid diagrams, one at a time or in batches
- Templates: browse and clone
- Comments: read open threads, comment, reply, resolve, reopen
- @agent comments: a listener key lets your agent pick up comments addressed to it on a canvas
Connect
Server URL: https://mcp.unpaged.io/mcp (Streamable HTTP, OAuth 2.1). Setup guides for Claude, Claude Code, Codex, ChatGPT, Cursor and VS Code: https://unpaged.io/mcp. Any client that supports OAuth with dynamic client registration works.
Pricing
Free: 5 document creations per account, up to 50 canvases per document you own, 5 collaborators per document. Premium ($10/month or $100/year) removes the document and canvas limits and allows 50 collaborators.
How to connect
How to connect Unpaged to Claude
The server address to paste into Claude settings:
https://unpaged--unpaged.run.tools
- Open Claude (claude.ai or the desktop app).
- Go to Settings → Connectors.
- Click Add custom connector.
- Paste the server address copied below into Remote MCP server URL and click Add.
- In a chat, click + → Connectors and switch the new connector on.
Custom connectors are available on Free, Pro, Max, Team and Enterprise plans (Free is limited to one). On Team and Enterprise an organization Owner adds the connector first under Organization settings → Connectors.
Authorization
After you click Add, a sign-in window for the service opens. Sign in with your own account and approve access. Claude never sees your password.
How to connect Unpaged to ChatGPT
The server address to paste into ChatGPT settings:
https://unpaged--unpaged.run.tools
- Open ChatGPT in a browser (chatgpt.com). A Plus, Pro, Business, Enterprise or Edu plan is required.
- Turn on developer mode once: Settings → Apps → Advanced settings → Developer mode.
- Open Settings → Connectors and click Create.
- Fill in the form: Name (anything), Description (one line about what the service does), MCP server URL (copy it below).
- Under Authentication choose OAuth if the service requires sign-in, otherwise None. Click Create.
- In a new chat open + → Apps/Connectors and enable the connector.
OpenAI has renamed this section before (Connectors → Apps/Plugins). If the label differs, search settings for "developer mode". On Business/Enterprise workspaces an admin must allow custom connectors first.
Authorization
On first use ChatGPT opens the service's sign-in window. Sign in and approve access.
How to connect Unpaged to Cursor
The server address to paste into Cursor settings:
https://unpaged--unpaged.run.tools
Fastest: click Open in Cursor below and confirm the prompt.
Manually:
- In Cursor open Settings → Cursor Settings → MCP and click Add new global MCP server.
- Paste the JSON copied below into
~/.cursor/mcp.json(per project:.cursor/mcp.jsonin the repo root). - Save the file. The server appears in the MCP list; authorize it there if asked.
Authorization
If the service needs sign-in, an authorize button appears next to the server in the MCP list.
Server tool list (46)
Raw names from tools/list. Only developers need these.
| document_create | Start a new whiteboard — for a plan the team should review, an architecture to show in a design review, research to map, decisions to keep. Returns the document with `rootNodeId` (the first canvas to draw on, e.g. with batch_create_elements) and the id for the link to hand back (the /document/<id>/edit page on this server's web app). Optionally file it in a library folder: `folder` (a name, created if missing) or `folderId` (an existing id, or the reserved `visual-plans` created on demand — race-free, the way to file plan boards). Filing is best-effort: if the folder cannot be resolved the document is still created unfiled and the result carries `folderWarning`. |
| document_get | Read a whole whiteboard — every canvas (node) and every element on it — to understand or extend it before editing, or to answer questions about what is on it. |
| document_list | Find the user's whiteboards by title — the first call when they mention 'the roadmap board', 'the architecture board' or 'that plan we made': lists documents you own or that were shared with you, with ids, titles and folders. Owned documents carry `folderId` and the folder's display name as `folder` (null when unfiled). |
| document_update | Rename a whiteboard, make it PUBLIC (isPublic: true — anyone with its /share/<id> link on this server's web app can view it without an account: the answer to 'give me a link I can send'; find the board with document_list first), or move it to a folder: `folder` (a name, created if missing) or `folderId` (existing or reserved); pass null in either to unfile. |
| document_delete | Delete a document permanently |
| document_share | Invite people to a whiteboard you OWN, by email — 'let Maria edit it', 'share it with the team': everyone in `emails` gets view access; anyone also listed in `editorEmails` gets edit (live-coediting) access. You can only share documents you own. For a link that needs no account, use document_update with isPublic instead. |
| folder_list | List your document-library folders with the number of documents in each. Folders are yours alone; membership is the document's folderId (see document_list). The reserved folder id 'visual-plans' is created on demand by document_create({ folderId: 'visual-plans' }). |
| folder_create | Create a folder by name, or return the existing one when you already have a folder with that name (names are unique per user, case-insensitive). Prefer document_create's `folder` / `folderId` when the goal is to file a document. |
| folder_rename | Rename one of your folders. The reserved 'visual-plans' folder can be renamed too — its id, not its name, is what the plan plugin files into. |
| folder_delete | Delete a folder. Its documents are NOT deleted — they move to Unfiled first, then the folder record is removed. A reserved folder is recreated the next time something files into it. |
| node_create | Add an empty canvas (a node) inside a whiteboard — one canvas per phase, subsystem or topic. Prefer node_create_with_elements to draw it in one call. |
| node_create_with_id | Create a node with a specific ID (useful for pre-linking) |
| node_create_with_elements | Add a canvas inside a whiteboard with its whole diagram drawn in one atomic call — one canvas per phase, subsystem or topic. Whiteboards nest: put a box on the parent canvas with isLink and linkTarget = this node's id so people click through. More efficient than creating a node then adding elements separately. All elements are validated before anything is created (all or nothing). Supported types: rectangle, text, connector, triangle, diamond, hexagon, ellipse, line, bezier-curve, block-arrow, freehand, table, checklist, uml-class, uml-interface, uml-component, uml-package, uml-artifact, uml-note. |
| node_get | Get a node with its elements |
| node_list | List the canvases (nodes) of a whiteboard — ids and titles — to find where something lives. |
| node_update | Rename a canvas or change its description, size or background colour. |
| node_delete | Delete a node permanently |
| element_create | Draw one shape on a canvas — a box, connector, table, checklist, note or text. Supported types: rectangle, text, connector, triangle, diamond, hexagon, ellipse, line, bezier-curve, block-arrow, freehand, table, checklist, uml-class, uml-interface, uml-component, uml-package, uml-artifact, uml-note.. Pass the full element object matching the type's schema (e.g., {type: "rectangle", x: 100, y: 100, width: 200, height: 100, fillColor: "#FF5733"}). |
| element_get | Get an element by ID |
| element_list | List every shape on a canvas, each with its revision token for safe edits. |
| element_update | Move, resize, restyle or rewrite one shape — its text, colours, geometry, table cells or checklist items. |
| element_delete | Delete an element permanently |
| table_update_cell | Replace exactly ONE table cell, addressed by 0-indexed row and column (row 0 is the header by convention). Works on the table's CURRENT state inside a transaction, so it cannot clobber concurrent edits and needs no revision token — prefer it over element_update when editing a cell of a board a human may also be editing. Cell content is CommonMark Markdown. |
| table_append_row | Append one row to a table. Values are padded/truncated to the table's CURRENT column count, and the element height grows proportionally — no follow-up geometry write needed. Runs on current state in a transaction: safe under concurrent edits, no revision token. Rejected at the 20-row cap and on locked tables. |
| checklist_toggle_item | Set one checklist item's checked state by its stable item id (ids ship in every element read). Omit `checked` to toggle. Touches nothing but that item's checked flag — safe under concurrent edits, no revision token. |
| batch_create_elements | Draw many shapes on a canvas at once — boxes, connectors, tables, checklists, notes, text — the fast, atomic way to lay out a diagram or a plan. All elements are validated before any are created. Supported types: rectangle, text, connector, triangle, diamond, hexagon, ellipse, line, bezier-curve, block-arrow, freehand, table, checklist, uml-class, uml-interface, uml-component, uml-package, uml-artifact, uml-note. |
| batch_update_elements | Move, restyle or rewrite many shapes at once, atomically — for restructuring a canvas after feedback. |
| batch_delete_elements | Delete multiple elements atomically |
| template_list | Browse starting points: list the templates that can be cloned into a new whiteboard. Admins see all templates (including unpublished); regular users see only published templates. |
| template_get | Get a template with all its nodes and elements |
| template_clone | Start a whiteboard from a template — clone it into a new document owned by the current user (counts toward the user's document-creation allowance) |
| template_create | Create a new template document with a root node (requires admin) |
| template_update | Update a template's title (requires admin) |
| template_delete | Delete a template permanently (requires admin) |
| template_publish | Publish a template, making it visible to all users (requires admin) |
| template_unpublish | Unpublish a template, hiding it from regular users (requires admin) |
| welcome_template_set | Designate a template as the auto-seeded welcome doc for new accounts. Admin-only. Validates that the target is a real template with rootNodeId, schemaVersion, and at most 50 nodes. Does not require the template to be published. |
| welcome_template_clear | Clear the designated welcome template. New signups will not be auto-seeded until a new welcome template is set. Admin-only. |
| comments_list_unresolved | Did anyone leave feedback? List every open comment thread on a whiteboard (by its id — document_list first when the user names the board), with the element each one concerns, so you can act without re-reading the board. Threads where someone wrote @agent are addressed to you (mentionsAgent: true) — the usual sweep is: read these, act on the board, comment_reply with what you changed, and leave the thread open (resolving is the human's call). A thread whose last message has actor: 'agent' has already been swept — skip it unless a human replied after, or the thread carries reopened: true (a human reopened it after that reply) or editedAfterLastReply: true (a human revised a message after that reply): either flag means the feedback is NOT addressed. Agent messages carry the delegating human's authorName, so actor is the only reliable authorship signal. |
| comment_create | Leave feedback on a whiteboard — a question, a review remark, a note for collaborators — as a comment thread. Pin it to an element by elementId (the pin follows the element), or to a point by giving BOTH x and y, or leave it unanchored. |
| comment_reply | Answer someone's comment on a whiteboard — 'tell Maria the box is moved' — or report what you changed on the board. Needs the board's id and the thread's id: document_list, then comments_list_unresolved, then this. Replying is the end of a sweep: leave the thread open for the human to resolve. |
| comment_resolve | Mark a comment thread resolved. Resolving is normally the human's call (resolved threads disappear from the canvas) — call this only when the user explicitly asked you to resolve the thread; after acting on feedback, reply and leave the thread open instead. |
| comment_reopen | Reopen a resolved comment thread when the feedback was not actually addressed. |
| agent_listener_key_create | Receive @agent notifications for ONE board. Mint a receive-only listener key bound to its documentId after proving you can open the board. Installed plugins use pollUrl with Authorization: Bearer <key> and short HTTP polls every 30 seconds, or every 60 seconds after an idle hour; return to 30 seconds after a new event. Responses contain {events:[...],nextCursor} and must be deduplicated by id. Continue the bounded scan with the returned cursor query parameter; null restarts it. The key is shown ONCE: store it locally, never in a URL. HTTP 401 means invalid or revoked, 409 means a newer key took over this board (STOP), and 429/503/network failures retry the same key. One key hears one board; different boards work independently. Revoke with agent_listener_key_revoke. |
| agent_listener_keys_list | List your live listener keys (id, label, board, created, last seen) — never the key material. A key with documentId null predates per-board keys: the polling endpoint refuses it, revoke it. |
| agent_listener_key_revoke | Revoke one of your listener keys. Polls authenticated after revocation are refused with HTTP 401, so the listener stops on its next poll without reminting automatically. |