[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-83534":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":17,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":18,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":25,"readmeContent":26,"aiSummary":10,"trendingCount":16,"starSnapshotCount":16,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},83534,"mcp_excalidraw","yctimlin\u002Fmcp_excalidraw","yctimlin","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.","",null,"JavaScript",2040,217,12,29,0,13,39,86.82,"MIT License",false,"main",true,[],"2026-06-12 04:01:41","# Excalidraw MCP Server & Agent Skill\n\n[![CI](https:\u002F\u002Fgithub.com\u002Fyctimlin\u002Fmcp_excalidraw\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fyctimlin\u002Fmcp_excalidraw\u002Factions\u002Fworkflows\u002Fci.yml)\n[![Docker Build & Push](https:\u002F\u002Fgithub.com\u002Fyctimlin\u002Fmcp_excalidraw\u002Factions\u002Fworkflows\u002Fdocker.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fyctimlin\u002Fmcp_excalidraw\u002Factions\u002Fworkflows\u002Fdocker.yml)\n[![NPM Version](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Fmcp-excalidraw-server)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fmcp-excalidraw-server)\n[![License](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-MIT-blue.svg)](LICENSE)\n\nRun a live Excalidraw canvas and control it from AI agents. This repo provides:\n\n- **MCP Server**: Connect via Model Context Protocol (Claude Desktop, Cursor, Codex CLI, etc.)\n- **Agent Skill**: Portable skill for Claude Code, Codex CLI, and other skill-enabled agents\n\nKeywords: Excalidraw agent skill, Excalidraw MCP server, AI diagramming, Claude Code skill, Codex CLI skill, Claude Desktop MCP, Cursor MCP, Mermaid to Excalidraw.\n\n## Demo\n\n![MCP Excalidraw Demo](demo.gif)\n\n*AI agent creates a complete architecture diagram from a single prompt (4x speed). [Watch full video on YouTube](https:\u002F\u002Fyoutu.be\u002FufW78Amq5qA)*\n\n## Table of Contents\n\n- [Demo](#demo)\n- [What It Is](#what-it-is)\n- [How We Differ from the Official Excalidraw MCP](#how-we-differ-from-the-official-excalidraw-mcp)\n- [What's New](#whats-new)\n- [Quick Start (Local)](#quick-start-local)\n- [Quick Start (Docker)](#quick-start-docker)\n- [Configure MCP Clients](#configure-mcp-clients)\n  - [Claude Desktop](#claude-desktop)\n  - [Claude Code](#claude-code)\n  - [Cursor](#cursor)\n  - [Codex CLI](#codex-cli)\n  - [OpenCode](#opencode)\n  - [Antigravity (Google)](#antigravity-google)\n- [Agent Skill (Optional)](#agent-skill-optional)\n- [MCP Tools (26 Total)](#mcp-tools-26-total)\n- [Testing](#testing)\n- [Troubleshooting](#troubleshooting)\n- [Known Issues \u002F TODO](#known-issues--todo)\n- [Development](#development)\n\n## What It Is\n\nThis repo contains two separate processes:\n\n- Canvas server: web UI + REST API + WebSocket updates (default `http:\u002F\u002F127.0.0.1:3000`)\n- MCP server: exposes MCP tools over stdio; syncs to the canvas via `EXPRESS_SERVER_URL`\n\n## How We Differ from the Official Excalidraw MCP\n\nExcalidraw now has an [official MCP](https:\u002F\u002Fgithub.com\u002Fexcalidraw\u002Fexcalidraw-mcp) — it's great for quick, prompt-to-diagram generation rendered inline in chat. We solve a different problem.\n\n| | Official Excalidraw MCP | This Project |\n|---|---|---|\n| **Approach** | Prompt in, diagram out (one-shot) | Programmatic element-level control (26 tools) |\n| **State** | Stateless — each call is independent | Persistent live canvas with real-time sync |\n| **Element CRUD** | No | Full create \u002F read \u002F update \u002F delete per element |\n| **AI sees the canvas** | No | `describe_scene` (structured text) + `get_canvas_screenshot` (image) |\n| **Iterative refinement** | No — regenerate the whole diagram | Draw → look → adjust → look again, element by element |\n| **Layout tools** | No | `align_elements`, `distribute_elements`, `group \u002F ungroup` |\n| **File I\u002FO** | No | `export_scene` \u002F `import_scene` (.excalidraw JSON) |\n| **Snapshot & rollback** | No | `snapshot_scene` \u002F `restore_snapshot` |\n| **Mermaid conversion** | No | `create_from_mermaid` |\n| **Shareable URLs** | Yes | Yes — `export_to_excalidraw_url` |\n| **Design guide** | `read_me` cheat sheet | `read_diagram_guide` (colors, sizing, layout, anti-patterns) |\n| **Viewport control** | Camera animations | `set_viewport` (zoom-to-fit, center on element, manual zoom) |\n| **Live canvas UI** | Rendered inline in chat | Standalone Excalidraw app synced via WebSocket |\n| **Multi-agent** | Single user | Multiple agents can draw on the same canvas concurrently |\n| **Works without MCP** | No | Yes — REST API fallback via agent skill |\n\n**TL;DR** — The official MCP generates diagrams. We give AI agents a full canvas toolkit to build, inspect, and iteratively refine diagrams — including the ability to see what they drew.\n\n## What's New\n\n### v2.0 — Canvas Toolkit\n\n- 13 new MCP tools (26 total): `get_element`, `clear_canvas`, `export_scene`, `import_scene`, `export_to_image`, `duplicate_elements`, `snapshot_scene`, `restore_snapshot`, `describe_scene`, `get_canvas_screenshot`, `read_diagram_guide`, `export_to_excalidraw_url`, `set_viewport`\n- **Closed feedback loop**: AI can now inspect the canvas (`describe_scene`) and see it (`get_canvas_screenshot` returns an image) — enabling iterative refinement\n- **Design guide**: `read_diagram_guide` returns best-practice color palettes, sizing rules, layout patterns, and anti-patterns — dramatically improves AI-generated diagram quality\n- **Shareable URLs**: `export_to_excalidraw_url` encrypts and uploads the scene to excalidraw.com, returns a shareable link anyone can open\n- **Viewport control**: `set_viewport` with `scrollToContent`, `scrollToElementId`, or manual zoom\u002Foffset — agents can auto-fit diagrams after creation\n- **File I\u002FO**: export\u002Fimport full `.excalidraw` JSON files\n- **Snapshots**: save and restore named canvas states\n- **Skill fallback**: Agent skill auto-detects MCP vs REST API mode, gracefully falls back to HTTP endpoints when MCP server isn't configured\n- Fixed all previously known issues: `align_elements` \u002F `distribute_elements` fully implemented, points type normalization, removed invalid `label` type, removed HTTP transport dead code, `ungroup_elements` now errors on failure\n\n### v1.x\n\n- Agent skill: `skills\u002Fexcalidraw-skill\u002F` (portable instructions + helper scripts for export\u002Fimport and repeatable CRUD)\n- Better testing loop: MCP Inspector CLI examples + browser screenshot checks (`agent-browser`)\n- Bugfixes: batch create now preserves element ids (fixes update\u002Fdelete after batch); frontend entrypoint fixed (`main.tsx`)\n\n## Quick Start (Local)\n\nPrereqs: Node >= 18, npm\n\n```bash\nnpm ci\nnpm run build\n```\n\nTerminal 1: start the canvas\n```bash\nPORT=3000 npm run canvas\n```\n\n> **Security note:** The server defaults to binding on `127.0.0.1` only. If you need to expose it on a network interface (e.g. Docker, remote access), set `HOST=0.0.0.0` — but ensure you have network-level access controls in place, as the API has no built-in authentication.\n\nOpen `http:\u002F\u002F127.0.0.1:3000`.\n\nTerminal 2: run the MCP server (stdio)\n```bash\nEXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 node dist\u002Findex.js\n```\n\n## Quick Start (Docker)\n\nCanvas server:\n```bash\ndocker run -d -p 3000:3000 --name mcp-excalidraw-canvas ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw-canvas:latest\n```\n\nMCP server (stdio) is typically launched by your MCP client (Claude Desktop\u002FCursor\u002Fetc.). If you want a local container for it, use the image `ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw:latest` and set `EXPRESS_SERVER_URL` to point at the canvas.\n\n## Configure MCP Clients\n\nThe MCP server runs over stdio and can be configured with any MCP-compatible client. Below are configurations for both **local** (requires cloning and building) and **Docker** (pull-and-run) setups.\n\n### Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `EXPRESS_SERVER_URL` | URL of the canvas server | `http:\u002F\u002F127.0.0.1:3000` |\n| `ENABLE_CANVAS_SYNC` | Enable real-time canvas sync | `true` |\n\n---\n\n### Claude Desktop\n\nConfig location:\n- macOS: `~\u002FLibrary\u002FApplication Support\u002FClaude\u002Fclaude_desktop_config.json`\n- Windows: `%APPDATA%\\Claude\\claude_desktop_config.json`\n- Linux: `~\u002F.config\u002FClaude\u002Fclaude_desktop_config.json`\n\n**Local (node)**\n```json\n{\n  \"mcpServers\": {\n    \"excalidraw\": {\n      \"command\": \"node\",\n      \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fmcp_excalidraw\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"EXPRESS_SERVER_URL\": \"http:\u002F\u002F127.0.0.1:3000\",\n        \"ENABLE_CANVAS_SYNC\": \"true\"\n      }\n    }\n  }\n}\n```\n\n**Docker**\n```json\n{\n  \"mcpServers\": {\n    \"excalidraw\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-e\", \"EXPRESS_SERVER_URL=http:\u002F\u002Fhost.docker.internal:3000\",\n        \"-e\", \"ENABLE_CANVAS_SYNC=true\",\n        \"ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw:latest\"\n      ]\n    }\n  }\n}\n```\n\n---\n\n### Claude Code\n\nUse the `claude mcp add` command to register the MCP server.\n\n**Local (node)** - User-level (available across all projects):\n```bash\nclaude mcp add excalidraw --scope user \\\n  -e EXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 \\\n  -e ENABLE_CANVAS_SYNC=true \\\n  -- node \u002Fabsolute\u002Fpath\u002Fto\u002Fmcp_excalidraw\u002Fdist\u002Findex.js\n```\n\n**Local (node)** - Project-level (shared via `.mcp.json`):\n```bash\nclaude mcp add excalidraw --scope project \\\n  -e EXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 \\\n  -e ENABLE_CANVAS_SYNC=true \\\n  -- node \u002Fabsolute\u002Fpath\u002Fto\u002Fmcp_excalidraw\u002Fdist\u002Findex.js\n```\n\n**Docker**\n```bash\nclaude mcp add excalidraw --scope user \\\n  -- docker run -i --rm \\\n  -e EXPRESS_SERVER_URL=http:\u002F\u002Fhost.docker.internal:3000 \\\n  -e ENABLE_CANVAS_SYNC=true \\\n  ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw:latest\n```\n\n**Manage servers:**\n```bash\nclaude mcp list              # List configured servers\nclaude mcp remove excalidraw # Remove a server\n```\n\n---\n\n### Cursor\n\nConfig location: `.cursor\u002Fmcp.json` in your project root (or `~\u002F.cursor\u002Fmcp.json` for global config)\n\n**Local (node)**\n```json\n{\n  \"mcpServers\": {\n    \"excalidraw\": {\n      \"command\": \"node\",\n      \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fmcp_excalidraw\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"EXPRESS_SERVER_URL\": \"http:\u002F\u002F127.0.0.1:3000\",\n        \"ENABLE_CANVAS_SYNC\": \"true\"\n      }\n    }\n  }\n}\n```\n\n**Docker**\n```json\n{\n  \"mcpServers\": {\n    \"excalidraw\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-e\", \"EXPRESS_SERVER_URL=http:\u002F\u002Fhost.docker.internal:3000\",\n        \"-e\", \"ENABLE_CANVAS_SYNC=true\",\n        \"ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw:latest\"\n      ]\n    }\n  }\n}\n```\n\n---\n\n### Codex CLI\n\nUse the `codex mcp add` command to register the MCP server.\n\n**Local (node)**\n```bash\ncodex mcp add excalidraw \\\n  --env EXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 \\\n  --env ENABLE_CANVAS_SYNC=true \\\n  -- node \u002Fabsolute\u002Fpath\u002Fto\u002Fmcp_excalidraw\u002Fdist\u002Findex.js\n```\n\n**Docker**\n```bash\ncodex mcp add excalidraw \\\n  -- docker run -i --rm \\\n  -e EXPRESS_SERVER_URL=http:\u002F\u002Fhost.docker.internal:3000 \\\n  -e ENABLE_CANVAS_SYNC=true \\\n  ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw:latest\n```\n\n**Manage servers:**\n```bash\ncodex mcp list              # List configured servers\ncodex mcp remove excalidraw # Remove a server\n```\n\n---\n\n### OpenCode\n\nConfig location: `~\u002F.config\u002Fopencode\u002Fopencode.json` or project-level `opencode.json`\n\n**Local (node)**\n```json\n{\n  \"$schema\": \"https:\u002F\u002Fopencode.ai\u002Fconfig.json\",\n  \"mcp\": {\n    \"excalidraw\": {\n      \"type\": \"local\",\n      \"command\": [\"node\", \"\u002Fabsolute\u002Fpath\u002Fto\u002Fmcp_excalidraw\u002Fdist\u002Findex.js\"],\n      \"enabled\": true,\n      \"environment\": {\n        \"EXPRESS_SERVER_URL\": \"http:\u002F\u002F127.0.0.1:3000\",\n        \"ENABLE_CANVAS_SYNC\": \"true\"\n      }\n    }\n  }\n}\n```\n\n**Docker**\n```json\n{\n  \"$schema\": \"https:\u002F\u002Fopencode.ai\u002Fconfig.json\",\n  \"mcp\": {\n    \"excalidraw\": {\n      \"type\": \"local\",\n      \"command\": [\"docker\", \"run\", \"-i\", \"--rm\", \"-e\", \"EXPRESS_SERVER_URL=http:\u002F\u002Fhost.docker.internal:3000\", \"-e\", \"ENABLE_CANVAS_SYNC=true\", \"ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw:latest\"],\n      \"enabled\": true\n    }\n  }\n}\n```\n\n---\n\n### Antigravity (Google)\n\nConfig location: `~\u002F.gemini\u002Fantigravity\u002Fmcp_config.json`\n\n**Local (node)**\n```json\n{\n  \"mcpServers\": {\n    \"excalidraw\": {\n      \"command\": \"node\",\n      \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fmcp_excalidraw\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"EXPRESS_SERVER_URL\": \"http:\u002F\u002F127.0.0.1:3000\",\n        \"ENABLE_CANVAS_SYNC\": \"true\"\n      }\n    }\n  }\n}\n```\n\n**Docker**\n```json\n{\n  \"mcpServers\": {\n    \"excalidraw\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-e\", \"EXPRESS_SERVER_URL=http:\u002F\u002Fhost.docker.internal:3000\",\n        \"-e\", \"ENABLE_CANVAS_SYNC=true\",\n        \"ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw:latest\"\n      ]\n    }\n  }\n}\n```\n\n---\n\n### Notes\n\n- **Docker networking**: Use `host.docker.internal` to reach the canvas server running on your host machine. On Linux, you may need `--add-host=host.docker.internal:host-gateway` or use `172.17.0.1`.\n- **Canvas server**: Must be running before the MCP server connects. Start it with `npm run canvas` (local) or `docker run -d -p 3000:3000 ghcr.io\u002Fyctimlin\u002Fmcp_excalidraw-canvas:latest` (Docker).\n- **Absolute paths**: When using local node setup, replace `\u002Fabsolute\u002Fpath\u002Fto\u002Fmcp_excalidraw` with the actual path where you cloned and built the repo.\n- **In-memory storage**: The canvas server stores elements in memory. Restarting the server will clear all elements. Use the export\u002Fimport scripts if you need persistence.\n\n## Agent Skill (Optional)\n\nThis repo includes a skill at `skills\u002Fexcalidraw-skill\u002F` that provides:\n\n- **Workflow playbook** (`SKILL.md`): step-by-step guidance for drawing, refining, and exporting diagrams\n- **Cheatsheet** (`references\u002Fcheatsheet.md`): MCP tool and REST API reference\n- **Helper scripts** (`scripts\u002F*.cjs`): export, import, clear, healthcheck, CRUD operations\n\nThe skill complements the MCP server by giving your AI agent structured workflows to follow.\n\n### Install The Skill (Codex CLI example)\n\n```bash\nmkdir -p ~\u002F.codex\u002Fskills\ncp -R skills\u002Fexcalidraw-skill ~\u002F.codex\u002Fskills\u002Fexcalidraw-skill\n```\n\nTo update an existing installation, remove the old folder first (`rm -rf ~\u002F.codex\u002Fskills\u002Fexcalidraw-skill`) then re-copy.\n\n### Install The Skill (Claude Code)\n\n**User-level** (available across all your projects):\n```bash\nmkdir -p ~\u002F.claude\u002Fskills\ncp -R skills\u002Fexcalidraw-skill ~\u002F.claude\u002Fskills\u002Fexcalidraw-skill\n```\n\n**Project-level** (scoped to a specific project, can be committed to the repo):\n```bash\nmkdir -p \u002Fpath\u002Fto\u002Fyour\u002Fproject\u002F.claude\u002Fskills\ncp -R skills\u002Fexcalidraw-skill \u002Fpath\u002Fto\u002Fyour\u002Fproject\u002F.claude\u002Fskills\u002Fexcalidraw-skill\n```\n\nThen invoke the skill in Claude Code with `\u002Fexcalidraw-skill`.\n\nTo update an existing installation, remove the old folder first then re-copy.\n\n### Use The Skill Scripts\n\nAll scripts respect `EXPRESS_SERVER_URL` (default `http:\u002F\u002F127.0.0.1:3000`) or accept `--url`.\n\n```bash\nEXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 node skills\u002Fexcalidraw-skill\u002Fscripts\u002Fhealthcheck.cjs\nEXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 node skills\u002Fexcalidraw-skill\u002Fscripts\u002Fexport-elements.cjs --out diagram.elements.json\nEXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 node skills\u002Fexcalidraw-skill\u002Fscripts\u002Fimport-elements.cjs --in diagram.elements.json --mode batch\n```\n\n### When The Skill Is Useful\n\n- Repository workflow: export elements as JSON, commit it, and re-import later.\n- Reliable refactors: clear + re-import in `sync` mode to make canvas match a file.\n- Automated smoke tests: create\u002Fupdate\u002Fdelete a known element to validate a deployment.\n- Repeatable diagrams: keep a library of element JSON snippets and import them.\n\nSee `skills\u002Fexcalidraw-skill\u002FSKILL.md` and `skills\u002Fexcalidraw-skill\u002Freferences\u002Fcheatsheet.md`.\n\n## MCP Tools (26 Total)\n\n| Category | Tools |\n|---|---|\n| **Element CRUD** | `create_element`, `get_element`, `update_element`, `delete_element`, `query_elements`, `batch_create_elements`, `duplicate_elements` |\n| **Layout** | `align_elements`, `distribute_elements`, `group_elements`, `ungroup_elements`, `lock_elements`, `unlock_elements` |\n| **Scene Awareness** | `describe_scene`, `get_canvas_screenshot` |\n| **File I\u002FO** | `export_scene`, `import_scene`, `export_to_image`, `export_to_excalidraw_url`, `create_from_mermaid` |\n| **State Management** | `clear_canvas`, `snapshot_scene`, `restore_snapshot` |\n| **Viewport** | `set_viewport` |\n| **Design Guide** | `read_diagram_guide` |\n| **Resources** | `get_resource` |\n\nFull schemas are discoverable via `tools\u002Flist` or in `skills\u002Fexcalidraw-skill\u002Freferences\u002Fcheatsheet.md`.\n\n## Testing\n\n### Canvas Smoke Test (HTTP)\n\n```bash\ncurl http:\u002F\u002F127.0.0.1:3000\u002Fhealth\n```\n\n### Local Bind Regression Test\n\n```bash\nnpm run test:bind\n```\n\n### MCP Smoke Test (MCP Inspector)\n\nList tools:\n```bash\nnpx @modelcontextprotocol\u002Finspector --cli \\\n  -e EXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 \\\n  -e ENABLE_CANVAS_SYNC=true -- \\\n  node dist\u002Findex.js --method tools\u002Flist\n```\n\nCreate a rectangle:\n```bash\nnpx @modelcontextprotocol\u002Finspector --cli \\\n  -e EXPRESS_SERVER_URL=http:\u002F\u002F127.0.0.1:3000 \\\n  -e ENABLE_CANVAS_SYNC=true -- \\\n  node dist\u002Findex.js --method tools\u002Fcall --tool-name create_element \\\n  --tool-arg type=rectangle --tool-arg x=100 --tool-arg y=100 \\\n  --tool-arg width=300 --tool-arg height=200\n```\n\n### Frontend Screenshots (agent-browser)\n\nIf you use `agent-browser` for UI checks:\n```bash\nagent-browser install\nagent-browser open http:\u002F\u002F127.0.0.1:3000\nagent-browser wait --load networkidle\nagent-browser screenshot \u002Ftmp\u002Fcanvas.png\n```\n\n## Troubleshooting\n\n- Canvas not updating: confirm `EXPRESS_SERVER_URL` points at the running canvas server.\n- Updates\u002Fdeletes fail after batch creation: ensure you are on a build that includes the batch id preservation fix (merged via PR #34).\n\n## Known Issues \u002F TODO\n\nAll previously listed bugs have been fixed in v2.0. Remaining items:\n\n- [ ] **Persistent storage**: Elements are stored in-memory — restarting the server clears everything. Use `export_scene` \u002F snapshots as a workaround.\n- [ ] **Image export requires a browser**: `export_to_image` and `get_canvas_screenshot` rely on the frontend doing the actual rendering. The canvas UI must be open in a browser.\n\nContributions welcome!\n\n## Development\n\n```bash\nnpm run type-check\nnpm run build\n```\n",2,"2026-06-11 04:11:19","high_star"]