apps/mcp-app/README.md
This is the tldraw MCP app. It exposes an interactive tldraw canvas to AI agents via the Model Context Protocol, so agents in Cursor, Claude Desktop, ChatGPT, and VS Code can draw diagrams and shapes on a canvas during a conversation.
The app has two parts: a server and a widget.
The server registers MCP tools (create_shapes, update_shapes, delete_shapes, diagram_drawing_read_me) and serves the widget HTML as an MCP App resource.
There are two entry points:
main.ts — Node.js stdio transport, for local clients like Claude Desktop and Cursorsrc/worker.ts — Cloudflare Workers with a Durable Object (TldrawMCP) backed by SQLite for persistent checkpoint storageBoth entry points share tool registration logic in src/register-tools.ts.
The widget is a React app (src/widget/mcp-app.tsx) that renders a full tldraw canvas inside the MCP host's iframe. Vite bundles it into a single HTML file (dist/mcp-app.html) using vite-plugin-singlefile, which the server injects bootstrap data into before serving.
The widget handles streaming previews (shapes appear as the model streams tool arguments), checkpoint persistence to localStorage, and syncing state back to the server.
Run all commands from apps/mcp-app.
| Command | What it does |
|---|---|
yarn build | Build the widget HTML |
yarn dev | Build widget + start local Cloudflare worker (HTTP MCP on localhost:8787) |
yarn dev:stdio | Start a local stdio MCP server |
yarn dev:tunnel | Start a Cloudflare tunnel + local worker with WORKER_ORIGIN set to the tunnel URL |
yarn deploy | Build widget + deploy the Cloudflare worker to production |
yarn dev:tunnel requires the cloudflared CLI to be installed on your machine.
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.
Add up to three servers in ~/.cursor/mcp.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"]
},
"tldraw-local-stdio": {
"command": "yarn",
"args": [
"--cwd",
"<path-to-tldraw-repo>/tldraw/apps/mcp-app",
"run",
"-s",
"tsx",
"main.ts",
"--stdio"
]
}
}
}
--cwd ensures Cursor launches in the app folder. -s stops yarn from writing non-JSON noise to stdout, which breaks the stdio transport.
Update ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"tldraw": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://tldraw-mcp-app.tldraw.workers.dev/mcp"]
},
"tldraw-local": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://127.0.0.1:8787/mcp"]
},
"tldraw-local-stdio": {
"command": "yarn",
"args": [
"--cwd",
"<path-to-tldraw-repo>/tldraw/apps/mcp-app",
"run",
"-s",
"tsx",
"main.ts",
"--stdio"
]
}
}
}
ChatGPT requires an HTTPS origin, so you need a Cloudflare tunnel. You must be a workspace admin.
yarn dev:tunnel in apps/mcp-apphttps://...trycloudflare.com tunnel URLdev:tunnel automatically wires WORKER_ORIGIN to the tunnel URL and sets MCP_IS_DEV=true for the local worker.
MCP_AUTH_TOKEN controls bearer auth for the HTTP worker. If it is unset, the worker accepts unauthenticated local requests.MCP_IS_DEV controls local-only widget behavior, such as suppressing ui.domain for local HTTP/tunnel connectors.These flags are intentionally separate so auth configuration does not change widget-domain behavior.
apps/mcp-appdev, dev:stdio, or dev:tunnel)yarn dev does this automaticallyReconnecting the server after changes is the most reliable way to pick up new code, especially when the widget HTML changes.
The code in this folder is Copyright (c) 2024-present tldraw Inc. The tldraw SDK is provided under the tldraw license.
Copyright (c) 2024-present tldraw Inc. The tldraw name and logo are trademarks of tldraw. Please see our trademark guidelines for info on acceptable usage.
Find us on Twitter/X at @tldraw.
Have questions, comments or feedback? Join our discord. For the latest news and release notes, visit tldraw.dev.