* feat(canvas): native field preservation, label materialization, batch workspace delete
- fillNativeFields() + repairContainerBinding() in db layer ensure every
element stored in SQLite is a complete, round-trippable Excalidraw element
with correct containerId ↔ boundElements bidirectional binding
- materializeLabel() in server.ts: shapes with label.text/text produce a
native bound text element at write time (create, update, batch) so text
follows its container when moved — matches VSCode Excalidraw extension behavior
- Batch workspace UI: Select/Unselect All, per-row checkboxes, Delete N
workspaces button with confirmation
- POST /api/tenants/batch-delete: delete up to 50 tenants in one request
- 42 new backend tests; 519 total passing
- Bump version 1.0.6 → 1.1.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(tests): update e2e assertions for label materialization
phase2-regressions: label is now a native bound text element
(id: pos-stable-1-label) — check bound text element text instead
of container.label?.text which is no longer stored.
sync-flows FTS: search now matches the bound text element (fts-el-label)
rather than the container — accept either id as valid match.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace Unix-only `2>/dev/null || true` with a `node -e` inline script
that silently ignores better-sqlite3 rebuild failures on all platforms.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@modelcontextprotocol/sdk@1.26.0 uses zod/v4 APIs (specifically
z.literal().value getter). When installed globally, npm shared the
project's zod@3.25.5 instead of the SDK's nested zod@4.3.6; the
3.25.5 v4 compat shim lacks the .value getter, throwing
'Schema method literal must be a string' on startup.
Also updates z.record(z.any()) to z.record(z.string(), z.any())
for zod v4 strict record key typing.
446/446 tests passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds postinstall script to rebuild better-sqlite3 native bindings for
the current Node.js version. Fixes ERR_DLOPEN_FAILED when installing
via npx on a different Node version than was used to publish.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Existing users who update the npm package often forget to update the agent
skill files, leaving their AI agent working with stale workflow guidance
(sizing rules, color palettes, anti-patterns). The new `update` subcommand
solves this by detecting and updating all skill installations automatically.
🔧 Interactive update wizard:
- Scan all agent directories (Cursor, Claude Code, Codex CLI) across global
and local scopes for existing excalidraw-skill installations
- Batch-update found installations with a single Y/n confirmation
- Offer to install the skill for detected agents that don't have it yet
- Optionally re-apply MCP config (defaults to no for non-breaking updates)
📝 Documentation:
- Rewrite README "Updating" section to lead with the interactive command
- Add collapsible example session showing the update flow
- Retain manual update methods as fallback for each installation path
🎯 Ensures skill files stay in sync with MCP tools across releases,
preventing the subtle drift where new tool capabilities exist but the
agent's workflow guidance doesn't reference them.
The postinstall ran prebuild-install and node-gyp in the wrong context
(our package instead of better-sqlite3), always failing with "binding.gyp
not found". better-sqlite3 handles its own native compilation via its
install script — the package-level postinstall was redundant.
Co-authored-by: sanjibdevnathlabs <devnath.sanjib@gmail.com>
- Use fs.realpathSync for entry point detection to fix npx symlink failures
- Add --help and --version CLI flags with explicit process.exit(0)
- Add TTY detection in setup wizard to prevent non-interactive hangs
- Wrap JSON.parse in mergeJsonConfig with try/catch for malformed configs
- Update engines.node to >=20.0.0 to match better-sqlite3 requirements
- Update Dockerfiles from node:18-slim to node:20-slim
- Remove error-swallowing || true from postinstall script
- Replace deprecated windows-build-tools with VS Build Tools link
Establish comprehensive quality infrastructure for a project that previously
had zero tests, enabling confident refactoring and community contributions
with automated guardrails. Port upstream enhancements for font normalization,
image element support, and arrow binding preservation.
🏗️ Testing infrastructure:
- Unit tests for SQLite persistence layer and element validation helpers
- Integration tests for REST API, WebSocket broadcast, and arrow binding
- E2E tests with Playwright for canvas rendering and real-time sync
- Vitest + Playwright configuration with proper isolation
👷 CI/CD pipeline:
- Auto-versioning from conventional commits on push to main
- Auto-publish to NPM and Docker Hub on GitHub release
- Matrix testing across Node 18/20/22 with pinned dependencies
- Docker health check with diagnostic logging on failure
- Preserve rollup status checks for branch protection gates
📦 Developer experience:
- Interactive setup wizard for first-time configuration
- Canvas clear confirmation and scene description tools
- Frontend helpers extracted for testability
🔧 Upstream feature ports:
- Font family normalization (string names to numeric IDs)
- Image element support with file management API
- Arrow binding preservation through server round-trips
- Vite config fix for font subsetting worker chunk names
- Idempotent database initialization for standalone Docker mode
🐛 Docker fixes:
- Set EXCALIDRAW_DB_PATH in both Dockerfiles to writable /app/data/
- Make initDb() idempotent and closeDb() reset-safe for test isolation
🎯 Provides the safety net needed for rapid iteration — every PR is
validated across 120 test cases before merge, and releases are fully
automated from commit to published package.
Co-authored-by: sanjibdevnathlabs <devnath.sanjib@gmail.com>
* 🔧 chore: reset version to 1.0.0 for independent NPM package
This is a new scoped package (@sanjibdevnath/mcp-excalidraw-local),
so versioning starts fresh at 1.0.0 rather than continuing upstream's
numbering.
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: trigger PR
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace in-memory storage with SQLite (WAL mode), add workspace-based
multi-tenancy with auto-detection via server.listRoots(), and embed the
canvas server into the MCP process for single-process operation.
🔧 Core enhancements:
- SQLite persistence with versioning, element history, and search
- Multi-tenancy: isolated canvases per workspace (SHA-256 tenant IDs)
- Embedded canvas lifecycle (single node process starts MCP + canvas)
- Auto-sync with 3s debounce and manual override toggle
- Configurable canvas port via CANVAS_PORT env var
- 6 new MCP tools (search, history, tenants, projects)
- Workspace switcher UI with dropdown search
- Sync normalization to prevent bound-text breakage on reload
🐳 Docker & CI improvements:
- BuildKit cache mounts for faster npm installs across builds
- Skip native compilation in frontend-builder stage (--ignore-scripts)
- Build only linux/amd64 on PRs, multi-arch on push to main
- Docker Hub registry with proper build tools for better-sqlite3
- CI and Docker status check gates (github/ci-status-check, github/docker-build-check)
📦 Package & publishing:
- Renamed to @sanjibdevnath/mcp-excalidraw-local (v3.0.0)
- Updated npm-publish workflow for scoped package
- Updated bin entry, keywords, and files list
📝 Documentation:
- README with UI screenshots, architecture diagram, and full feature docs
- Updated agent skill with 32-tool cheatsheet and workflow playbooks
- Fork attribution and upstream comparison table
Co-authored-by: Cursor <cursoragent@cursor.com>
- Updated package.json to point to compiled TypeScript files in the dist directory.
- Improved TypeScript configuration with stricter type checks and removed JavaScript support.
- Migrated frontend entry point to TypeScript and added a new App component with enhanced functionality.
- Implemented a new server structure with TypeScript, including WebSocket support and improved element management.
- Updated README to reflect changes in architecture and usage instructions.
- Added comprehensive type definitions for Excalidraw elements and server responses.
- Update package.json to include separate build scripts for frontend and types, and add a build server script.
- Introduce tsconfig.json for TypeScript configuration, enabling declaration files and source maps.
- Add TypeScript and Node types as development dependencies.
- Include TypeScript declaration files in the package distribution.
- Introduce LICENSE file with MIT License details.
- Change project name to 'mcp-excalidraw-server' and update description in package.json for clarity on features.
- Revise README.md to include new installation options and usage instructions for the npm package.
- Add shebang to index.js for direct CLI execution.
- Update .gitignore to include additional build artifacts, logs, and editor files
- Modify package.json scripts for improved development workflow and remove unused scripts
- Change Vite output directory to 'dist' for consistency
- Simplify App.jsx by removing unused state and functions, enhancing readability
- Adjust server.js to serve static files from the new 'dist' directory
- Add React frontend with Excalidraw integration (App.jsx, main.jsx)
- Add Express server with MCP protocol support (server.js)
- Update CLI with new functionality (cli.js)
- Add Vite configuration for frontend build
- Update package.json with new dependencies
- Add public assets and build files
- Update .gitignore to exclude build artifacts