Excalidraw MCP for Codex
Give an AI assistant a canvas it can build, inspect, revise and export as an editable diagram.
Server & canvas integration development
The problem
A diagram is rarely finished after its first draft. A useful assistant needs to inspect the scene, correct the layout and export it while leaving the result editable by a person.
Engineering decision
I built around an edit–inspect–revise loop, rather than treating an exported image as the only output. Keeping a structured scene makes it possible to adjust individual elements and continue working in the canvas.
Demonstration and evidence
The browser editor runs the Excalidraw canvas engine only. The MCP integration is shown in an original application capture and a separate recorded local run with a small test scene. This page does not connect an assistant or MCP server.
Canvas editor
Interactive demo
Draw, edit and export with the Excalidraw canvas engine. No assistant or MCP server is connected to this browser demo; the recorded workflow below shows the local integration.

Recorded workflow
Create, inspect, revise, export and reopen a synthetic diagram, then edit the reopened element.
Recorded on . Version 0.1.1. These are recorded tool responses; opening them does not run a server or connect to your files. Source identity is in Verification details.
1. Create a small synthetic workflow
{
"name": "batch_create_elements",
"arguments": {
"elements": [
{
"id": "draft",
"type": "rectangle",
"x": 80,
"y": 100,
"width": 200,
"height": 90,
"label": {
"text": "Draft"
}
},
{
"id": "review",
"type": "rectangle",
"x": 380,
"y": 100,
"width": 200,
"height": 90,
"label": {
"text": "Review"
}
}
]
}
}
Created 2 element(s). Scene now has 2 element(s).
{
"created": 2,
"total": 2,
"ids": [
"draft",
"review"
]
}2. Inspect the created diagram
{
"name": "describe_scene",
"arguments": {}
}
Scene has 2 element(s). Bounds: 80,100 500x90.
{
"description": {
"count": 2,
"bounds": {
"x": 80,
"y": 100,
"width": 500,
"height": 90
},
"elements": [
{
"id": "draft",
"type": "rectangle",
"x": 80,
"y": 100,
"width": 200,
"height": 90,
"label": "Draft"
},
{
"id": "review",
"type": "rectangle",
"x": 380,
"y": 100,
"width": 200,
"height": 90,
"label": "Review"
}
]
}
}3. Revise the review step by stable ID
{
"name": "update_elements",
"arguments": {
"updates": [
{
"id": "review",
"backgroundColor": "#d3f9d8"
}
]
}
}
Updated 1 element(s).
{
"updated": 1,
"ids": [
"review"
]
}4. Export editable diagram data
{
"name": "export_scene",
"arguments": {
"filePath": "workflow.excalidraw"
}
}
Exported scene JSON to [synthetic workspace]\workflow.excalidraw.
{
"path": "[synthetic workspace]\\workflow.excalidraw",
"elements": 2
}5. Clear this disposable demonstration scene
{
"name": "clear_canvas",
"arguments": {}
}
Canvas cleared.
{
"total": 0
}6. Reopen the editable export
{
"name": "import_scene",
"arguments": {
"filePath": "workflow.excalidraw",
"mode": "replace"
}
}
Imported scene in replace mode. Scene now has 2 element(s).
{
"mode": "replace",
"total": 2
}7. Edit the reopened element to prove editability
{
"name": "update_elements",
"arguments": {
"updates": [
{
"id": "review",
"x": 400
}
]
}
}
Updated 1 element(s).
{
"updated": 1,
"ids": [
"review"
]
}8. Inspect the reopened revised element
{
"name": "query_elements",
"arguments": {
"id": "review"
}
}
Found 1 matching element(s).
{
"count": 1,
"matches": [
{
"backgroundColor": "#d3f9d8",
"strokeColor": "#1e1e1e",
"fillStyle": "hachure",
"strokeWidth": 2,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"angle": 0,
"groupIds": [],
"locked": false,
"id": "review",
"type": "rectangle",
"x": 400,
"y": 100,
"width": 200,
"height": 90,
"label": {
"text": "Review"
},
"version": 2,
"updated": 1790453223809
}
]
}Synthetic content only. Export paths are replaced with [synthetic workspace].
How it works
A local MCP server manages the scene and synchronizes it with an Excalidraw browser canvas through an HTTP/WebSocket bridge. Tools cover creating and inspecting elements, importing structured diagrams and exporting the result.
Collaboration & credits
Excalidraw supplies the drawing editor; the MCP SDK supplies the protocol foundation. My contribution is the server, scene tools, synchronization and workflow integration.
Verification details
The original browser test rendered a synchronized scene and verified PNG export. Type checking and the web/server build passed. Mermaid tests that timed out during a concurrent run passed unchanged in isolation.
- Evidence date
- Source revision
79a371e50a50c5b3b8f78427404a4f809838682d- Working tree
- clean
Revision recorded during the original local verification. This does not establish production readiness. Fresh synthetic MCP workflow recorded on 2026-09-26 from the same clean revision; earlier captures retain their original dates. The workflow JSON records the version and entry artifact hash.
- excalidraw-workflow.json
SHA-256: b324fd4af606f118df5d18d7b5b5c230d85a96496f49960bdfbbae35102037ad - excalidraw-workflow.excalidraw
SHA-256: 308389e04e960cfcbd9433569a6630db826db154e68336d222ed91e253a95f02 - excalidraw-canvas.png
SHA-256: 3bf12fe72265899c624336055b6d431a893089de46f5f07fb8e826aca01b0861
Publication checked : release source record. Public npm version and publication date checked in registry metadata; tarball integrity verified. The local demonstration has a separate revision/date and does not establish verification of this published artifact.
Source availability checked : public repository. GitHub repository metadata confirmed public source on this date. This does not establish a license, release, individual authorship or production readiness.