@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.
Files changed (64) hide show
  1. package/README.md +176 -16
  2. package/dist/checkpoint-store.d.ts +1 -0
  3. package/dist/checkpoint-store.d.ts.map +1 -1
  4. package/dist/checkpoint-store.js +23 -2
  5. package/dist/checkpoint-store.js.map +1 -1
  6. package/dist/httpServer.d.ts +4 -0
  7. package/dist/httpServer.d.ts.map +1 -0
  8. package/dist/httpServer.js +199 -0
  9. package/dist/httpServer.js.map +1 -0
  10. package/dist/index.d.ts +0 -7
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +35 -177
  13. package/dist/index.js.map +1 -1
  14. package/dist/server/animationTools.d.ts +9 -0
  15. package/dist/server/animationTools.d.ts.map +1 -0
  16. package/dist/server/animationTools.js +254 -0
  17. package/dist/server/animationTools.js.map +1 -0
  18. package/dist/server/checkpointTools.d.ts +5 -0
  19. package/dist/server/checkpointTools.d.ts.map +1 -0
  20. package/dist/server/checkpointTools.js +22 -0
  21. package/dist/server/checkpointTools.js.map +1 -0
  22. package/dist/server/elementNormalizer.d.ts +3 -0
  23. package/dist/server/elementNormalizer.d.ts.map +1 -0
  24. package/dist/server/elementNormalizer.js +52 -0
  25. package/dist/server/elementNormalizer.js.map +1 -0
  26. package/dist/server/geometry.d.ts +24 -0
  27. package/dist/server/geometry.d.ts.map +1 -0
  28. package/dist/server/geometry.js +102 -0
  29. package/dist/server/geometry.js.map +1 -0
  30. package/dist/server/queryTools.d.ts +28 -0
  31. package/dist/server/queryTools.d.ts.map +1 -0
  32. package/dist/server/queryTools.js +107 -0
  33. package/dist/server/queryTools.js.map +1 -0
  34. package/dist/server/referenceText.d.ts +3 -0
  35. package/dist/server/referenceText.d.ts.map +1 -0
  36. package/dist/server/referenceText.js +268 -0
  37. package/dist/server/referenceText.js.map +1 -0
  38. package/dist/server/sceneTools.d.ts +4 -0
  39. package/dist/server/sceneTools.d.ts.map +1 -0
  40. package/dist/server/sceneTools.js +86 -0
  41. package/dist/server/sceneTools.js.map +1 -0
  42. package/dist/server/shareTools.d.ts +11 -0
  43. package/dist/server/shareTools.d.ts.map +1 -0
  44. package/dist/server/shareTools.js +81 -0
  45. package/dist/server/shareTools.js.map +1 -0
  46. package/dist/server/stateContext.d.ts +21 -0
  47. package/dist/server/stateContext.d.ts.map +1 -0
  48. package/dist/server/stateContext.js +85 -0
  49. package/dist/server/stateContext.js.map +1 -0
  50. package/dist/server.d.ts +5 -10
  51. package/dist/server.d.ts.map +1 -1
  52. package/dist/server.js +24 -891
  53. package/dist/server.js.map +1 -1
  54. package/dist/shareRoutes.d.ts +4 -0
  55. package/dist/shareRoutes.d.ts.map +1 -0
  56. package/dist/shareRoutes.js +44 -0
  57. package/dist/shareRoutes.js.map +1 -0
  58. package/dist/stdioServer.d.ts +3 -0
  59. package/dist/stdioServer.d.ts.map +1 -0
  60. package/dist/stdioServer.js +5 -0
  61. package/dist/stdioServer.js.map +1 -0
  62. package/package.json +6 -2
  63. package/SKILL.md +0 -110
  64. package/references/REFERENCE.md +0 -192
package/dist/index.js CHANGED
@@ -1,190 +1,48 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Excalimate MCP Server — Entry Point
4
- *
5
- * Supports two transports:
6
- * --stdio : For Claude Desktop / Copilot CLI
7
- * (default) : Streamable HTTP on port 3001
8
- */
9
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
11
- import cors from 'cors';
12
- import crypto from 'node:crypto';
13
- import express from 'express';
14
- import helmet from 'helmet';
15
- import rateLimit from 'express-rate-limit';
16
2
  import { FileCheckpointStore } from './checkpoint-store.js';
17
- import { createServer, getSharedState } from './server.js';
18
- async function startStdioServer(factory) {
19
- await factory().connect(new StdioServerTransport());
20
- }
21
- async function startHTTPServer(factoryWithSSE) {
22
- const port = parseInt(process.env.PORT ?? '3001', 10);
23
- const app = express();
24
- app.use(helmet({ contentSecurityPolicy: false })); // Security headers
25
- app.use(cors({
26
- origin: process.env.CORS_ORIGIN ?? '*',
27
- }));
28
- // Rate limiting
29
- const limiter = rateLimit({
30
- windowMs: 60 * 1000, // 1 minute
31
- max: 200, // 200 requests per minute
32
- standardHeaders: true,
33
- legacyHeaders: false,
34
- });
35
- app.use(limiter);
36
- // Stricter rate limit for share uploads
37
- const shareLimiter = rateLimit({
38
- windowMs: 60 * 1000,
39
- max: 10, // 10 shares per minute
40
- standardHeaders: true,
41
- legacyHeaders: false,
42
- });
43
- // Parse JSON only for non-share routes (share uses raw binary)
44
- app.use((req, res, next) => {
45
- if (req.path === '/share' && req.method === 'POST') {
46
- next();
47
- }
48
- else {
49
- express.json()(req, res, next);
50
- }
51
- });
52
- // SSE clients for live state broadcasting
53
- const sseClients = new Set();
54
- // Factory that wires SSE broadcasting
55
- const factory = () => factoryWithSSE(sseClients);
56
- // Session map: keep server + transport alive across requests
57
- const sessions = new Map();
58
- app.all('/mcp', async (req, res) => {
59
- const sessionId = req.headers['mcp-session-id'];
60
- // Route to existing session
61
- if (sessionId && sessions.has(sessionId)) {
62
- const session = sessions.get(sessionId);
63
- try {
64
- await session.transport.handleRequest(req, res, req.body);
65
- }
66
- catch (error) {
67
- console.error('MCP session error:', error);
68
- if (!res.headersSent) {
69
- res.status(500).json({
70
- jsonrpc: '2.0',
71
- error: { code: -32603, message: 'Internal server error' },
72
- id: null,
73
- });
74
- }
75
- }
76
- return;
77
- }
78
- // New session
79
- const server = factory();
80
- const transport = new StreamableHTTPServerTransport({
81
- sessionIdGenerator: () => crypto.randomUUID(),
82
- });
83
- transport.onclose = () => {
84
- const sid = transport.sessionId;
85
- if (sid)
86
- sessions.delete(sid);
87
- server.close().catch(() => { });
88
- };
89
- try {
90
- await server.connect(transport);
91
- await transport.handleRequest(req, res, req.body);
92
- // Store session after first successful request (session ID is now set)
93
- const sid = transport.sessionId;
94
- if (sid) {
95
- sessions.set(sid, { server, transport });
96
- }
97
- }
98
- catch (error) {
99
- console.error('MCP error:', error);
100
- if (!res.headersSent) {
101
- res.status(500).json({
102
- jsonrpc: '2.0',
103
- error: { code: -32603, message: 'Internal server error' },
104
- id: null,
105
- });
106
- }
3
+ import { createServer } from './server.js';
4
+ import { startStdioServer } from './stdioServer.js';
5
+ import { startHTTPServer } from './httpServer.js';
6
+ /** Parse --port=NNNN or --port NNNN from argv */
7
+ function parsePort() {
8
+ for (let i = 0; i < process.argv.length; i++) {
9
+ const arg = process.argv[i];
10
+ if (arg.startsWith('--port=')) {
11
+ return parseInt(arg.slice('--port='.length), 10);
12
+ }
13
+ if (arg === '--port' && process.argv[i + 1]) {
14
+ return parseInt(process.argv[i + 1], 10);
15
+ }
16
+ if (arg === '-p' && process.argv[i + 1]) {
17
+ return parseInt(process.argv[i + 1], 10);
107
18
  }
108
- });
109
- // SSE endpoint — web app connects here to receive live state updates
110
- app.get('/live', (req, res) => {
111
- res.writeHead(200, {
112
- 'Content-Type': 'text/event-stream',
113
- 'Cache-Control': 'no-cache',
114
- Connection: 'keep-alive',
115
- 'Access-Control-Allow-Origin': '*',
116
- });
117
- res.write('data: {"type":"connected"}\n\n');
118
- sseClients.add(res);
119
- req.on('close', () => sseClients.delete(res));
120
- });
121
- // Current state endpoint
122
- app.get('/state', (_req, res) => {
123
- res.json(getSharedState());
124
- });
125
- // ── E2E Encrypted Sharing ──────────────────────────────────────
126
- // The server only stores encrypted blobs. It never sees the encryption key.
127
- const shareStore = new Map();
128
- const MAX_SHARE_SIZE = 10 * 1024 * 1024; // 10 MB
129
- const MAX_SHARES = 500;
130
- // Upload encrypted blob
131
- app.post('/share', shareLimiter, express.raw({ type: 'application/octet-stream', limit: '10mb' }), (req, res) => {
132
- const id = crypto.randomUUID().replace(/-/g, '').slice(0, 16);
133
- const body = req.body;
134
- if (!body || body.length === 0) {
135
- res.status(400).json({ error: 'Empty body. Send as application/octet-stream.' });
136
- return;
137
- }
138
- if (body.length > MAX_SHARE_SIZE) {
139
- res.status(413).json({ error: 'Payload too large' });
140
- return;
141
- }
142
- // Evict oldest if over limit
143
- if (shareStore.size >= MAX_SHARES) {
144
- const oldest = shareStore.keys().next().value;
145
- if (oldest !== undefined)
146
- shareStore.delete(oldest);
147
- }
148
- shareStore.set(id, body);
149
- res.json({ id, url: `/share/${id}` });
150
- });
151
- // Download encrypted blob
152
- app.get('/share/:id', (req, res) => {
153
- const data = shareStore.get(req.params.id);
154
- if (!data) {
155
- res.status(404).json({ error: 'Not found' });
156
- return;
157
- }
158
- res.set('Content-Type', 'application/octet-stream');
159
- res.send(data);
160
- });
161
- app.listen(port, () => {
162
- console.log(`Excalimate MCP server listening on http://localhost:${port}/mcp`);
163
- console.log(`Live preview SSE at http://localhost:${port}/live`);
164
- });
165
- const shutdown = () => {
166
- console.log('\nShutting down...');
167
- process.exit(0);
168
- };
169
- process.on('SIGINT', shutdown);
170
- process.on('SIGTERM', shutdown);
19
+ }
20
+ return undefined;
171
21
  }
172
22
  async function main() {
23
+ process.on('unhandledRejection', (reason) => {
24
+ console.error('Unhandled rejection:', reason);
25
+ });
26
+ process.on('uncaughtException', (err) => {
27
+ console.error('Uncaught exception:', err);
28
+ });
173
29
  const store = new FileCheckpointStore();
30
+ const cliPort = parsePort();
174
31
  if (process.argv.includes('--stdio')) {
175
- const factory = () => createServer(store);
176
- await startStdioServer(factory);
32
+ await startStdioServer(() => createServer(store));
177
33
  }
178
34
  else {
179
- await startHTTPServer((sseClients) => {
180
- return createServer(store, (state) => {
181
- // Broadcast state to all SSE clients
182
- const data = JSON.stringify({ type: 'state', state });
183
- for (const client of sseClients) {
184
- client.write(`data: ${data}\n\n`);
35
+ await startHTTPServer((_sseClients, broadcastSSE, port) => {
36
+ return createServer(store, (delta) => {
37
+ try {
38
+ const data = JSON.stringify({ type: 'state', state: delta });
39
+ broadcastSSE(data);
40
+ }
41
+ catch (err) {
42
+ console.error('Failed to broadcast state:', err);
185
43
  }
186
- });
187
- });
44
+ }, port);
45
+ }, cliPort);
188
46
  }
189
47
  }
190
48
  main().catch((e) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,iDAAiD;AACjD,SAAS,SAAS;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC5C,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACxC,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,EAAE;QAC1C,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;QACtC,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,mBAAmB,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE;YACxD,OAAO,YAAY,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;gBACnC,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC7D,YAAY,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC,EAAE,IAAI,CAAC,CAAC;QACX,CAAC,EAAE,OAAO,CAAC,CAAC;IACd,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { StateContext } from './stateContext.js';
3
+ export declare function registerAnimationTools(server: McpServer, ctx: StateContext, getElementBounds: (el: any) => {
4
+ minX: number;
5
+ minY: number;
6
+ maxX: number;
7
+ maxY: number;
8
+ }): void;
9
+ //# sourceMappingURL=animationTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animationTools.d.ts","sourceRoot":"","sources":["../../src/server/animationTools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,YAAY,EACjB,gBAAgB,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxF,IAAI,CAkTN"}
@@ -0,0 +1,254 @@
1
+ import { z } from 'zod';
2
+ import { addKeyframeToState } from '../state.js';
3
+ import { ANIMATABLE_PROPERTIES, EASING_TYPES } from '../types.js';
4
+ import { ORIGIN_MAP } from './geometry.js';
5
+ export function registerAnimationTools(server, ctx, getElementBounds) {
6
+ ctx.mutatingTool('add_keyframe', 'Add a keyframe to an animation track. Auto-creates the track if it doesn\'t exist.', {
7
+ targetId: z.string().describe('Element or group ID'),
8
+ property: z.enum(ANIMATABLE_PROPERTIES).describe('Animatable property'),
9
+ time: z.number().min(0).describe('Time in milliseconds'),
10
+ value: z.number().describe('Property value at this time'),
11
+ easing: z.enum(EASING_TYPES).optional().describe('Easing to next keyframe'),
12
+ }, async ({ targetId, property, time, value, easing }) => {
13
+ const state = ctx.getState();
14
+ ctx.updateState(addKeyframeToState(state, targetId, property, time, value, easing ?? 'linear'));
15
+ return { content: [{ type: 'text', text: `Keyframe added: ${property} = ${value} at ${time}ms for ${targetId}` }] };
16
+ });
17
+ ctx.mutatingTool('add_keyframes_batch', 'Add multiple keyframes at once. For scaleX/scaleY keyframes, include a "scaleOrigin" field per keyframe to control where scaling anchors from (auto-adds translate compensation). Origins: center, top-left, top-right, bottom-left, bottom-right, top, bottom, left, right.', {
18
+ keyframes: z.string().describe('JSON array of {targetId, property, time, value, easing?, scaleOrigin?}'),
19
+ }, async ({ keyframes }) => {
20
+ try {
21
+ const parsed = JSON.parse(keyframes);
22
+ if (!Array.isArray(parsed))
23
+ return { content: [{ type: 'text', text: 'Error: must be array' }] };
24
+ const scaleCompensation = new Map();
25
+ for (const kf of parsed) {
26
+ if ((kf.property === 'scaleX' || kf.property === 'scaleY') && kf.scaleOrigin && kf.scaleOrigin !== 'top-left') {
27
+ const key = `${kf.targetId}@${kf.time}`;
28
+ const existing = scaleCompensation.get(key) ?? { targetId: kf.targetId, time: kf.time, sx: 1, sy: 1, origin: kf.scaleOrigin, easing: kf.easing ?? 'linear' };
29
+ if (kf.property === 'scaleX')
30
+ existing.sx = kf.value;
31
+ if (kf.property === 'scaleY')
32
+ existing.sy = kf.value;
33
+ existing.origin = kf.scaleOrigin;
34
+ scaleCompensation.set(key, existing);
35
+ }
36
+ }
37
+ const validProperties = new Set(ANIMATABLE_PROPERTIES);
38
+ let count = 0;
39
+ let skipped = 0;
40
+ for (const kf of parsed) {
41
+ if (!validProperties.has(kf.property)) {
42
+ skipped++;
43
+ continue;
44
+ }
45
+ const state = ctx.getState();
46
+ ctx.updateState(addKeyframeToState(state, kf.targetId, kf.property, kf.time, kf.value, kf.easing ?? 'linear'));
47
+ count++;
48
+ }
49
+ for (const skf of scaleCompensation.values()) {
50
+ const [ox, oy] = ORIGIN_MAP[skf.origin] ?? [0.5, 0.5];
51
+ const state = ctx.getState();
52
+ const el = state.scene.elements.find((e) => e.id === skf.targetId);
53
+ if (!el)
54
+ continue;
55
+ const bounds = getElementBounds(el);
56
+ const w = bounds.maxX - bounds.minX;
57
+ const h = bounds.maxY - bounds.minY;
58
+ const tx = -w * (skf.sx - 1) * ox;
59
+ const ty = -h * (skf.sy - 1) * oy;
60
+ ctx.updateState(addKeyframeToState(state, skf.targetId, 'translateX', skf.time, tx, skf.easing));
61
+ const updated = ctx.getState();
62
+ ctx.updateState(addKeyframeToState(updated, skf.targetId, 'translateY', skf.time, ty, skf.easing));
63
+ count += 2;
64
+ }
65
+ return { content: [{ type: 'text', text: `Added ${count} keyframes.${skipped ? ` Skipped ${skipped} with invalid properties.` : ''}` }] };
66
+ }
67
+ catch (e) {
68
+ return { content: [{ type: 'text', text: `Error: ${e}` }] };
69
+ }
70
+ });
71
+ ctx.mutatingTool('remove_keyframe', 'Remove a keyframe by track and keyframe ID.', {
72
+ trackId: z.string().describe('Track ID'),
73
+ keyframeId: z.string().describe('Keyframe ID'),
74
+ }, async ({ trackId, keyframeId }) => {
75
+ const state = ctx.getState();
76
+ const track = state.timeline.tracks.find(t => t.id === trackId);
77
+ if (!track)
78
+ return { content: [{ type: 'text', text: 'Track not found.' }] };
79
+ const before = track.keyframes.length;
80
+ track.keyframes = track.keyframes.filter(kf => kf.id !== keyframeId);
81
+ return { content: [{ type: 'text', text: `Removed ${before - track.keyframes.length} keyframe(s).` }] };
82
+ });
83
+ ctx.mutatingTool('create_sequence', 'Create a reveal sequence — elements appear one after another with configurable timing.', {
84
+ elementIds: z.array(z.string()).describe('Element IDs in reveal order'),
85
+ property: z.enum(['opacity', 'drawProgress']).default('opacity').describe('Property to animate'),
86
+ startTime: z.number().min(0).default(0).describe('When sequence starts (ms)'),
87
+ delay: z.number().min(0).default(300).describe('Delay between each reveal (ms)'),
88
+ duration: z.number().min(50).default(500).describe('Duration of each reveal (ms)'),
89
+ }, async ({ elementIds, property, startTime, delay, duration }) => {
90
+ for (let i = 0; i < elementIds.length; i++) {
91
+ const revealStart = startTime + i * delay;
92
+ const revealEnd = revealStart + duration;
93
+ const targetId = elementIds[i];
94
+ if (revealStart > 0) {
95
+ const state = ctx.getState();
96
+ ctx.updateState(addKeyframeToState(state, targetId, property, 0, 0));
97
+ }
98
+ if (revealStart > 10) {
99
+ const state = ctx.getState();
100
+ ctx.updateState(addKeyframeToState(state, targetId, property, revealStart, 0));
101
+ }
102
+ const state = ctx.getState();
103
+ ctx.updateState(addKeyframeToState(state, targetId, property, revealEnd, 1, 'easeOut'));
104
+ }
105
+ const totalDuration = startTime + (elementIds.length - 1) * delay + duration;
106
+ return { content: [{ type: 'text', text: `Sequence created: ${elementIds.length} elements, total ${totalDuration}ms.` }] };
107
+ });
108
+ ctx.mutatingTool('set_clip_range', 'Set the export clip start and end times.', {
109
+ start: z.number().min(0).describe('Clip start time (ms)'),
110
+ end: z.number().min(100).describe('Clip end time (ms)'),
111
+ }, async ({ start, end }) => {
112
+ const state = ctx.getState();
113
+ state.clipStart = start;
114
+ state.clipEnd = Math.max(start + 100, end);
115
+ return { content: [{ type: 'text', text: `Clip range: ${start}ms – ${end}ms (${(end - start) / 1000}s)` }] };
116
+ });
117
+ server.tool('get_timeline', 'Return the current animation timeline as JSON.', {}, async () => {
118
+ const state = ctx.getState();
119
+ return {
120
+ content: [{
121
+ type: 'text',
122
+ text: JSON.stringify({
123
+ timeline: state.timeline,
124
+ clipStart: state.clipStart,
125
+ clipEnd: state.clipEnd,
126
+ cameraFrame: state.cameraFrame,
127
+ }, null, 2),
128
+ }],
129
+ };
130
+ });
131
+ ctx.mutatingTool('clear_animation', 'Clear all animation tracks.', {}, async () => {
132
+ const state = ctx.getState();
133
+ state.timeline.tracks = [];
134
+ return { content: [{ type: 'text', text: 'All animation tracks cleared.' }] };
135
+ });
136
+ ctx.mutatingTool('add_scale_animation', 'Add scale keyframes with a specific origin (edge/corner/center). Auto-computes translate compensation to keep the origin point fixed during scaling.', {
137
+ targetId: z.string().describe('Element ID'),
138
+ origin: z.enum(['center', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'top', 'bottom', 'left', 'right']).describe('Scale origin point'),
139
+ keyframes: z.string().describe('JSON array of {time, scaleX, scaleY, easing?}'),
140
+ }, async ({ targetId, origin, keyframes }) => {
141
+ try {
142
+ const parsed = JSON.parse(keyframes);
143
+ if (!Array.isArray(parsed))
144
+ return { content: [{ type: 'text', text: 'Error: must be array' }] };
145
+ const state = ctx.getState();
146
+ const el = state.scene.elements.find((e) => e.id === targetId);
147
+ if (!el)
148
+ return { content: [{ type: 'text', text: `Element "${targetId}" not found.` }] };
149
+ const bounds = getElementBounds(el);
150
+ const w = bounds.maxX - bounds.minX;
151
+ const h = bounds.maxY - bounds.minY;
152
+ const [ox, oy] = ORIGIN_MAP[origin] ?? [0.5, 0.5];
153
+ let count = 0;
154
+ for (const kf of parsed) {
155
+ const sx = kf.scaleX ?? 1;
156
+ const sy = kf.scaleY ?? 1;
157
+ const easing = kf.easing ?? 'linear';
158
+ let currentState = ctx.getState();
159
+ ctx.updateState(addKeyframeToState(currentState, targetId, 'scaleX', kf.time, sx, easing));
160
+ currentState = ctx.getState();
161
+ ctx.updateState(addKeyframeToState(currentState, targetId, 'scaleY', kf.time, sy, easing));
162
+ const tx = -w * (sx - 1) * ox;
163
+ const ty = -h * (sy - 1) * oy;
164
+ if (Math.abs(tx) > 0.1 || Math.abs(ty) > 0.1 || ox !== 0 || oy !== 0) {
165
+ currentState = ctx.getState();
166
+ ctx.updateState(addKeyframeToState(currentState, targetId, 'translateX', kf.time, tx, easing));
167
+ currentState = ctx.getState();
168
+ ctx.updateState(addKeyframeToState(currentState, targetId, 'translateY', kf.time, ty, easing));
169
+ }
170
+ count++;
171
+ }
172
+ return { content: [{ type: 'text', text: `Added ${count} scale keyframes with origin "${origin}" for "${targetId}".` }] };
173
+ }
174
+ catch (e) {
175
+ return { content: [{ type: 'text', text: `Error: ${e}` }] };
176
+ }
177
+ });
178
+ ctx.mutatingTool('set_camera_frame', 'Set the camera frame position, size, and aspect ratio. Also creates initial keyframes at time 0 for translateX, translateY, scaleX, scaleY so the camera starts at this position.', {
179
+ x: z.number().optional().describe('Camera center X (scene coords)'),
180
+ y: z.number().optional().describe('Camera center Y (scene coords)'),
181
+ width: z.number().optional().describe('Camera width (scene units)'),
182
+ aspectRatio: z.enum(['16:9', '4:3', '1:1', '3:2']).optional().describe('Aspect ratio'),
183
+ }, async ({ x, y, width, aspectRatio }) => {
184
+ const state = ctx.getState();
185
+ if (x !== undefined)
186
+ state.cameraFrame.x = x;
187
+ if (y !== undefined)
188
+ state.cameraFrame.y = y;
189
+ if (width !== undefined)
190
+ state.cameraFrame.width = width;
191
+ if (aspectRatio !== undefined)
192
+ state.cameraFrame.aspectRatio = aspectRatio;
193
+ const CAMERA_ID = '__camera_frame__';
194
+ let currentState = ctx.getState();
195
+ ctx.updateState(addKeyframeToState(currentState, CAMERA_ID, 'translateX', 0, 0));
196
+ currentState = ctx.getState();
197
+ ctx.updateState(addKeyframeToState(currentState, CAMERA_ID, 'translateY', 0, 0));
198
+ currentState = ctx.getState();
199
+ ctx.updateState(addKeyframeToState(currentState, CAMERA_ID, 'scaleX', 0, 1));
200
+ currentState = ctx.getState();
201
+ ctx.updateState(addKeyframeToState(currentState, CAMERA_ID, 'scaleY', 0, 1));
202
+ const updated = ctx.getState();
203
+ return { content: [{ type: 'text', text: `Camera: ${updated.cameraFrame.aspectRatio} at (${updated.cameraFrame.x}, ${updated.cameraFrame.y}), width ${updated.cameraFrame.width}. Initial keyframes created at t=0.` }] };
204
+ });
205
+ ctx.mutatingTool('add_camera_keyframe', 'Add a keyframe for camera pan/zoom animation.', {
206
+ property: z.enum(['translateX', 'translateY', 'scaleX', 'scaleY']).describe('Camera property'),
207
+ time: z.number().min(0).describe('Time in ms'),
208
+ value: z.number().describe('Value'),
209
+ easing: z.enum(EASING_TYPES).optional(),
210
+ }, async ({ property, time, value, easing }) => {
211
+ const CAMERA_ID = '__camera_frame__';
212
+ const state = ctx.getState();
213
+ ctx.updateState(addKeyframeToState(state, CAMERA_ID, property, time, value, easing ?? 'linear'));
214
+ return { content: [{ type: 'text', text: `Camera keyframe: ${property} = ${value} at ${time}ms` }] };
215
+ });
216
+ ctx.mutatingTool('add_camera_keyframes_batch', 'Add multiple camera keyframes at once. Properties: translateX, translateY, scaleX, scaleY.', {
217
+ keyframes: z.string().describe('JSON array of {property: "translateX"|"translateY"|"scaleX"|"scaleY", time, value, easing?}'),
218
+ }, async ({ keyframes }) => {
219
+ try {
220
+ const parsed = JSON.parse(keyframes);
221
+ if (!Array.isArray(parsed))
222
+ return { content: [{ type: 'text', text: 'Error: must be array' }] };
223
+ const CAMERA_ID = '__camera_frame__';
224
+ const validCameraProps = new Set(['translateX', 'translateY', 'scaleX', 'scaleY']);
225
+ const propMap = {
226
+ x: 'translateX',
227
+ y: 'translateY',
228
+ panX: 'translateX',
229
+ panY: 'translateY',
230
+ zoom: 'scaleX',
231
+ scale: 'scaleX',
232
+ };
233
+ let count = 0;
234
+ let skipped = 0;
235
+ for (const kf of parsed) {
236
+ let prop = kf.property;
237
+ if (propMap[prop])
238
+ prop = propMap[prop];
239
+ if (!validCameraProps.has(prop)) {
240
+ skipped++;
241
+ continue;
242
+ }
243
+ const state = ctx.getState();
244
+ ctx.updateState(addKeyframeToState(state, CAMERA_ID, prop, kf.time, kf.value, kf.easing ?? 'linear'));
245
+ count++;
246
+ }
247
+ return { content: [{ type: 'text', text: `Added ${count} camera keyframes.${skipped ? ` Skipped ${skipped} with invalid properties (use translateX, translateY, scaleX, scaleY).` : ''}` }] };
248
+ }
249
+ catch (e) {
250
+ return { content: [{ type: 'text', text: `Error: ${e}` }] };
251
+ }
252
+ });
253
+ }
254
+ //# sourceMappingURL=animationTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animationTools.js","sourceRoot":"","sources":["../../src/server/animationTools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CheckpointStore } from '../checkpoint-store.js';
3
+ import type { StateContext } from './stateContext.js';
4
+ export declare function registerCheckpointTools(server: McpServer, ctx: StateContext, store: CheckpointStore): void;
5
+ //# sourceMappingURL=checkpointTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpointTools.d.ts","sourceRoot":"","sources":["../../src/server/checkpointTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,eAAe,GACrB,IAAI,CAkCN"}
@@ -0,0 +1,22 @@
1
+ import { nanoid } from 'nanoid';
2
+ import { z } from 'zod';
3
+ export function registerCheckpointTools(server, ctx, store) {
4
+ ctx.mutatingTool('save_checkpoint', 'Save current scene + animation state to a checkpoint.', { id: z.string().optional().describe('Checkpoint ID (auto-generated if omitted)') }, async ({ id }) => {
5
+ const checkpointId = id ?? nanoid(12);
6
+ await store.save(checkpointId, ctx.getState());
7
+ return { content: [{ type: 'text', text: `Saved checkpoint: ${checkpointId}` }] };
8
+ });
9
+ ctx.mutatingTool('load_checkpoint', 'Load scene + animation state from a checkpoint.', { id: z.string().describe('Checkpoint ID') }, async ({ id }) => {
10
+ const loaded = await store.load(id);
11
+ if (!loaded)
12
+ return { content: [{ type: 'text', text: `Checkpoint "${id}" not found.` }] };
13
+ ctx.updateState(loaded);
14
+ const state = ctx.getState();
15
+ return { content: [{ type: 'text', text: `Loaded checkpoint "${id}": ${state.scene.elements.length} elements, ${state.timeline.tracks.length} tracks.` }] };
16
+ });
17
+ server.tool('list_checkpoints', 'List all saved checkpoints.', {}, async () => {
18
+ const ids = await store.list();
19
+ return { content: [{ type: 'text', text: ids.length > 0 ? `Checkpoints:\n${ids.join('\n')}` : 'No checkpoints saved.' }] };
20
+ });
21
+ }
22
+ //# sourceMappingURL=checkpointTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpointTools.js","sourceRoot":"","sources":["../../src/server/checkpointTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,GAAiB,EACjB,KAAsB;IAEtB,GAAG,CAAC,YAAY,CACd,iBAAiB,EACjB,uDAAuD,EACvD,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC,EAAE,EACnF,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;QACf,MAAM,YAAY,GAAG,EAAE,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC;IACpF,CAAC,CACF,CAAC;IAEF,GAAG,CAAC,YAAY,CACd,iBAAiB,EACjB,iDAAiD,EACjD,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,EAC5C,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;QACf,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;QAC3F,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACxB,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,cAAc,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,UAAU,EAAE,CAAC,EAAE,CAAC;IAC9J,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,6BAA6B,EAC7B,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,uBAAuB,EAAE,CAAC,EAAE,CAAC;IACtI,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function normalizeElement(el: any): any;
2
+ export declare function normalizeElements(elements: any[]): any[];
3
+ //# sourceMappingURL=elementNormalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementNormalizer.d.ts","sourceRoot":"","sources":["../../src/server/elementNormalizer.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,GAAG,GAAG,GAAG,CA8C7C;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAExD"}