excalidraw-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@excalidraw-mcpCreate a vertical flowchart with three steps: Start, Process, End."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
excalidraw-mcp
A file-based MCP server that makes Excalidraw diagrams a first-class data type for LLMs. The server owns all spatial reasoning – coordinate math, element bindings, text measurement, overlap detection – so the LLM operates purely at the semantic level of nodes and edges.
Supports both .excalidraw (raw JSON) and .excalidraw.md (Obsidian plugin format with LZ-String compression).
Best suited for: flowcharts, state machines, ER diagrams, architecture diagrams, and other graph-shaped diagrams – rectangles, ellipses, and diamonds connected by arrows.
Not suited for: wireframes, freeform sketches, annotated screenshots, or spatial layouts where precise pixel positioning matters more than connectivity. These elements are still readable via read_diagram (they appear in the other bucket) but cannot be created through the semantic API.
Install
bun add excalidraw-mcpOr build from source:
git clone https://github.com/dtour/excalidraw-mcp.git
cd excalidraw-mcp
bun install && bun run buildFor PNG rendering support (optional – SVG works out of the box):
bun add @resvg/resvg-jsRelated MCP server: Excalidraw MCP Server
Configure
Claude Code (~/.claude/settings.json):
{
"mcpServers": {
"excalidraw": {
"command": "bunx",
"args": ["excalidraw-mcp"]
}
}
}Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"excalidraw": {
"command": "bunx",
"args": ["excalidraw-mcp"]
}
}
}Or point directly to a local build:
{
"mcpServers": {
"excalidraw": {
"command": "node",
"args": ["/path/to/excalidraw-mcp/dist/index.js"]
}
}
}Tools
read_diagram
Parse any Excalidraw file and return a semantic GraphSummary.
{ "path": "./diagram.excalidraw" }Returns nodes, edges, groups, and an other bucket for non-graph elements (freehand, images, frames) – everything the LLM needs to reason about the diagram's structure:
{
"nodes": [
{ "id": "abc123", "type": "rectangle", "text": "API Gateway", "x": 100, "y": 50, "width": 180, "height": 60 }
],
"edges": [
{ "id": "def456", "from": "abc123", "to": "ghi789", "label": "REST" }
],
"groups": [],
"other": [],
"boundingBox": { "x": 50, "y": 20, "width": 600, "height": 400 }
}create_diagram
Create a new diagram from a declarative spec. The server handles coordinates, layout, bindings, and IDs. Output format is determined by file extension.
{
"path": "./flowchart.excalidraw",
"spec": {
"nodes": [
{ "type": "rectangle", "text": "Start" },
{ "type": "diamond", "text": "Decision?" },
{ "type": "rectangle", "text": "End" }
],
"edges": [
{ "from": "Start", "to": "Decision?" },
{ "from": "Decision?", "to": "End", "label": "yes" }
],
"layout": { "type": "vertical-flow", "spacing": 100 }
}
}Three layout algorithms are available:
Layout | Description |
| Nodes stacked top to bottom (default) |
| Nodes arranged left to right |
| N-column grid (set |
A low-level escape hatch is available for pixel-precise control:
{
"path": "./precise.excalidraw",
"spec": {
"elements": [{ "type": "rectangle", "x": 100, "y": 100, "width": 200, "height": 80 }]
}
}modify_diagram
Apply semantic operations to an existing diagram. All operations are atomic – if any fails, no changes are written.
{
"path": "./flowchart.excalidraw",
"operations": [
{ "type": "change_text", "target": "Start", "text": "Begin" },
{
"type": "add_node",
"spec": { "type": "rectangle", "text": "Retry" },
"position": { "type": "relative", "anchor": "End", "direction": "below" }
},
{ "type": "connect", "from": "End", "to": "Retry" },
{
"type": "restyle",
"target": "Decision?",
"style": { "backgroundColor": "#ffc9c9", "fillStyle": "solid" }
}
]
}Seven operations:
Operation | Description |
| Update an element's text content |
| Create a new shape with absolute or relative positioning |
| Delete an element and clean up all bindings |
| Create an arrow between two elements |
| Remove an arrow connection |
| Update visual properties (colors, stroke, fill, opacity) |
| Move an element to absolute coordinates or relative to another |
Target elements by ID or text content. If a text match is ambiguous (multiple elements share the same text), the server returns an error listing all candidates with their IDs so the LLM can disambiguate – it never silently picks the first match.
Relative positioning lets you place nodes relative to existing elements:
{ "type": "relative", "anchor": "Error", "direction": "right", "gap": 120 }Directions: above, below, left, right. Default gap is 80px.
render_diagram
Render to SVG (built-in, no dependencies) or PNG (requires optional @resvg/resvg-js).
{ "path": "./flowchart.excalidraw", "format": "svg", "scale": 1.5 }Returns an inline image so the LLM can visually verify its work. The built-in SVG renderer is useful for checking topology (are the right things connected?) but does not match Excalidraw's full visual fidelity – no roughness textures or hachure fills.
Style Reference
All style properties are optional and can be used with create_diagram node specs or modify_diagram's restyle operation.
Property | Values | Default |
| Any CSS color |
|
| Any CSS color or |
|
|
|
|
| Number (px) |
|
|
|
|
|
|
|
|
|
|
| Number (px) |
|
|
|
|
Resource
excalidraw://schema
Element type definitions, valid style properties, layout types, operation types, and example specs. MCP clients can load this on demand for validation and autocompletion.
Architecture
src/
├── index.ts # MCP server entry, tool registration
├── schemas/spec.ts # Zod input validation
├── tools/
│ ├── read.ts # read_diagram
│ ├── create.ts # create_diagram
│ ├── modify.ts # modify_diagram
│ └── render.ts # render_diagram
├── core/
│ ├── bindings.ts # Binding integrity engine
│ ├── elements.ts # Element factories (rect, ellipse, diamond, arrow)
│ ├── graph.ts # Raw elements → GraphSummary
│ ├── ids.ts # ID, seed, and nonce generation
│ ├── layout.ts # Auto-layout algorithms
│ ├── overlap.ts # Text–line overlap detection and nudging
│ ├── parser.ts # Format detection, .excalidraw / .excalidraw.md parsing
│ ├── resolve-target.ts # Target resolution with disambiguation errors
│ ├── serializer.ts # Serialization (JSON + LZ-String)
│ └── text.ts # Text measurement (character-width averages)
└── types/index.ts # TypeScript type definitionsDesign decisions
GraphSummary abstraction – the LLM sees a semantic graph (nodes, edges, groups), not raw Excalidraw elements. Non-graph elements like freehand drawings and images land in the
otherbucket, preserving round-trip fidelity.Binding integrity engine – Excalidraw uses bidirectional references between arrows and shapes. The engine validates and repairs these after every mutation, preventing orphaned or dangling bindings.
Atomic writes – files are written via temp file +
rename(2), so a crash mid-write never corrupts the original.Text measurement without native deps – pre-computed character-width tables for all five Excalidraw font families. Intentionally over-estimates by ~15% so containers never clip; Excalidraw recalculates precisely on load.
Development
bun install # Install dependencies
bun test # Run all tests (unit + property-based + integration)
bun run typecheck # Type-check without emitting
bun run dev # Run server directly
bun run build # Build to dist/Tests use bun:test with fast-check for property-based testing of the binding integrity engine and overlap resolution.
Known Limitations
Text sizing is approximate – character-width averages mean diagrams reflow slightly when opened in Excalidraw. Opening and saving in Excalidraw recalculates text metrics.
Straight-line arrow routing – arrows use direct point-to-point paths. Excalidraw applies its own curve routing when you open the file.
No appState/files round-trip – viewport position, theme, and embedded images are not preserved through edits.
No concurrency handling – concurrent writes to the same file use last-writer-wins semantics.
SVG renderer is simplified – useful for topology verification but does not reproduce Excalidraw's roughness textures or hachure fills.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
AI agent draws editable hand-drawn diagrams (flowchart, ER, architecture) via MCP, not static images
Shared semantic graph for AI reviews, classification and structured memory across AI assistants.
Shared long-term memory for AI agents: save and recall context as a searchable knowledge graph.
Create and edit architecture diagrams from your AI agent; get an SVG and a live editable canvas.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI agents to programmatically generate, edit, and view Excalidraw diagrams with real-time browser synchronization. It provides a suite of tools for adding shapes, text, and arrows to diagrams through natural language interactions.112,455 npm100MIT
- AlicenseNot gradedqualityFmaintenanceEnables AI agents to programmatically control a live Excalidraw canvas through element-level CRUD operations and real-time synchronization. It allows agents to iteratively build, inspect, and refine diagrams while providing visual feedback via screenshots and scene descriptions.1,645 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to programmatically control a live Excalidraw canvas with element-level CRUD operations and real-time synchronization. It supports iterative diagramming through scene descriptions, screenshots, and advanced layout tools for collaborative AI-human workflows.1,645 npm2MIT
- FlicenseAqualityBmaintenanceGenerates beautiful Excalidraw diagrams from natural language descriptions using a local llama.cpp LLM, entirely offline.3-