Tldraw MCP Server
Allows Claude to create and manipulate tldraw diagrams based on natural language instructions.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Tldraw MCP ServerCreate a flowchart with steps: Start, Process, End"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Tldraw MCP Server
// rebuild after a latest change cd ~/tldraw-mcp && docker compose up -d --build
//to check whether the tool is available or not
curl -s -X POST http://127.0.0.1:3102/mcp
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream'
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
| tr ',' '\n' | grep drawArrow
This project integrates tldraw with Claude AI using the Model Context Protocol (MCP). It allows Claude to create and manipulate diagrams based on natural language instructions.
Getting Started
Prerequisites
Node.js 18+ installed
Claude Desktop installed
Visual Studio Code (recommended)
Installation and Setup
Clone and install dependencies:
cd tldraw-mcp npm install cd server npm installBuild the server code:
cd server npm run buildConfigure Claude Desktop:
Create or edit the Claude Desktop configuration file at
%AppData%\Claude\claude_desktop_config.json:{ "mcpServers": { "tldrawserver": { "command": "node", "args": ["D:\\tldraw-mcp\\server\\dist\\index.js"] } } }Replace the path with the absolute path to the compiled server file.
Starting the Application
The MCP server and the SSE/HTTP bridge (port 3002) run in a single process that
Claude Desktop launches for you from claude_desktop_config.json. Do not start a
server manually (npm start / npm run start:http) — a second copy would grab port
3002 and the canvas would attach to the wrong process, so nothing would render.
You only start the frontend yourself:
Start the Next.js Frontend:
# In the root directory npm run devStart Claude Desktop and enable the MCP Server:
Launch Claude Desktop
Open settings (gear icon)
Go to the "Advanced" tab
Under "MCP Servers", enable "tldrawserver"
Click "Apply"
Claude Desktop now owns the server process. If you ever restart it and an old copy is still holding port 3002, the freshly launched process automatically asks the stale one to step down and takes over — just refresh the browser to reconnect.
Verifying the Setup
Open your browser to
http://localhost:3000You should see the tldraw canvas
In Claude Desktop, try a command like:
Create a flowchart with two steps: "Start" and "Process Data"
Testing the System
To fully test the integration, try the following Claude commands:
Create a simple diagram:
Create a rectangle labeled "Database" at position (200, 300) with width 150 and height 100Create and connect shapes:
Create an ellipse labeled "User" at position (100, 100) with width 120 and height 80, and a rectangle labeled "API" at position (300, 100) with width 150 and height 80. Then connect the "User" shape to the "API" shape.Create a flowchart:
Create a flowchart with the following steps: 1. "Start Process" 2. "Collect Data" 3. "Analyze Results" 4. "Generate Report"Add standalone text:
Add text "CONFIDENTIAL" at position (400, 50) with font size 24Get a snapshot of the current diagram:
Take a snapshot of the current diagram
Verifying Event Flow
To verify that events are flowing correctly through the system:
Open your browser's developer tools (F12 or Ctrl+Shift+I)
Go to the Console tab
Look for log messages with prefixes:
[EventBus]- Events being broadcast internally[HTTP Server]- Messages from the HTTP server[API]- Messages from the Next.js API routesLog messages from TldrawEditor component
When you issue a command in Claude, you should see a sequence of logs showing the operation moving through each part of the system.
Troubleshooting
HTTP Server not starting: Check if port 3002 is already in use
Claude not connecting: Verify the path in
claude_desktop_config.jsonDiagram not updating: Check browser console for errors in the event stream
Types of operations not working: Check log messages for errors in parsing or handling specific operations
Snapshot functionality issues: Check if
snapshot-responseevents are being correctly processed
Common Issues and Solutions
Port conflicts: If port 3002 is in use, edit
httpServer.tsto use a different port, and update the API routes accordinglyTiming issues: If operations seem to drop, increase logging and check for race conditions
Type errors: If you encounter "any" type errors, define proper interfaces in
eventBus.tsMissing dependencies: Run
npm installin both the root and server directories
Related MCP server: tldraw-mcp
Architecture Overview
The application consists of:
MCP Server: Handles function calls from Claude AI
HTTP Server: Provides Server-Sent Events (SSE) endpoints
Next.js Frontend: Renders the tldraw canvas and listens for operations
EventBus: Facilitates type-safe communication between components
Key Interactions
1. Creating a Shape
When a user asks Claude to create a diagram element, the following sequence occurs:
sequenceDiagram
participant User
participant Claude
participant MCP Server
participant EventBus
participant HTTP Server
participant Frontend
User->>Claude: "Draw a rectangle labeled 'Database'"
Claude->>MCP Server: createShape(type: "rectangle", x: 100, y: 150, ...)
MCP Server->>EventBus: emit("tldraw-operation", {type: "createShape", ...})
EventBus->>HTTP Server: notify listeners
HTTP Server->>Frontend: SSE event
Frontend->>Frontend: Update tldraw canvasStep-by-Step Process:
User Request: User asks Claude to create a diagram element
Claude Analysis: Claude processes the request and calls the appropriate MCP function
MCP Function Call: The
createShapefunction is executed with parametersEvent Broadcasting: The operation is broadcast through the EventBus
HTTP Transmission: The HTTP server forwards the event as an SSE message
Frontend Rendering: The frontend receives the event and updates the tldraw canvas
2. Getting a Snapshot
When Claude needs the current state of the diagram:
sequenceDiagram
participant Claude
participant MCP Server
participant EventBus
participant HTTP Server
participant Frontend
Claude->>MCP Server: getSnapshot()
MCP Server->>EventBus: emit("tldraw-operation", {type: "requestSnapshot", requestId: "abc123"})
EventBus->>HTTP Server: notify listeners
HTTP Server->>Frontend: SSE event
Frontend->>Frontend: Get tldraw snapshot
Frontend->>HTTP Server: POST /api/snapshot
HTTP Server->>EventBus: emit("snapshot-response", {requestId: "abc123", snapshot: {...}})
EventBus->>MCP Server: notify listeners
MCP Server->>Claude: Return snapshot dataStep-by-Step Process:
Snapshot Request: Claude calls the
getSnapshotfunctionRequest ID Generation: The MCP server generates a unique request ID
Snapshot Request Broadcasting: The request is broadcast through EventBus
Frontend Processing: The frontend receives the request and captures the current canvas state
Snapshot Submission: The frontend sends the snapshot back to the server
Response Processing: The EventBus routes the snapshot back to the waiting MCP function
Return to Claude: The snapshot data is returned to Claude
Why We Use EventBus
The EventBus provides several important benefits, even in a single-client scenario:
1. Decoupled Architecture
EventBus creates a clean separation between different components:
MCP server can focus on handling Claude's function calls
HTTP server can focus on client communication
Components can communicate without direct references to each other
2. Asynchronous Communication
The EventBus enables asynchronous communication patterns:
MCP functions can trigger operations without waiting for UI updates
Snapshot requests can be handled asynchronously with promises
3. Centralized Event Management
All communication flows through a single channel:
Consistent event handling patterns
Easier debugging (all events can be logged in one place)
Simplified error handling
4. Extensibility
The EventBus pattern makes the system more extensible:
New event types can be added without changing the communication architecture
Additional listeners can be added without modifying existing code
Future support for multiple clients would be easier to implement
Getting Started
Install dependencies for both the frontend and server:
# Install Next.js frontend dependencies npm install # Install MCP server dependencies cd server npm install cd ..Build the server, then start only the frontend. Claude Desktop launches the server (which also hosts the HTTP/SSE bridge on port 3002) — do not run it manually, or the duplicate process will fight over port 3002 and the canvas will render nothing.
# Build the MCP server once (rebuild after editing server/src) cd server npm run build cd .. # Start the Next.js frontend npm run devConfigure Claude Desktop to connect to your MCP server:
# Run the setup script to automatically configure Claude Desktop ./setup-claude.batOr manually update your Claude Desktop configuration file (typically located at
%AppData%\Claude\claude_desktop_config.json):{ "mcpServers": { "tldrawserver": { "command": "node", "args": ["PATH_TO_COMPILED_JS_FILE"] } } }Replace
PATH_TO_COMPILED_JS_FILEwith the absolute path to the compiled JavaScript file, e.g.,D:\\tldraw-mcp\\server\\dist\\index.js.Open http://localhost:3000 in your browser to see the tldraw interface
Restart Claude Desktop and tell it: "I'd like to use the tldrawserver MCP server to draw a diagram"
Project Structure
server/: MCP server implementation
src/: TypeScript source files
index.ts: Main MCP server with function definitions
httpServer.ts: HTTP server for SSE communication
eventBus.ts: Event bus implementation with TypeScript interfaces
dist/: Compiled JavaScript files (generated)
build.bat: Script to compile TypeScript
start.bat: Script to build and run the MCP server
start-http.bat: Script to build and run the HTTP server
app/: Next.js frontend
components/TldrawEditor.tsx: Frontend component with tldraw integration
api/events/route.ts: Next.js API route for SSE events
api/snapshot/route.ts: Next.js API route for snapshots
Tldraw Shape Types
Important note about tldraw's shape types:
Tldraw uses a specific shape type system that differs from our simple descriptive names. The mapping is as follows:
For basic shapes (rectangle, ellipse, triangle, diamond), tldraw uses a "geo" type with a "geo" property specifying the actual shape
For text, tldraw uses a "text" type
For arrows/connectors, tldraw uses an "arrow" type
For example, when we specify a "rectangle" in our API, TldrawEditor.tsx maps this to:
editor.createShape({
type: "geo",
props: {
geo: "rectangle",
// other properties
},
});This mapping is handled automatically in the TldrawEditor component.
Available MCP Tools
The following tools are available to Claude via the MCP server:
createShape: Create basic shapes (rectangle, ellipse, triangle, diamond)connectShapes: Connect two shapes with a bound arrow (by theirlabel/text handle)drawArrow: Draw a free-form arrow between two points (not bound to shapes)addText: Add standalone text elementscreateFlowchartStep: Create a flowchart step (with optional connection to previous step)deleteShape: Delete a single shape by itslabel/text handledeleteShapesByLabels: Delete multiple shapes by theirlabel/text handlesclearCanvas: Delete all shapes on the current pagegetSnapshot: Get a snapshot of the current diagramcreatePage: Create a new page and switch to it (subsequent shapes land there)switchPage: Switch the active page by namedeletePage: Delete a page by name (cannot delete the only/last page)listPages: List all pages and which one is active
Technology Stack
Backend: Node.js, TypeScript, Model Context Protocol SDK
Frontend: Next.js, React
Diagramming: tldraw
Communication: Server-Sent Events (SSE), EventBus
Type Safety
The project implements TypeScript interfaces for all message types to ensure type safety across the application, including:
Specific payload types for each event
Type guards for runtime type checking
Strong typing for all MCP function parameters
Remote Deployment
To run this on a server and connect Claude over a remote MCP URL
(https://<your-domain>/mcp) instead of a local stdio process, see
DEPLOY.md. It ships the canvas and the MCP/bridge server as two
docker compose containers bound to loopback, with your existing nginx terminating TLS
and routing /tldraw-mcp to the MCP endpoint.
Server environment variables:
MCP_TRANSPORT—stdio(default, local Claude Desktop) orhttp(remote/mcp)PORT— HTTP/SSE + MCP port (default3002)BRIDGE_URL(frontend) — where the Next API routes reach the bridge (defaulthttp://localhost:3002)
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/farhadjaman/tldraw-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server