Excalidraw MCP
OFFICIAL SERVERDraws hand-drawn Excalidraw diagrams inline in the chat, with editing and export to excalidraw.com
A local Excalidraw canvas that assistants can draw on, inspect, screenshot and export to files
By yctimlin (individual) TypeScript Local · stdio Design
79 popularity score ★ 2.6k ↓ 3.2k/wk
Opens the app, which asks before it adds the server.
claude mcp add excalidraw -- npx -y mcp-excalidraw-server{
"mcpServers": {
"excalidraw": {
"command": "npx",
"args": [
"-y",
"mcp-excalidraw-server"
]
}
}
}{
"mcpServers": {
"excalidraw": {
"command": "npx",
"args": [
"-y",
"mcp-excalidraw-server"
]
}
}
}{
"servers": {
"excalidraw": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"mcp-excalidraw-server"
]
}
}
}[mcp_servers.excalidraw]
command = "npx"
args = ["-y", "mcp-excalidraw-server"]gemini mcp add --scope user excalidraw npx -- -y mcp-excalidraw-serverOpens the app, which asks before it adds the server.
docker run -d -p 3000:3000 --name mcp-excalidraw-canvas ghcr.io/yctimlin/mcp_excalidraw-canvas:latestclaude 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{
"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"
]
}
}
}{
"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"
]
}
}
}{
"servers": {
"excalidraw": {
"type": "stdio",
"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"
]
}
}
}[mcp_servers.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"]gemini mcp add --scope user excalidraw docker -- run -i --rm -e EXPRESS_SERVER_URL=http://host.docker.internal:3000 -e ENABLE_CANVAS_SYNC=true ghcr.io/yctimlin/mcp_excalidraw:latestOpens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.
git clone https://github.com/yctimlin/mcp_excalidraw.git
cd mcp_excalidraw
npm ci
npm run buildclaude mcp add excalidraw -- node '<ABSOLUTE_PATH_TO_CLONE>/dist/index.js'{
"mcpServers": {
"excalidraw": {
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/dist/index.js"
]
}
}
}{
"mcpServers": {
"excalidraw": {
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/dist/index.js"
]
}
}
}{
"servers": {
"excalidraw": {
"type": "stdio",
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/dist/index.js"
]
}
}
}[mcp_servers.excalidraw]
command = "node"
args = ["<ABSOLUTE_PATH_TO_CLONE>/dist/index.js"]gemini mcp add --scope user excalidraw node -- '<ABSOLUTE_PATH_TO_CLONE>/dist/index.js'EXPRESS_SERVER_URL |
Optional: Address of the canvas server the MCP server drives. |
|---|---|
ENABLE_CANVAS_SYNC |
Optional: Set to false to turn off syncing to the canvas. |
EXCALIDRAW_NO_AUTOSTART |
Optional: Set to 1 to stop the MCP server starting the canvas itself (the Docker MCP image sets it). |
EXCALIDRAW_EXPORT_DIR |
Optional: Folder that file paths for exports and imports must resolve inside. |
EXCALIDRAW_RENDER_MAX_DIM |
Optional: Largest side of a headless PNG in pixels. |
LOG_LEVEL |
Optional: Log detail: error, warn, info or debug. |
LOG_FILE_PATH |
Optional: Where the log file is written. |
| Set together: canvas server | |
PORT |
Optional: Port the canvas server listens on. |
HOST |
Optional: Address the canvas server binds to; 0.0.0.0 exposes the unauthenticated API. |
In a container, a setting goes in with -e NAME=value after docker run.
mcp-excalidraw-server runs an Excalidraw canvas on your own machine and gives an assistant element-level control over it. The assistant can add, read, change and delete single shapes, arrows and text, line them up, group or lock them, and then check its own work. It can ask for a text summary of the scene or a PNG screenshot and use these to fix labels that are cut off or shapes that overlap.
The package has two parts. A canvas server (web editor, REST API and WebSocket sync, on 127.0.0.1:3000 by default) holds the scene. The MCP server talks stdio to your client and drives that canvas, and it starts the canvas itself if nothing is listening. The same package also ships a command-line tool and an agent skill, and the project recommends those for coding agents. The MCP server is aimed at chat clients such as Claude Desktop. Version 2.1.2 registers 26 tools and no MCP resources or prompts.
Finished diagrams can be saved as .excalidraw files to commit next to code, or as .excalidraw.md files for the Obsidian Excalidraw plugin. They can also be exported as PNG or SVG, built from Mermaid text, or uploaded to excalidraw.com as an encrypted share link. Named snapshots let the assistant roll back within a session. Screenshots and image exports render without a browser since version 2.1.
The current README also documents durable canvas state (EXCALIDRAW_DATA_DIR) and a configurable share target for self-hosted Excalidraw (EXCALIDRAW_SHARE_UPLOAD_URL, EXCALIDRAW_SHARE_BASE_URL). Both were added on the main branch after the 2.1.2 release of 2026-10-04 and are not in the published npm package: at the v2.1.2 tag the share upload address is fixed in src/core/share-url.ts.
This is a community project, not the Excalidraw team's own MCP server. Its README contrasts the two: the official server streams one diagram into a chat, while this one keeps a lasting canvas that the assistant edits element by element.
| Runtime | Node.js 20+ |
|---|---|
| Runs on | macOS, Windows, Linux |
| Also |
|
Node.js 20 or later for the npx route; no account or API key. Docker is optional: the MCP image does not start a canvas, so run the separate canvas image (ghcr.io/yctimlin/mcp_excalidraw-canvas) first. Mermaid conversion and viewport control need the canvas page open at http://127.0.0.1:3000.
By default the canvas lives in memory, so a restart clears it unless EXCALIDRAW_DATA_DIR is set. Durable state supports one writer on a local file system, not network shares. Mermaid conversion and set_viewport do not work without an open browser tab. Headless renders only bundle fonts for Latin scripts, so CJK and emoji depend on fonts installed on the machine. The canvas page loads its hand-drawn fonts from the esm.sh CDN and falls back to system fonts when offline. The canvas API has no authentication of its own.
Suits developers who want an assistant to produce editable architecture diagrams or flowcharts, refine them over several steps and keep them in a repository. It runs locally with no key. For a terminal coding agent, its README points to the bundled CLI and skill rather than MCP setup. Teams that need share links on their own Excalidraw instance, or a canvas that survives restarts, have to build from main until a release carries those features. If you only want a quick one-off diagram shown inside a chat, the official Excalidraw MCP server (github.com/excalidraw/excalidraw-mcp) is the lighter choice: it streams a diagram from one prompt but has no element-level editing or file export.
7 only read, 16 change things, 3 can delete or overwrite. A ? marks an optional parameter.
create_element changestype: enumx: numbery: numberwidth?: numberheight?: numberid?: stringtext?: stringbackgroundColor?: stringstrokeColor?: stringstrokeWidth?: numberstrokeStyle?: stringroughness?: numberopacity?: numberfontSize?: numberfontFamily?: anystartElementId?: stringendElementId?: stringstartArrowhead?: stringendArrowhead?: stringget_elementid: stringupdate_element changesid: stringtype?: enumx?: numbery?: numberwidth?: numberheight?: numbertext?: stringbackgroundColor?: stringstrokeColor?: stringstrokeWidth?: numberstrokeStyle?: stringroughness?: numberopacity?: numberfontSize?: numberfontFamily?: anydelete_element deletesid: stringquery_elementstype?: enumfilter?: objectbbox?: objectbatch_create_elements changeselements: arrayduplicate_elements changeselementIds: arrayoffsetX?: numberoffsetY?: numberalign_elements changeselementIds: arrayalignment: enumdistribute_elements changeselementIds: arraydirection: enumgroup_elements changeselementIds: arrayungroup_elements changesgroupId: stringlock_elements changeselementIds: arrayunlock_elements changeselementIds: arraydescribe_sceneget_canvas_screenshotbackground?: booleanrenderer?: enumdark?: booleanscale?: numberpadding?: numberelementIds?: arrayframeId?: stringexport_scene changesfilePath?: stringimport_scene changesmode: enumfilePath?: stringdata?: stringexport_to_image changesformat: enumfilePath?: stringbackground?: booleanrenderer?: enumdark?: booleanscale?: numberpadding?: numberelementIds?: arrayframeId?: stringexport_to_excalidraw_url changescreate_from_mermaid changesmermaidDiagram: stringconfig?: objectclear_canvas deletessnapshot_scene changesname: stringrestore_snapshot deletesname: stringset_viewportscrollToContent?: booleanscrollToElementIds?: arrayscrollToElementId?: stringviewportZoomFactor?: numberzoom?: numberoffsetX?: numberoffsetY?: numberread_diagram_guideget_resourceresource: enum