Developer platform
MCP server
Connect an AI agent to your Excaliwow account. The MCP server lets Claude and other clients create, read, render, and edit your diagrams through a small set of tools.
What it is
@excaliwow/mcp is a Model Context Protocol server that runs over stdio. Any MCP client (Claude Desktop, Claude Code, and others) launches it on demand with npx, so there is nothing to install or keep running yourself. The agent works against your hosted account through the same operations the CLI and REST API expose.
Install
Mint a Personal Access Token with read + write at excaliwow.com/app/settings (add delete only if you want the agent to trash and restore diagrams), then add the server to your MCP client and pass the token as EXCALIWOW_TOKEN.
Claude Code (CLI)
Export your token first, then add the server so the literal PAT never appears on the claude mcp add line (where it would land in your shell history). --scope local stores the server in your own settings, so the token never lands in a file you might commit either.
export EXCALIWOW_TOKEN=excw_pat_…
claude mcp add excaliwow \
--scope local \
--env EXCALIWOW_TOKEN="$EXCALIWOW_TOKEN" \
-- npx -y @excaliwow/mcpClaude Desktop (and other JSON-config clients)
Add this to claude_desktop_config.json (other clients have their own MCP settings file):
{
"mcpServers": {
"excaliwow": {
"command": "npx",
"args": ["-y", "@excaliwow/mcp"],
"env": {
"EXCALIWOW_TOKEN": "excw_pat_…"
}
}
}
}Floating package, visible version
Both snippets float so a version copied into these docs cannot go stale. A global or npx-cached copy can still shadow the current npm release, so the server prints its running version in your MCP client logs. If tools appear to be missing, run npx -y @excaliwow/mcp --version and use the troubleshooting steps below. For more on tokens and capabilities, see Authentication.
Tools
The server exposes eighteen tools, scoped to safe agent use. The Capability column is the PAT capability each tool requires.
| Tool | Capability | Description |
|---|---|---|
generate_diagram | write | Create a diagram from the node/edge DSL (auto-laid-out). Returns the editor URL. Best for a quick flowchart. |
create_scene | write | Create a rich, hand-authored diagram from a raw Excalidraw scene — full control of layout, style, and typography. The path for polished, custom diagrams. Author elements tersely; the Excalidraw boilerplate is filled in for you. |
read_diagram | read | Return a compact summary (title and per-type element counts) plus a rendered PNG. Pass includeGeometry to also get a bounded { id, type, label, x, y, w, h } bounds list for detecting layout collisions. |
get_scene | read | Return a diagram's full raw scene ({ elements, appState }) for editing — read it, mutate the elements, then regenerate_diagram with the edited scene. Distinct from read_diagram, which never emits raw JSON. |
export_diagram | read | Render a diagram to full-fidelity bytes for SAVING to a file (png base64, or svg as raw text). Unlike read_diagram (which returns an image for a vision model), this returns the bytes to keep — decode and write them in a client with filesystem access, or save via the CLI. |
list_diagrams | read | Page through the diagrams in your account (active or trash). |
move_diagram | write | Move a diagram into a folder, or back to the root. |
edit_diagram | write | Additively merge a DSL fragment: add nodes and edges, or update a node's style or label. |
trash_diagram | delete | Soft-delete a diagram to trash. Reversible — restore it with restore_diagram. Requires the delete capability. |
restore_diagram | delete | Restore a trashed diagram, reopening it at its original id and URL. Requires the delete capability. |
regenerate_diagram | write | Replace a diagram's contents in place from a fresh spec (re-run auto-layout) OR a raw scene, keeping the same id and URL — for iterating on one diagram instead of spawning new ones. |
patch_elements | write | Apply ordered, element-addressable deltas (add / update / move / resize / restyle / delete) in place by element id — the cheapest edit path, keeping the same id and URL. Pairs with read_diagram includeScene='compact'. |
generate_from_template | write | Create a diagram from a named layout template (swimlane, layered-stack, matrix, container-with-children) — supply a little data and auto-layout builds the container tree. |
lint_diagram | read | Check a diagram for machine-detectable layout and legibility defects (overlaps, clipped labels, out-of-frame elements, low-contrast text) as a bounded JSON list, so an agent can fix its own layout without a render. |
list_icons | read | List the curated icons you can embed in a diagram (id, label, category). Add an image element with fileId set to the icon id (e.g. "icon-database"); only ids returned here resolve. |
list_folders | read | List your folders (flat) as { id, name, parentId } — resolve a folder name to the id you pass as folderId when creating or moving a diagram. The only way to discover the id of an empty folder. |
create_folder | write | Create a folder to organize diagrams. Pass a name, and optionally a parentId to nest it; returns the new { id, name, parentId } to use as a folderId. |
rename_diagram | write | Change only a diagram's title, keeping the same id, URL, and contents — the cheap metadata edit, without pulling or rewriting the scene the way regenerate_diagram does. |
Safe by design
read_diagram returns a summary and a rendered PNG (optionally a compact element-bounds list with includeGeometry), never the raw scene. trash_diagram and restore_diagram are a reversible pair gated on the delete capability — a read + write token can't trash anything. Hard-deleting (purge) and making a diagram public are deliberately not agent tools, because they are irreversible — a misled agent cannot destroy or expose your diagrams. Purge or publish from the dashboard or the CLI instead.
Saving a diagram to a file. An MCP server runs over stdio and cannot write to your repo, so there are two ways to get the rendered file onto disk. export_diagram returns the bytes (png base64 or raw svg) for a client that can write files itself — e.g. in Claude Code, the agent decodes and saves them. Or skip the round-trip through the model and stream straight to disk with the CLI: excaliwow diagrams render <id> -o out.png (or --format svg -o out.svg — the CLI writes the format from --format, which defaults to png, not from the filename). The CLI path is also the fallback when a render is too large to return inline.
DSL discovery
The agent does not need to read these docs to write diagrams. The grammar and a worked example ride along in the generate_diagram tool description, and the full reference is served as an MCP resource at excaliwow://dsl/reference. You can read the same content in the Diagram DSL reference.
For the rich, hand-authored path, a compact authoring primer and a worked example ride in the create_scene tool description, and the full guide — every element type, all styling props, bindings, groups, frames, a recommended palette, and layout heuristics — is served as an MCP resource at excaliwow://scene/authoring.
Environment variables
| Variable | Type | Description |
|---|---|---|
EXCALIWOW_TOKEN* | string | Your Personal Access Token. Required for a standalone install. The server reads it per call from the environment and never writes it to disk. |
EXCALIWOW_API_URL | string | API origin. Defaults to https://excaliwow.com. Normally leave it unset. |
EXCALIWOW_MCP_DEBUG | string | Set to 1 to trace every tool call — name, status, duration, effective API origin, and request id — to stderr. The first thing to turn on when a call misbehaves or hits the wrong API. Unset by default. |
Troubleshooting
“Not authenticated” / 401 / the agent’s tool calls fail
The server starts even without a token (so it can list its tools), so a missing or invalid EXCALIWOW_TOKEN only surfaces when the agent first calls a tool. To check the token directly, run a health probe — it makes one authenticated read and prints a clear verdict:
npx -y @excaliwow/mcp --healthIt reports ok, 401 — token is invalid or expired, or that the API is unreachable. Starting the server with no token also prints a one-line EXCALIWOW_TOKEN is not set warning to stderr, and --version prints the installed version.
A tool call misbehaves or hits the wrong API
Set EXCALIWOW_MCP_DEBUG=1 in the server’s env block to trace each tool call — name, status, duration, the effective API origin, and the request id — as one line per call to stderr (stdout is the MCP transport). It is read per call, so you can flip it on without restarting.
Security notes
Treat the config like a secrets file
- Keep the token out of anything you commit. A project-scoped config that lives in the repo (e.g. a committed
.mcp.json, orclaude mcp add --scope project) puts the token into git history. Use a user- or local-scoped config (--scope local) instead, or reference an environment variable rather than pasting the literal token. Typing a literal token as a command argument also records it in your shell history (~/.zsh_history, fish history), so pass it through an exportedEXCALIWOW_TOKEN(--env EXCALIWOW_TOKEN="$EXCALIWOW_TOKEN") instead. - Mint the token with only the capabilities the tools use —
read+write.read_diagram,get_scene,export_diagram,list_diagrams,lint_diagram,list_icons, andlist_foldersneedread;generate_diagram,create_scene,edit_diagram,move_diagram,regenerate_diagram,patch_elements,generate_from_template,create_folder, andrename_diagramneedwrite. None of these read/write tools ever publish or delete, so aread+writetoken can neither expose your diagrams publicly nor delete them, even if the agent is misled. Adddeleteonly if you wanttrash_diagram/restore_diagram— that pair is reversible, but still grant it deliberately. Pick capabilities specifically — the coarseread-writepreset additionally grantspublishanddelete. - The token lives only in your MCP client config and environment. This server does not persist it, so protect that config the way you would any secrets file.