@sanjibdevnath/mcp-excalidraw-local 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +458 -0
- package/dist/db.d.ts +58 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +379 -0
- package/dist/db.js.map +1 -0
- package/dist/frontend/assets/Assistant-Bold-gm-uSS1B.woff2 +0 -0
- package/dist/frontend/assets/Assistant-Medium-DrcxCXg3.woff2 +0 -0
- package/dist/frontend/assets/Assistant-Regular-DVxZuzxb.woff2 +0 -0
- package/dist/frontend/assets/Assistant-SemiBold-SCI4bEL9.woff2 +0 -0
- package/dist/frontend/assets/Tableau10-B-NsZVaP.js +1 -0
- package/dist/frontend/assets/_commonjs-dynamic-modules-TDtrdbi3.js +1 -0
- package/dist/frontend/assets/advancedFormat-BvOvfnfC.js +1 -0
- package/dist/frontend/assets/ar-SA-G6X2FPQ2-75HMOOy8.js +10 -0
- package/dist/frontend/assets/arc-D-322MQz.js +1 -0
- package/dist/frontend/assets/array-BKyUJesY.js +1 -0
- package/dist/frontend/assets/az-AZ-76LH7QW2-DPDwkDvh.js +1 -0
- package/dist/frontend/assets/band-dPffDWoQ.js +1 -0
- package/dist/frontend/assets/bg-BG-XCXSNQG7-DrFYc9eo.js +5 -0
- package/dist/frontend/assets/blockDiagram-38ab4fdb-Ch8bwO7g.js +118 -0
- package/dist/frontend/assets/blockDiagram-68f4deed-BVqzkDiu.js +118 -0
- package/dist/frontend/assets/bn-BD-2XOGV67Q-B1Y75Cvj.js +5 -0
- package/dist/frontend/assets/c4Diagram-15b5d702-D5U2mSdf.js +10 -0
- package/dist/frontend/assets/c4Diagram-3d4e48cf-eT2EEN_c.js +10 -0
- package/dist/frontend/assets/ca-ES-6MX7JW3Y-00BTiK3Z.js +8 -0
- package/dist/frontend/assets/channel-CudwHHli.js +1 -0
- package/dist/frontend/assets/classDiagram-70f12bd4-CcNOdQHv.js +2 -0
- package/dist/frontend/assets/classDiagram-d40c83e7-nRIgRTMT.js +2 -0
- package/dist/frontend/assets/classDiagram-v2-d5a6b087-Cfbvao44.js +2 -0
- package/dist/frontend/assets/classDiagram-v2-f2320105-1Sjp5Uqh.js +2 -0
- package/dist/frontend/assets/clone-D_tGm99B.js +1 -0
- package/dist/frontend/assets/createText-2e5e7dd3-Bpmkp1eZ.js +5 -0
- package/dist/frontend/assets/createText-d213de94-3MLB4fd8.js +5 -0
- package/dist/frontend/assets/cs-CZ-2BRQDIVT-R7SCWLLF.js +11 -0
- package/dist/frontend/assets/cytoscape-cose-bilkent-CoIxD6ON.js +331 -0
- package/dist/frontend/assets/da-DK-5WZEPLOC-Db1yebad.js +5 -0
- package/dist/frontend/assets/de-DE-XR44H4JA-HRE-6fuh.js +8 -0
- package/dist/frontend/assets/directory-open-01563666-DWU9wJ6I.js +1 -0
- package/dist/frontend/assets/directory-open-4ed118d0-BzWybGaI.js +1 -0
- package/dist/frontend/assets/edges-332bd1c7-DZAOA9uP.js +4 -0
- package/dist/frontend/assets/edges-e0da2a9e-CP-XTLb4.js +4 -0
- package/dist/frontend/assets/el-GR-BZB4AONW-CfNczSdx.js +10 -0
- package/dist/frontend/assets/elk.bundled-BZDcWavb.js +26 -0
- package/dist/frontend/assets/erDiagram-880f2ed8-Bk96tDga.js +51 -0
- package/dist/frontend/assets/erDiagram-9861fffd-BvkEkcRK.js +51 -0
- package/dist/frontend/assets/es-ES-U4NZUMDT-BBJZ1_wD.js +9 -0
- package/dist/frontend/assets/eu-ES-A7QVB2H4-CCLNmdnk.js +11 -0
- package/dist/frontend/assets/fa-IR-HGAKTJCU-BtKS5FOW.js +8 -0
- package/dist/frontend/assets/fi-FI-Z5N7JZ37-DEQi6vbL.js +6 -0
- package/dist/frontend/assets/file-open-002ab408-DIuFHtCF.js +1 -0
- package/dist/frontend/assets/file-open-7c801643-684qeFg4.js +1 -0
- package/dist/frontend/assets/file-save-3189631c-x92wctJd.js +1 -0
- package/dist/frontend/assets/file-save-745eba88-Bb9F9Kg7.js +1 -0
- package/dist/frontend/assets/flowDb-7c981674-JJMg1ttK.js +10 -0
- package/dist/frontend/assets/flowDb-956e92f1-CVVUllPW.js +10 -0
- package/dist/frontend/assets/flowDiagram-66a62f08-wGFuUp6y.js +4 -0
- package/dist/frontend/assets/flowDiagram-cbd28bf7-CXKT_tHC.js +4 -0
- package/dist/frontend/assets/flowDiagram-v2-96b9c2cf-CN4ht1EM.js +1 -0
- package/dist/frontend/assets/flowDiagram-v2-ffc7f31a-CFiBItzu.js +1 -0
- package/dist/frontend/assets/flowchart-elk-definition-36e2d292-Cam5JBwn.js +114 -0
- package/dist/frontend/assets/flowchart-elk-definition-4a651766-BoyD4myW.js +114 -0
- package/dist/frontend/assets/fr-FR-RHASNOE6-_AQjPuKS.js +9 -0
- package/dist/frontend/assets/ganttDiagram-04f9e578-DrDI9_oS.js +257 -0
- package/dist/frontend/assets/ganttDiagram-c361ad54-CKSyNc2k.js +257 -0
- package/dist/frontend/assets/gitGraphDiagram-21fc4d3e-BHBdnwSb.js +70 -0
- package/dist/frontend/assets/gitGraphDiagram-72cf32ee-BHN9qiXg.js +70 -0
- package/dist/frontend/assets/gl-ES-HMX3MZ6V-Bp2h6sBC.js +10 -0
- package/dist/frontend/assets/graph-CRb9j7zI.js +1 -0
- package/dist/frontend/assets/graph-EK5j_nPe.js +1 -0
- package/dist/frontend/assets/he-IL-6SHJWFNN-hsaAKZ5K.js +10 -0
- package/dist/frontend/assets/hi-IN-IWLTKZ5I-sgYSNzoz.js +4 -0
- package/dist/frontend/assets/hu-HU-A5ZG7DT2-DxYZr0yq.js +7 -0
- package/dist/frontend/assets/id-ID-SAP4L64H-z0RzSKPQ.js +10 -0
- package/dist/frontend/assets/image-blob-reduce.esm-B6b2_-a4.js +7 -0
- package/dist/frontend/assets/index-3862675e-CQPsxwvk.js +1 -0
- package/dist/frontend/assets/index-6079d271-pTR-OMc-.js +1 -0
- package/dist/frontend/assets/index-B9Rh8YyQ.css +1 -0
- package/dist/frontend/assets/index-BcHA28Dx.js +87 -0
- package/dist/frontend/assets/index-DGmpr33w.js +3 -0
- package/dist/frontend/assets/index-DPgZw9ew.js +349 -0
- package/dist/frontend/assets/infoDiagram-4a4f5b27-OIxyK2_N.js +7 -0
- package/dist/frontend/assets/infoDiagram-f8f76790-BTkoanKB.js +7 -0
- package/dist/frontend/assets/init-Gi6I4Gst.js +1 -0
- package/dist/frontend/assets/it-IT-JPQ66NNP-Cu6RM7DP.js +11 -0
- package/dist/frontend/assets/ja-JP-DBVTYXUO-lD7U4Zkf.js +8 -0
- package/dist/frontend/assets/journeyDiagram-29694f62-BS4Xl0A-.js +139 -0
- package/dist/frontend/assets/journeyDiagram-49397b02-BbBAwEfu.js +139 -0
- package/dist/frontend/assets/kaa-6HZHGXH3-DM9LwXUP.js +1 -0
- package/dist/frontend/assets/kab-KAB-ZGHBKWFO-BAojmp2_.js +8 -0
- package/dist/frontend/assets/katex-ChWnQ-fc.js +261 -0
- package/dist/frontend/assets/kk-KZ-P5N5QNE5-Dp0K1W81.js +1 -0
- package/dist/frontend/assets/km-KH-HSX4SM5Z-BzYGKbAg.js +11 -0
- package/dist/frontend/assets/ko-KR-MTYHY66A-DOvEMk4H.js +9 -0
- package/dist/frontend/assets/ku-TR-6OUDTVRD-B6l-ghqp.js +9 -0
- package/dist/frontend/assets/layout-CGydnLJa.js +1 -0
- package/dist/frontend/assets/layout-DbdMIGYe.js +1 -0
- package/dist/frontend/assets/line-CbImtxDK.js +1 -0
- package/dist/frontend/assets/linear-DvIsU3aM.js +1 -0
- package/dist/frontend/assets/lt-LT-XHIRWOB4-BYcRk8Uj.js +3 -0
- package/dist/frontend/assets/lv-LV-5QDEKY6T-DS3krNIe.js +7 -0
- package/dist/frontend/assets/mindmap-definition-ac74a2e8-C0Sp7ICZ.js +95 -0
- package/dist/frontend/assets/mindmap-definition-fc14e90a-BZrjRbkr.js +95 -0
- package/dist/frontend/assets/mr-IN-CRQNXWMA-BfxQL7Vh.js +13 -0
- package/dist/frontend/assets/my-MM-5M5IBNSE-C3EfnOvD.js +1 -0
- package/dist/frontend/assets/nb-NO-T6EIAALU-BIbPZokm.js +10 -0
- package/dist/frontend/assets/nl-NL-IS3SIHDZ-BqQloGBT.js +8 -0
- package/dist/frontend/assets/nn-NO-6E72VCQL-zGR8NYQf.js +8 -0
- package/dist/frontend/assets/oc-FR-POXYY2M6-B8-HsJFE.js +8 -0
- package/dist/frontend/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/frontend/assets/pa-IN-N4M65BXN-B2Ta58Tu.js +4 -0
- package/dist/frontend/assets/path-CbwjOpE9.js +1 -0
- package/dist/frontend/assets/pica-DSD-O3at.js +7 -0
- package/dist/frontend/assets/pie-Dk_pQnuO.js +1 -0
- package/dist/frontend/assets/pieDiagram-421022e6-9oAq5fk_.js +35 -0
- package/dist/frontend/assets/pieDiagram-8a3498a8-B5SMrdDh.js +35 -0
- package/dist/frontend/assets/pl-PL-T2D74RX3-rZKvQ0zQ.js +9 -0
- package/dist/frontend/assets/pt-BR-5N22H2LF-ij6wtU6I.js +9 -0
- package/dist/frontend/assets/pt-PT-UZXXM6DQ-BIgtUnbW.js +9 -0
- package/dist/frontend/assets/quadrantDiagram-0957ecba-Cr3mj6c1.js +7 -0
- package/dist/frontend/assets/quadrantDiagram-120e2f19-CQnc4s0f.js +7 -0
- package/dist/frontend/assets/requirementDiagram-23d650b8-Bs7pP1vJ.js +52 -0
- package/dist/frontend/assets/requirementDiagram-deff3bca-G5e-Qxao.js +52 -0
- package/dist/frontend/assets/ro-RO-JPDTUUEW-DPj_79nt.js +11 -0
- package/dist/frontend/assets/roundRect-0PYZxl1G.js +1 -0
- package/dist/frontend/assets/ru-RU-B4JR7IUQ-fdYiaqbX.js +9 -0
- package/dist/frontend/assets/sankeyDiagram-04a897e0-CJogadkF.js +8 -0
- package/dist/frontend/assets/sankeyDiagram-23345273-DKUWMCrX.js +8 -0
- package/dist/frontend/assets/sankeyLinkHorizontal-DgqkLiUE.js +1 -0
- package/dist/frontend/assets/selectAll-tNeSnQY6.js +1 -0
- package/dist/frontend/assets/sequenceDiagram-17ac3bff-DCw9xUbw.js +122 -0
- package/dist/frontend/assets/sequenceDiagram-704730f1-BgClSrOI.js +122 -0
- package/dist/frontend/assets/si-LK-N5RQ5JYF-DfPBk-rU.js +1 -0
- package/dist/frontend/assets/sk-SK-C5VTKIMK-Cbj4yoD_.js +6 -0
- package/dist/frontend/assets/sl-SI-NN7IZMDC-C_rL7eDE.js +6 -0
- package/dist/frontend/assets/stateDiagram-587899a1-DuFGG-SI.js +1 -0
- package/dist/frontend/assets/stateDiagram-9c5f0230-Bwj38hfH.js +1 -0
- package/dist/frontend/assets/stateDiagram-v2-51a3dcff-3c0yKNdL.js +1 -0
- package/dist/frontend/assets/stateDiagram-v2-d93cdb3a-CAaqB4wm.js +1 -0
- package/dist/frontend/assets/styles-2ab5d517-Dxg7wKah.js +116 -0
- package/dist/frontend/assets/styles-5f03d8d2-DD32XMGL.js +160 -0
- package/dist/frontend/assets/styles-6aaf32cf-B5DxK_RW.js +207 -0
- package/dist/frontend/assets/styles-9a916d00-C6L6Mj2P.js +160 -0
- package/dist/frontend/assets/styles-c10674c1-BPM_bB3H.js +116 -0
- package/dist/frontend/assets/styles-edf9a4b0-CbQDxrwP.js +207 -0
- package/dist/frontend/assets/subset-shared.chunk-B_DQsaBC.js +84 -0
- package/dist/frontend/assets/subset-worker.chunk-DL6tLP7M.js +1 -0
- package/dist/frontend/assets/sv-SE-XGPEYMSR-BmmcOaVK.js +10 -0
- package/dist/frontend/assets/svgDrawCommon-08f97a94-aUx8qfJx.js +1 -0
- package/dist/frontend/assets/svgDrawCommon-3ba9043b-1JM8RiLc.js +1 -0
- package/dist/frontend/assets/ta-IN-2NMHFXQM-Kxnb_Mwk.js +9 -0
- package/dist/frontend/assets/th-TH-HPSO5L25-BqTLgxJz.js +2 -0
- package/dist/frontend/assets/timeline-definition-7e6b55e7-BbFhIPTl.js +61 -0
- package/dist/frontend/assets/timeline-definition-85554ec2-C1G9H6m5.js +61 -0
- package/dist/frontend/assets/tr-TR-DEFEU3FU-DhlYP6tL.js +7 -0
- package/dist/frontend/assets/uk-UA-QMV73CPH-pMrN1qBS.js +6 -0
- package/dist/frontend/assets/union-Cu1rbD_D.js +1 -0
- package/dist/frontend/assets/vi-VN-M7AON7JQ-BPMcH84R.js +5 -0
- package/dist/frontend/assets/xml-BOsq7VnW.js +1 -0
- package/dist/frontend/assets/xychartDiagram-b6496bcd-BDm9pYtk.js +7 -0
- package/dist/frontend/assets/xychartDiagram-e933f94c-BlrTBDHC.js +7 -0
- package/dist/frontend/assets/zh-CN-LNUGB5OW-B8kYYibM.js +10 -0
- package/dist/frontend/assets/zh-HK-E62DVLB3-CaI0gehP.js +1 -0
- package/dist/frontend/assets/zh-TW-RAJ6MFWO-DKCVg17j.js +9 -0
- package/dist/frontend/assets/zipObject-iRVIFf6r.js +1 -0
- package/dist/frontend/index.html +420 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2241 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +980 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +225 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +30 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +23 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +108 -0
- package/skills/excalidraw-skill/SKILL.md +370 -0
- package/skills/excalidraw-skill/references/cheatsheet.md +195 -0
- package/skills/excalidraw-skill/scripts/clear-canvas.cjs +38 -0
- package/skills/excalidraw-skill/scripts/create-element.cjs +68 -0
- package/skills/excalidraw-skill/scripts/delete-element.cjs +48 -0
- package/skills/excalidraw-skill/scripts/export-elements.cjs +53 -0
- package/skills/excalidraw-skill/scripts/healthcheck.cjs +35 -0
- package/skills/excalidraw-skill/scripts/import-elements.cjs +81 -0
- package/skills/excalidraw-skill/scripts/update-element.cjs +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 MCP Excalidraw Server
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
# MCP Excalidraw Local
|
|
2
|
+
|
|
3
|
+
[](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/docker.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
A fully local, self-hosted Excalidraw MCP server with **SQLite persistence**, **multi-tenancy**, and **auto-sync** — designed to run entirely on your machine without depending on `excalidraw.com`.
|
|
8
|
+
|
|
9
|
+
Run a live Excalidraw canvas and control it from any AI agent. This repo provides:
|
|
10
|
+
|
|
11
|
+
- **MCP Server**: 32 tools over stdio — works with any MCP-compatible client
|
|
12
|
+
- **Agent Skill**: Portable skill with workflow playbooks, cheatsheets, and helper scripts
|
|
13
|
+
- **Live Canvas**: Real-time Excalidraw UI synced via WebSocket
|
|
14
|
+
- **SQLite Persistence**: Elements survive restarts, with versioning and search
|
|
15
|
+
- **Multi-Tenancy**: Isolated canvases per workspace, auto-detected
|
|
16
|
+
|
|
17
|
+
> **Fork notice:** This project is forked from [yctimlin/mcp_excalidraw](https://github.com/yctimlin/mcp_excalidraw) and extends it with persistence, multi-workspace support, and numerous UX improvements. Full credit to the original author for the excellent foundation. See [What Changed From Upstream](#what-changed-from-upstream) for details.
|
|
18
|
+
|
|
19
|
+
Keywords: Excalidraw MCP server, AI diagramming, local Excalidraw, self-hosted, SQLite persistence, multi-tenant, Mermaid to Excalidraw.
|
|
20
|
+
|
|
21
|
+
## Screenshots
|
|
22
|
+
|
|
23
|
+
### Canvas UI
|
|
24
|
+
|
|
25
|
+
The live Excalidraw canvas with toolbar, connection status, sync controls, and workspace badge:
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
### Workspace Switcher
|
|
30
|
+
|
|
31
|
+
Click the workspace badge to switch between isolated canvases — each workspace has its own set of diagrams:
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
> For a demo of the upstream project (before persistence/multi-tenancy), see the [original video by @yctimlin](https://youtu.be/ufW78Amq5qA).
|
|
36
|
+
|
|
37
|
+
## Table of Contents
|
|
38
|
+
|
|
39
|
+
- [Screenshots](#screenshots)
|
|
40
|
+
- [What It Is](#what-it-is)
|
|
41
|
+
- [How We Differ from the Official Excalidraw MCP](#how-we-differ-from-the-official-excalidraw-mcp)
|
|
42
|
+
- [What Changed From Upstream](#what-changed-from-upstream)
|
|
43
|
+
- [What's New](#whats-new)
|
|
44
|
+
- [Architecture](#architecture)
|
|
45
|
+
- [Quick Start](#quick-start)
|
|
46
|
+
- [Quick Start (Docker)](#quick-start-docker)
|
|
47
|
+
- [Configuration](#configuration)
|
|
48
|
+
- [Environment Variables](#environment-variables)
|
|
49
|
+
- [Multi-Tenancy (Workspaces)](#multi-tenancy-workspaces)
|
|
50
|
+
- [Agent Skill (Optional)](#agent-skill-optional)
|
|
51
|
+
- [MCP Tools (32 Total)](#mcp-tools-32-total)
|
|
52
|
+
- [Testing](#testing)
|
|
53
|
+
- [Troubleshooting](#troubleshooting)
|
|
54
|
+
- [Known Issues / TODO](#known-issues--todo)
|
|
55
|
+
- [Development](#development)
|
|
56
|
+
- [Credits](#credits)
|
|
57
|
+
|
|
58
|
+
## What It Is
|
|
59
|
+
|
|
60
|
+
This MCP server gives AI agents a full canvas toolkit to build, inspect, and iteratively refine Excalidraw diagrams — including the ability to see what they drew.
|
|
61
|
+
|
|
62
|
+
The repo contains a single Node.js process that runs:
|
|
63
|
+
|
|
64
|
+
- **MCP server** (stdio): 32 tools for element CRUD, layout, scene awareness, file I/O, snapshots, search, multi-tenancy, and more
|
|
65
|
+
- **Canvas server** (embedded): web UI + REST API + WebSocket updates at `http://localhost:<CANVAS_PORT>`
|
|
66
|
+
- **SQLite database**: persistent storage at `~/.excalidraw-mcp/excalidraw.db`
|
|
67
|
+
|
|
68
|
+
## How We Differ from the Official Excalidraw MCP
|
|
69
|
+
|
|
70
|
+
Excalidraw now has an [official MCP](https://github.com/excalidraw/excalidraw-mcp) — it's great for quick, prompt-to-diagram generation rendered inline in chat. We solve a different problem.
|
|
71
|
+
|
|
72
|
+
| | Official Excalidraw MCP | This Project |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| **Approach** | Prompt in, diagram out (one-shot) | Programmatic element-level control (32 tools) |
|
|
75
|
+
| **State** | Stateless — each call is independent | Persistent live canvas with real-time sync |
|
|
76
|
+
| **Storage** | None | SQLite with WAL mode, versioning, element history |
|
|
77
|
+
| **Multi-tenancy** | No | Workspace-based isolation, auto-detected |
|
|
78
|
+
| **Element CRUD** | No | Full create / read / update / delete per element |
|
|
79
|
+
| **AI sees the canvas** | No | `describe_scene` (structured text) + `get_canvas_screenshot` (image) |
|
|
80
|
+
| **Iterative refinement** | No — regenerate the whole diagram | Draw → look → adjust → look again, element by element |
|
|
81
|
+
| **Layout tools** | No | `align_elements`, `distribute_elements`, `group / ungroup` |
|
|
82
|
+
| **File I/O** | No | `export_scene` / `import_scene` (.excalidraw JSON) |
|
|
83
|
+
| **Snapshot & rollback** | No | `snapshot_scene` / `restore_snapshot` |
|
|
84
|
+
| **Mermaid conversion** | No | `create_from_mermaid` |
|
|
85
|
+
| **Search** | No | `search_elements` — full-text search across labels |
|
|
86
|
+
| **Design guide** | `read_me` cheat sheet | `read_diagram_guide` (colors, sizing, layout, anti-patterns) |
|
|
87
|
+
| **Viewport control** | Camera animations | `set_viewport` (zoom-to-fit, center on element, manual zoom) |
|
|
88
|
+
| **Live canvas UI** | Rendered inline in chat | Standalone Excalidraw app synced via WebSocket |
|
|
89
|
+
| **Multi-agent** | Single user | Multiple agents can draw on the same canvas concurrently |
|
|
90
|
+
| **Works without MCP** | No | Yes — REST API fallback via agent skill |
|
|
91
|
+
|
|
92
|
+
**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.
|
|
93
|
+
|
|
94
|
+
## What Changed From Upstream
|
|
95
|
+
|
|
96
|
+
This fork extends [yctimlin/mcp_excalidraw](https://github.com/yctimlin/mcp_excalidraw) with the following enhancements:
|
|
97
|
+
|
|
98
|
+
| Area | Upstream | This Fork |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| **Storage** | In-memory (lost on restart) | SQLite with WAL mode, versioning, element history |
|
|
101
|
+
| **Multi-tenancy** | None | Workspace-based tenant isolation (auto-detected via `server.listRoots()`) |
|
|
102
|
+
| **Canvas lifecycle** | Separate process (2 terminals) | Embedded in MCP process (single `node dist/index.js`) |
|
|
103
|
+
| **Auto-sync** | Manual "Sync to Backend" button | Debounced auto-sync (3s idle) with manual override |
|
|
104
|
+
| **Canvas port** | Hardcoded 3000 | Configurable via `CANVAS_PORT` env var |
|
|
105
|
+
| **MCP tools** | 26 | 32 (added search, history, tenants, projects) |
|
|
106
|
+
| **Workspace switcher** | None | Dropdown with search in canvas UI |
|
|
107
|
+
| **Sync normalization** | Bound text breaks on reload | Elements normalized to MCP format before storage |
|
|
108
|
+
| **Projects** | None | Multiple projects per tenant |
|
|
109
|
+
| **Element history** | None | Full version history per element |
|
|
110
|
+
| **Search** | None | Full-text search across elements |
|
|
111
|
+
|
|
112
|
+
### New MCP Tools (6 added)
|
|
113
|
+
|
|
114
|
+
| Tool | Description |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `search_elements` | Full-text search across element labels and text |
|
|
117
|
+
| `element_history` | View version history for any element |
|
|
118
|
+
| `list_projects` | List projects within the active tenant |
|
|
119
|
+
| `switch_project` | Switch between projects |
|
|
120
|
+
| `list_tenants` | List all workspace tenants |
|
|
121
|
+
| `switch_tenant` | Switch the active workspace tenant |
|
|
122
|
+
|
|
123
|
+
## What's New
|
|
124
|
+
|
|
125
|
+
### v1.0 — This Fork (Persistence & Multi-Tenancy)
|
|
126
|
+
|
|
127
|
+
- **SQLite persistence**: Elements, projects, tenants, snapshots, and element versions stored in `~/.excalidraw-mcp/excalidraw.db` with WAL mode and `busy_timeout` for multi-process safety
|
|
128
|
+
- **Multi-tenancy**: Each workspace gets an isolated canvas. Tenant auto-detected from workspace path via `server.listRoots()`. UI dropdown with search for switching workspaces
|
|
129
|
+
- **Embedded canvas**: Canvas server runs inside the MCP process — single `node dist/index.js` starts everything, stops together
|
|
130
|
+
- **Auto-sync with debounce**: Canvas changes are automatically persisted after 3s of inactivity. Manual sync button as fallback. Toggle auto-sync on/off
|
|
131
|
+
- **Configurable port**: `CANVAS_PORT` env var (default `3000`)
|
|
132
|
+
- **Sync normalization**: Excalidraw's internal bound-text representation is normalized to MCP format before storage, preventing text overflow/detachment on reload
|
|
133
|
+
- **6 new MCP tools**: `search_elements`, `element_history`, `list_projects`, `switch_project`, `list_tenants`, `switch_tenant`
|
|
134
|
+
- **Updated agent skill**: Comprehensive workflow playbook with iterative write-check-review cycle, sizing rules, anti-patterns, and quality checklist
|
|
135
|
+
- **Workspace switcher UI**: Click "Workspace: ..." badge to search and switch between workspaces
|
|
136
|
+
|
|
137
|
+
### v2.0 — Canvas Toolkit (upstream)
|
|
138
|
+
|
|
139
|
+
- 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`
|
|
140
|
+
- **Closed feedback loop**: AI can now inspect the canvas (`describe_scene`) and see it (`get_canvas_screenshot` returns an image) — enabling iterative refinement
|
|
141
|
+
- **Design guide**: `read_diagram_guide` returns best-practice color palettes, sizing rules, layout patterns, and anti-patterns
|
|
142
|
+
- **Viewport control**: `set_viewport` with `scrollToContent`, `scrollToElementId`, or manual zoom/offset
|
|
143
|
+
- **File I/O**: export/import full `.excalidraw` JSON files
|
|
144
|
+
- **Snapshots**: save and restore named canvas states
|
|
145
|
+
- **Skill fallback**: Agent skill auto-detects MCP vs REST API mode
|
|
146
|
+
- Fixed all previously known issues: `align_elements` / `distribute_elements` fully implemented, points type normalization, removed invalid `label` type, `ungroup_elements` now errors on failure
|
|
147
|
+
|
|
148
|
+
### v1.x (upstream)
|
|
149
|
+
|
|
150
|
+
- Agent skill: `skills/excalidraw-skill/` (portable instructions + helper scripts for export/import and repeatable CRUD)
|
|
151
|
+
- Better testing loop: MCP Inspector CLI examples + browser screenshot checks
|
|
152
|
+
- Bugfixes: batch create now preserves element ids (fixes update/delete after batch); frontend entrypoint fixed
|
|
153
|
+
|
|
154
|
+
## Architecture
|
|
155
|
+
|
|
156
|
+

|
|
157
|
+
|
|
158
|
+
- **Single process**: The MCP server embeds the canvas server. Starting the MCP starts both; stopping it stops both.
|
|
159
|
+
- **SQLite**: Stored at `~/.excalidraw-mcp/excalidraw.db` by default. WAL mode + `busy_timeout` for multi-process safety.
|
|
160
|
+
- **Multi-tenancy**: Each workspace gets an isolated tenant (SHA-256 hash of workspace path). The UI shows a workspace switcher dropdown with search.
|
|
161
|
+
|
|
162
|
+
## Quick Start
|
|
163
|
+
|
|
164
|
+
### Option A: NPM (recommended)
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npx @sanjibdevnath/mcp-excalidraw-local
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Or install globally:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
npm install -g @sanjibdevnath/mcp-excalidraw-local
|
|
174
|
+
mcp-excalidraw-local
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Option B: From source
|
|
178
|
+
|
|
179
|
+
**Prerequisites:** Node >= 18, npm or pnpm
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
git clone https://github.com/sanjibdevnathlabs/mcp-excalidraw-local.git
|
|
183
|
+
cd mcp-excalidraw-local
|
|
184
|
+
|
|
185
|
+
# Install dependencies (pnpm or npm)
|
|
186
|
+
pnpm install
|
|
187
|
+
pnpm rebuild better-sqlite3 esbuild
|
|
188
|
+
|
|
189
|
+
# Build frontend + server
|
|
190
|
+
pnpm run build
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The MCP server is typically started by your MCP client — see [Configuration](#configuration). To run manually:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
node dist/index.js
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
This starts the MCP server (stdio) **and** the canvas server. Open `http://localhost:3000` in your browser.
|
|
200
|
+
|
|
201
|
+
## Quick Start (Docker)
|
|
202
|
+
|
|
203
|
+
Canvas server:
|
|
204
|
+
```bash
|
|
205
|
+
docker run -d -p 3000:3000 --name mcp-excalidraw-canvas sanjibdevnath/mcp-excalidraw-local-canvas:latest
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
MCP server (stdio) is typically launched by your MCP client. If you want a local container, use `sanjibdevnath/mcp-excalidraw-local:latest`.
|
|
209
|
+
|
|
210
|
+
## Configuration
|
|
211
|
+
|
|
212
|
+
This is a standard MCP server communicating over **stdio**. It works with any MCP-compatible client (Cursor, Claude Desktop, Claude Code, Codex CLI, OpenCode, Gemini, or any other agent that supports the Model Context Protocol).
|
|
213
|
+
|
|
214
|
+
### JSON config (most clients)
|
|
215
|
+
|
|
216
|
+
Add this to your client's MCP configuration file:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"mcpServers": {
|
|
221
|
+
"excalidraw-canvas": {
|
|
222
|
+
"command": "node",
|
|
223
|
+
"args": ["/absolute/path/to/mcp-excalidraw-local/dist/index.js"],
|
|
224
|
+
"env": {
|
|
225
|
+
"CANVAS_PORT": "3000"
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Replace `/absolute/path/to/mcp-excalidraw-local` with the actual path where you cloned and built the repo.
|
|
233
|
+
|
|
234
|
+
### CLI-based registration
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Example for Claude Code
|
|
238
|
+
claude mcp add excalidraw-canvas --scope user \
|
|
239
|
+
-e CANVAS_PORT=3000 \
|
|
240
|
+
-- node /absolute/path/to/mcp-excalidraw-local/dist/index.js
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Docker
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"mcpServers": {
|
|
248
|
+
"excalidraw-canvas": {
|
|
249
|
+
"command": "docker",
|
|
250
|
+
"args": [
|
|
251
|
+
"run", "-i", "--rm",
|
|
252
|
+
"-e", "CANVAS_PORT=3000",
|
|
253
|
+
"sanjibdevnath/mcp-excalidraw-local:latest"
|
|
254
|
+
]
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
> **Note:** For Docker on Linux, you may need `--add-host=host.docker.internal:host-gateway`.
|
|
261
|
+
|
|
262
|
+
### Key points
|
|
263
|
+
|
|
264
|
+
- **Single process** — The canvas server is embedded. No separate terminal or process needed.
|
|
265
|
+
- **Browser required for screenshots** — `export_to_image` and `get_canvas_screenshot` rely on the frontend. Open `http://localhost:3000` in a browser.
|
|
266
|
+
|
|
267
|
+
## Environment Variables
|
|
268
|
+
|
|
269
|
+
| Variable | Description | Default |
|
|
270
|
+
|----------|-------------|---------|
|
|
271
|
+
| `CANVAS_PORT` | Port for the embedded canvas server | `3000` |
|
|
272
|
+
| `EXCALIDRAW_DB_PATH` | Path to the SQLite database file | `~/.excalidraw-mcp/excalidraw.db` |
|
|
273
|
+
| `EXCALIDRAW_EXPORT_DIR` | Allowed directory for file exports | `process.cwd()` |
|
|
274
|
+
| `EXPRESS_SERVER_URL` | Canvas server URL (only if running canvas separately) | `http://localhost:3000` |
|
|
275
|
+
| `ENABLE_CANVAS_SYNC` | Enable real-time canvas sync | `true` |
|
|
276
|
+
|
|
277
|
+
## Multi-Tenancy (Workspaces)
|
|
278
|
+
|
|
279
|
+
Each workspace (codebase) gets an isolated canvas. The tenant is identified by a SHA-256 hash of the workspace path.
|
|
280
|
+
|
|
281
|
+
### How it works
|
|
282
|
+
|
|
283
|
+
1. **Auto-detection**: When the MCP starts, it calls `server.listRoots()` to get the actual workspace path from the MCP client. This is hashed to create a unique tenant ID.
|
|
284
|
+
2. **Per-request scoping**: Every HTTP request includes an `X-Tenant-Id` header. The canvas server uses this to scope all CRUD operations to the correct tenant.
|
|
285
|
+
3. **UI switcher**: The canvas UI shows a "Workspace: <name>" badge. Click it to open a dropdown with all known workspaces, complete with search.
|
|
286
|
+
4. **Multi-instance safe**: SQLite WAL mode with `busy_timeout = 5000ms` handles concurrent access from multiple client instances.
|
|
287
|
+
|
|
288
|
+
### Projects within a tenant
|
|
289
|
+
|
|
290
|
+
Each tenant can have multiple projects (collections of elements). Use the `list_projects` and `switch_project` MCP tools, or manage via the REST API.
|
|
291
|
+
|
|
292
|
+
## Agent Skill (Optional)
|
|
293
|
+
|
|
294
|
+
This repo includes a skill at `skills/excalidraw-skill/` that provides:
|
|
295
|
+
|
|
296
|
+
- **Workflow playbook** (`SKILL.md`): step-by-step guidance for drawing, refining, and exporting diagrams — including an iterative write-check-review cycle, sizing rules, color palettes, and anti-patterns
|
|
297
|
+
- **Cheatsheet** (`references/cheatsheet.md`): MCP tool and REST API reference for all 32 tools
|
|
298
|
+
- **Helper scripts** (`scripts/*.cjs`): export, import, clear, healthcheck, CRUD operations
|
|
299
|
+
|
|
300
|
+
The skill complements the MCP server by giving your AI agent structured workflows to follow.
|
|
301
|
+
|
|
302
|
+
### Install the Skill
|
|
303
|
+
|
|
304
|
+
Copy the skill folder to your agent's skill directory:
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
# Claude Code
|
|
308
|
+
mkdir -p ~/.claude/skills
|
|
309
|
+
cp -R skills/excalidraw-skill ~/.claude/skills/excalidraw-skill
|
|
310
|
+
|
|
311
|
+
# Cursor
|
|
312
|
+
mkdir -p ~/.cursor/skills
|
|
313
|
+
cp -R skills/excalidraw-skill ~/.cursor/skills/excalidraw-skill
|
|
314
|
+
|
|
315
|
+
# Codex CLI
|
|
316
|
+
mkdir -p ~/.codex/skills
|
|
317
|
+
cp -R skills/excalidraw-skill ~/.codex/skills/excalidraw-skill
|
|
318
|
+
|
|
319
|
+
# Or any agent that supports a skills directory
|
|
320
|
+
cp -R skills/excalidraw-skill /path/to/your/agent/skills/
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
To update an existing installation, remove the old folder first then re-copy.
|
|
324
|
+
|
|
325
|
+
### Use the Skill Scripts
|
|
326
|
+
|
|
327
|
+
All scripts respect `EXPRESS_SERVER_URL` (default `http://localhost:3000`) or accept `--url`.
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
EXPRESS_SERVER_URL=http://127.0.0.1:3000 node skills/excalidraw-skill/scripts/healthcheck.cjs
|
|
331
|
+
EXPRESS_SERVER_URL=http://127.0.0.1:3000 node skills/excalidraw-skill/scripts/export-elements.cjs --out diagram.elements.json
|
|
332
|
+
EXPRESS_SERVER_URL=http://127.0.0.1:3000 node skills/excalidraw-skill/scripts/import-elements.cjs --in diagram.elements.json --mode batch
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### When the Skill Is Useful
|
|
336
|
+
|
|
337
|
+
- **Repository workflow**: export elements as JSON, commit it, and re-import later
|
|
338
|
+
- **Reliable refactors**: clear + re-import in `sync` mode to make canvas match a file
|
|
339
|
+
- **Automated smoke tests**: create/update/delete a known element to validate a deployment
|
|
340
|
+
- **Repeatable diagrams**: keep a library of element JSON snippets and import them
|
|
341
|
+
|
|
342
|
+
See `skills/excalidraw-skill/SKILL.md` and `skills/excalidraw-skill/references/cheatsheet.md`.
|
|
343
|
+
|
|
344
|
+
## MCP Tools (32 Total)
|
|
345
|
+
|
|
346
|
+
| Category | Tools |
|
|
347
|
+
|---|---|
|
|
348
|
+
| **Element CRUD** | `create_element`, `get_element`, `update_element`, `delete_element`, `query_elements`, `batch_create_elements`, `duplicate_elements` |
|
|
349
|
+
| **Layout** | `align_elements`, `distribute_elements`, `group_elements`, `ungroup_elements`, `lock_elements`, `unlock_elements` |
|
|
350
|
+
| **Scene Awareness** | `describe_scene`, `get_canvas_screenshot` |
|
|
351
|
+
| **File I/O** | `export_scene`, `import_scene`, `export_to_image`, `export_to_excalidraw_url`, `create_from_mermaid` |
|
|
352
|
+
| **State Management** | `clear_canvas`, `snapshot_scene`, `restore_snapshot` |
|
|
353
|
+
| **Viewport** | `set_viewport` |
|
|
354
|
+
| **Design Guide** | `read_diagram_guide` |
|
|
355
|
+
| **Resources** | `get_resource` |
|
|
356
|
+
| **Search & History** | `search_elements`, `element_history` |
|
|
357
|
+
| **Multi-Tenancy** | `list_tenants`, `switch_tenant` |
|
|
358
|
+
| **Projects** | `list_projects`, `switch_project` |
|
|
359
|
+
|
|
360
|
+
Full schemas are discoverable via `tools/list` or in `skills/excalidraw-skill/references/cheatsheet.md`.
|
|
361
|
+
|
|
362
|
+
## Testing
|
|
363
|
+
|
|
364
|
+
### Health check
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
curl http://localhost:3000/health
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### MCP Inspector
|
|
371
|
+
|
|
372
|
+
List tools:
|
|
373
|
+
```bash
|
|
374
|
+
npx @modelcontextprotocol/inspector --cli \
|
|
375
|
+
-e CANVAS_PORT=3000 -- \
|
|
376
|
+
node dist/index.js --method tools/list
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Create a rectangle:
|
|
380
|
+
```bash
|
|
381
|
+
npx @modelcontextprotocol/inspector --cli \
|
|
382
|
+
-e CANVAS_PORT=3000 -- \
|
|
383
|
+
node dist/index.js --method tools/call --tool-name create_element \
|
|
384
|
+
--tool-arg type=rectangle --tool-arg x=100 --tool-arg y=100 \
|
|
385
|
+
--tool-arg width=300 --tool-arg height=200
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Frontend Screenshots
|
|
389
|
+
|
|
390
|
+
If you use a browser automation tool for UI checks:
|
|
391
|
+
```bash
|
|
392
|
+
# Open the canvas and take a screenshot for verification
|
|
393
|
+
open http://127.0.0.1:3000
|
|
394
|
+
# Or use agent-browser, Playwright, Puppeteer, etc.
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## Troubleshooting
|
|
398
|
+
|
|
399
|
+
- **Canvas not loading**: Ensure `CANVAS_PORT` isn't occupied by another process. Check `lsof -i :3000`.
|
|
400
|
+
- **Canvas not updating**: Confirm the MCP process is running and the browser is connected (check the status dot in the header).
|
|
401
|
+
- **Wrong workspace shown**: The MCP uses `server.listRoots()` to detect the workspace. Restart your MCP client if the workspace changed.
|
|
402
|
+
- **Elements missing after restart**: Check `~/.excalidraw-mcp/excalidraw.db` exists. If you previously ran the upstream (in-memory) version, data wasn't persisted.
|
|
403
|
+
- **Port conflict with multiple instances**: Set different `CANVAS_PORT` values for each workspace, or rely on multi-tenancy (same port, different tenants).
|
|
404
|
+
- **Updates/deletes fail after batch creation**: Ensure you are on a build that includes the batch id preservation fix.
|
|
405
|
+
|
|
406
|
+
## Known Issues / TODO
|
|
407
|
+
|
|
408
|
+
All previously listed bugs from the upstream have been fixed. Remaining items:
|
|
409
|
+
|
|
410
|
+
- [ ] **Image export requires a browser**: `export_to_image` and `get_canvas_screenshot` rely on the frontend rendering. The canvas UI must be open in a browser.
|
|
411
|
+
- [ ] **`export_to_excalidraw_url` blocked**: Organizations that block `excalidraw.com` cannot use shareable URL export. Use `export_scene` for local `.excalidraw` files instead.
|
|
412
|
+
|
|
413
|
+
Contributions welcome!
|
|
414
|
+
|
|
415
|
+
## Development
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
# Type check
|
|
419
|
+
pnpm run type-check
|
|
420
|
+
|
|
421
|
+
# Full build (frontend + server)
|
|
422
|
+
pnpm run build
|
|
423
|
+
|
|
424
|
+
# Dev mode (watch)
|
|
425
|
+
pnpm run dev
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Database
|
|
429
|
+
|
|
430
|
+
SQLite database: `~/.excalidraw-mcp/excalidraw.db`
|
|
431
|
+
|
|
432
|
+
Override with `EXCALIDRAW_DB_PATH` environment variable.
|
|
433
|
+
|
|
434
|
+
### REST API
|
|
435
|
+
|
|
436
|
+
The canvas server exposes a REST API alongside the WebSocket interface:
|
|
437
|
+
|
|
438
|
+
| Method | Endpoint | Description |
|
|
439
|
+
|--------|----------|-------------|
|
|
440
|
+
| GET | `/health` | Health check |
|
|
441
|
+
| GET | `/api/elements` | List all elements |
|
|
442
|
+
| POST | `/api/elements` | Create an element |
|
|
443
|
+
| PUT | `/api/elements/:id` | Update an element |
|
|
444
|
+
| DELETE | `/api/elements/:id` | Delete an element |
|
|
445
|
+
| POST | `/api/elements/sync` | Sync all elements (bulk upsert) |
|
|
446
|
+
| GET | `/api/tenants` | List all tenants |
|
|
447
|
+
| GET | `/api/tenant/active` | Get the active tenant |
|
|
448
|
+
| PUT | `/api/tenant/active` | Set the active tenant |
|
|
449
|
+
|
|
450
|
+
All endpoints accept an `X-Tenant-Id` header for per-request tenant scoping.
|
|
451
|
+
|
|
452
|
+
## Credits
|
|
453
|
+
|
|
454
|
+
This project is forked from [yctimlin/mcp_excalidraw](https://github.com/yctimlin/mcp_excalidraw) — an excellent Excalidraw MCP server with a live canvas, 26 tools, real-time WebSocket sync, Mermaid conversion, and a comprehensive agent skill. Full credit to [@yctimlin](https://github.com/yctimlin) for the original design and implementation.
|
|
455
|
+
|
|
456
|
+
This fork adds SQLite persistence, multi-tenancy, auto-sync, embedded canvas lifecycle, and workspace management on top of that foundation.
|
|
457
|
+
|
|
458
|
+
Licensed under [MIT](LICENSE).
|
package/dist/db.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ServerElement, Snapshot } from './types.js';
|
|
2
|
+
export interface Tenant {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
workspace_path: string;
|
|
6
|
+
created_at: string;
|
|
7
|
+
last_accessed_at: string;
|
|
8
|
+
}
|
|
9
|
+
export interface Project {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string | null;
|
|
13
|
+
tenant_id: string;
|
|
14
|
+
created_at: string;
|
|
15
|
+
updated_at: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ElementVersion {
|
|
18
|
+
id: number;
|
|
19
|
+
element_id: string;
|
|
20
|
+
project_id: string;
|
|
21
|
+
version: number;
|
|
22
|
+
data: ServerElement;
|
|
23
|
+
operation: 'create' | 'update' | 'delete';
|
|
24
|
+
created_at: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function initDb(dbPath?: string): void;
|
|
27
|
+
export declare function getDefaultProjectForTenant(tenantId: string): string;
|
|
28
|
+
export declare function getElement(id: string, projectId?: string): ServerElement | undefined;
|
|
29
|
+
export declare function hasElement(id: string, projectId?: string): boolean;
|
|
30
|
+
export declare function setElement(id: string, element: ServerElement, projectId?: string): void;
|
|
31
|
+
export declare function deleteElement(id: string, projectId?: string): boolean;
|
|
32
|
+
export declare function getAllElements(projectId?: string): ServerElement[];
|
|
33
|
+
export declare function getElementCount(projectId?: string): number;
|
|
34
|
+
export declare function clearElements(projectId?: string): number;
|
|
35
|
+
export declare function queryElements(type?: string, filter?: Record<string, any>, projectId?: string): ServerElement[];
|
|
36
|
+
export declare function searchElements(query: string, projectId?: string): ServerElement[];
|
|
37
|
+
export declare function getElementHistory(elementId: string, limit?: number, projectId?: string): ElementVersion[];
|
|
38
|
+
export declare function getProjectHistory(limit?: number, projectId?: string): ElementVersion[];
|
|
39
|
+
export declare function saveSnapshot(name: string, elements: ServerElement[], projectId?: string): void;
|
|
40
|
+
export declare function getSnapshot(name: string, projectId?: string): Snapshot | undefined;
|
|
41
|
+
export declare function listSnapshots(projectId?: string): {
|
|
42
|
+
name: string;
|
|
43
|
+
elementCount: number;
|
|
44
|
+
createdAt: string;
|
|
45
|
+
}[];
|
|
46
|
+
export declare function ensureTenant(id: string, name: string, workspacePath: string): Tenant;
|
|
47
|
+
export declare function setActiveTenant(id: string): void;
|
|
48
|
+
export declare function getActiveTenant(): Tenant;
|
|
49
|
+
export declare function getActiveTenantId(): string;
|
|
50
|
+
export declare function listTenants(): Tenant[];
|
|
51
|
+
export declare function createProject(name: string, description?: string): Project;
|
|
52
|
+
export declare function listProjects(): Project[];
|
|
53
|
+
export declare function setActiveProject(id: string): void;
|
|
54
|
+
export declare function getActiveProject(): Project;
|
|
55
|
+
export declare function getActiveProjectId(): string;
|
|
56
|
+
export declare function bulkReplaceElements(elements: ServerElement[], projectId?: string): number;
|
|
57
|
+
export declare function closeDb(): void;
|
|
58
|
+
//# sourceMappingURL=db.d.ts.map
|
package/dist/db.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
|