Skip to content

Commit 6724b1c

Browse files
docs: replace ASCII architecture diagram with generated image
- Add CI badge linked to GitHub Actions workflow status - Generate architecture-diagram.png (dark theme, three-layer flow) - Remove Express and WebSocket badges (distracting, redundant detail) - Move Architecture section above Quick Start for logical hierarchy - Tighten MCP Tools section header (20 tools count) - Add sticky notes to Roadmap - Remove redundant 'Example .mcp.json:' label and duplicate inspector example Co-Authored-By: AdaL <adal@sylph.ai>
1 parent 182ad0e commit 6724b1c

2 files changed

Lines changed: 36 additions & 104 deletions

File tree

README.md

Lines changed: 36 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44

55
# tldraw MCP Server
66

7-
> Programmatic canvas toolkit for AI agents - create, read, update, and delete tldraw shapes in real time via the Model Context Protocol.
7+
> Programmatic canvas toolkit for AI agents create, read, update, and delete tldraw shapes in real time via the Model Context Protocol.
88
9+
[![CI](https://github.com/chindris-mihai-alexandru/tldraw-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/chindris-mihai-alexandru/tldraw-mcp-server/actions/workflows/ci.yml)
910
[![Node.js](https://img.shields.io/badge/Node.js-18%2B-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
1011
[![TypeScript](https://img.shields.io/badge/TypeScript-5.6-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
1112
[![React](https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=black)](https://react.dev/)
1213
[![tldraw](https://img.shields.io/badge/tldraw-4.5-000000)](https://tldraw.dev/)
1314
[![MCP](https://img.shields.io/badge/Model_Context_Protocol-Server-5E5CE6)](https://modelcontextprotocol.io/)
14-
[![Express](https://img.shields.io/badge/Express-4.21-000000?logo=express&logoColor=white)](https://expressjs.com/)
15-
[![WebSocket](https://img.shields.io/badge/WebSocket-ws_8.21-010101)](https://github.com/websockets/ws)
1615
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
1716

1817
## What It Is
@@ -21,6 +20,14 @@ An MCP server that gives AI agents (AdaL, Claude, Cursor, Codex CLI…) programm
2120

2221
**Inspired by** [mcp_excalidraw](https://github.com/yctimlin/mcp_excalidraw) — the same quality and completeness, built for the tldraw ecosystem.
2322

23+
## Architecture
24+
25+
<img src="assets/architecture-diagram.png" alt="tldraw MCP Server architecture — three-layer flow from MCP clients through the MCP server to the canvas server and browser UI" />
26+
27+
**Flow:** MCP client → MCP server (Zod validation) → Canvas server (Express HTTP) → WebSocket broadcast → Browser (tldraw editor, real time).
28+
29+
---
30+
2431
## Quick Start
2532

2633
### Prerequisites
@@ -68,52 +75,31 @@ The `.mcp.json` at the repo root works out-of-the-box for any project-level MCP
6875

6976
## MCP Client Configuration
7077

71-
The default launch mode is still **stdio**, so existing AdaL/Claude/Cursor configs continue to work. Set `MCP_TRANSPORT=http` only when you want a shared Streamable HTTP endpoint.
78+
The default transport is **stdio**, so existing configs continue to work. Set `MCP_TRANSPORT=http` for shared HTTP endpoints (OpenAI Agents SDK, etc.).
7279

7380
### Transport and adapter options
7481

7582
| Variable | Default | Purpose |
7683
|----------|---------|---------|
7784
| `MCP_TRANSPORT` | `stdio` | `stdio` for subprocess clients, `http` for Streamable HTTP |
78-
| `MCP_CLIENT` | `generic` | Optional client hint: `adal`, `claude`, `cursor`, `openai`, `generic` |
79-
| `MCP_SERVER_NAME` | `tldraw` | Server name used for optional tool prefixes |
80-
| `INCLUDE_SERVER_IN_TOOL_NAMES` | `false` | Expose tools as `tldraw__create_element` while still accepting prefixed calls |
85+
| `MCP_CLIENT` | `generic` | Client hint: `adal`, `claude`, `cursor`, `openai`, `generic` |
86+
| `MCP_SERVER_NAME` | `tldraw` | Server name for optional tool prefixes |
87+
| `INCLUDE_SERVER_IN_TOOL_NAMES` | `false` | Expose tools as `tldraw__create_element` |
8188
| `MCP_PERFORMANCE_MODE` | `false` | Compact tool descriptions to reduce discovery context |
8289
| `MCP_HTTP_HOST` | `127.0.0.1` | HTTP bind host |
8390
| `MCP_HTTP_PORT` | `3333` | HTTP bind port |
8491
| `MCP_HTTP_PATH` | `/mcp` | Streamable HTTP MCP path |
85-
| `MCP_ALLOWED_ORIGINS` | local origins | Comma-separated Origin allowlist for HTTP |
86-
| `MCP_ALLOWED_HOSTS` | local hosts | Comma-separated Host allowlist for HTTP |
87-
| `MCP_AUTH_TOKEN` | unset | Optional bearer-token auth for HTTP |
88-
89-
HTTP auth is disabled by default for local development. For shared endpoints, set `MCP_AUTH_TOKEN` and send `Authorization: Bearer <token>`.
92+
| `MCP_ALLOWED_ORIGINS` | local origins | Comma-separated Origin allowlist |
93+
| `MCP_ALLOWED_HOSTS` | local hosts | Comma-separated Host allowlist |
94+
| `MCP_AUTH_TOKEN` | unset | Bearer-token auth for HTTP (set and send `Authorization: Bearer <token>`) |
9095

9196
### AdaL CLI
9297

93-
**Project-level** — the `.mcp.json` in this repo is pre-configured. Just open AdaL in this directory and the server is auto-discovered.
98+
Project-level — the `.mcp.json` in this repo is pre-configured. Open AdaL in this directory and the server is auto-discovered.
9499

95100
```bash
96101
cd tldraw-mcp-server
97102
adal
98-
# AdaL auto-loads .mcp.json — tldraw tools are available immediately
99-
```
100-
101-
Example `.mcp.json`:
102-
103-
```json
104-
{
105-
"mcpServers": {
106-
"tldraw": {
107-
"command": "node",
108-
"args": ["dist/index.js"],
109-
"env": {
110-
"EXPRESS_SERVER_URL": "http://127.0.0.1:3000",
111-
"MCP_TRANSPORT": "stdio",
112-
"MCP_CLIENT": "adal"
113-
}
114-
}
115-
}
116-
}
117103
```
118104

119105
Performance mode for lower discovery overhead:
@@ -138,7 +124,7 @@ Performance mode for lower discovery overhead:
138124
### Claude Code
139125

140126
```bash
141-
# Project-level (commits .mcp.json to the repo)
127+
# Project-level
142128
claude mcp add tldraw --scope project \
143129
-e EXPRESS_SERVER_URL=http://127.0.0.1:3000 \
144130
-e MCP_TRANSPORT=stdio \
@@ -186,30 +172,14 @@ Config: `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global)
186172
"env": {
187173
"EXPRESS_SERVER_URL": "http://127.0.0.1:3000",
188174
"MCP_TRANSPORT": "stdio",
189-
"MCP_CLIENT": "cursor",
190-
"INCLUDE_SERVER_IN_TOOL_NAMES": "false"
175+
"MCP_CLIENT": "cursor"
191176
}
192177
}
193178
}
194179
}
195180
```
196181

197-
If a gateway/client expects server-prefixed tool names, set:
198-
199-
```json
200-
{
201-
"mcpServers": {
202-
"tldraw": {
203-
"command": "node",
204-
"args": ["/absolute/path/to/tldraw-mcp-server/dist/index.js"],
205-
"env": {
206-
"EXPRESS_SERVER_URL": "http://127.0.0.1:3000",
207-
"INCLUDE_SERVER_IN_TOOL_NAMES": "true"
208-
}
209-
}
210-
}
211-
}
212-
```
182+
If a gateway expects server-prefixed tool names (`tldraw__create_element`), add `"INCLUDE_SERVER_IN_TOOL_NAMES": "true"` to the env.
213183

214184
### OpenAI Agents SDK
215185

@@ -225,8 +195,6 @@ MCP_CLIENT=openai \
225195
node dist/index.js
226196
```
227197

228-
Example Agents SDK server entry:
229-
230198
```ts
231199
import { Agent } from '@openai/agents'
232200

@@ -254,9 +222,9 @@ codex mcp add tldraw \
254222
-- node /absolute/path/to/tldraw-mcp-server/dist/index.js
255223
```
256224

257-
### Supergateway / systemd example
225+
### Supergateway / systemd
258226

259-
If you need an HTTP endpoint while keeping the stdio server path, `supergateway` can wrap the existing command:
227+
Wrap the stdio server with `supergateway` for an HTTP endpoint:
260228

261229
```bash
262230
npx -y supergateway \
@@ -289,13 +257,11 @@ WantedBy=multi-user.target
289257

290258
### Migration and rollback
291259

292-
No migration is required for existing AdaL users: stdio remains the default. To roll back optional behavior, unset `MCP_TRANSPORT`, `MCP_PERFORMANCE_MODE`, and `INCLUDE_SERVER_IN_TOOL_NAMES`, then use the original `.mcp.json` shape with only `EXPRESS_SERVER_URL`.
260+
No migration is required for existing AdaL users stdio remains the default. To roll back optional behavior, unset `MCP_TRANSPORT`, `MCP_PERFORMANCE_MODE`, and `INCLUDE_SERVER_IN_TOOL_NAMES`, then use the original `.mcp.json` shape with only `EXPRESS_SERVER_URL`.
293261

294262
---
295263

296-
## MCP Tools
297-
298-
### Implemented (20 tools)
264+
## MCP Tools (20 tools)
299265

300266
| Tool | Description |
301267
|------|-------------|
@@ -304,7 +270,7 @@ No migration is required for existing AdaL users: stdio remains the default. To
304270
| `update_element` | Partially update any element property |
305271
| `delete_element` | Delete an element by ID |
306272
| `query_elements` | List/filter elements by type and bounding box |
307-
| `batch_create_elements` | Create multiple elements atomically (efficient for diagrams) |
273+
| `batch_create_elements` | Create multiple elements atomically |
308274
| `clear_canvas` | Remove all elements (requires `confirm: true`) |
309275
| `read_diagram_guide` | Return tldraw color names, presets, and layout best practices |
310276
| `describe_scene` | Summarize the current canvas elements, positions, labels, and connections |
@@ -318,14 +284,15 @@ No migration is required for existing AdaL users: stdio remains the default. To
318284
| `distribute_elements` | Distribute multiple elements evenly using an atomic batch update |
319285
| `auto_layout` | Automatically arrange elements using dagre, force-directed, or grid layout |
320286
| `export_svg` | Export the current canvas as an SVG string |
321-
| `export_pdf` | Export the current canvas as a PDF file (requires Playwright for full fidelity) |
287+
| `export_pdf` | Export the current canvas as a PDF file |
322288

323289
### Roadmap
324290

325291
| Category | Tools | Status |
326292
|----------|-------|--------|
327293
| **Grouping** | `group_elements`, `ungroup_elements` | Planned |
328294
| **Advanced Export** | `export_png` (via Playwright), `export_jpg` | Planned |
295+
| **Sticky Notes** | `create_sticky`, `update_sticky`, `list_sticky_templates` | Planned |
329296

330297
---
331298

@@ -345,34 +312,6 @@ No migration is required for existing AdaL users: stdio remains the default. To
345312

346313
---
347314

348-
## Architecture
349-
350-
```
351-
┌─────────────────────┐ ┌─────────────────────────┐
352-
│ MCP Client │ stdio │ MCP Server │
353-
│ AdaL, Claude, │◀───────▶│ src/index.ts │
354-
│ Cursor, etc. │ │ 17 tools · Zod validate│
355-
└─────────────────────┘ └────────────┬────────────┘
356-
│ HTTP REST
357-
358-
┌─────────────────────────┐
359-
│ Canvas Server │
360-
│ src/canvas-server.ts │
361-
│ Express · Port 3000 │
362-
└────────────┬────────────┘
363-
│ WebSocket /ws
364-
365-
┌─────────────────────────┐
366-
│ Browser UI │
367-
│ frontend/src/App.tsx │
368-
│ tldraw React app │
369-
└─────────────────────────┘
370-
```
371-
372-
**Flow:** MCP client calls a tool → MCP server validates with Zod → HTTP POST to canvas server → canvas server broadcasts via WebSocket → browser frontend applies to tldraw editor in real time.
373-
374-
---
375-
376315
## Development
377316

378317
```bash
@@ -389,24 +328,10 @@ npm run dev:frontend # Vite dev server on :5173
389328
# Build everything
390329
npm run build:all
391330

392-
# Run regression tests once
393-
npm test -- --run
394-
395-
# Test MCP tools directly
396-
npx @modelcontextprotocol/inspector --cli \
397-
-e EXPRESS_SERVER_URL=http://127.0.0.1:3000 \
398-
-- node dist/index.js --method tools/list
399-
```
400-
401-
### Testing
402-
403-
```bash
404-
# Run the Vitest regression suite once
331+
# Run the full test suite once
405332
npm test -- --run
406333
```
407334

408-
The tests cover REST edge cases such as duplicate custom IDs, atomic batch create validation, and atomic batch updates.
409-
410335
### Testing a Tool
411336

412337
```bash
@@ -418,8 +343,15 @@ npx @modelcontextprotocol/inspector --cli \
418343
--tool-arg type=rectangle --tool-arg x=100 --tool-arg y=100 \
419344
--tool-arg width=200 --tool-arg height=80 \
420345
--tool-arg text="Hello" --tool-arg color=blue --tool-arg fill=semi
346+
347+
# List all tools
348+
npx @modelcontextprotocol/inspector --cli \
349+
-e EXPRESS_SERVER_URL=http://127.0.0.1:3000 \
350+
-- node dist/index.js --method tools/list
421351
```
422352

353+
---
354+
423355
## Troubleshooting
424356

425357
### Screenshot tools return an error

assets/architecture-diagram.png

1.92 MB
Loading

0 commit comments

Comments
 (0)