Open Excalidraw → Start collab → Give link to Claude → Shapes appear live
Claude connects to the Excalidraw collaboration server using the native protocol (socket.io + AES-128-GCM encryption). No browser extension. No DevTools. No Excalidraw API key. Just the same protocol your browser uses when you collaborate with someone.
npx excaliclaude setupThat's it. Restart Claude Code and you're ready.
Manual setup
claude mcp add -s user excaliclaude -- npx -y excaliclaudeRun the server locally, expose it through a tunnel, add the URL to Claude.ai.
1. Start the server
# With auth (recommended when using a tunnel)
EXCALICLAUDE_TOKEN=your-secret npx excaliclaude serve
# Or pass the token directly
npx excaliclaude serve --token your-secret --port 30002. Open a tunnel
# ngrok (free tier works fine)
ngrok http 3000
# → https://abc123.ngrok-free.appCloudflare Tunnel, bore.pub, or any other HTTP tunnel also works.
3. Add to Claude.ai
Go to Customize → Connectors → Add custom connector and paste the tunnel URL. That's it — Claude.ai only takes a URL.
Token configuration (for non-Claude.ai clients)
Claude.ai only accepts a URL — it does not support custom auth headers. The --token option is for other HTTP clients (Cursor, scripts, etc.) that can send Authorization: Bearer <token>.
# CLI flag
npx excaliclaude serve --token my-secret
# Environment variable
export EXCALICLAUDE_TOKEN=my-secret
npx excaliclaude serveFor Claude.ai, the ngrok URL is your only access control — close the tunnel when done.
Custom port
npx excaliclaude serve --port 8080{
"mcpServers": {
"excaliclaude": {
"command": "npx",
"args": ["-y", "excaliclaude"]
}
}
}Run from source
git clone https://github.com/dev-smurf/excaliclaude.git
cd excaliclaude
npm install && npm run build
npm start| Tool | Description |
|---|---|
connect |
Join an Excalidraw collab room via URL. Auto-reconnects on drop. |
draw_elements |
Draw rectangles, ellipses, diamonds, text, arrows, lines, frames, images |
update_elements |
Move, resize, restyle, or change text of existing elements by ID |
get_scene |
Read all elements — compact or full mode with all properties |
group_elements |
Group elements so they move together |
delete_elements |
Remove specific elements by their ID |
undo_last_draw |
Undo the last draw_elements call |
clear_canvas |
Wipe the entire canvas clean |
status |
Check connection state and element count |
You: Connect to https://excalidraw.com/#room=abc,key123
and draw a system architecture with a load balancer,
3 API servers, and a database.
Claude: Connected to room abc12345... (2 users in room)
Drawing 9 elements...
*rectangles, arrows, and labels appear live in your browser*
Important
The room key never leaves your machine unencrypted. The Excalidraw relay server only sees ciphertext.
| Feature | Detail |
|---|---|
| E2E Encrypted | AES-128-GCM with 12-byte IV. Room key derived from URL fragment (never sent to server). |
| Key in memory only | Never written to disk. Never logged. Cleared on disconnect. |
| Validated inputs | Every tool input goes through Zod schemas before execution. |
| Rate limited | Max 500 elements per draw call to prevent abuse. |
bin/excaliclaude.ts CLI entry point
| ├─ stdio transport → Claude Code
| └─ HTTP/SSE transport → Claude.ai (via tunnel)
|
src/server.ts MCP server with 9 tools
src/http.ts HTTP server factory (StreamableHTTP + Bearer auth)
|
src/collab.ts Socket.io connection + room management + element cache
|
|-- src/crypto.ts AES-128-GCM encrypt/decrypt (WebCrypto API)
|-- src/elements.ts Element factory with Excalidraw defaults
|-- src/url.ts Parse collab URLs into roomId + roomKey
|-- src/types.ts Shared TypeScript interfaces
| Requirement | Notes |
|---|---|
| Node.js 18+ | Uses native crypto.subtle (WebCrypto) |
| Excalidraw collab link | Free, no account needed. Click "Live collaboration" in Excalidraw. |
Built for Claude Code and Claude.ai
by @dev-smurf