@excalimate/mcp-server 0.1.0 → 0.3.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/README.md +176 -16
- package/dist/checkpoint-store.d.ts +1 -0
- package/dist/checkpoint-store.d.ts.map +1 -1
- package/dist/checkpoint-store.js +23 -2
- package/dist/checkpoint-store.js.map +1 -1
- package/dist/httpServer.d.ts +4 -0
- package/dist/httpServer.d.ts.map +1 -0
- package/dist/httpServer.js +199 -0
- package/dist/httpServer.js.map +1 -0
- package/dist/index.d.ts +0 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -177
- package/dist/index.js.map +1 -1
- package/dist/server/animationTools.d.ts +9 -0
- package/dist/server/animationTools.d.ts.map +1 -0
- package/dist/server/animationTools.js +254 -0
- package/dist/server/animationTools.js.map +1 -0
- package/dist/server/checkpointTools.d.ts +5 -0
- package/dist/server/checkpointTools.d.ts.map +1 -0
- package/dist/server/checkpointTools.js +22 -0
- package/dist/server/checkpointTools.js.map +1 -0
- package/dist/server/elementNormalizer.d.ts +3 -0
- package/dist/server/elementNormalizer.d.ts.map +1 -0
- package/dist/server/elementNormalizer.js +52 -0
- package/dist/server/elementNormalizer.js.map +1 -0
- package/dist/server/geometry.d.ts +24 -0
- package/dist/server/geometry.d.ts.map +1 -0
- package/dist/server/geometry.js +102 -0
- package/dist/server/geometry.js.map +1 -0
- package/dist/server/queryTools.d.ts +28 -0
- package/dist/server/queryTools.d.ts.map +1 -0
- package/dist/server/queryTools.js +107 -0
- package/dist/server/queryTools.js.map +1 -0
- package/dist/server/referenceText.d.ts +3 -0
- package/dist/server/referenceText.d.ts.map +1 -0
- package/dist/server/referenceText.js +268 -0
- package/dist/server/referenceText.js.map +1 -0
- package/dist/server/sceneTools.d.ts +4 -0
- package/dist/server/sceneTools.d.ts.map +1 -0
- package/dist/server/sceneTools.js +86 -0
- package/dist/server/sceneTools.js.map +1 -0
- package/dist/server/shareTools.d.ts +11 -0
- package/dist/server/shareTools.d.ts.map +1 -0
- package/dist/server/shareTools.js +81 -0
- package/dist/server/shareTools.js.map +1 -0
- package/dist/server/stateContext.d.ts +21 -0
- package/dist/server/stateContext.d.ts.map +1 -0
- package/dist/server/stateContext.js +85 -0
- package/dist/server/stateContext.js.map +1 -0
- package/dist/server.d.ts +5 -10
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +24 -891
- package/dist/server.js.map +1 -1
- package/dist/shareRoutes.d.ts +4 -0
- package/dist/shareRoutes.d.ts.map +1 -0
- package/dist/shareRoutes.js +44 -0
- package/dist/shareRoutes.js.map +1 -0
- package/dist/stdioServer.d.ts +3 -0
- package/dist/stdioServer.d.ts.map +1 -0
- package/dist/stdioServer.js +5 -0
- package/dist/stdioServer.js.map +1 -0
- package/package.json +6 -2
- package/SKILL.md +0 -110
- package/references/REFERENCE.md +0 -192
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
export const REFERENCE_TEXT = `# Excalimate MCP Reference
|
|
2
|
+
|
|
3
|
+
## Excalidraw Element Format
|
|
4
|
+
|
|
5
|
+
Every element has these base properties:
|
|
6
|
+
\`\`\`json
|
|
7
|
+
{
|
|
8
|
+
"id": "unique-id",
|
|
9
|
+
"type": "rectangle|ellipse|diamond|arrow|line|text|freedraw|image",
|
|
10
|
+
"x": 100, "y": 200,
|
|
11
|
+
"width": 300, "height": 150,
|
|
12
|
+
"angle": 0,
|
|
13
|
+
"strokeColor": "#1e1e1e",
|
|
14
|
+
"backgroundColor": "transparent",
|
|
15
|
+
"fillStyle": "solid",
|
|
16
|
+
"strokeWidth": 2,
|
|
17
|
+
"roughness": 1,
|
|
18
|
+
"opacity": 100,
|
|
19
|
+
"groupIds": [],
|
|
20
|
+
"isDeleted": false
|
|
21
|
+
}
|
|
22
|
+
\`\`\`
|
|
23
|
+
|
|
24
|
+
### Text Elements
|
|
25
|
+
\`\`\`json
|
|
26
|
+
{
|
|
27
|
+
"type": "text",
|
|
28
|
+
"text": "Hello World",
|
|
29
|
+
"fontSize": 20,
|
|
30
|
+
"fontFamily": 5,
|
|
31
|
+
"textAlign": "center",
|
|
32
|
+
"verticalAlign": "middle"
|
|
33
|
+
}
|
|
34
|
+
\`\`\`
|
|
35
|
+
|
|
36
|
+
### Arrow/Line Elements
|
|
37
|
+
\`\`\`json
|
|
38
|
+
{
|
|
39
|
+
"type": "arrow",
|
|
40
|
+
"points": [[0, 0], [200, 100]],
|
|
41
|
+
"startArrowhead": null,
|
|
42
|
+
"endArrowhead": "arrow",
|
|
43
|
+
"startBinding": null,
|
|
44
|
+
"endBinding": null
|
|
45
|
+
}
|
|
46
|
+
\`\`\`
|
|
47
|
+
|
|
48
|
+
### Bound Text (Label on Shape)
|
|
49
|
+
Create a text element with \`containerId\` pointing to the shape:
|
|
50
|
+
\`\`\`json
|
|
51
|
+
{ "type": "text", "containerId": "shape-id", ... }
|
|
52
|
+
\`\`\`
|
|
53
|
+
And add to the shape: \`"boundElements": [{"id": "text-id", "type": "text"}]\`
|
|
54
|
+
|
|
55
|
+
## Color Palettes
|
|
56
|
+
|
|
57
|
+
**Stroke**: #1e1e1e, #e03131, #2f9e44, #1971c2, #f08c00, #6741d9, #0c8599, #e8590c
|
|
58
|
+
**Background**: transparent, #ffc9c9, #b2f2bb, #a5d8ff, #ffec99, #d0bfff, #99e9f2, #ffd8a8
|
|
59
|
+
|
|
60
|
+
## Animatable Properties
|
|
61
|
+
|
|
62
|
+
| Property | Range | Description |
|
|
63
|
+
|----------|-------|-------------|
|
|
64
|
+
| opacity | 0–1 | Element visibility (0=hidden, 1=visible) |
|
|
65
|
+
| translateX | px | Horizontal position offset |
|
|
66
|
+
| translateY | px | Vertical position offset |
|
|
67
|
+
| scaleX | 0.1+ | Horizontal scale (1=normal) |
|
|
68
|
+
| scaleY | 0.1+ | Vertical scale (1=normal) |
|
|
69
|
+
| rotation | degrees | Rotation angle |
|
|
70
|
+
| drawProgress | 0–1 | Stroke draw-on progress (for lines/arrows) |
|
|
71
|
+
|
|
72
|
+
## Easing Types
|
|
73
|
+
|
|
74
|
+
linear, easeIn, easeOut, easeInOut, easeInQuad, easeOutQuad, easeInOutQuad,
|
|
75
|
+
easeInCubic, easeOutCubic, easeInOutCubic, easeInBack, easeOutBack, easeInOutBack,
|
|
76
|
+
easeInElastic, easeOutElastic, easeInBounce, easeOutBounce, step
|
|
77
|
+
|
|
78
|
+
## Workflow
|
|
79
|
+
|
|
80
|
+
1. Call \`read_me\` (this tool) to get the reference
|
|
81
|
+
2. Call \`create_scene\` with Excalidraw elements JSON (or \`clear_scene\` to start fresh)
|
|
82
|
+
3. Call \`add_keyframe\` or \`add_keyframes_batch\` to animate elements
|
|
83
|
+
4. Use \`create_sequence\` for reveal animations
|
|
84
|
+
5. Call \`set_clip_range\` to set export bounds
|
|
85
|
+
6. Call \`save_checkpoint\` to persist
|
|
86
|
+
7. User opens the checkpoint in the Excalimate web app for preview/export
|
|
87
|
+
|
|
88
|
+
Use \`clear_scene\` to reset everything (elements + animations) or \`clear_animation\` to keep elements but remove all keyframes.
|
|
89
|
+
|
|
90
|
+
## Example: Fade-in Rectangle
|
|
91
|
+
|
|
92
|
+
\`\`\`
|
|
93
|
+
1. create_scene: [{"id":"rect1","type":"rectangle","x":100,"y":100,"width":200,"height":100,...}]
|
|
94
|
+
2. add_keyframe: {targetId:"rect1", property:"opacity", time:0, value:0}
|
|
95
|
+
3. add_keyframe: {targetId:"rect1", property:"opacity", time:1000, value:1, easing:"easeOut"}
|
|
96
|
+
\`\`\`
|
|
97
|
+
`;
|
|
98
|
+
export const EXAMPLES_TEXT = `# Excalimate — Few-Shot Examples
|
|
99
|
+
|
|
100
|
+
## Example 1: Single Rectangle
|
|
101
|
+
\`\`\`
|
|
102
|
+
create_scene({ elements: '[{"id":"box1","type":"rectangle","x":200,"y":150,"width":250,"height":120,"strokeColor":"#1971c2","backgroundColor":"#a5d8ff","fillStyle":"solid"}]' })
|
|
103
|
+
\`\`\`
|
|
104
|
+
|
|
105
|
+
## Example 2: Rectangle with Bound Text Label
|
|
106
|
+
\`\`\`
|
|
107
|
+
create_scene({ elements: '[{"id":"server","type":"rectangle","x":100,"y":100,"width":200,"height":80,"strokeColor":"#1e1e1e","backgroundColor":"#a5d8ff","fillStyle":"solid","boundElements":[{"id":"server-label","type":"text"}]},{"id":"server-label","type":"text","x":140,"y":125,"width":120,"height":30,"text":"API Server","fontSize":20,"fontFamily":5,"textAlign":"center","verticalAlign":"middle","containerId":"server"}]' })
|
|
108
|
+
\`\`\`
|
|
109
|
+
|
|
110
|
+
## Example 3: Two Shapes Connected by Arrow
|
|
111
|
+
\`\`\`
|
|
112
|
+
create_scene({ elements: '[{"id":"A","type":"rectangle","x":100,"y":200,"width":150,"height":80,"strokeColor":"#1e1e1e","backgroundColor":"#b2f2bb","fillStyle":"solid"},{"id":"B","type":"rectangle","x":500,"y":200,"width":150,"height":80,"strokeColor":"#1e1e1e","backgroundColor":"#a5d8ff","fillStyle":"solid"},{"id":"arrow1","type":"arrow","x":250,"y":240,"width":250,"height":0,"points":[[0,0],[250,0]],"endArrowhead":"arrow","startBinding":{"elementId":"A","focus":0,"gap":1},"endBinding":{"elementId":"B","focus":0,"gap":1}}]' })
|
|
113
|
+
\`\`\`
|
|
114
|
+
|
|
115
|
+
## Example 4: Ellipse and Diamond
|
|
116
|
+
\`\`\`
|
|
117
|
+
add_elements({ elements: '[{"id":"circle1","type":"ellipse","x":300,"y":100,"width":120,"height":120,"strokeColor":"#e03131","backgroundColor":"#ffc9c9","fillStyle":"solid"},{"id":"diamond1","type":"diamond","x":500,"y":90,"width":140,"height":140,"strokeColor":"#6741d9","backgroundColor":"#d0bfff","fillStyle":"solid"}]' })
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
## Example 5: Multi-Point Line
|
|
121
|
+
\`\`\`
|
|
122
|
+
add_elements({ elements: '[{"id":"line1","type":"line","x":100,"y":300,"width":400,"height":80,"points":[[0,0],[200,-80],[400,0]],"strokeColor":"#e03131","strokeWidth":3}]' })
|
|
123
|
+
\`\`\`
|
|
124
|
+
|
|
125
|
+
## Example 6: Standalone Text
|
|
126
|
+
\`\`\`
|
|
127
|
+
add_elements({ elements: '[{"id":"title","type":"text","x":200,"y":50,"width":300,"height":50,"text":"Architecture Overview","fontSize":36,"fontFamily":5,"textAlign":"center","strokeColor":"#1e1e1e"}]' })
|
|
128
|
+
\`\`\`
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
# Animation Examples
|
|
133
|
+
|
|
134
|
+
## Example 7: Fade In
|
|
135
|
+
\`\`\`
|
|
136
|
+
add_keyframe({ targetId: "box1", property: "opacity", time: 0, value: 0 })
|
|
137
|
+
add_keyframe({ targetId: "box1", property: "opacity", time: 800, value: 1, easing: "easeOut" })
|
|
138
|
+
\`\`\`
|
|
139
|
+
|
|
140
|
+
## Example 8: Slide In from Left
|
|
141
|
+
\`\`\`
|
|
142
|
+
add_keyframes_batch({ keyframes: '[{"targetId":"box1","property":"translateX","time":0,"value":-300},{"targetId":"box1","property":"translateX","time":1000,"value":0,"easing":"easeOutCubic"},{"targetId":"box1","property":"opacity","time":0,"value":0},{"targetId":"box1","property":"opacity","time":500,"value":1,"easing":"easeOut"}]' })
|
|
143
|
+
\`\`\`
|
|
144
|
+
|
|
145
|
+
## Example 9: Pop In from Center (Scale Up with Bounce)
|
|
146
|
+
\`\`\`
|
|
147
|
+
add_keyframes_batch({ keyframes: '[{"targetId":"box1","property":"scaleX","time":0,"value":0.3,"scaleOrigin":"center"},{"targetId":"box1","property":"scaleY","time":0,"value":0.3,"scaleOrigin":"center"},{"targetId":"box1","property":"scaleX","time":600,"value":1,"easing":"easeOutBack","scaleOrigin":"center"},{"targetId":"box1","property":"scaleY","time":600,"value":1,"easing":"easeOutBack","scaleOrigin":"center"},{"targetId":"box1","property":"opacity","time":0,"value":0},{"targetId":"box1","property":"opacity","time":300,"value":1}]' })
|
|
148
|
+
\`\`\`
|
|
149
|
+
|
|
150
|
+
## Example 9b: Scale from Bottom Edge
|
|
151
|
+
\`\`\`
|
|
152
|
+
add_scale_animation({ targetId: "box1", origin: "bottom", keyframes: '[{"time":0,"scaleX":1,"scaleY":0},{"time":800,"scaleX":1,"scaleY":1,"easing":"easeOutCubic"}]' })
|
|
153
|
+
\`\`\`
|
|
154
|
+
Scale origins: center, top-left, top-right, bottom-left, bottom-right, top, bottom, left, right.
|
|
155
|
+
Add "scaleOrigin" per scaleX/scaleY keyframe in add_keyframes_batch, or use add_scale_animation for a single element.
|
|
156
|
+
|
|
157
|
+
## Example 10: Draw In an Arrow (Stroke Animation)
|
|
158
|
+
\`\`\`
|
|
159
|
+
add_keyframe({ targetId: "arrow1", property: "drawProgress", time: 0, value: 0 })
|
|
160
|
+
add_keyframe({ targetId: "arrow1", property: "drawProgress", time: 1200, value: 1, easing: "easeInOut" })
|
|
161
|
+
\`\`\`
|
|
162
|
+
|
|
163
|
+
## Example 11: Sequential Reveal — A → Arrow → B (Most Common Pattern)
|
|
164
|
+
\`\`\`
|
|
165
|
+
add_keyframes_batch({ keyframes: '[
|
|
166
|
+
{"targetId":"A","property":"opacity","time":0,"value":0},
|
|
167
|
+
{"targetId":"A","property":"opacity","time":600,"value":1,"easing":"easeOut"},
|
|
168
|
+
{"targetId":"arrow1","property":"opacity","time":0,"value":0},
|
|
169
|
+
{"targetId":"arrow1","property":"opacity","time":600,"value":0},
|
|
170
|
+
{"targetId":"arrow1","property":"opacity","time":700,"value":1},
|
|
171
|
+
{"targetId":"arrow1","property":"drawProgress","time":600,"value":0},
|
|
172
|
+
{"targetId":"arrow1","property":"drawProgress","time":1800,"value":1,"easing":"easeInOut"},
|
|
173
|
+
{"targetId":"B","property":"opacity","time":0,"value":0},
|
|
174
|
+
{"targetId":"B","property":"opacity","time":1800,"value":0},
|
|
175
|
+
{"targetId":"B","property":"opacity","time":2400,"value":1,"easing":"easeOut"}
|
|
176
|
+
]' })
|
|
177
|
+
\`\`\`
|
|
178
|
+
|
|
179
|
+
## Example 12: Bidirectional Flow — A ↔ B
|
|
180
|
+
\`\`\`
|
|
181
|
+
add_keyframes_batch({ keyframes: '[
|
|
182
|
+
{"targetId":"A","property":"opacity","time":0,"value":0},
|
|
183
|
+
{"targetId":"A","property":"opacity","time":500,"value":1,"easing":"easeOut"},
|
|
184
|
+
{"targetId":"arrowAB","property":"opacity","time":0,"value":0},
|
|
185
|
+
{"targetId":"arrowAB","property":"opacity","time":500,"value":1},
|
|
186
|
+
{"targetId":"arrowAB","property":"drawProgress","time":500,"value":0},
|
|
187
|
+
{"targetId":"arrowAB","property":"drawProgress","time":1500,"value":1,"easing":"easeInOut"},
|
|
188
|
+
{"targetId":"B","property":"opacity","time":0,"value":0},
|
|
189
|
+
{"targetId":"B","property":"opacity","time":1500,"value":0},
|
|
190
|
+
{"targetId":"B","property":"opacity","time":2000,"value":1,"easing":"easeOut"},
|
|
191
|
+
{"targetId":"arrowBA","property":"opacity","time":0,"value":0},
|
|
192
|
+
{"targetId":"arrowBA","property":"opacity","time":2000,"value":1},
|
|
193
|
+
{"targetId":"arrowBA","property":"drawProgress","time":2000,"value":0},
|
|
194
|
+
{"targetId":"arrowBA","property":"drawProgress","time":3000,"value":1,"easing":"easeInOut"}
|
|
195
|
+
]' })
|
|
196
|
+
\`\`\`
|
|
197
|
+
|
|
198
|
+
## Example 13: Staggered Reveal via create_sequence
|
|
199
|
+
\`\`\`
|
|
200
|
+
create_sequence({ elementIds: ["title","box1","arrow1","box2","arrow2","box3"], property: "opacity", startTime: 0, delay: 400, duration: 600 })
|
|
201
|
+
\`\`\`
|
|
202
|
+
Result: title at 0ms, box1 at 400ms, arrow1 at 800ms, box2 at 1200ms, arrow2 at 1600ms, box3 at 2000ms.
|
|
203
|
+
|
|
204
|
+
## Example 14: Camera Pan
|
|
205
|
+
\`\`\`
|
|
206
|
+
set_camera_frame({ x: 300, y: 200, width: 800, aspectRatio: "16:9" })
|
|
207
|
+
add_camera_keyframe({ property: "translateX", time: 0, value: -200 })
|
|
208
|
+
add_camera_keyframe({ property: "translateX", time: 3000, value: 200, easing: "easeInOut" })
|
|
209
|
+
\`\`\`
|
|
210
|
+
|
|
211
|
+
## Example 15: Camera Zoom In
|
|
212
|
+
\`\`\`
|
|
213
|
+
add_camera_keyframe({ property: "scaleX", time: 0, value: 2 })
|
|
214
|
+
add_camera_keyframe({ property: "scaleY", time: 0, value: 2 })
|
|
215
|
+
add_camera_keyframe({ property: "scaleX", time: 2000, value: 1, easing: "easeInOutCubic" })
|
|
216
|
+
add_camera_keyframe({ property: "scaleY", time: 2000, value: 1, easing: "easeInOutCubic" })
|
|
217
|
+
\`\`\`
|
|
218
|
+
|
|
219
|
+
## Example 16: Clip Range + Save
|
|
220
|
+
\`\`\`
|
|
221
|
+
set_clip_range({ start: 0, end: 5000 })
|
|
222
|
+
save_checkpoint({ id: "my-animation" })
|
|
223
|
+
\`\`\`
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
# Tips
|
|
228
|
+
|
|
229
|
+
1. Always call create_scene first (or clear_scene to start fresh), then animate.
|
|
230
|
+
2. Use add_keyframes_batch for efficiency — one call for many keyframes.
|
|
231
|
+
3. Use create_sequence for simple staggered reveals.
|
|
232
|
+
4. Bound text inherits container animation — animating arrow opacity also hides its label.
|
|
233
|
+
5. drawProgress only works on arrows and lines.
|
|
234
|
+
6. easeOutBack gives a nice bounce for pop-in effects.
|
|
235
|
+
7. easeInOutCubic is the best general-purpose easing.
|
|
236
|
+
8. Set elements to opacity 0 at time 0 if they should appear later.
|
|
237
|
+
9. Set clip range before saving — it defines what gets exported.
|
|
238
|
+
10. Camera scale > 1 = zoomed out, < 1 = zoomed in.
|
|
239
|
+
11. Use delete_items to remove elements AND their animation tracks in one call.
|
|
240
|
+
12. Verify your work with animations_of_item, items_visible_in_camera, are_items_in_line, is_camera_centered.
|
|
241
|
+
|
|
242
|
+
## Example 17: Verify Animation
|
|
243
|
+
\`\`\`
|
|
244
|
+
animations_of_item({ targetId: "box1" })
|
|
245
|
+
// Returns:
|
|
246
|
+
// opacity:
|
|
247
|
+
// 0ms 0% ↑ 100% 600ms (easeOut)
|
|
248
|
+
|
|
249
|
+
items_visible_in_camera({ time: 1000 })
|
|
250
|
+
// Returns: 5/8 items visible (62%) at 1000ms
|
|
251
|
+
|
|
252
|
+
are_items_in_line({ ids: ["box1","box2","box3"], axis: "horizontal" })
|
|
253
|
+
// Returns: ✅ Aligned (max deviation: 3px)
|
|
254
|
+
|
|
255
|
+
is_camera_centered({ axis: "both", time: 0 })
|
|
256
|
+
// Returns: ✅ Centered (offsets: dx=5 dy=2)
|
|
257
|
+
\`\`\`
|
|
258
|
+
|
|
259
|
+
## Example 18: Delete and Rebuild
|
|
260
|
+
\`\`\`
|
|
261
|
+
delete_items({ ids: ["old_box", "old_arrow"] })
|
|
262
|
+
// Removes elements + all their animation tracks
|
|
263
|
+
|
|
264
|
+
clear_scene()
|
|
265
|
+
// Nuclear option: removes everything
|
|
266
|
+
\`\`\`
|
|
267
|
+
`;
|
|
268
|
+
//# sourceMappingURL=referenceText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referenceText.js","sourceRoot":"","sources":["../../src/server/referenceText.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgG7B,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyK5B,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { StateContext } from './stateContext.js';
|
|
3
|
+
export declare function registerSceneTools(server: McpServer, ctx: StateContext, normalizeElements: (elements: any[]) => any[]): void;
|
|
4
|
+
//# sourceMappingURL=sceneTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneTools.d.ts","sourceRoot":"","sources":["../../src/server/sceneTools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,YAAY,EACjB,iBAAiB,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,GAC5C,IAAI,CAsHN"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerSceneTools(server, ctx, normalizeElements) {
|
|
3
|
+
ctx.mutatingTool('create_scene', 'Create or replace the Excalidraw scene with the given elements.', { elements: z.string().describe('JSON string of Excalidraw elements array') }, async ({ elements }) => {
|
|
4
|
+
try {
|
|
5
|
+
const parsed = JSON.parse(elements);
|
|
6
|
+
if (!Array.isArray(parsed))
|
|
7
|
+
return { content: [{ type: 'text', text: 'Error: elements must be a JSON array' }] };
|
|
8
|
+
const state = ctx.getState();
|
|
9
|
+
state.scene.elements = normalizeElements(parsed);
|
|
10
|
+
return { content: [{ type: 'text', text: `Scene created with ${parsed.length} elements.` }] };
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
return { content: [{ type: 'text', text: `Error parsing elements: ${e}` }] };
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
ctx.mutatingTool('add_elements', 'Add elements to the existing scene.', { elements: z.string().describe('JSON string of elements to add') }, async ({ elements }) => {
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(elements);
|
|
19
|
+
if (!Array.isArray(parsed))
|
|
20
|
+
return { content: [{ type: 'text', text: 'Error: must be array' }] };
|
|
21
|
+
const state = ctx.getState();
|
|
22
|
+
state.scene.elements.push(...normalizeElements(parsed));
|
|
23
|
+
return { content: [{ type: 'text', text: `Added ${parsed.length} elements. Total: ${state.scene.elements.length}.` }] };
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
return { content: [{ type: 'text', text: `Error: ${e}` }] };
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
ctx.mutatingTool('remove_elements', 'Remove elements by their IDs.', { ids: z.array(z.string()).describe('Array of element IDs to remove') }, async ({ ids }) => {
|
|
30
|
+
const state = ctx.getState();
|
|
31
|
+
const idSet = new Set(ids);
|
|
32
|
+
const before = state.scene.elements.length;
|
|
33
|
+
state.scene.elements = state.scene.elements.filter((el) => !idSet.has(el.id));
|
|
34
|
+
const removed = before - state.scene.elements.length;
|
|
35
|
+
return { content: [{ type: 'text', text: `Removed ${removed} elements. Total: ${state.scene.elements.length}.` }] };
|
|
36
|
+
});
|
|
37
|
+
ctx.mutatingTool('update_elements', 'Update properties of existing elements.', { updates: z.string().describe('JSON string of array [{id, ...properties}]') }, async ({ updates }) => {
|
|
38
|
+
try {
|
|
39
|
+
const parsed = JSON.parse(updates);
|
|
40
|
+
if (!Array.isArray(parsed))
|
|
41
|
+
return { content: [{ type: 'text', text: 'Error: must be array' }] };
|
|
42
|
+
const state = ctx.getState();
|
|
43
|
+
// Build id→index map for O(1) lookups instead of O(n) findIndex per update
|
|
44
|
+
const indexById = new Map();
|
|
45
|
+
for (let i = 0; i < state.scene.elements.length; i++) {
|
|
46
|
+
indexById.set(state.scene.elements[i].id, i);
|
|
47
|
+
}
|
|
48
|
+
let updated = 0;
|
|
49
|
+
for (const upd of parsed) {
|
|
50
|
+
const idx = indexById.get(upd.id);
|
|
51
|
+
if (idx !== undefined) {
|
|
52
|
+
state.scene.elements[idx] = { ...state.scene.elements[idx], ...upd };
|
|
53
|
+
updated++;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { content: [{ type: 'text', text: `Updated ${updated} elements.` }] };
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
return { content: [{ type: 'text', text: `Error: ${e}` }] };
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
server.tool('get_scene', 'Return the current scene elements as JSON.', {}, async () => ({
|
|
63
|
+
content: [{ type: 'text', text: JSON.stringify(ctx.getState().scene.elements, null, 2) }],
|
|
64
|
+
}));
|
|
65
|
+
ctx.mutatingTool('clear_scene', 'Clear all elements and all animation tracks. Resets the scene to a blank canvas.', {}, async () => {
|
|
66
|
+
const state = ctx.getState();
|
|
67
|
+
state.scene.elements = [];
|
|
68
|
+
state.scene.files = {};
|
|
69
|
+
state.timeline.tracks = [];
|
|
70
|
+
return { content: [{ type: 'text', text: 'Scene and all animations cleared.' }] };
|
|
71
|
+
});
|
|
72
|
+
ctx.mutatingTool('delete_items', 'Delete specific elements and all their animation tracks. Batch operation.', {
|
|
73
|
+
ids: z.array(z.string()).describe('Element IDs to delete'),
|
|
74
|
+
}, async ({ ids }) => {
|
|
75
|
+
const state = ctx.getState();
|
|
76
|
+
const idSet = new Set(ids);
|
|
77
|
+
const beforeEl = state.scene.elements.length;
|
|
78
|
+
const beforeTr = state.timeline.tracks.length;
|
|
79
|
+
state.scene.elements = state.scene.elements.filter((el) => !idSet.has(el.id));
|
|
80
|
+
state.timeline.tracks = state.timeline.tracks.filter((t) => !idSet.has(t.targetId));
|
|
81
|
+
const removedEl = beforeEl - state.scene.elements.length;
|
|
82
|
+
const removedTr = beforeTr - state.timeline.tracks.length;
|
|
83
|
+
return { content: [{ type: 'text', text: `Deleted ${removedEl} elements and ${removedTr} animation tracks.` }] };
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=sceneTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneTools.js","sourceRoot":"","sources":["../../src/server/sceneTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: share_project
|
|
3
|
+
*
|
|
4
|
+
* Creates an E2E encrypted share URL containing the complete project state.
|
|
5
|
+
* Uses AES-256-GCM encryption — the key is returned to the AI in the URL
|
|
6
|
+
* hash fragment and never stored on the server.
|
|
7
|
+
*/
|
|
8
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
9
|
+
import type { StateContext } from './stateContext.js';
|
|
10
|
+
export declare function registerShareTools(server: McpServer, ctx: StateContext, serverPort: number): void;
|
|
11
|
+
//# sourceMappingURL=shareTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shareTools.d.ts","sourceRoot":"","sources":["../../src/server/shareTools.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAwBtD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,MAAM,GACjB,IAAI,CA6DN"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/**
|
|
3
|
+
* MCP tool: share_project
|
|
4
|
+
*
|
|
5
|
+
* Creates an E2E encrypted share URL containing the complete project state.
|
|
6
|
+
* Uses AES-256-GCM encryption — the key is returned to the AI in the URL
|
|
7
|
+
* hash fragment and never stored on the server.
|
|
8
|
+
*/
|
|
9
|
+
import crypto from 'node:crypto';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { promisify } from 'node:util';
|
|
12
|
+
import { gzip } from 'node:zlib';
|
|
13
|
+
const gzipAsync = promisify(gzip);
|
|
14
|
+
/**
|
|
15
|
+
* Encrypt data with AES-256-GCM.
|
|
16
|
+
* Returns: [IV (12 bytes)] [ciphertext + GCM auth tag]
|
|
17
|
+
*/
|
|
18
|
+
function encrypt(plaintext) {
|
|
19
|
+
const key = crypto.randomBytes(32); // 256-bit key
|
|
20
|
+
const iv = crypto.randomBytes(12); // 96-bit IV for GCM
|
|
21
|
+
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
|
|
22
|
+
const enc = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
23
|
+
const tag = cipher.getAuthTag(); // 16 bytes
|
|
24
|
+
// Layout: [IV (12)] [ciphertext] [GCM tag (16)]
|
|
25
|
+
const result = Buffer.concat([iv, enc, tag]);
|
|
26
|
+
// Export key as base64url (no padding) for shortest URL
|
|
27
|
+
const keyBase64url = key.toString('base64url');
|
|
28
|
+
return { encrypted: result, keyBase64url };
|
|
29
|
+
}
|
|
30
|
+
export function registerShareTools(server, ctx, serverPort) {
|
|
31
|
+
server.tool('share_project', 'Create an E2E encrypted share URL for the current project. The URL contains the encryption key in the hash fragment (never sent to the server). Returns the shareable URL.', {
|
|
32
|
+
baseUrl: z.string().optional().describe('Base URL for the share link (default: https://excalimate.com)'),
|
|
33
|
+
}, async ({ baseUrl }) => {
|
|
34
|
+
const state = ctx.getState();
|
|
35
|
+
if (!state.scene.elements || state.scene.elements.length === 0) {
|
|
36
|
+
return { content: [{ type: 'text', text: 'Error: No elements in the scene. Create a scene first.' }] };
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
// Build the full project payload
|
|
40
|
+
const payload = JSON.stringify({
|
|
41
|
+
scene: state.scene,
|
|
42
|
+
timeline: state.timeline,
|
|
43
|
+
clipStart: state.clipStart,
|
|
44
|
+
clipEnd: state.clipEnd,
|
|
45
|
+
cameraFrame: state.cameraFrame,
|
|
46
|
+
});
|
|
47
|
+
// Compress + encrypt
|
|
48
|
+
const compressed = await gzipAsync(Buffer.from(payload, 'utf-8'));
|
|
49
|
+
const { encrypted, keyBase64url } = encrypt(compressed);
|
|
50
|
+
// Upload to the local share endpoint
|
|
51
|
+
const shareUrl = `http://localhost:${serverPort}/share`;
|
|
52
|
+
const response = await fetch(shareUrl, {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
55
|
+
body: new Uint8Array(encrypted),
|
|
56
|
+
});
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const err = await response.text();
|
|
59
|
+
return { content: [{ type: 'text', text: `Error uploading share: ${err}` }] };
|
|
60
|
+
}
|
|
61
|
+
const { id } = await response.json();
|
|
62
|
+
// Build the shareable URL — key in hash fragment (never sent to server)
|
|
63
|
+
const appBase = baseUrl ?? 'https://excalimate.com';
|
|
64
|
+
const fullUrl = `${appBase}/#share=${id},${keyBase64url}`;
|
|
65
|
+
return {
|
|
66
|
+
content: [{
|
|
67
|
+
type: 'text',
|
|
68
|
+
text: `Share URL created:\n${fullUrl}\n\n` +
|
|
69
|
+
`Elements: ${state.scene.elements.length}, ` +
|
|
70
|
+
`Tracks: ${state.timeline.tracks.length}, ` +
|
|
71
|
+
`Encrypted size: ${(encrypted.length / 1024).toFixed(1)} KB\n\n` +
|
|
72
|
+
`The encryption key is in the URL hash — the server only stores an encrypted blob it cannot read.`,
|
|
73
|
+
}],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
return { content: [{ type: 'text', text: `Error creating share: ${e}` }] };
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=shareTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shareTools.js","sourceRoot":"","sources":["../../src/server/shareTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { ServerState } from '../types.js';
|
|
3
|
+
export type StateChangeListener = (delta: Partial<ServerState>) => void;
|
|
4
|
+
export declare function getSharedState(): ServerState;
|
|
5
|
+
export interface StateContext {
|
|
6
|
+
getState: () => ServerState;
|
|
7
|
+
updateState: (newState: ServerState) => void;
|
|
8
|
+
emitChange: () => void;
|
|
9
|
+
/** Mark a state area as dirty for delta broadcasting. */
|
|
10
|
+
markDirty: (area: 'scene' | 'timeline' | 'clip' | 'cameraFrame' | 'all') => void;
|
|
11
|
+
mutatingTool: (name: string, description: string, schema: any, handler: (args: any) => Promise<{
|
|
12
|
+
content: {
|
|
13
|
+
type: 'text';
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
}>,
|
|
17
|
+
/** Which state areas this tool modifies (for delta broadcasting). Defaults to 'all'. */
|
|
18
|
+
dirtyAreas?: Array<'scene' | 'timeline' | 'clip' | 'cameraFrame'>) => void;
|
|
19
|
+
}
|
|
20
|
+
export declare function createStateContext(serverId: string, server: McpServer, onStateChange?: StateChangeListener): StateContext;
|
|
21
|
+
//# sourceMappingURL=stateContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateContext.d.ts","sourceRoot":"","sources":["../../src/server/stateContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;AAKxE,wBAAgB,cAAc,IAAI,WAAW,CAAyB;AAEtE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,WAAW,CAAC;IAC5B,WAAW,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,yDAAyD;IACzD,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,KAAK,KAAK,IAAI,CAAC;IACjF,YAAY,EAAE,CACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,CAAC;IAC9E,wFAAwF;IACxF,UAAU,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,aAAa,CAAC,KAC9D,IAAI,CAAC;CACX;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,EACjB,aAAa,CAAC,EAAE,mBAAmB,GAClC,YAAY,CAgFd"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createDefaultState } from '../state.js';
|
|
2
|
+
let _activeState = createDefaultState();
|
|
3
|
+
let _activeServerId = null;
|
|
4
|
+
export function getSharedState() { return _activeState; }
|
|
5
|
+
export function createStateContext(serverId, server, onStateChange) {
|
|
6
|
+
if (_activeServerId !== null) {
|
|
7
|
+
console.warn(`[excalimate] New server ${serverId} replacing active server ${_activeServerId}. ` +
|
|
8
|
+
'Concurrent MCP sessions share the same state (single-tenant design).');
|
|
9
|
+
}
|
|
10
|
+
_activeServerId = serverId;
|
|
11
|
+
// ── Delta broadcasting with debounce ───────────────────────────
|
|
12
|
+
// Track which top-level state areas are dirty via flags set by tools.
|
|
13
|
+
// When the debounced emit fires, only serialize and broadcast the
|
|
14
|
+
// dirty fields. This avoids serializing the entire scene+timeline
|
|
15
|
+
// on every keyframe addition.
|
|
16
|
+
let _emitTimer = null;
|
|
17
|
+
const _dirty = { scene: false, timeline: false, clip: false, cameraFrame: false };
|
|
18
|
+
/** Mark a state area as dirty so it's included in the next broadcast. */
|
|
19
|
+
function markDirty(area) {
|
|
20
|
+
if (area === 'all') {
|
|
21
|
+
_dirty.scene = _dirty.timeline = _dirty.clip = _dirty.cameraFrame = true;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
_dirty[area] = true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const emitChange = () => {
|
|
28
|
+
// Default: mark everything dirty (tools that don't specify get full broadcast).
|
|
29
|
+
// Specific tools can call markDirty() before emitChange() for fine-grained deltas.
|
|
30
|
+
if (!_dirty.scene && !_dirty.timeline && !_dirty.clip && !_dirty.cameraFrame) {
|
|
31
|
+
markDirty('all');
|
|
32
|
+
}
|
|
33
|
+
if (_emitTimer)
|
|
34
|
+
clearTimeout(_emitTimer);
|
|
35
|
+
_emitTimer = setTimeout(() => {
|
|
36
|
+
_emitTimer = null;
|
|
37
|
+
try {
|
|
38
|
+
if (!onStateChange)
|
|
39
|
+
return;
|
|
40
|
+
const delta = {};
|
|
41
|
+
if (_dirty.scene)
|
|
42
|
+
delta.scene = _activeState.scene;
|
|
43
|
+
if (_dirty.timeline)
|
|
44
|
+
delta.timeline = _activeState.timeline;
|
|
45
|
+
if (_dirty.clip) {
|
|
46
|
+
delta.clipStart = _activeState.clipStart;
|
|
47
|
+
delta.clipEnd = _activeState.clipEnd;
|
|
48
|
+
}
|
|
49
|
+
if (_dirty.cameraFrame)
|
|
50
|
+
delta.cameraFrame = _activeState.cameraFrame;
|
|
51
|
+
// Reset dirty flags
|
|
52
|
+
_dirty.scene = _dirty.timeline = _dirty.clip = _dirty.cameraFrame = false;
|
|
53
|
+
if (Object.keys(delta).length === 0)
|
|
54
|
+
return;
|
|
55
|
+
onStateChange(delta);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.error('emitChange failed:', err);
|
|
59
|
+
}
|
|
60
|
+
}, 50);
|
|
61
|
+
};
|
|
62
|
+
server.__getState = () => _activeState;
|
|
63
|
+
const updateState = (newState) => {
|
|
64
|
+
_activeState = newState;
|
|
65
|
+
};
|
|
66
|
+
const mutatingTool = (name, description, schema, handler, dirtyAreas) => {
|
|
67
|
+
server.tool(name, description, schema, async (args) => {
|
|
68
|
+
const result = await handler(args);
|
|
69
|
+
if (dirtyAreas) {
|
|
70
|
+
for (const area of dirtyAreas)
|
|
71
|
+
markDirty(area);
|
|
72
|
+
}
|
|
73
|
+
emitChange();
|
|
74
|
+
return result;
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
getState: () => _activeState,
|
|
79
|
+
updateState,
|
|
80
|
+
emitChange,
|
|
81
|
+
markDirty,
|
|
82
|
+
mutatingTool,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=stateContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateContext.js","sourceRoot":"","sources":["../../src/server/stateContext.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Excalimate MCP Server
|
|
3
|
-
*
|
|
4
|
-
* Provides tools for creating Excalidraw scenes, animating them with keyframes,
|
|
5
|
-
* and exporting the results. Designed for AI agent integration via MCP.
|
|
6
|
-
*/
|
|
7
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
2
|
import type { CheckpointStore } from './checkpoint-store.js';
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
export
|
|
12
|
-
export
|
|
3
|
+
import { getSharedState } from './server/stateContext.js';
|
|
4
|
+
import type { StateChangeListener } from './server/stateContext.js';
|
|
5
|
+
export { getSharedState };
|
|
6
|
+
export type { StateChangeListener } from './server/stateContext.js';
|
|
7
|
+
export declare function createServer(store: CheckpointStore, onStateChange?: StateChangeListener, serverPort?: number): McpServer;
|
|
13
8
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAa7D,OAAO,EAAsB,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,wBAAgB,YAAY,CAC1B,KAAK,EAAE,eAAe,EACtB,aAAa,CAAC,EAAE,mBAAmB,EACnC,UAAU,GAAE,MAAa,GACxB,SAAS,CAyBX"}
|