Excalidraw
STDIOMCP server enabling AI agents to create and manipulate live Excalidraw diagrams in real-time
MCP server enabling AI agents to create and manipulate live Excalidraw diagrams in real-time
A comprehensive TypeScript-based system that combines Excalidraw's powerful drawing capabilities with Model Context Protocol (MCP) integration, enabling AI agents to create and manipulate diagrams in real-time on a live canvas.
📋 Choose Your Installation Method
| Component | Local | Docker | Status | 
|---|---|---|---|
| Canvas Server | ✅ Fully Working | ✅ Fully Working | Production Ready | 
| MCP Server | ✅ Fully Working | ✅ Fully Working | Production Ready | 
| NPM Published | 🔧 In Progress | N/A | Development testing | 
This system consists of two independent components:
You can choose any combination:
Both local and Docker setups are fully working and production-ready!
See MCP Excalidraw in Action!
Watch how AI agents create and manipulate diagrams in real-time on the live canvas
┌─────────────────────────────────────────────────────────────────┐
│                         Component 1                              │
│                     🎨 CANVAS SERVER                             │
│                   (Runs Independently)                           │
│                                                                  │
│  ┌─────────────────┐         ┌─────────────────┐               │
│  │  Canvas Server  │◀───────▶│   Frontend      │               │
│  │ (src/server.js) │         │  (React + WS)   │               │
│  │  Port 3000      │         │  Excalidraw UI  │               │
│  └─────────────────┘         └─────────────────┘               │
│                                                                  │
│  📍 Start: npm run canvas  OR  docker run (canvas)              │
└─────────────────────────────────────────────────────────────────┘
                              ▲
                              │ HTTP API
                              │ (Optional)
                              │
┌─────────────────────────────────────────────────────────────────┐
│                         Component 2                              │
│                      🤖 MCP SERVER                               │
│                   (Runs Independently)                           │
│                                                                  │
│  ┌─────────────────┐         ┌─────────────────┐               │
│  │   AI Agent      │◀───────▶│   MCP Server    │               │
│  │   (Claude)      │         │ (src/index.js)  │               │
│  │  Desktop/Code   │  stdio  │  MCP Protocol   │               │
│  └─────────────────┘         └─────────────────┘               │
│                                                                  │
│  📍 Configure in: claude_desktop_config.json OR .mcp.json       │
└─────────────────────────────────────────────────────────────────┘
🎯 Key Points:
• Canvas and MCP server are SEPARATE processes
• Canvas can run locally OR in Docker
• MCP server can run locally OR in Docker
• Canvas provides the visual interface (optional)
• MCP server connects Claude to the canvas (via HTTP API)
The canvas server provides the live Excalidraw interface.
git clone https://github.com/yctimlin/mcp_excalidraw.git cd mcp_excalidraw npm install
npm run build
# Production mode (recommended) npm run canvas
http://localhost:3000
Option B1: Use Pre-built Image from GHCR (Recommended)
docker pull ghcr.io/yctimlin/mcp_excalidraw-canvas:latest docker run -d -p 3000:3000 --name mcp-excalidraw-canvas ghcr.io/yctimlin/mcp_excalidraw-canvas:latest
Option B2: Build Locally
git clone https://github.com/yctimlin/mcp_excalidraw.git cd mcp_excalidraw docker build -f Dockerfile.canvas -t mcp-excalidraw-canvas . docker run -d -p 3000:3000 --name mcp-excalidraw-canvas mcp-excalidraw-canvas
http://localhost:3000
The MCP server connects your AI assistant (Claude) to the canvas. Choose local OR Docker format based on your preference.
You can mix and match any combination:
| Canvas Server | MCP Server | Status | 
|---|---|---|
| ✅ Local | ✅ Local | Recommended | 
| ✅ Local | ✅ Docker | Fully Working | 
| ✅ Docker | ✅ Local | Fully Working | 
| ✅ Docker | ✅ Docker | Fully Working | 
Configuration examples are provided in the next section for:
| Script | Description | 
|---|---|
npm start | Build and start MCP server (dist/index.js) | 
npm run canvas | Build and start canvas server (dist/server.js) | 
npm run build | Build both frontend and TypeScript backend | 
npm run build:frontend | Build React frontend only | 
npm run build:server | Compile TypeScript backend to JavaScript | 
npm run dev | Start TypeScript watch mode + Vite dev server | 
npm run type-check | Run TypeScript type checking without compilation | 
npm run production | Build + start in production mode | 
http://localhost:3000The MCP server provides these tools for creating visual diagrams:
// Create a rectangle { "type": "rectangle", "x": 100, "y": 100, "width": 200, "height": 100, "backgroundColor": "#e3f2fd", "strokeColor": "#1976d2", "strokeWidth": 2 }
{ "type": "text", "x": 150, "y": 125, "text": "Process Step", "fontSize": 16, "strokeColor": "#333333" }
{ "type": "arrow", "x": 300, "y": 130, "width": 100, "height": 0, "strokeColor": "#666666", "strokeWidth": 2 }
{ "elements": [ { "type": "rectangle", "x": 100, "y": 100, "width": 120, "height": 60, "backgroundColor": "#fff3e0", "strokeColor": "#ff9800" }, { "type": "text", "x": 130, "y": 125, "text": "Start", "fontSize": 16 } ] }
✅ Ensure your canvas server is running (from Step 1):
npm run canvasdocker run -d -p 3000:3000 mcp-excalidraw-canvasCanvas should be accessible at http://localhost:3000
Choose your configuration based on IDE and preference:
| IDE | Config File | Format Options | 
|---|---|---|
| Claude Desktop | claude_desktop_config.json | Local ⭐ / Docker ✅ | 
| Claude Code | .mcp.json (project root) | Local ⭐ / Docker ✅ | 
| Cursor | .cursor/mcp.json | Local ⭐ / Docker ✅ | 
⭐ = Recommended | ✅ = Fully Working
Edit your claude_desktop_config.json file:
{ "mcpServers": { "excalidraw": { "command": "node", "args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"], "env": { "EXPRESS_SERVER_URL": "http://localhost:3000", "ENABLE_CANVAS_SYNC": "true" } } } }
Important: Replace /absolute/path/to/mcp_excalidraw with your actual installation path.
Using Pre-built Image from GHCR (Recommended):
{ "mcpServers": { "excalidraw": { "command": "docker", "args": [ "run", "-i", "--rm", "--network", "host", "-e", "EXPRESS_SERVER_URL=http://localhost:3000", "-e", "ENABLE_CANVAS_SYNC=true", "ghcr.io/yctimlin/mcp_excalidraw:latest" ] } } }
OR Build Locally:
cd mcp_excalidraw docker build -f Dockerfile -t mcp-excalidraw .
Then use mcp-excalidraw as the image name in the configuration above.
Create or edit .mcp.json in your project root:
{ "mcpServers": { "excalidraw": { "command": "node", "args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"], "env": { "EXPRESS_SERVER_URL": "http://localhost:3000", "ENABLE_CANVAS_SYNC": "true" } } } }
Important: Replace /absolute/path/to/mcp_excalidraw with your actual installation path.
Using Pre-built Image from GHCR (Recommended):
{ "mcpServers": { "excalidraw": { "command": "docker", "args": [ "run", "-i", "--rm", "--network", "host", "-e", "EXPRESS_SERVER_URL=http://localhost:3000", "-e", "ENABLE_CANVAS_SYNC=true", "ghcr.io/yctimlin/mcp_excalidraw:latest" ] } } }
OR Build Locally:
cd mcp_excalidraw docker build -f Dockerfile -t mcp-excalidraw .
Then use mcp-excalidraw as the image name in the configuration above.
# Project-scoped (recommended) claude mcp add --scope project --transport stdio excalidraw \ -- docker run -i --rm --network host \ -e EXPRESS_SERVER_URL=http://localhost:3000 \ -e ENABLE_CANVAS_SYNC=true \ mcp-excalidraw # User-scoped (available across all projects) claude mcp add --scope user --transport stdio excalidraw \ -- docker run -i --rm --network host \ -e EXPRESS_SERVER_URL=http://localhost:3000 \ -e ENABLE_CANVAS_SYNC=true \ mcp-excalidraw
Edit .cursor/mcp.json:
{ "mcpServers": { "excalidraw": { "command": "node", "args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"], "env": { "EXPRESS_SERVER_URL": "http://localhost:3000", "ENABLE_CANVAS_SYNC": "true" } } } }
Using Pre-built Image from GHCR (Recommended):
{ "mcpServers": { "excalidraw": { "command": "docker", "args": [ "run", "-i", "--rm", "--network", "host", "-e", "EXPRESS_SERVER_URL=http://localhost:3000", "-e", "ENABLE_CANVAS_SYNC=true", "ghcr.io/yctimlin/mcp_excalidraw:latest" ] } } }
OR Build Locally:
cd mcp_excalidraw docker build -f Dockerfile -t mcp-excalidraw .
Then use mcp-excalidraw as the image name in the configuration above.
| Setting | Purpose | Required | 
|---|---|---|
EXPRESS_SERVER_URL | Canvas server URL | Yes (default: http://localhost:3000) | 
ENABLE_CANVAS_SYNC | Enable real-time canvas sync | Yes (set to "true") | 
--network host | Docker access to localhost | Required for Docker | 
-i flag | Interactive stdin/stdout | Required for Docker | 
Canvas is optional: The MCP server works without the canvas in API-only mode (for programmatic access only).
| Variable | Default | Description | 
|---|---|---|
EXPRESS_SERVER_URL | http://localhost:3000 | Canvas server URL for MCP sync | 
ENABLE_CANVAS_SYNC | true | Enable/disable canvas synchronization | 
LOG_FILE_PATH | excalidraw.log | Path to the log file | 
DEBUG | false | Enable debug logging | 
PORT | 3000 | Canvas server port | 
HOST | localhost | Canvas server host | 
The canvas server provides these REST endpoints:
| Method | Endpoint | Description | 
|---|---|---|
GET | /api/elements | Get all elements | 
POST | /api/elements | Create new element | 
PUT | /api/elements/:id | Update element | 
DELETE | /api/elements/:id | Delete element | 
POST | /api/elements/batch | Create multiple elements | 
GET | /health | Server health check | 
create_element - Create any type of Excalidraw elementupdate_element - Modify existing elementsdelete_element - Remove elementsquery_elements - Search elements with filtersbatch_create_elements - Create complex diagrams in one callgroup_elements - Group multiple elementsungroup_elements - Ungroup element groupsalign_elements - Align elements (left, center, right, top, middle, bottom)distribute_elements - Distribute elements evenlylock_elements / unlock_elements - Lock/unlock elementsget_resource - Access scene, library, theme, or elements datafrontend/src/)@excalidraw/excalidraw package with TypeScript typessrc/server.ts → dist/server.js)src/index.ts → dist/index.js)src/types.ts)npm run build completed successfullydist/index.html and dist/frontend/ directory existlsof -i :3000 (macOS/Linux) or netstat -ano | findstr :3000 (Windows)ENABLE_CANVAS_SYNC=true in MCP server environment configurationEXPRESS_SERVER_URL points to correct canvas server URL--network host flag is usedcurl http://localhost:3000/healthCanvas Container:
docker ps | grep canvasdocker logs mcp-excalidraw-canvasMCP Container:
--network host is used (required to access localhost:3000)-i flag is present (required for MCP stdin/stdout protocol)node_modules and dist/ directories, then run npm install && npm run buildnode --versionnpm run type-check to identify TypeScript issuesdist/ directory contains both index.js, server.js, and frontend/ after buildmcp_excalidraw/
├── frontend/
│   ├── src/
│   │   ├── App.tsx          # Main React component (TypeScript)
│   │   └── main.tsx         # React entry point (TypeScript)
│   └── index.html           # HTML template
├── src/ (TypeScript Source)
│   ├── index.ts            # MCP server (TypeScript)
│   ├── server.ts           # Canvas server (Express + WebSocket, TypeScript)
│   ├── types.ts            # Comprehensive type definitions
│   └── utils/
│       └── logger.ts       # Logging utility (TypeScript)
├── dist/ (Compiled Output)
│   ├── index.js            # Compiled MCP server
│   ├── server.js           # Compiled Canvas server
│   ├── types.js            # Compiled type definitions
│   ├── utils/
│   │   └── logger.js       # Compiled logging utility
│   └── frontend/           # Built React frontend
├── tsconfig.json          # TypeScript configuration
├── vite.config.js         # Vite build configuration
├── package.json           # Dependencies and scripts
└── README.md              # This file
We welcome contributions! If you're experiencing issues with the NPM package or Docker version, please:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)This project is licensed under the MIT License - see the LICENSE file for details.