excalidraw-ai
excalidraw-ai — MCP server (AI interface to Excalidraw)
The clean, non-clunky interface for an AI to read, watch, and edit a live Excalidraw room. Instead of browser automation (fiber-read + drag-drop + remote browser drops), it joins the room as a socket-bot over the collab relay and speaks the AES-GCM-encrypted scene protocol directly — deterministic, headless, scalable.
POC status: core bridge + MCP stdio surface working end-to-end against a
self-hosted excalidraw-room relay (selftest + MCP smoke pass).
Why a relay we control
The bot talks to a relay. Excalidraw's hosted relay
(oss-collab.excalidraw.com) origin-guards non-browser bots (403/400), so for
our own rooms we run excalidraw/excalidraw-room (MIT, same code as prod) and
point an Excalidraw UI at it via VITE_APP_WS_SERVER_URL.
Architecture
Excalidraw UI (fork) ──socket.io──▶ relay (excalidraw-room) ◀──socket-bot── excalidraw-ai (MCP)
(humans) self-hosted (the AI's interface)Tools
Tool | What it does |
| new room id/key for our relay |
| join a room, read scene, start listening |
| disconnect |
| board elements + texts |
| add/update/remove deltas since last call ("hear the room") |
| append elements (broadcast live) |
| move / retitle / recolor existing (version bump) |
| mark deleted |
Run
npm install
# relay (one terminal):
cd /tmp/excalidraw-room && PORT=3002 node dist/index.js
# self-test the bridge core:
npm run selftest
# MCP smoke (stdio handshake + join + get_scene):
npm run mcp-smoke
# start the MCP server (stdio) — wire into Hermes/Copilot/Claude:
node src/server.jsWire into Hermes (~/.hermes/config.yaml)
The server can run two ways:
Local (stdio) — spawn as a subprocess:
mcp_servers:
excalidraw_ai:
command: node
args: ["/root/workspace/mcclawd-org/excalidraw-ai/src/server.js"]Deployed on a VPS (HTTP / StreamableHTTP) — reach it over the network with token auth. See the Deploy section below.
mcp_servers:
excalidraw_ai:
url: "http://<vps>:4000/mcp"
headers:
Authorization: "Bearer <EXCALIDRAW_AI_TOKEN>"
timeout: 90Restart Hermes → tools appear as mcp_excalidraw_ai_*.
Deploy (VPS, PM2)
Run the server as a headless service next to the relay. Currently deployed to
72.62.115.153 (srv1544821): relay :3002, MCP :4000 (token-authed), under
PM2 (excalidraw-room, excalidraw-ai), ecosystem.config.cjs in this repo.
# on the VPS
# /opt/excalidraw-room (relay: PORT=3002 node dist/index.js)
# /opt/excalidraw-ai (MCP: node src/server-http.js)
cd /opt/excalidraw-ai && npm ci
# put EXCALIDRAW_AI_TOKEN=<long-random> into /opt/excalidraw-ai/.env (chmod 600)
pm2 start ecosystem.config.cjs && pm2 save && pm2 startup systemd
# firewall: ufw allow 3002/tcp 4000/tcpEndpoints: GET /health, POST/GET /mcp (StreamableHTTP). Unauthorized
requests → 401. Hardening note: TLS via nginx+Let's Encrypt still TODO.
Layout
src/crypto.js— AES-GCM E2E helpers (Node Web Crypto)src/elements.js— element builders + scene merge/diff (id+version semantics)src/room.js— RoomClient: socket join, read, write, change feedsrc/app.js— shared tool registration (used by both entrypoints)src/server.js— MCP stdio entrypointsrc/server-http.js— MCP HTTP entrypoint (token auth + /health)ecosystem.config.cjs— PM2 config for relay + server (ESM-safe)scripts/selftest.mjs,scripts/mcp-smoke.mjs— verification
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- 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/McClawdDigital/excalidraw-ai'
If you have feedback or need assistance with the MCP directory API, please join our Discord server