excalix
Generates architecture diagrams as editable Excalidraw files with automatic layout, hand-drawn styling, labeled and bound arrows, plus SVG and PNG exports.
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., "@excalixGenerate an Excalidraw architecture diagram from this topology spec"
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.
excalix
Architecture diagrams from a topology spec, drawn in Excalidraw's hand-drawn style. You say what exists and what talks to what, and excalix decides where everything goes.

Why
An .excalidraw file is all geometry. Every box carries an x, a y, a width and a height, every label has to be measured in Excalifont before it can be centred, and an arrow only stays attached to its boxes if it is bound to them by element id and a fixed point on the border. Ask an agent to "sketch the architecture in Excalidraw" and it has to invent every one of those numbers. What comes back tends to have boxes sitting on top of each other and text that re-wraps the moment the file is opened, and the arrows are plain lines, so they stay behind when you drag a node.
People have a milder version of the same problem. The diagram in the design doc was laid out by hand a long time ago, nobody wants to move twelve boxes to fit one new queue, and so it slowly stops matching the system.
excalix splits the job. The caller owns topology: nodes with a kind, the edges between them, and any groups such as a VPC or a cluster that they sit in. Everything geometric belongs to the tool, which covers layout, the shape and colour for each kind, text measurement, arrow binding, and element ids and seeds. Nothing visual is configurable. Two diagrams made a year apart by different agents still look like one set, and because the same spec always produces a byte-identical .excalidraw, on a laptop and in CI alike, a diagram change shows up as a reviewable diff in a pull request. (Labels with emoji or CJK are the exception: those glyphs come from a system font, which measures differently per platform.)
What lands on disk is a real .excalidraw file next to an SVG and a PNG. Drop it on excalidraw.com and the labels and arrow bindings are all intact, so you can keep editing by hand from wherever the generator stopped.
Related MCP server: Excalidraw MCP Server
Quick start
pnpm install
pnpm exec playwright install chromium
pnpm build
node dist/cli.js render examples/order-pipeline.json -o out/order-pipelineThe Chromium download is required. Excalidraw's export code and the font measurement both run inside a headless browser.
excalix render <spec.json> [-o <basename>] write <basename>.excalidraw, .svg and .png
excalix validate <spec.json> check the spec, print its counts or every problem
excalix schema print the JSON Schema of the spec
excalix mcp serve the sketch tool over stdiorender defaults the basename to the spec path without its extension. A trailing slash on -o means a directory.
The spec
examples/order-pipeline.json drew the diagram above:
{
"title": "order pipeline",
"direction": "lr",
"groups": [
{ "id": "aws", "label": "AWS eu-north-1" },
{ "id": "k8s", "label": "EKS", "parent": "aws" }
],
"nodes": [
{ "id": "web", "label": "Web app", "kind": "client" },
{ "id": "api", "label": "Order API", "kind": "service", "group": "k8s" },
{ "id": "worker", "label": "Fulfilment", "kind": "service", "group": "k8s" },
{ "id": "q", "label": "orders.created", "kind": "queue", "group": "aws" },
{ "id": "pg", "label": "Postgres", "kind": "datastore", "group": "aws" },
{ "id": "redis", "label": "Redis", "kind": "cache", "group": "aws" },
{ "id": "stripe", "label": "Stripe", "kind": "external" }
],
"edges": [
{ "from": "web", "to": "api", "label": "POST /orders" },
{ "from": "api", "to": "pg" },
{ "from": "api", "to": "redis", "arrows": "both" },
{ "from": "api", "to": "q", "style": "async" },
{ "from": "q", "to": "worker", "style": "async" },
{ "from": "worker", "to": "stripe", "label": "charge" }
]
}node.kind fixes a node's shape and colour:
kind | what it is |
| people, browsers, mobile apps, anything that initiates requests |
| an application component you run, or managed infrastructure you configure inside your own boundary: load balancer, CDN, API gateway, DNS |
| database or durable storage |
| message queue, topic, or stream |
| cache or in-memory store |
| a system another company operates and you only call, such as a payment API or a hosted identity provider |
The line between service and external is who operates the thing. An ALB or a CloudFront distribution is configuration you own, so it draws as a service; Stripe sits on somebody else's side of the boundary and you only call it, so it is external.
edge.style says how the two ends talk, and edge.arrows says which ends get an arrowhead:
value | meaning |
| request/response, solid arrow |
| message or event, dashed arrow |
| one arrowhead, at the target |
| an arrowhead at each end, for a bidirectional link |
| no arrowhead, a plain association |
direction is lr by default, or tb for top to bottom; examples/auth-flow.json is a top-to-bottom one without groups. Groups nest through parent, and a node names at most one of them: a component that spans two boundaries goes in the one it runs in, with an edge across the border for the other relationship.
Siblings keep the order the spec lists them in, as far as edge crossings allow, so it pays to write the nodes in reading order. That is the whole of what order does. It places siblings next to each other and has no say in where an arrow is routed, so reshuffling the edges array to chase a route is wasted effort; what changes a layout is the direction of an edge, which nodes share a group, and direction.
An edge label rides on its arrow and reserves that much width in the layout, which is why a short one is worth the effort: put a sentence on an edge and the whole diagram stretches to fit it. A \n in any label starts a new line. An edge may loop from a node back to itself, and two edges between the same pair stay two arrows.
One diagram holds about twenty nodes before it stops being readable at a glance, and fewer when they run in a single chain, which stretches one way and stays thin the other. Beyond that the PNG gets big enough that anyone looking at it scaled down, an agent especially, starts losing thin lines and small labels. Split the system into an overview and a detail diagram instead; render and the sketch tool both add a line saying so once the longest side of the PNG passes 6000 pixels.
Unknown keys are rejected, and excalix validate reports every problem at once, so a typo costs one round trip instead of several. Each line names the path, shows what it found and says what would have been valid, and an id that is nearly right comes back with the id it is nearly:
edges[0].to: unknown node "apy", did you mean "api"?
nodes[2].kind: got "db", expected one of "client", "service", "datastore", "queue", "cache", "external"A spec with nothing wrong prints ok: 7 nodes, 6 edges, 2 groups and exits 0. excalix schema prints the full JSON Schema.
For agents
excalix mcp is an MCP server with one tool, sketch. Its input is the spec plus an optional out basename (default diagrams/<title slug>, resolved against the server's working directory). It returns the three written paths and then the PNG inline, so the calling agent sees the diagram in the same turn it asked for it and can send back an adjusted spec. The same paths come back as structured content too, with the pixel size of that PNG next to them; a client that ignores structured content loses nothing.
The tool advertises the spec schema that excalix schema prints, with out added. Both are serialized from the same zod schema, and a test compares them so the two cannot drift apart. A spec it turns down comes back as the problem list excalix validate prints, every problem in the one call, so fixing a bad spec costs one round trip there too.
Register it with Claude Code for every project:
claude mcp add excalix --scope user -- node /absolute/path/to/excalix/dist/cli.js mcpThe repo's .mcp.json does the same at project scope through a relative path, which only resolves when the client starts inside this repo. Agents that prefer the CLI can read skills/excalix/SKILL.md.
How it works
The spec is validated with zod. Labels are measured with canvas measureText against the real Excalifont in headless Chromium, because a label sized with the wrong metrics re-wraps when the file is opened in the editor. ELK lays out the graph in layers, with groups as compound nodes and orthogonal edges. The element builder derives every id and seed from a hash of the spec, and @excalidraw/utils exports the SVG and PNG inside the same browser page.
DESIGN.md is the full contract, module by module. stress/ holds adversarial specs (dense nested groups in both directions, self loops and repeated pairs, long labels, groups nested three deep); render them and look at the PNGs before trusting a layout change.
Development
pnpm test vitest; the suites under src/render/ launch Chromium
pnpm typecheck tsc --noEmitLicense
MIT. excalix is an independent project and is not affiliated with Excalidraw; it builds on @excalidraw/utils, which is MIT licensed too.
This server cannot be deployed
Maintenance
Related MCP Connectors
Create and edit architecture diagrams from your AI agent; get an SVG and a live editable canvas.
Generate cloud architecture diagrams, flowcharts, and sequence diagrams.
Create and edit collaborative architecture diagrams with any AI assistant using the Trident 2D DSL.
Discover cloud shapes and create, inspect, validate, patch, and review architecture diagrams.
Related MCP Servers
- AlicenseBqualityAmaintenanceAn MCP server that generates beautiful Excalidraw architecture diagrams with perfect auto-layout, stateful editing, and architecture-aware component styling.26313 PyPI151MIT
- FlicenseAqualityBmaintenanceGenerates beautiful Excalidraw diagrams from natural language descriptions using a local llama.cpp LLM, entirely offline.3-
- AlicenseAqualityDmaintenanceGenerates Excalidraw architecture diagrams with support for 60+ components including GCP, Kafka, and AI/Agentic shapes. Provides MCP tools for creating, modifying, and converting diagrams from structured input or Mermaid syntax.41MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to build, edit, organize, and export Excalidraw diagrams (architecture, flowcharts, etc.) entirely headless, producing .excalidraw files, SVG, and PNG renders.3,095 npmMIT