Skip to main content
Glama
yctimlin

Excalidraw MCP Server

by yctimlin

Excalidraw MCP Server & Agent Skill

CI Docker Build & Push NPM Version License

Run a live Excalidraw canvas and control it from AI agents. This repo provides:

  • MCP Server: Connect via Model Context Protocol (Claude Desktop, Cursor, Codex CLI, etc.)

  • Agent Skill: Portable skill for Claude Code, Codex CLI, and other skill-enabled agents

Keywords: Excalidraw agent skill, Excalidraw MCP server, AI diagramming, Claude Code skill, Codex CLI skill, Claude Desktop MCP, Cursor MCP, Mermaid to Excalidraw.

Demo

MCP Excalidraw Demo

Watch AI agents create and manipulate diagrams in real-time on the live canvas

Related MCP server: Excalidraw MCP Server

Table of Contents

What It Is

This repo contains two separate processes:

  • Canvas server: web UI + REST API + WebSocket updates (default http://localhost:3000)

  • MCP server: exposes MCP tools over stdio; syncs to the canvas via EXPRESS_SERVER_URL

What's New

  • Agent skill: skills/excalidraw-mcp/ (portable instructions + helper scripts for export/import and repeatable CRUD)

  • Better testing loop: MCP Inspector CLI examples + browser screenshot checks (agent-browser)

  • Bugfixes: batch create now preserves element ids (fixes update/delete after batch); frontend entrypoint fixed (main.tsx)

Quick Start (Local)

Prereqs: Node >= 18, npm

npm ci npm run build

Terminal 1: start the canvas

HOST=0.0.0.0 PORT=3000 npm run canvas

Open http://localhost:3000.

Terminal 2: run the MCP server (stdio)

EXPRESS_SERVER_URL=http://localhost:3000 node dist/index.js

Quick Start (Docker)

Canvas server:

docker run -d -p 3000:3000 --name mcp-excalidraw-canvas ghcr.io/yctimlin/mcp_excalidraw-canvas:latest

MCP server (stdio) is typically launched by your MCP client (Claude Desktop/Cursor/etc.). If you want a local container for it, use the image ghcr.io/yctimlin/mcp_excalidraw:latest and set EXPRESS_SERVER_URL to point at the canvas.

Configure MCP Clients

The MCP server runs over stdio and can be configured with any MCP-compatible client. Below are configurations for both local (requires cloning and building) and Docker (pull-and-run) setups.

Environment Variables

Variable

Description

Default

EXPRESS_SERVER_URL

URL of the canvas server

http://localhost:3000

ENABLE_CANVAS_SYNC

Enable real-time canvas sync

true


Claude Desktop

Config location:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

Local (node)

{ "mcpServers": { "excalidraw": { "command": "node", "args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"], "env": { "EXPRESS_SERVER_URL": "http://localhost:3000", "ENABLE_CANVAS_SYNC": "true" } } } }

Docker

{ "mcpServers": { "excalidraw": { "command": "docker", "args": [ "run", "-i", "--rm", "-e", "EXPRESS_SERVER_URL=http://host.docker.internal:3000", "-e", "ENABLE_CANVAS_SYNC=true", "ghcr.io/yctimlin/mcp_excalidraw:latest" ] } } }

Claude Code

Use the claude mcp add command to register the MCP server.

Local (node) - User-level (available across all projects):

claude mcp add excalidraw --scope user \ -e EXPRESS_SERVER_URL=http://localhost:3000 \ -e ENABLE_CANVAS_SYNC=true \ -- node /absolute/path/to/mcp_excalidraw/dist/index.js

Local (node) - Project-level (shared via .mcp.json):

claude mcp add excalidraw --scope project \ -e EXPRESS_SERVER_URL=http://localhost:3000 \ -e ENABLE_CANVAS_SYNC=true \ -- node /absolute/path/to/mcp_excalidraw/dist/index.js

Docker

claude mcp add excalidraw --scope user \ -- docker run -i --rm \ -e EXPRESS_SERVER_URL=http://host.docker.internal:3000 \ -e ENABLE_CANVAS_SYNC=true \ ghcr.io/yctimlin/mcp_excalidraw:latest

Manage servers:

claude mcp list # List configured servers claude mcp remove excalidraw # Remove a server

Cursor

Config location: .cursor/mcp.json in your project root (or ~/.cursor/mcp.json for global config)

Local (node)

{ "mcpServers": { "excalidraw": { "command": "node", "args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"], "env": { "EXPRESS_SERVER_URL": "http://localhost:3000", "ENABLE_CANVAS_SYNC": "true" } } } }

Docker

{ "mcpServers": { "excalidraw": { "command": "docker", "args": [ "run", "-i", "--rm", "-e", "EXPRESS_SERVER_URL=http://host.docker.internal:3000", "-e", "ENABLE_CANVAS_SYNC=true", "ghcr.io/yctimlin/mcp_excalidraw:latest" ] } } }

Codex CLI

Use the codex mcp add command to register the MCP server.

Local (node)

codex mcp add excalidraw \ --env EXPRESS_SERVER_URL=http://localhost:3000 \ --env ENABLE_CANVAS_SYNC=true \ -- node /absolute/path/to/mcp_excalidraw/dist/index.js

Docker

codex mcp add excalidraw \ -- docker run -i --rm \ -e EXPRESS_SERVER_URL=http://host.docker.internal:3000 \ -e ENABLE_CANVAS_SYNC=true \ ghcr.io/yctimlin/mcp_excalidraw:latest

Manage servers:

codex mcp list # List configured servers codex mcp remove excalidraw # Remove a server

OpenCode

Config location: ~/.config/opencode/opencode.json or project-level opencode.json

Local (node)

{ "$schema": "https://opencode.ai/config.json", "mcp": { "excalidraw": { "type": "local", "command": ["node", "/absolute/path/to/mcp_excalidraw/dist/index.js"], "enabled": true, "environment": { "EXPRESS_SERVER_URL": "http://localhost:3000", "ENABLE_CANVAS_SYNC": "true" } } } }

Docker

{ "$schema": "https://opencode.ai/config.json", "mcp": { "excalidraw": { "type": "local", "command": ["docker", "run", "-i", "--rm", "-e", "EXPRESS_SERVER_URL=http://host.docker.internal:3000", "-e", "ENABLE_CANVAS_SYNC=true", "ghcr.io/yctimlin/mcp_excalidraw:latest"], "enabled": true } } }

Antigravity (Google)

Config location: ~/.gemini/antigravity/mcp_config.json

Local (node)

{ "mcpServers": { "excalidraw": { "command": "node", "args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"], "env": { "EXPRESS_SERVER_URL": "http://localhost:3000", "ENABLE_CANVAS_SYNC": "true" } } } }

Docker

{ "mcpServers": { "excalidraw": { "command": "docker", "args": [ "run", "-i", "--rm", "-e", "EXPRESS_SERVER_URL=http://host.docker.internal:3000", "-e", "ENABLE_CANVAS_SYNC=true", "ghcr.io/yctimlin/mcp_excalidraw:latest" ] } } }

Notes

  • Docker networking: Use host.docker.internal to reach the canvas server running on your host machine. On Linux, you may need --add-host=host.docker.internal:host-gateway or use 172.17.0.1.

  • Canvas server: Must be running before the MCP server connects. Start it with npm run canvas (local) or docker run -d -p 3000:3000 ghcr.io/yctimlin/mcp_excalidraw-canvas:latest (Docker).

  • Absolute paths: When using local node setup, replace /absolute/path/to/mcp_excalidraw with the actual path where you cloned and built the repo.

  • In-memory storage: The canvas server stores elements in memory. Restarting the server will clear all elements. Use the export/import scripts if you need persistence.

Agent Skill (Optional)

This repo includes a skill at skills/excalidraw-mcp/ that provides:

  • Workflow playbook (SKILL.md): step-by-step guidance for drawing, refining, and exporting diagrams

  • Cheatsheet (references/cheatsheet.md): MCP tool and REST API reference

  • Helper scripts (scripts/*.cjs): export, import, clear, healthcheck, CRUD operations

The skill complements the MCP server by giving your AI agent structured workflows to follow.

Install The Skill (Codex CLI example)

mkdir -p ~/.codex/skills cp -R skills/excalidraw-mcp ~/.codex/skills/excalidraw-mcp

To update an existing installation, remove the old folder first (rm -rf ~/.codex/skills/excalidraw-mcp) then re-copy.

Install The Skill (Claude Code)

User-level (available across all your projects):

mkdir -p ~/.claude/skills cp -R skills/excalidraw-mcp ~/.claude/skills/excalidraw-mcp

Project-level (scoped to a specific project, can be committed to the repo):

mkdir -p /path/to/your/project/.claude/skills cp -R skills/excalidraw-mcp /path/to/your/project/.claude/skills/excalidraw-mcp

Then invoke the skill in Claude Code with /excalidraw-mcp.

To update an existing installation, remove the old folder first then re-copy.

Use The Skill Scripts

All scripts respect EXPRESS_SERVER_URL (default http://localhost:3000) or accept --url.

EXPRESS_SERVER_URL=http://127.0.0.1:3000 node skills/excalidraw-mcp/scripts/healthcheck.cjs EXPRESS_SERVER_URL=http://127.0.0.1:3000 node skills/excalidraw-mcp/scripts/export-elements.cjs --out diagram.elements.json EXPRESS_SERVER_URL=http://127.0.0.1:3000 node skills/excalidraw-mcp/scripts/import-elements.cjs --in diagram.elements.json --mode batch

When The Skill Is Useful

  • Repository workflow: export elements as JSON, commit it, and re-import later.

  • Reliable refactors: clear + re-import in sync mode to make canvas match a file.

  • Automated smoke tests: create/update/delete a known element to validate a deployment.

  • Repeatable diagrams: keep a library of element JSON snippets and import them.

See skills/excalidraw-mcp/SKILL.md and skills/excalidraw-mcp/references/cheatsheet.md.

MCP Tools (High Level)

The MCP server exposes tools such as:

  • create_element, update_element, delete_element

  • query_elements, get_resource

  • batch_create_elements

  • align_elements, distribute_elements

  • group_elements, ungroup_elements

  • lock_elements, unlock_elements

  • create_from_mermaid (frontend converts Mermaid to Excalidraw elements)

The full tool list and schemas are discoverable via MCP Inspector (tools/list) or by reading src/index.ts.

Testing

Canvas Smoke Test (HTTP)

curl http://localhost:3000/health

MCP Smoke Test (MCP Inspector)

List tools:

npx @modelcontextprotocol/inspector --cli \ -e EXPRESS_SERVER_URL=http://localhost:3000 \ -e ENABLE_CANVAS_SYNC=true -- \ node dist/index.js --method tools/list

Create a rectangle:

npx @modelcontextprotocol/inspector --cli \ -e EXPRESS_SERVER_URL=http://localhost:3000 \ -e ENABLE_CANVAS_SYNC=true -- \ node dist/index.js --method tools/call --tool-name create_element \ --tool-arg type=rectangle --tool-arg x=100 --tool-arg y=100 \ --tool-arg width=300 --tool-arg height=200

Frontend Screenshots (agent-browser)

If you use agent-browser for UI checks:

agent-browser install agent-browser open http://127.0.0.1:3000 agent-browser wait --load networkidle agent-browser screenshot /tmp/canvas.png

Troubleshooting

  • Canvas not updating: confirm EXPRESS_SERVER_URL points at the running canvas server.

  • Updates/deletes fail after batch creation: ensure you are on a build that includes the batch id preservation fix (merged via PR #34).

Known Issues / TODO

The following issues are known and tracked for future improvement:

  • align_elements: These tools log and return success but do not actually move elements. Implementation needed in src/index.ts:782-806.

  • points: The Zod schema expects [{x, y}] objects but Excalidraw expects [[x, y]] tuples. This may cause issues when creating arrows/lines via MCP. See src/index.ts:187 vs src/types.ts:64.

  • label: The label type is defined in EXCALIDRAW_ELEMENT_TYPES but has no corresponding interface in the type union. See src/types.ts:109,118.

  • HTTP transport mode placeholder: MCP_TRANSPORT_MODE=http is accepted but falls back to stdio. See src/index.ts:989-996.

  • ungroup_elements: Returns success even when no elements are ungrouped (e.g., elements not found). See src/index.ts:765-769.

Contributions welcome!

Development

npm run type-check npm run build

Latest Blog Posts

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/yctimlin/mcp_excalidraw'

If you have feedback or need assistance with the MCP directory API, please join our Discord server