@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.
Files changed (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +458 -0
  3. package/dist/db.d.ts +58 -0
  4. package/dist/db.d.ts.map +1 -0
  5. package/dist/db.js +379 -0
  6. package/dist/db.js.map +1 -0
  7. package/dist/frontend/assets/Assistant-Bold-gm-uSS1B.woff2 +0 -0
  8. package/dist/frontend/assets/Assistant-Medium-DrcxCXg3.woff2 +0 -0
  9. package/dist/frontend/assets/Assistant-Regular-DVxZuzxb.woff2 +0 -0
  10. package/dist/frontend/assets/Assistant-SemiBold-SCI4bEL9.woff2 +0 -0
  11. package/dist/frontend/assets/Tableau10-B-NsZVaP.js +1 -0
  12. package/dist/frontend/assets/_commonjs-dynamic-modules-TDtrdbi3.js +1 -0
  13. package/dist/frontend/assets/advancedFormat-BvOvfnfC.js +1 -0
  14. package/dist/frontend/assets/ar-SA-G6X2FPQ2-75HMOOy8.js +10 -0
  15. package/dist/frontend/assets/arc-D-322MQz.js +1 -0
  16. package/dist/frontend/assets/array-BKyUJesY.js +1 -0
  17. package/dist/frontend/assets/az-AZ-76LH7QW2-DPDwkDvh.js +1 -0
  18. package/dist/frontend/assets/band-dPffDWoQ.js +1 -0
  19. package/dist/frontend/assets/bg-BG-XCXSNQG7-DrFYc9eo.js +5 -0
  20. package/dist/frontend/assets/blockDiagram-38ab4fdb-Ch8bwO7g.js +118 -0
  21. package/dist/frontend/assets/blockDiagram-68f4deed-BVqzkDiu.js +118 -0
  22. package/dist/frontend/assets/bn-BD-2XOGV67Q-B1Y75Cvj.js +5 -0
  23. package/dist/frontend/assets/c4Diagram-15b5d702-D5U2mSdf.js +10 -0
  24. package/dist/frontend/assets/c4Diagram-3d4e48cf-eT2EEN_c.js +10 -0
  25. package/dist/frontend/assets/ca-ES-6MX7JW3Y-00BTiK3Z.js +8 -0
  26. package/dist/frontend/assets/channel-CudwHHli.js +1 -0
  27. package/dist/frontend/assets/classDiagram-70f12bd4-CcNOdQHv.js +2 -0
  28. package/dist/frontend/assets/classDiagram-d40c83e7-nRIgRTMT.js +2 -0
  29. package/dist/frontend/assets/classDiagram-v2-d5a6b087-Cfbvao44.js +2 -0
  30. package/dist/frontend/assets/classDiagram-v2-f2320105-1Sjp5Uqh.js +2 -0
  31. package/dist/frontend/assets/clone-D_tGm99B.js +1 -0
  32. package/dist/frontend/assets/createText-2e5e7dd3-Bpmkp1eZ.js +5 -0
  33. package/dist/frontend/assets/createText-d213de94-3MLB4fd8.js +5 -0
  34. package/dist/frontend/assets/cs-CZ-2BRQDIVT-R7SCWLLF.js +11 -0
  35. package/dist/frontend/assets/cytoscape-cose-bilkent-CoIxD6ON.js +331 -0
  36. package/dist/frontend/assets/da-DK-5WZEPLOC-Db1yebad.js +5 -0
  37. package/dist/frontend/assets/de-DE-XR44H4JA-HRE-6fuh.js +8 -0
  38. package/dist/frontend/assets/directory-open-01563666-DWU9wJ6I.js +1 -0
  39. package/dist/frontend/assets/directory-open-4ed118d0-BzWybGaI.js +1 -0
  40. package/dist/frontend/assets/edges-332bd1c7-DZAOA9uP.js +4 -0
  41. package/dist/frontend/assets/edges-e0da2a9e-CP-XTLb4.js +4 -0
  42. package/dist/frontend/assets/el-GR-BZB4AONW-CfNczSdx.js +10 -0
  43. package/dist/frontend/assets/elk.bundled-BZDcWavb.js +26 -0
  44. package/dist/frontend/assets/erDiagram-880f2ed8-Bk96tDga.js +51 -0
  45. package/dist/frontend/assets/erDiagram-9861fffd-BvkEkcRK.js +51 -0
  46. package/dist/frontend/assets/es-ES-U4NZUMDT-BBJZ1_wD.js +9 -0
  47. package/dist/frontend/assets/eu-ES-A7QVB2H4-CCLNmdnk.js +11 -0
  48. package/dist/frontend/assets/fa-IR-HGAKTJCU-BtKS5FOW.js +8 -0
  49. package/dist/frontend/assets/fi-FI-Z5N7JZ37-DEQi6vbL.js +6 -0
  50. package/dist/frontend/assets/file-open-002ab408-DIuFHtCF.js +1 -0
  51. package/dist/frontend/assets/file-open-7c801643-684qeFg4.js +1 -0
  52. package/dist/frontend/assets/file-save-3189631c-x92wctJd.js +1 -0
  53. package/dist/frontend/assets/file-save-745eba88-Bb9F9Kg7.js +1 -0
  54. package/dist/frontend/assets/flowDb-7c981674-JJMg1ttK.js +10 -0
  55. package/dist/frontend/assets/flowDb-956e92f1-CVVUllPW.js +10 -0
  56. package/dist/frontend/assets/flowDiagram-66a62f08-wGFuUp6y.js +4 -0
  57. package/dist/frontend/assets/flowDiagram-cbd28bf7-CXKT_tHC.js +4 -0
  58. package/dist/frontend/assets/flowDiagram-v2-96b9c2cf-CN4ht1EM.js +1 -0
  59. package/dist/frontend/assets/flowDiagram-v2-ffc7f31a-CFiBItzu.js +1 -0
  60. package/dist/frontend/assets/flowchart-elk-definition-36e2d292-Cam5JBwn.js +114 -0
  61. package/dist/frontend/assets/flowchart-elk-definition-4a651766-BoyD4myW.js +114 -0
  62. package/dist/frontend/assets/fr-FR-RHASNOE6-_AQjPuKS.js +9 -0
  63. package/dist/frontend/assets/ganttDiagram-04f9e578-DrDI9_oS.js +257 -0
  64. package/dist/frontend/assets/ganttDiagram-c361ad54-CKSyNc2k.js +257 -0
  65. package/dist/frontend/assets/gitGraphDiagram-21fc4d3e-BHBdnwSb.js +70 -0
  66. package/dist/frontend/assets/gitGraphDiagram-72cf32ee-BHN9qiXg.js +70 -0
  67. package/dist/frontend/assets/gl-ES-HMX3MZ6V-Bp2h6sBC.js +10 -0
  68. package/dist/frontend/assets/graph-CRb9j7zI.js +1 -0
  69. package/dist/frontend/assets/graph-EK5j_nPe.js +1 -0
  70. package/dist/frontend/assets/he-IL-6SHJWFNN-hsaAKZ5K.js +10 -0
  71. package/dist/frontend/assets/hi-IN-IWLTKZ5I-sgYSNzoz.js +4 -0
  72. package/dist/frontend/assets/hu-HU-A5ZG7DT2-DxYZr0yq.js +7 -0
  73. package/dist/frontend/assets/id-ID-SAP4L64H-z0RzSKPQ.js +10 -0
  74. package/dist/frontend/assets/image-blob-reduce.esm-B6b2_-a4.js +7 -0
  75. package/dist/frontend/assets/index-3862675e-CQPsxwvk.js +1 -0
  76. package/dist/frontend/assets/index-6079d271-pTR-OMc-.js +1 -0
  77. package/dist/frontend/assets/index-B9Rh8YyQ.css +1 -0
  78. package/dist/frontend/assets/index-BcHA28Dx.js +87 -0
  79. package/dist/frontend/assets/index-DGmpr33w.js +3 -0
  80. package/dist/frontend/assets/index-DPgZw9ew.js +349 -0
  81. package/dist/frontend/assets/infoDiagram-4a4f5b27-OIxyK2_N.js +7 -0
  82. package/dist/frontend/assets/infoDiagram-f8f76790-BTkoanKB.js +7 -0
  83. package/dist/frontend/assets/init-Gi6I4Gst.js +1 -0
  84. package/dist/frontend/assets/it-IT-JPQ66NNP-Cu6RM7DP.js +11 -0
  85. package/dist/frontend/assets/ja-JP-DBVTYXUO-lD7U4Zkf.js +8 -0
  86. package/dist/frontend/assets/journeyDiagram-29694f62-BS4Xl0A-.js +139 -0
  87. package/dist/frontend/assets/journeyDiagram-49397b02-BbBAwEfu.js +139 -0
  88. package/dist/frontend/assets/kaa-6HZHGXH3-DM9LwXUP.js +1 -0
  89. package/dist/frontend/assets/kab-KAB-ZGHBKWFO-BAojmp2_.js +8 -0
  90. package/dist/frontend/assets/katex-ChWnQ-fc.js +261 -0
  91. package/dist/frontend/assets/kk-KZ-P5N5QNE5-Dp0K1W81.js +1 -0
  92. package/dist/frontend/assets/km-KH-HSX4SM5Z-BzYGKbAg.js +11 -0
  93. package/dist/frontend/assets/ko-KR-MTYHY66A-DOvEMk4H.js +9 -0
  94. package/dist/frontend/assets/ku-TR-6OUDTVRD-B6l-ghqp.js +9 -0
  95. package/dist/frontend/assets/layout-CGydnLJa.js +1 -0
  96. package/dist/frontend/assets/layout-DbdMIGYe.js +1 -0
  97. package/dist/frontend/assets/line-CbImtxDK.js +1 -0
  98. package/dist/frontend/assets/linear-DvIsU3aM.js +1 -0
  99. package/dist/frontend/assets/lt-LT-XHIRWOB4-BYcRk8Uj.js +3 -0
  100. package/dist/frontend/assets/lv-LV-5QDEKY6T-DS3krNIe.js +7 -0
  101. package/dist/frontend/assets/mindmap-definition-ac74a2e8-C0Sp7ICZ.js +95 -0
  102. package/dist/frontend/assets/mindmap-definition-fc14e90a-BZrjRbkr.js +95 -0
  103. package/dist/frontend/assets/mr-IN-CRQNXWMA-BfxQL7Vh.js +13 -0
  104. package/dist/frontend/assets/my-MM-5M5IBNSE-C3EfnOvD.js +1 -0
  105. package/dist/frontend/assets/nb-NO-T6EIAALU-BIbPZokm.js +10 -0
  106. package/dist/frontend/assets/nl-NL-IS3SIHDZ-BqQloGBT.js +8 -0
  107. package/dist/frontend/assets/nn-NO-6E72VCQL-zGR8NYQf.js +8 -0
  108. package/dist/frontend/assets/oc-FR-POXYY2M6-B8-HsJFE.js +8 -0
  109. package/dist/frontend/assets/ordinal-Cboi1Yqb.js +1 -0
  110. package/dist/frontend/assets/pa-IN-N4M65BXN-B2Ta58Tu.js +4 -0
  111. package/dist/frontend/assets/path-CbwjOpE9.js +1 -0
  112. package/dist/frontend/assets/pica-DSD-O3at.js +7 -0
  113. package/dist/frontend/assets/pie-Dk_pQnuO.js +1 -0
  114. package/dist/frontend/assets/pieDiagram-421022e6-9oAq5fk_.js +35 -0
  115. package/dist/frontend/assets/pieDiagram-8a3498a8-B5SMrdDh.js +35 -0
  116. package/dist/frontend/assets/pl-PL-T2D74RX3-rZKvQ0zQ.js +9 -0
  117. package/dist/frontend/assets/pt-BR-5N22H2LF-ij6wtU6I.js +9 -0
  118. package/dist/frontend/assets/pt-PT-UZXXM6DQ-BIgtUnbW.js +9 -0
  119. package/dist/frontend/assets/quadrantDiagram-0957ecba-Cr3mj6c1.js +7 -0
  120. package/dist/frontend/assets/quadrantDiagram-120e2f19-CQnc4s0f.js +7 -0
  121. package/dist/frontend/assets/requirementDiagram-23d650b8-Bs7pP1vJ.js +52 -0
  122. package/dist/frontend/assets/requirementDiagram-deff3bca-G5e-Qxao.js +52 -0
  123. package/dist/frontend/assets/ro-RO-JPDTUUEW-DPj_79nt.js +11 -0
  124. package/dist/frontend/assets/roundRect-0PYZxl1G.js +1 -0
  125. package/dist/frontend/assets/ru-RU-B4JR7IUQ-fdYiaqbX.js +9 -0
  126. package/dist/frontend/assets/sankeyDiagram-04a897e0-CJogadkF.js +8 -0
  127. package/dist/frontend/assets/sankeyDiagram-23345273-DKUWMCrX.js +8 -0
  128. package/dist/frontend/assets/sankeyLinkHorizontal-DgqkLiUE.js +1 -0
  129. package/dist/frontend/assets/selectAll-tNeSnQY6.js +1 -0
  130. package/dist/frontend/assets/sequenceDiagram-17ac3bff-DCw9xUbw.js +122 -0
  131. package/dist/frontend/assets/sequenceDiagram-704730f1-BgClSrOI.js +122 -0
  132. package/dist/frontend/assets/si-LK-N5RQ5JYF-DfPBk-rU.js +1 -0
  133. package/dist/frontend/assets/sk-SK-C5VTKIMK-Cbj4yoD_.js +6 -0
  134. package/dist/frontend/assets/sl-SI-NN7IZMDC-C_rL7eDE.js +6 -0
  135. package/dist/frontend/assets/stateDiagram-587899a1-DuFGG-SI.js +1 -0
  136. package/dist/frontend/assets/stateDiagram-9c5f0230-Bwj38hfH.js +1 -0
  137. package/dist/frontend/assets/stateDiagram-v2-51a3dcff-3c0yKNdL.js +1 -0
  138. package/dist/frontend/assets/stateDiagram-v2-d93cdb3a-CAaqB4wm.js +1 -0
  139. package/dist/frontend/assets/styles-2ab5d517-Dxg7wKah.js +116 -0
  140. package/dist/frontend/assets/styles-5f03d8d2-DD32XMGL.js +160 -0
  141. package/dist/frontend/assets/styles-6aaf32cf-B5DxK_RW.js +207 -0
  142. package/dist/frontend/assets/styles-9a916d00-C6L6Mj2P.js +160 -0
  143. package/dist/frontend/assets/styles-c10674c1-BPM_bB3H.js +116 -0
  144. package/dist/frontend/assets/styles-edf9a4b0-CbQDxrwP.js +207 -0
  145. package/dist/frontend/assets/subset-shared.chunk-B_DQsaBC.js +84 -0
  146. package/dist/frontend/assets/subset-worker.chunk-DL6tLP7M.js +1 -0
  147. package/dist/frontend/assets/sv-SE-XGPEYMSR-BmmcOaVK.js +10 -0
  148. package/dist/frontend/assets/svgDrawCommon-08f97a94-aUx8qfJx.js +1 -0
  149. package/dist/frontend/assets/svgDrawCommon-3ba9043b-1JM8RiLc.js +1 -0
  150. package/dist/frontend/assets/ta-IN-2NMHFXQM-Kxnb_Mwk.js +9 -0
  151. package/dist/frontend/assets/th-TH-HPSO5L25-BqTLgxJz.js +2 -0
  152. package/dist/frontend/assets/timeline-definition-7e6b55e7-BbFhIPTl.js +61 -0
  153. package/dist/frontend/assets/timeline-definition-85554ec2-C1G9H6m5.js +61 -0
  154. package/dist/frontend/assets/tr-TR-DEFEU3FU-DhlYP6tL.js +7 -0
  155. package/dist/frontend/assets/uk-UA-QMV73CPH-pMrN1qBS.js +6 -0
  156. package/dist/frontend/assets/union-Cu1rbD_D.js +1 -0
  157. package/dist/frontend/assets/vi-VN-M7AON7JQ-BPMcH84R.js +5 -0
  158. package/dist/frontend/assets/xml-BOsq7VnW.js +1 -0
  159. package/dist/frontend/assets/xychartDiagram-b6496bcd-BDm9pYtk.js +7 -0
  160. package/dist/frontend/assets/xychartDiagram-e933f94c-BlrTBDHC.js +7 -0
  161. package/dist/frontend/assets/zh-CN-LNUGB5OW-B8kYYibM.js +10 -0
  162. package/dist/frontend/assets/zh-HK-E62DVLB3-CaI0gehP.js +1 -0
  163. package/dist/frontend/assets/zh-TW-RAJ6MFWO-DKCVg17j.js +9 -0
  164. package/dist/frontend/assets/zipObject-iRVIFf6r.js +1 -0
  165. package/dist/frontend/index.html +420 -0
  166. package/dist/index.d.ts +4 -0
  167. package/dist/index.d.ts.map +1 -0
  168. package/dist/index.js +2241 -0
  169. package/dist/index.js.map +1 -0
  170. package/dist/server.d.ts +6 -0
  171. package/dist/server.d.ts.map +1 -0
  172. package/dist/server.js +980 -0
  173. package/dist/server.js.map +1 -0
  174. package/dist/types.d.ts +225 -0
  175. package/dist/types.d.ts.map +1 -0
  176. package/dist/types.js +30 -0
  177. package/dist/types.js.map +1 -0
  178. package/dist/utils/logger.d.ts +4 -0
  179. package/dist/utils/logger.d.ts.map +1 -0
  180. package/dist/utils/logger.js +23 -0
  181. package/dist/utils/logger.js.map +1 -0
  182. package/package.json +108 -0
  183. package/skills/excalidraw-skill/SKILL.md +370 -0
  184. package/skills/excalidraw-skill/references/cheatsheet.md +195 -0
  185. package/skills/excalidraw-skill/scripts/clear-canvas.cjs +38 -0
  186. package/skills/excalidraw-skill/scripts/create-element.cjs +68 -0
  187. package/skills/excalidraw-skill/scripts/delete-element.cjs +48 -0
  188. package/skills/excalidraw-skill/scripts/export-elements.cjs +53 -0
  189. package/skills/excalidraw-skill/scripts/healthcheck.cjs +35 -0
  190. package/skills/excalidraw-skill/scripts/import-elements.cjs +81 -0
  191. 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
+ [![CI](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/ci.yml/badge.svg)](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/ci.yml)
4
+ [![Docker Build & Push](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/docker.yml/badge.svg)](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/docker.yml)
5
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](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
+ ![Canvas UI](docs/screenshots/canvas-ui.png)
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
+ ![Workspace Switcher](docs/screenshots/workspace-switcher.png)
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
+ ![Architecture](docs/screenshots/architecture.png)
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: &lt;name&gt;" 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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1D,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC;CACpB;AAaD,wBAAgB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAmC5C;AA+GD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAanE;AAID,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAKpF;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAKlE;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CA2BvF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAiBrE;AAED,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAKlE;AAED,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1D;AAED,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBxD;AAED,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAa9G;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAOjF;AA4BD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,CAO7G;AAED,wBAAgB,iBAAiB,CAAC,KAAK,GAAE,MAAY,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,CAO3F;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAM9F;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAOlF;AAED,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,CAS7G;AAID,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAcpF;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAsBhD;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC;AAID,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAOzE;AAED,wBAAgB,YAAY,IAAI,OAAO,EAAE,CAExC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAOjD;AAED,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAID,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CASzF;AAED,wBAAgB,OAAO,IAAI,IAAI,CAK9B"}