Skip to main content
Glama

tldraw-page-mcp

Unofficial. Not affiliated with, endorsed by, or officially associated with tldraw, Inc. tldraw is a trademark of tldraw, Inc. This project relies on an undocumented global on tldraw.com (window.editor) and may stop working whenever tldraw.com changes.

An MCP server that lets an agent draw on a real tldraw.com board. It's a fork of the idea behind tldraw's official MCP app: the same exec tool, the same focused shape format and helpers, but pointed at the window.editor that tldraw.com exposes on every file page, instead of a canvas widget inside the chat. Edits land on the shared board, so everyone who has it open sees them.

How it works

MCP client ──stdio──▶ src/server.mjs ──DevTools Protocol──▶ Chrome tab on tldraw.com/f/…
                                                              └─ dist/page-runtime.js
                                                                   wraps window.editor
  • The server finds or launches a Chrome with remote debugging, using its own profile (~/.tldraw-page-mcp/chrome-profile), and keeps one tab on the board.

  • It injects dist/page-runtime.js into that tab: tldraw's focused editor proxy and exec helpers (copied from apps/mcp-app), wrapped around the page's own editor.

  • exec sends the model's code to the tab through Chrome DevTools (Runtime.evaluate), the same way code runs from the browser console. The official widget loads code as a blob-URL module, which tldraw.com's page doesn't allow, so here it arrives through DevTools instead.

Related MCP server: Excalidraw MCP Server

Tools

Tool

Does

open_board(url)

Opens a tldraw.com file in the controlled Chrome, or switches to it

exec(code)

Runs JavaScript with editor (focused proxy), rawEditor (tldraw.com's editor) and the helpers in scope

get_image(scope?, shapeIds?)

A PNG of what's in view, the whole page, the selection, or given shapes

Setup

npm install
npm run build
claude mcp add tldraw-page -- node "$PWD/src/server.mjs"

The first open_board opens a Chrome window with its own profile. Link-shared boards work as a guest; for a private board, sign in to tldraw.com once in that window (the profile keeps it). Environment knobs: TLDRAW_CDP_PORT (default 9333), TLDRAW_CHROME (the Chrome binary), TLDRAW_CHROME_PROFILE, and TLDRAW_HEADLESS=1 (see below).

Try it without an MCP client:

npm run smoke -- "https://www.tldraw.com/f/<file-id>" info

Is window.editor enough?

Tested on 2026-10-18 against a link-shared board, tldraw.com running a tldraw 5.x editor.

  • Editing: yes. Every Editor method the official app's tools rely on exists (create, update, delete, bounds, select, group, align and distribute, zoom, pages, undo), and the focused proxy works unchanged on top of it. A note created with exec showed up in a separate browser's fresh load, at the same position, and its delete synced too.

  • Images: yes. editor.putExternalContent uploads files to tldraw.com's asset store (tldrawusercontent.com) like a drag-and-drop does (tested by hand through Chrome; there's no upload tool here yet, since the server would have to pass the file bytes into the page), and editor.toImage exports the PNGs behind get_image.

  • Running the model's code: through DevTools. tldraw.com's page doesn't let scripts evaluate code (its content security policy has no 'unsafe-eval' and no blob: scripts), so code reaches the editor the way it does from the browser console: through DevTools (this server) or an extension using chrome.debugger. A page script could instead take a fixed set of JSON commands over a local WebSocket.

  • Syncing: edits sync from both a normal and a headless Chrome. The catch: a write the editor rejects (a validation error, such as an unknown _type) puts tldraw.com into its "Something went wrong" state, and from then on that tab stops syncing while window.editor keeps working locally, so later calls look fine and are lost. Only a reload clears it. The server guards against this (below). Edits also need a moment to go out: exec waits 600 ms before returning, and a backgrounded tab that's reloaded right after an edit can drop it.

  • Stability: window.editor on tldraw.com isn't a documented API. It's there today (tldraw's own debugging hooks sit beside it), but tldraw could rename or remove it without notice.

Keeping the board in sync

A write tldraw.com's store rejects marks the store as possibly corrupted, and tldraw.com stops syncing that tab. So page/guard.ts:

  • refuses an unknown focused _type with the list of real ones

  • runs tldraw's own record validators on every shape create and update, from the focused editor, rawEditor and the helpers, and refuses a bad one before the store sees it

  • checks editor.store.isPossiblyCorrupted() and editor.getCrashingError() before and after each call

If a tab has crashed anyway (code that writes through the page's unguarded window.editor can still do it), the server reloads it from tldraw.com and tells the agent its changes may be lost and to re-read the board. open_board and get_image reload a crashed tab too.

Staying faithful

tldraw's MCP app and tldraw.com both change without notice. AUDIT.md is the recipe for checking the fork against both: npm run faithfulness for upstream drift, --board <url> for tldraw.com's live contract, and --agents for a set of tasks run by fresh agents.

Differences from the official app

  • No canvas widget or checkpoints: the board itself is the state.

  • No search tool yet. The official one serves an Editor API spec extracted with a TypeScript 7 build of the tldraw monorepo; here the model can introspect with exec instead.

  • page/method-map.json is generated from the published @tldraw/editor types (scripts/gen-method-map.mjs) with the official rules.

  • One fix in the proxy: methods mapped as returning this only return the proxy when the real method returned the editor. Upstream, editor.getShapePageBounds('a') comes back as the editor instead of its bounds.

  • The page runtime bundles its own copy of tldraw's helpers (about 1.9 MB, injected once per page load). It could be trimmed to the few utilities it uses.

Using it responsibly

  • Use it on boards you can already edit. The server drives your own browser, signed in as you or as a guest, and its edits sync like yours.

  • Your use of tldraw.com is governed by its Terms of Service.

  • Exporting a board to an AI provider shares its contents. Ask before doing that with a board other people work on.

Licenses and credits

This project's own code is MIT (LICENSE).

page/focused/ and page/helpers.ts come from tldraw's apps/mcp-app, which is MIT licensed (LICENSE.tldraw-mcp-app.md).

The tldraw npm package it builds against is not MIT: it's under the tldraw license. npm run build bundles parts of it into dist/page-runtime.js on your machine. That bundle isn't committed or distributed here, and using it is subject to tldraw's license.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to programmatically control a live Excalidraw canvas through element-level CRUD operations and real-time synchronization. It allows agents to iteratively build, inspect, and refine diagrams while providing visual feedback via screenshots and scene descriptions.
    1,236 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude to draw on a live tldraw canvas from prompts, with real-time visualization in a browser. Provides tools for creating, updating, deleting shapes and retrieving canvas state.
    14
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables remote agents to control tldraw Desktop's Canvas API, manage documents, scripts, assets, and take screenshots.
    1
    -