Tldraw

io.github.tldraw由 GitHub 帳號 tldraw 發布v0.1.0更新於 Oct 25, 2026

Draw and visually collaborate with your agents on tldraw's canvas.

已驗證Streamable HTTP可網頁執行開發者工具媒體與設計

概覽

AI 產生的概覽

遠端 tldraw 畫布伺服器,讓助理檢索編輯器 API 並執行 JavaScript,在共用畫布上繪製與編輯圖形。

可以做什麼
透過撰寫接收 spec 物件的 JavaScript,檢索 tldraw 編輯器 API 規格中的方法、屬性、分類與圖形類型。對即時 tldraw 畫布執行 JavaScript,未提供 canvasId 時建立新畫布。儲存與讀取畫布檢查點,包括儲存使用者編輯產生的圖形。僅應用程式內工具用於處理待執行的 exec 請求並取得畫布最新檢查點。
適用情境
當希望代理在支援 MCP app 規格的 MCP 用戶端中繪圖、製圖或在 tldraw 畫布上視覺化協作,而不只是輸出文字時使用。
執行需求
使用託管於 Cloudflare Workers 的遠端端點,或開發時使用 localhost:8787 的本機 worker。用戶端需支援 MCP app 規格並在 iframe 中呈現畫布元件。本機開發需要 Node.js 與 pnpm、建置儲存庫;ChatGPT 另需 HTTPS 的 Cloudflare 通道及 OpenAI 組織管理員權限。
安裝前請注意
exec 工具會對即時編輯器執行任意 JavaScript,程式碼可能建立、修改或刪除畫布內容。畫布狀態會儲存到伺服器端 SQLite 儲存與瀏覽器本機儲存,工作階段閒置 7 天後銷毀。Claude Desktop 自訂連接器可能需要付費方案。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Tldraw,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.tldraw%2Ftldraw/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "tldraw": {
      "type": "http",
      "url": "https://tldraw-mcp-app.tldraw.workers.dev/mcp"
    }
  }
}

README

tldraw MCP app

This is the tldraw MCP app. It exposes an interactive tldraw canvas to AI agents via the Model Context Protocol app specification, so you can work in tldraw with agents in any MCP client that supports the MCP app spec.

Architecture

The app has two parts: a server and a widget.

Server

The server runs in Cloudflare Workers via src/worker.ts, using a Durable Object (TldrawMCP) backed by SQLite for persistent checkpoint storage.

It exposes:

  • search — query the extracted Editor API spec in a sandboxed dynamic worker
  • exec — execute JavaScript against the live editor in the widget via a pending-request callback bridge
  • _exec_callback — app-only tool the widget calls to resolve a pending exec request
  • save_checkpoint / read_checkpoint — app-only tools used by the widget for checkpoint persistence

Widget

The widget is a React app (src/widget/mcp-app.tsx) that renders a full tldraw canvas inside the MCP host's iframe.

When the AI calls exec, the server creates a pending request and the widget picks it up, runs the code through a focused editor proxy (src/widget/focused/) that translates between an AI-friendly shape format (simple string IDs, flat _type shapes) and tldraw's internal TLShape/TLShapeId types, then calls _exec_callback to resolve the pending request with the result. Canvas state is checkpointed to the Durable Object's SQLite database and to the browser's local storage.

Developing

Prerequisites

The widget build depends on generated files (editor-api.json, method-map.json) that are extracted from the editor's TypeScript declarations. Before you can develop or build the mcp-app, you need to build the core packages first:

bash
# from the repo rootpnpm build

This produces the .tsbuild/ output that pnpm extract-api reads from. The build and dev scripts run extract-api automatically, so you don't need to call it separately.

Package scripts

Run all commands from apps/mcp-app.

CommandWhat it does
pnpm buildBuild the widget HTML
pnpm devBuild widget + start local Cloudflare worker (HTTP MCP on localhost:8787)
pnpm dev:tunnelBuild widget + start a stable named Cloudflare tunnel + local worker with WORKER_ORIGIN set to the tunnel URL
pnpm run deployBuild widget + deploy the Cloudflare worker to production

pnpm dev:tunnel requires the cloudflared CLI to be installed on your machine and a one-time cloudflared tunnel login. It serves a stable per-user hostname (<user>-mcp-app-dev.tldraw.xyz) via a named tunnel, so the URL you register in hosted MCP clients stays the same across runs instead of changing every time. The user slug defaults to whoami; override it (or the zone/port) with MCP_TUNNEL_USER, MCP_TUNNEL_ZONE, and PORT. The zone must be a Cloudflare-hosted zone (tldraw.xyz is; tldraw.dev/tldraw.com are on Vercel and won't work).

The worker defaults to production-safe behavior in wrangler.toml, including setting MCP_IS_DEV="false". Local HTTP dev scripts override that with MCP_IS_DEV=true so local Claude/ChatGPT connectors suppress ui.domain while production deployments keep it enabled.

Cursor setup

Add these two servers in ~/.cursor/mcp.json:

json
{	"mcpServers": {		"tldraw": {			"transport": "http",			"url": "https://tldraw-mcp-app.tldraw.workers.dev/mcp"		},		"tldraw-local": {			"command": "npx",			"args": ["-y", "mcp-remote", "http://127.0.0.1:8787/mcp"]		}	}}

Claude Desktop local setup

For local Claude Desktop development, use claude_desktop_config.json with the local HTTP server:

json
{	"mcpServers": {		"tldraw-local": {			"command": "npx",			"args": ["-y", "mcp-remote", "http://127.0.0.1:8787/mcp"]		}	}}

Claude Desktop remote setup

If you'd like to try the remote MCP server in Claude Desktop, use the in-app connector flow rather than adding the production URL to claude_desktop_config.json.

  1. Open Claude Desktop
  2. In the sidebar, go to Customize
  3. Open Connectors
  4. Click the button to add a connector, then choose Add custom connector
  5. Give it a name such as tldraw
  6. Paste https://tldraw-mcp-app.tldraw.workers.dev/mcp as the server URL

The Add custom connector option is not available on the free plan, so you may need Max or another paid plan.

If you need Notion access in Claude Desktop, use the Notion MCP connector for that separately.

ChatGPT local dev

ChatGPT requires an HTTPS origin, so you need a Cloudflare tunnel. You must be an admin of your OpenAI org/workspace to do local dev.

First-time setup (once per machine):

  1. Run cloudflared tunnel login and choose the tldraw.xyz zone

Then, each session:

  1. Run pnpm dev:tunnel in apps/mcp-app
  2. It serves your stable hostname, e.g. https://<user>-mcp-app-dev.tldraw.xyz (the first run also creates the named tunnel and its DNS route)
  3. In ChatGPT web (not the desktop app), go to Apps and add your app using that URL
  4. You can then test in both ChatGPT web and the desktop or mobile apps

Because the hostname is stable per user, you only add the app in ChatGPT once — subsequent pnpm dev:tunnel runs reuse the same URL.

dev:tunnel automatically wires WORKER_ORIGIN to the stable tunnel URL and sets MCP_IS_DEV=true for the local worker.

Iteration loop

  1. Make code changes in apps/mcp-app
  2. Run the relevant script (dev or dev:tunnel)
  3. Disconnect and reconnect the MCP server in your client (or reload the page/app)
  4. When making widget changes, make sure to rebuild, either by running pnpm build or rerunning any of the dev scripts.

Reconnecting the server after changes is the most reliable way to pick up new code, especially when the widget HTML changes.

Session storage lifecycle

Each MCP session is a TldrawMCP Durable Object. It keeps up to MAX_CHECKPOINTS (50) canvas snapshots and destroys itself after IDLE_TTL_MS (7 days) without a checkpoint save — a schedule armed in init() and re-armed on every check.

Contact

Find us on Twitter/X at @tldraw.

Community

Have questions, comments or feedback? Join our discord. For the latest news and release notes, visit tldraw.dev.

來源:apps/mcp-app/README.md,提交 a0cd8f2

工具

6

exec

Execute Code

Execute JavaScript code on a tldraw canvas. The code runs in the widget with access to the live `editor` instance, helper functions, and normal js. Use the `search` tool first to discover available Editor methods and shape types. Each canvas has a unique `canvasId`. Omit `canvasId` to create a new blank canvas. To edit an existing canvas, pass the `canvasId` that was returned by a previous exec call. Shapes and text grow depending on the amount of text they have. Use clever scripting to ensure there are no unintended overlaps. Examples: - Create a rectangle: editor.createShape({ _type: 'rectangle', shapeId: 'box1', x: 200, y: 120, w: 320, h: 180, text: 'Hello' }) - Connect shapes with an arrow: editor.createShape({ _type: 'arrow', shapeId: 'a1', fromId: 'box1', toId: 'box2', x1: 0, y1: 0, x2: 100, y2: 0 }) - Select and zoom: editor.select('box1'); editor.zoomToSelection() - Read shapes: return editor.getCurrentPageShapes() - Distribute evenly: editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal') - Box around shapes: boxShapes(['box1', 'box2'], { text: 'Group label', color: 'blue' }) - Stack shapes dynamically: editor.createShape({ _type: 'rectangle', shapeId: 'a', x: 0, y: 0, w: 300, h: 200, text: 'First box\nwith wrapping text' }); const bounds = editor.getShapePageBounds('a'); editor.createShape({ _type: 'rectangle', shapeId: 'b', x: 0, y: bounds.maxY + 20, w: 300, h: 200, text: 'Below first' })

輸入參數code必填canvasId

_exec_callback

Exec Callback

App-only: widget calls this to resolve a pending exec request.

輸入參數errorresultchannel必填execKey

_get_canvas_state

Get Canvas State

App-only: get the latest checkpoint for a canvas by its canvasId.

輸入參數canvasId必填

read_checkpoint

Read Checkpoint

App-only: read shapes from a checkpoint by ID.

輸入參數checkpointId必填

save_checkpoint

Save Checkpoint

App-only: save shapes to a checkpoint (from user edits). shapesJson and assetsJson must be JSON array strings.

輸入參數canvasIdassetsJsonshapesJson必填bindingsJsoncheckpointId必填

版本歷史

1
  1. v0.1.0最新Sep 16, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

    請在儲存庫或註冊中心條目中宣告授權條款。