mcp_excalidraw replaced its browser tab with a Node renderer and kept the tab as a flag
MCP server and Claude Code skill for Excalidraw — programmatic canvas toolkit to create, edit, and export diagrams via AI agents with real-time canvas sync.
At a glance
- What is it?
- A Model Context Protocol server, a command line tool and an agent skill over one persistent Excalidraw canvas, twenty-six tools, two processes and a comparison table against the official Excalidraw server. The current release replaces browser-based screenshots with an SVG exporter running under Node, rasterised by a native library, and claims byte-identical output for an unchanged scene.
- Who is it for?
- Adopt this if your agent needs to produce diagrams that live in your repository as files, because that is the specific thing it does and the export format is the point. The loop it closes, draw, look at a screenshot, fix the element that overlaps, look again, is genuinely different from asking for a picture.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- yctimlin/mcp_excalidraw2,647 ★ · +234
| Repository | 2026-09-11 | 2026-11-14 |
|---|---|---|
| yctimlin/mcp_excalidraw | 2.4k | 2.6k |
234 Stars in the last 64 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Screenshots stopped needing a browser tab
The current release line is headless rendering, and the change is worth understanding because it is the difference between a tool that works in continuous integration and one that does not. Previously, taking a screenshot or exporting an image meant driving a real browser tab showing the canvas. Now the exporter from Excalidraw itself runs inside Node under a DOM emulation library, and a native rasteriser turns its SVG into a PNG, with four font families bundled in so the output does not depend on the host's fonts. The page claims three things about this: the same output as the tab, determinism in the sense that an unchanged scene renders byte-identically, and a few milliseconds per render. The old path is still there behind a renderer flag on the command line, which is the right way to keep a behavioural escape hatch. There is also a new command that renders a committed diagram file to an image with no canvas server running at all.
Zero-size elements used to export as invisible
Two bugs from the same release are worth naming because they describe a whole class of failure in this kind of tool. The first: shapes created without a width or a height collapsed to zero by zero in exports and renders, so they appeared on the canvas but vanished in the image. The fix gives them a default of one hundred by one hundred to match what the canvas shows. The second is the same disease in text: a scene stored with zero width and zero height, which is what a server older than version two wrote, exported as invisible text, and is now re-measured on export instead. The second one carries an issue number, which is a good sign about how the project handles reports. Together they say something useful about the format: a scene file is a document with numeric geometry that different producers fill in differently, and any tool reading it has to defend against the zeros.
It speaks a protocol revision with no handshake, and keeps the old handshake
The server declares support for a dated protocol revision, in this case one from July 2026, and describes what that revision changes: clients may call tools statelessly, with no initialisation step, using a discovery call and a per-request metadata envelope. Clients from the previous generation still work, because those open with the initialisation call as before. That combination, new and old in one binary, is the interesting engineering claim here, and it is the kind of thing that is either cheap or very expensive depending on how the protocol layer is structured. The runtime floor moved in the same release, from Node 18 to Node 20, and the stated reason is that version two of the protocol's TypeScript library sets it. Everything else was kept backward compatible, including existing client configurations, which is the right boundary to draw for a tool people have already wired into editors.
The canvas binds to all interfaces in Docker and the project tests the local bind
Two facts that only make sense together. The canvas server serves a web interface, a REST API and a real-time sync channel, and its documented default address is a loopback address on port three thousand. In the container configuration, that is overridden: the host variable is set to all interfaces, port three thousand is published to the host, cross-origin access is enabled as a dependency, and a health check polls a health endpoint every thirty seconds with a forty-second grace period. Since this is a server that can read and rewrite a diagram, that is the line to think about before running it anywhere shared. The mitigation is that the project has a check for it: one of the three scripts in the default test command inspects the local bind. So the loopback default is not merely documented, it is verified by a test that runs before the render checks.
The MCP-only compose scenario contradicts its own dependency
The compose file documents three ways to run it in comments at the top: canvas only, MCP only, and both together through a profile. The second of those says to bring up just the MCP service and notes that it requires a canvas running elsewhere. But the MCP service declares a dependency on the canvas container with the condition that the canvas must be healthy, and that dependency is inside the same service definition as the profile that gates the combined scenario. So the documented MCP-only invocation is in tension with the declared dependency: bringing up the MCP service alone would ask the orchestrator to start the canvas too. Both services also set the environment variable that disables canvas auto-start, the MCP container because it ships no user interface build and would otherwise serve a blank page, which is a neat piece of self-knowledge in a build file. Both images are built locally rather than pulled, and the MCP one keeps standard input open with a terminal attached, because it speaks a protocol over those two streams.
Three checks, each of which rebuilds the server first
The default test command is a chain of three named checks: one for the protocol over standard streams, one for the local bind, and one for rendering. Each one starts by rebuilding the server, so a full run compiles the TypeScript three times. That is slow and it is also the reason the checks are honest, because they exercise the compiled artefact rather than the sources. A fourth entry point runs the full build and hands off to a browser-driven suite, configured by its own file at the root, which is where the canvas interface itself gets tested. The production image is a two-stage build as well, compiling in one stage and copying only the compiled output and production dependencies into a slim runtime stage, where a non-root account is created with a fixed numeric identifier and given ownership of the application directory before the runtime command runs.
The comparison with the official server is twelve rows long
The page includes a side-by-side table against the official Excalidraw protocol server, and it is the most informative paragraph in the documentation because every row is a design decision rather than a feature. The official server is a chat widget that streams a finished diagram, giving the model two tools: a format reference and a create-view call. This project is element-level control over a persistent canvas, with create, read, update and delete per element, structured description plus screenshots so the model can see its own output, layout operations such as align, distribute, group, lock and duplicate, file import and export, named server-side snapshots, Mermaid conversion, viewport control, and multiple agents working on the same canvas concurrently. The summary the page settles on is that the official server shows diagrams in a chat, while this one gives a coding agent a workbench. Two claims in the table are the load-bearing ones: byte-stable rendering and concurrency, and both are things a reader should test on their own diagrams.
Local rendering, fonts and sharing
The naming runs to four conventions: the repository uses an underscore in its name, the published package uses a hyphen and a server suffix, the command exposes two binaries sharing one file, and the compose images use a third spelling. None of it is a problem, and it is all in one repository to check, but it is the kind of friction that costs a confused first-time user. The privacy story is equally short and worth stating in full. Core drawing is local and needs no keys, Mermaid conversion happens in the local canvas, and the optional share command uploads an encrypted scene to Excalidraw. The README also states that the canvas page loads fonts from the esm.sh CDN, so an offline or privacy-sensitive deployment should verify its network behavior. There is a second export to a shareable link for the same kind of artefact. Check the configured endpoint and deployment before sharing sensitive diagrams.
Editorial conclusion
Adopt this if your agent needs to produce diagrams that live in your repository as files, because that is the specific thing it does and the export format is the point. The loop it closes, draw, look at a screenshot, fix the element that overlaps, look again, is genuinely different from asking for a picture. Two things to check before you wire it into a pipeline. First, where the canvas listens: the default is a loopback address, but the container configuration overrides that to all interfaces on a published port, with cross-origin access enabled and a health endpoint, so a shared or hosted machine needs a firewall decision. Second, what you are trusting for visual verification: the renderer claims byte-identical output for an unchanged scene, which is the property you want, and it bundles four font families so that the claim does not depend on what fonts the machine has.
Frequently asked questions
What is mcp_excalidraw?
It is an MIT licensed Model Context Protocol server, command line tool and agent skill that gives AI agents a live Excalidraw canvas they can draw on, inspect, refine and export. It ships twenty-six tools over standard streams, a REST API for other frameworks, and an agent skill for coding agents, all driving one canvas server with real-time synchronisation.
Does mcp_excalidraw need API keys or a browser?
Core drawing requires no API key, and headless image exports use a Node renderer. The canvas page loads fonts from the esm.sh CDN, while optional sharing uploads an encrypted scene to Excalidraw. Check network access and privacy requirements for your deployment.
What is the difference between mcp_excalidraw and the official Excalidraw MCP?
The page's table has twelve rows. The official server is a one-shot chat widget giving the model a format reference and a create-view tool. This project is a persistent canvas with element-level create, read, update and delete, structured description and screenshot tools so the agent can see its work, layout operations, diagram files you can commit, named server-side snapshots, Mermaid conversion, viewport control, and support for several agents on one canvas.
How do I run mcp_excalidraw in Docker?
The compose file documents three modes: the canvas service alone, the MCP service alone which the comment says needs a canvas elsewhere, and both together through a profile. Both services disable canvas auto-start through an environment variable, the MCP container sets it because it ships no interface build, and the MCP container keeps standard input open with a terminal attached because it speaks its protocol over those streams.
What Node version does mcp_excalidraw need?
Node 20 or newer. The version 2.0 release notes record the floor moving from 18 because version two of the protocol's TypeScript library requires it, and state that everything else stayed backward compatible, including existing client configurations. The container images are built on a slim Node 20 base.
How does mcp_excalidraw verify itself?
The default test command chains three checks, each of which rebuilds the server first: one exercising the protocol over standard streams, one inspecting that the server binds locally, and one rendering. A separate entry point runs a full build and then a browser-driven suite. The protocol library itself is pinned exactly, while the rest of the dependencies use floating ranges.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/yctimlin-mcp-excalidraw)Star history chart for your README
[](https://hysenlabs.com/projects/yctimlin-mcp-excalidraw)Was this useful?