pmx-canvas 0.3.0 → 0.3.1

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 (156) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/canvas/index.js +2 -2
  3. package/dist/types/cli/daemon.d.ts +74 -0
  4. package/dist/types/cli/watch.d.ts +2 -2
  5. package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
  6. package/dist/types/client/canvas/CommandPalette.d.ts +1 -1
  7. package/dist/types/client/canvas/Minimap.d.ts +1 -1
  8. package/dist/types/client/nodes/FileNode.d.ts +1 -1
  9. package/dist/types/client/nodes/ImageNode.d.ts +1 -1
  10. package/dist/types/client/nodes/InlineFormatBar.d.ts +1 -1
  11. package/dist/types/client/nodes/MarkdownNode.d.ts +1 -1
  12. package/dist/types/client/nodes/PromptNode.d.ts +1 -1
  13. package/dist/types/client/nodes/ResponseNode.d.ts +1 -1
  14. package/dist/types/server/canvas-schema.d.ts +1 -1
  15. package/dist/types/server/html-primitives.d.ts +1 -1
  16. package/dist/types/server/index.d.ts +4 -4
  17. package/dist/types/server/operations/index.d.ts +1 -1
  18. package/dist/types/server/operations/ops/ax-read.d.ts +2 -0
  19. package/dist/types/server/operations/ops/canvas-wire.d.ts +2 -0
  20. package/dist/types/server/operations/ops/ext-app.d.ts +2 -0
  21. package/docs/http-api.md +28 -0
  22. package/docs/plans/plan-009-tech-debt-backlog.md +5 -5
  23. package/docs/tech-debt-assessment-2026-07.md +2 -2
  24. package/package.json +5 -2
  25. package/skills/pmx-canvas/SKILL.md +3 -1
  26. package/skills/pmx-canvas/references/full-reference.md +10 -3
  27. package/src/cli/agent.ts +1861 -1548
  28. package/src/cli/daemon.ts +460 -0
  29. package/src/cli/index.ts +63 -326
  30. package/src/cli/watch.ts +2 -10
  31. package/src/client/App.tsx +48 -46
  32. package/src/client/canvas/AttentionHistory.tsx +11 -1
  33. package/src/client/canvas/CanvasNode.tsx +41 -29
  34. package/src/client/canvas/CanvasViewport.tsx +101 -66
  35. package/src/client/canvas/CommandPalette.tsx +61 -27
  36. package/src/client/canvas/ContextMenu.tsx +13 -20
  37. package/src/client/canvas/ContextPinBar.tsx +1 -5
  38. package/src/client/canvas/ContextPinHud.tsx +1 -6
  39. package/src/client/canvas/DockedNode.tsx +4 -4
  40. package/src/client/canvas/EdgeLayer.tsx +37 -36
  41. package/src/client/canvas/ExpandedNodeOverlay.tsx +69 -45
  42. package/src/client/canvas/FocusFieldLayer.tsx +20 -22
  43. package/src/client/canvas/IntentLayer.tsx +31 -14
  44. package/src/client/canvas/Minimap.tsx +11 -16
  45. package/src/client/canvas/SelectionBar.tsx +4 -11
  46. package/src/client/canvas/ShortcutOverlay.tsx +3 -1
  47. package/src/client/canvas/SnapshotPanel.tsx +77 -95
  48. package/src/client/canvas/auto-fit.ts +15 -14
  49. package/src/client/canvas/snap-guides.ts +12 -12
  50. package/src/client/canvas/use-node-resize.ts +1 -5
  51. package/src/client/canvas/use-pan-zoom.ts +25 -26
  52. package/src/client/ext-app/bridge.ts +3 -12
  53. package/src/client/icons.tsx +63 -20
  54. package/src/client/nodes/ContextNode.tsx +14 -25
  55. package/src/client/nodes/ExtAppFrame.tsx +60 -39
  56. package/src/client/nodes/FileNode.tsx +74 -62
  57. package/src/client/nodes/GroupNode.tsx +4 -6
  58. package/src/client/nodes/HtmlNode.tsx +76 -46
  59. package/src/client/nodes/ImageNode.tsx +18 -27
  60. package/src/client/nodes/InlineFormatBar.tsx +4 -21
  61. package/src/client/nodes/InlineMarkdownEditor.tsx +0 -1
  62. package/src/client/nodes/LedgerNode.tsx +10 -4
  63. package/src/client/nodes/MarkdownNode.tsx +3 -10
  64. package/src/client/nodes/McpAppNode.tsx +26 -22
  65. package/src/client/nodes/MdFormatBar.tsx +10 -7
  66. package/src/client/nodes/PromptNode.tsx +23 -51
  67. package/src/client/nodes/ResponseNode.tsx +3 -13
  68. package/src/client/nodes/StatusNode.tsx +5 -9
  69. package/src/client/nodes/StatusSummary.tsx +2 -8
  70. package/src/client/nodes/WebpageNode.tsx +20 -14
  71. package/src/client/nodes/iframe-document-url.ts +25 -16
  72. package/src/client/nodes/image-warnings.ts +1 -7
  73. package/src/client/nodes/md-format.ts +20 -5
  74. package/src/client/state/attention-bridge.ts +4 -9
  75. package/src/client/state/attention-store.ts +1 -7
  76. package/src/client/state/canvas-store.ts +52 -36
  77. package/src/client/state/intent-bridge.ts +176 -112
  78. package/src/client/state/intent-store.ts +4 -1
  79. package/src/client/state/sse-bridge.ts +53 -70
  80. package/src/json-render/catalog.ts +12 -16
  81. package/src/json-render/charts/components.tsx +16 -20
  82. package/src/json-render/charts/extra-components.tsx +8 -16
  83. package/src/json-render/charts/extra-definitions.ts +1 -2
  84. package/src/json-render/charts/tufte-components.tsx +37 -20
  85. package/src/json-render/charts/tufte-definitions.ts +8 -2
  86. package/src/json-render/renderer/index.tsx +42 -22
  87. package/src/json-render/schema.ts +6 -3
  88. package/src/json-render/server.ts +33 -39
  89. package/src/mcp/canvas-access.ts +35 -21
  90. package/src/mcp/server.ts +132 -70
  91. package/src/server/agent-context.ts +63 -36
  92. package/src/server/ax-context.ts +7 -5
  93. package/src/server/ax-interaction.ts +176 -43
  94. package/src/server/ax-state-manager.ts +182 -39
  95. package/src/server/ax-state.ts +142 -47
  96. package/src/server/canvas-db.ts +213 -95
  97. package/src/server/canvas-operations.ts +177 -120
  98. package/src/server/canvas-provenance.ts +1 -4
  99. package/src/server/canvas-schema.ts +454 -73
  100. package/src/server/canvas-serialization.ts +27 -35
  101. package/src/server/canvas-state.ts +150 -58
  102. package/src/server/chart-template.ts +4 -5
  103. package/src/server/code-graph.ts +19 -6
  104. package/src/server/diagram-presets.ts +28 -29
  105. package/src/server/ext-app-lookup.ts +3 -12
  106. package/src/server/html-node-summary.ts +19 -10
  107. package/src/server/html-primitives.ts +326 -97
  108. package/src/server/html-surface.ts +6 -9
  109. package/src/server/image-source.ts +6 -4
  110. package/src/server/index.ts +320 -217
  111. package/src/server/intent-registry.ts +2 -5
  112. package/src/server/mcp-app-candidate.ts +5 -10
  113. package/src/server/mcp-app-host.ts +14 -38
  114. package/src/server/mcp-app-runtime.ts +12 -20
  115. package/src/server/mutation-history.ts +15 -5
  116. package/src/server/operations/composites.ts +1 -3
  117. package/src/server/operations/http.ts +2 -3
  118. package/src/server/operations/index.ts +7 -1
  119. package/src/server/operations/invoker.ts +4 -3
  120. package/src/server/operations/mcp.ts +22 -30
  121. package/src/server/operations/ops/annotation.ts +122 -10
  122. package/src/server/operations/ops/app.ts +98 -73
  123. package/src/server/operations/ops/ax-await.ts +17 -10
  124. package/src/server/operations/ops/ax-read.ts +347 -0
  125. package/src/server/operations/ops/ax-shared.ts +2 -7
  126. package/src/server/operations/ops/ax-state.ts +32 -14
  127. package/src/server/operations/ops/ax-timeline.ts +32 -19
  128. package/src/server/operations/ops/ax-work.ts +54 -37
  129. package/src/server/operations/ops/batch.ts +39 -14
  130. package/src/server/operations/ops/canvas-wire.ts +91 -0
  131. package/src/server/operations/ops/edges.ts +37 -25
  132. package/src/server/operations/ops/ext-app.ts +346 -0
  133. package/src/server/operations/ops/groups.ts +49 -20
  134. package/src/server/operations/ops/intent.ts +18 -12
  135. package/src/server/operations/ops/json-render.ts +239 -98
  136. package/src/server/operations/ops/nodes.ts +298 -109
  137. package/src/server/operations/ops/query.ts +46 -28
  138. package/src/server/operations/ops/snapshots.ts +35 -26
  139. package/src/server/operations/ops/validate.ts +2 -1
  140. package/src/server/operations/ops/viewport.ts +60 -16
  141. package/src/server/operations/ops/webview.ts +44 -18
  142. package/src/server/operations/registry.ts +2 -3
  143. package/src/server/operations/types.ts +7 -5
  144. package/src/server/operations/webview-runner.ts +1 -3
  145. package/src/server/placement.ts +8 -18
  146. package/src/server/server.ts +108 -1027
  147. package/src/server/spatial-analysis.ts +39 -25
  148. package/src/server/trace-manager.ts +3 -8
  149. package/src/server/web-artifacts.ts +23 -27
  150. package/src/server/webpage-node.ts +5 -13
  151. package/src/shared/auto-arrange.ts +12 -5
  152. package/src/shared/content-height-reporter.ts +8 -6
  153. package/src/shared/ext-app-tool-result.ts +2 -6
  154. package/src/shared/placement.ts +1 -4
  155. package/src/shared/semantic-attention.ts +39 -37
  156. package/src/shared/surface.ts +8 -4
@@ -62,7 +62,7 @@ const CANONICAL_GRAPH_TYPES = [
62
62
  'slopegraph',
63
63
  ] as const;
64
64
 
65
- type CanvasGraphType = typeof CANONICAL_GRAPH_TYPES[number];
65
+ type CanvasGraphType = (typeof CANONICAL_GRAPH_TYPES)[number];
66
66
 
67
67
  function readPackageVersion(): string | null {
68
68
  try {
@@ -88,7 +88,13 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
88
88
  { name: 'y', type: 'number', required: false, description: 'Optional Y position.' },
89
89
  { name: 'width', type: 'number', required: false, description: 'Optional node width.' },
90
90
  { name: 'height', type: 'number', required: false, description: 'Optional node height.' },
91
- { name: 'strictSize', type: 'boolean', required: false, description: 'Keep explicit width/height fixed and scroll overflowing content instead of browser auto-fitting.', aliases: ['strict-size', 'scroll-overflow'] },
91
+ {
92
+ name: 'strictSize',
93
+ type: 'boolean',
94
+ required: false,
95
+ description: 'Keep explicit width/height fixed and scroll overflowing content instead of browser auto-fitting.',
96
+ aliases: ['strict-size', 'scroll-overflow'],
97
+ },
92
98
  ],
93
99
  example: {
94
100
  type: 'markdown',
@@ -156,11 +162,26 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
156
162
  fields: [
157
163
  { name: 'title', type: 'string', required: false, description: 'Optional title.' },
158
164
  { name: 'content', type: 'string', required: false, description: 'Trace summary.' },
159
- { name: 'toolName', type: 'string', required: false, description: 'Tool or operation label shown in the trace pill; defaults to title.' },
160
- { name: 'category', type: 'string', required: false, description: 'Trace category color key: mcp, file, subagent, or other.' },
165
+ {
166
+ name: 'toolName',
167
+ type: 'string',
168
+ required: false,
169
+ description: 'Tool or operation label shown in the trace pill; defaults to title.',
170
+ },
171
+ {
172
+ name: 'category',
173
+ type: 'string',
174
+ required: false,
175
+ description: 'Trace category color key: mcp, file, subagent, or other.',
176
+ },
161
177
  { name: 'status', type: 'string', required: false, description: 'Trace status: running, success, or failed.' },
162
178
  { name: 'duration', type: 'string', required: false, description: 'Optional duration badge text.' },
163
- { name: 'resultSummary', type: 'string', required: false, description: 'Short trace result summary; defaults to content.' },
179
+ {
180
+ name: 'resultSummary',
181
+ type: 'string',
182
+ required: false,
183
+ description: 'Short trace result summary; defaults to content.',
184
+ },
164
185
  { name: 'error', type: 'string', required: false, description: 'Short error message shown in failed traces.' },
165
186
  ],
166
187
  example: {
@@ -195,12 +216,38 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
195
216
  endpoint: '/api/canvas/node',
196
217
  mcpTool: 'canvas_node (action:"add")',
197
218
  fields: [
198
- { name: 'content', type: 'string', required: true, description: 'Image path, URL, or data URI.', aliases: ['path'] },
219
+ {
220
+ name: 'content',
221
+ type: 'string',
222
+ required: true,
223
+ description: 'Image path, URL, or data URI.',
224
+ aliases: ['path'],
225
+ },
199
226
  { name: 'title', type: 'string', required: false, description: 'Optional title override.' },
200
- { name: 'data.warning', type: 'string | { title?: string; detail: string }', required: false, description: 'Optional agent-supplied warning shown above the image.' },
201
- { name: 'data.warnings', type: 'Array<string | { title?: string; detail: string }>', required: false, description: 'Optional list of agent-supplied image warnings.' },
202
- { name: 'data.validationStatus', type: '"passed" | "failed" | "invalid"', required: false, description: 'Optional agent validation result for evidence-style images.' },
203
- { name: 'data.validationMessage', type: 'string', required: false, description: 'Optional detail shown when validation fails.' },
227
+ {
228
+ name: 'data.warning',
229
+ type: 'string | { title?: string; detail: string }',
230
+ required: false,
231
+ description: 'Optional agent-supplied warning shown above the image.',
232
+ },
233
+ {
234
+ name: 'data.warnings',
235
+ type: 'Array<string | { title?: string; detail: string }>',
236
+ required: false,
237
+ description: 'Optional list of agent-supplied image warnings.',
238
+ },
239
+ {
240
+ name: 'data.validationStatus',
241
+ type: '"passed" | "failed" | "invalid"',
242
+ required: false,
243
+ description: 'Optional agent validation result for evidence-style images.',
244
+ },
245
+ {
246
+ name: 'data.validationMessage',
247
+ type: 'string',
248
+ required: false,
249
+ description: 'Optional detail shown when validation fails.',
250
+ },
204
251
  ],
205
252
  example: {
206
253
  type: 'image',
@@ -221,13 +268,25 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
221
268
  endpoint: '/api/canvas/node',
222
269
  mcpTool: 'canvas_node (action:"add")',
223
270
  fields: [
224
- { name: 'url', type: 'string', required: true, description: 'HTTP(S) URL to fetch and cache.', aliases: ['content'] },
271
+ {
272
+ name: 'url',
273
+ type: 'string',
274
+ required: true,
275
+ description: 'HTTP(S) URL to fetch and cache.',
276
+ aliases: ['content'],
277
+ },
225
278
  { name: 'title', type: 'string', required: false, description: 'Optional title override.' },
226
279
  { name: 'x', type: 'number', required: false, description: 'Optional X position.' },
227
280
  { name: 'y', type: 'number', required: false, description: 'Optional Y position.' },
228
281
  { name: 'width', type: 'number', required: false, description: 'Optional node width.' },
229
282
  { name: 'height', type: 'number', required: false, description: 'Optional node height.' },
230
- { name: 'strictSize', type: 'boolean', required: false, description: 'Keep explicit width/height fixed and scroll overflowing content instead of browser auto-fitting.', aliases: ['strict-size', 'scroll-overflow'] },
283
+ {
284
+ name: 'strictSize',
285
+ type: 'boolean',
286
+ required: false,
287
+ description: 'Keep explicit width/height fixed and scroll overflowing content instead of browser auto-fitting.',
288
+ aliases: ['strict-size', 'scroll-overflow'],
289
+ },
231
290
  ],
232
291
  example: {
233
292
  type: 'webpage',
@@ -246,21 +305,78 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
246
305
  endpoint: '/api/canvas/node',
247
306
  mcpTool: 'canvas_node (action:"add", type:"html")',
248
307
  fields: [
249
- { name: 'html', type: 'string', required: false, description: 'HTML document or fragment rendered in the sandboxed iframe.', aliases: ['content', 'stdin'] },
250
- { name: 'summary', type: 'string', required: false, description: 'Explicit agent-readable summary. If omitted, PMX derives one from visible HTML text.' },
251
- { name: 'agentSummary', type: 'string', required: false, description: 'Explicit semantic sidecar used by search, pinned context, and spatial context.', aliases: ['agent-summary'] },
252
- { name: 'embeddedNodeIds', type: 'string[]', required: false, description: 'Canvas node IDs represented or iframe-embedded by this HTML surface.', aliases: ['embedded-node-id', 'embedded-node-ids'] },
253
- { name: 'embeddedUrls', type: 'string[]', required: false, description: 'URLs represented or iframe-embedded by this HTML surface.', aliases: ['embedded-url', 'embedded-urls'] },
254
- { name: 'presentation', type: 'boolean', required: false, description: 'Marks this HTML surface as a fullscreen presentation/deck.' },
255
- { name: 'slideTitles', type: 'string[]', required: false, description: 'Agent-readable slide titles for presentation HTML.', aliases: ['slide-title', 'slide-titles'] },
256
- { name: 'primitive', type: 'HtmlPrimitiveKind', required: false, description: 'Generate HTML from a built-in communication primitive instead of passing raw HTML.', aliases: ['kind'] },
257
- { name: 'data', type: 'record<string, unknown>', required: false, description: 'Primitive data when --primitive is used, or arbitrary node metadata.' },
308
+ {
309
+ name: 'html',
310
+ type: 'string',
311
+ required: false,
312
+ description: 'HTML document or fragment rendered in the sandboxed iframe.',
313
+ aliases: ['content', 'stdin'],
314
+ },
315
+ {
316
+ name: 'summary',
317
+ type: 'string',
318
+ required: false,
319
+ description: 'Explicit agent-readable summary. If omitted, PMX derives one from visible HTML text.',
320
+ },
321
+ {
322
+ name: 'agentSummary',
323
+ type: 'string',
324
+ required: false,
325
+ description: 'Explicit semantic sidecar used by search, pinned context, and spatial context.',
326
+ aliases: ['agent-summary'],
327
+ },
328
+ {
329
+ name: 'embeddedNodeIds',
330
+ type: 'string[]',
331
+ required: false,
332
+ description: 'Canvas node IDs represented or iframe-embedded by this HTML surface.',
333
+ aliases: ['embedded-node-id', 'embedded-node-ids'],
334
+ },
335
+ {
336
+ name: 'embeddedUrls',
337
+ type: 'string[]',
338
+ required: false,
339
+ description: 'URLs represented or iframe-embedded by this HTML surface.',
340
+ aliases: ['embedded-url', 'embedded-urls'],
341
+ },
342
+ {
343
+ name: 'presentation',
344
+ type: 'boolean',
345
+ required: false,
346
+ description: 'Marks this HTML surface as a fullscreen presentation/deck.',
347
+ },
348
+ {
349
+ name: 'slideTitles',
350
+ type: 'string[]',
351
+ required: false,
352
+ description: 'Agent-readable slide titles for presentation HTML.',
353
+ aliases: ['slide-title', 'slide-titles'],
354
+ },
355
+ {
356
+ name: 'primitive',
357
+ type: 'HtmlPrimitiveKind',
358
+ required: false,
359
+ description: 'Generate HTML from a built-in communication primitive instead of passing raw HTML.',
360
+ aliases: ['kind'],
361
+ },
362
+ {
363
+ name: 'data',
364
+ type: 'record<string, unknown>',
365
+ required: false,
366
+ description: 'Primitive data when --primitive is used, or arbitrary node metadata.',
367
+ },
258
368
  { name: 'title', type: 'string', required: false, description: 'Optional node title.' },
259
369
  { name: 'x', type: 'number', required: false, description: 'Optional X position.' },
260
370
  { name: 'y', type: 'number', required: false, description: 'Optional Y position.' },
261
371
  { name: 'width', type: 'number', required: false, description: 'Optional node width.' },
262
372
  { name: 'height', type: 'number', required: false, description: 'Optional node height.' },
263
- { name: 'strictSize', type: 'boolean', required: false, description: 'Keep explicit width/height fixed and scroll overflowing content instead of browser auto-fitting.', aliases: ['strict-size', 'scroll-overflow'] },
373
+ {
374
+ name: 'strictSize',
375
+ type: 'boolean',
376
+ required: false,
377
+ description: 'Keep explicit width/height fixed and scroll overflowing content instead of browser auto-fitting.',
378
+ aliases: ['strict-size', 'scroll-overflow'],
379
+ },
264
380
  ],
265
381
  example: {
266
382
  type: 'html',
@@ -283,23 +399,37 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
283
399
  endpoint: '/api/canvas/node',
284
400
  mcpTool: 'canvas_node (action:"add", type:"html", primitive:"<kind>")',
285
401
  fields: [
286
- { name: 'kind', type: 'HtmlPrimitiveKind', required: true, description: 'Primitive kind. See top-level htmlPrimitives for the supported catalog.' },
287
- { name: 'data', type: 'record<string, unknown>', required: false, description: 'Primitive-specific JSON object payload.' },
402
+ {
403
+ name: 'kind',
404
+ type: 'HtmlPrimitiveKind',
405
+ required: true,
406
+ description: 'Primitive kind. See top-level htmlPrimitives for the supported catalog.',
407
+ },
408
+ {
409
+ name: 'data',
410
+ type: 'record<string, unknown>',
411
+ required: false,
412
+ description: 'Primitive-specific JSON object payload.',
413
+ },
288
414
  { name: 'title', type: 'string', required: false, description: 'Optional node title.' },
289
415
  { name: 'x', type: 'number', required: false, description: 'Optional X position.' },
290
416
  { name: 'y', type: 'number', required: false, description: 'Optional Y position.' },
291
417
  { name: 'width', type: 'number', required: false, description: 'Optional node width; defaults per primitive.' },
292
418
  { name: 'height', type: 'number', required: false, description: 'Optional node height; defaults per primitive.' },
293
- { name: 'strictSize', type: 'boolean', required: false, description: 'Keep explicit width/height fixed and scroll overflowing content instead of browser auto-fitting.', aliases: ['strict-size', 'scroll-overflow'] },
419
+ {
420
+ name: 'strictSize',
421
+ type: 'boolean',
422
+ required: false,
423
+ description: 'Keep explicit width/height fixed and scroll overflowing content instead of browser auto-fitting.',
424
+ aliases: ['strict-size', 'scroll-overflow'],
425
+ },
294
426
  ],
295
427
  example: {
296
428
  type: 'html-primitive',
297
429
  kind: 'choice-grid',
298
430
  title: 'Implementation Options',
299
431
  data: {
300
- items: [
301
- { title: 'Small patch', summary: 'Least disruption.', pros: ['Fast'], cons: ['Limited flexibility'] },
302
- ],
432
+ items: [{ title: 'Small patch', summary: 'Least disruption.', pros: ['Fast'], cons: ['Limited flexibility'] }],
303
433
  },
304
434
  },
305
435
  notes: [
@@ -336,8 +466,18 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
336
466
  mcpTool: 'canvas_app (action:"open-mcp-app")',
337
467
  fields: [
338
468
  { name: 'toolName', type: 'string', required: true, description: 'Tool name on the external MCP server.' },
339
- { name: 'transport', type: '{ type: "stdio", command, args? } | { type: "http", url, headers? }', required: true, description: 'External MCP transport definition.' },
340
- { name: 'toolArguments', type: 'record<string, unknown>', required: false, description: 'Arguments passed to the external MCP tool.' },
469
+ {
470
+ name: 'transport',
471
+ type: '{ type: "stdio", command, args? } | { type: "http", url, headers? }',
472
+ required: true,
473
+ description: 'External MCP transport definition.',
474
+ },
475
+ {
476
+ name: 'toolArguments',
477
+ type: 'record<string, unknown>',
478
+ required: false,
479
+ description: 'Arguments passed to the external MCP tool.',
480
+ },
341
481
  { name: 'title', type: 'string', required: false, description: 'Optional canvas node title override.' },
342
482
  ],
343
483
  example: {
@@ -360,7 +500,12 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
360
500
  fields: [
361
501
  { name: 'title', type: 'string', required: false, description: 'Group title.' },
362
502
  { name: 'childIds', type: 'string[]', required: false, description: 'Initial child node IDs.' },
363
- { name: 'childLayout', type: '"grid" | "column" | "flow"', required: false, description: 'Optional layout for grouped children.' },
503
+ {
504
+ name: 'childLayout',
505
+ type: '"grid" | "column" | "flow"',
506
+ required: false,
507
+ description: 'Optional layout for grouped children.',
508
+ },
364
509
  ],
365
510
  example: {
366
511
  title: 'API Layer',
@@ -375,8 +520,19 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
375
520
  endpoint: '/api/canvas/json-render',
376
521
  mcpTool: 'canvas_render (action:"add-json-render")',
377
522
  fields: [
378
- { name: 'title', type: 'string', required: false, description: 'Optional rendered node title; inferred from the root element when omitted.' },
379
- { name: 'spec', type: 'JsonRenderSpec | JsonRenderElement', required: true, description: 'Complete {root, elements} json-render spec, or a legacy single bare component object with a type field.' },
523
+ {
524
+ name: 'title',
525
+ type: 'string',
526
+ required: false,
527
+ description: 'Optional rendered node title; inferred from the root element when omitted.',
528
+ },
529
+ {
530
+ name: 'spec',
531
+ type: 'JsonRenderSpec | JsonRenderElement',
532
+ required: true,
533
+ description:
534
+ 'Complete {root, elements} json-render spec, or a legacy single bare component object with a type field.',
535
+ },
380
536
  { name: 'x', type: 'number', required: false, description: 'Optional X position.' },
381
537
  { name: 'y', type: 'number', required: false, description: 'Optional Y position.' },
382
538
  { name: 'width', type: 'number', required: false, description: 'Optional node width.' },
@@ -412,39 +568,206 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
412
568
  name: 'graphType',
413
569
  type: '"line" | "bar" | "pie" | "area" | "scatter" | "radar" | "stacked-bar" | "composed" | "sparkline" | "dot-plot" | "bullet" | "slopegraph"',
414
570
  required: true,
415
- description: 'Chart type. Includes the Tufte primitives sparkline, dot-plot (Cleveland), bullet (Few KPI vs target), and slopegraph (paired before/after). Aliases like "stack", "combo", "dot", and "slope" are normalized server-side.',
571
+ description:
572
+ 'Chart type. Includes the Tufte primitives sparkline, dot-plot (Cleveland), bullet (Few KPI vs target), and slopegraph (paired before/after). Aliases like "stack", "combo", "dot", and "slope" are normalized server-side.',
416
573
  aliases: ['graph-type'],
417
574
  },
418
- { name: 'data', type: 'Record<string, unknown>[]', required: true, description: 'Chart dataset. The CLI also accepts piped JSON via --stdin.', aliases: ['data-json', 'data-file'] },
575
+ {
576
+ name: 'data',
577
+ type: 'Record<string, unknown>[]',
578
+ required: true,
579
+ description: 'Chart dataset. The CLI also accepts piped JSON via --stdin.',
580
+ aliases: ['data-json', 'data-file'],
581
+ },
419
582
  { name: 'title', type: 'string', required: false, description: 'Optional graph title.' },
420
- { name: 'xKey', type: 'string', required: false, description: 'X-axis/category key for line, bar, area, scatter, stacked-bar, and composed charts.', aliases: ['x-key'] },
421
- { name: 'yKey', type: 'string', required: false, description: 'Y-axis value key for line, bar, area, and scatter charts. Also used as a fallback bar key for composed charts.', aliases: ['y-key'] },
422
- { name: 'zKey', type: 'string', required: false, description: 'Optional bubble-size key for scatter charts.', aliases: ['z-key'] },
423
- { name: 'nameKey', type: 'string', required: false, description: 'Slice name key for pie graphs.', aliases: ['name-key'] },
424
- { name: 'valueKey', type: 'string', required: false, description: 'Value key for pie slices, sparkline, dot-plot, and the bullet measure.', aliases: ['value-key'] },
425
- { name: 'axisKey', type: 'string', required: false, description: 'Category key for radar charts.', aliases: ['axis-key'] },
426
- { name: 'metrics', type: 'string[]', required: false, description: 'Series keys to plot as radar polygons. Defaults to non-axis numeric columns.' },
427
- { name: 'series', type: 'string[]', required: false, description: 'Series keys for stacked-bar segments. Defaults to non-x numeric columns.' },
428
- { name: 'barKey', type: 'string', required: false, description: 'Bar series key for composed charts.', aliases: ['bar-key'] },
429
- { name: 'lineKey', type: 'string', required: false, description: 'Line series key for composed charts.', aliases: ['line-key'] },
430
- { name: 'aggregate', type: '"sum" | "count" | "avg"', required: false, description: 'Optional aggregation for repeated x-axis values in line, bar, area, and stacked-bar charts.' },
431
- { name: 'color', type: 'string', required: false, description: 'Optional series color for line, bar, area, and scatter charts.' },
432
- { name: 'barColor', type: 'string', required: false, description: 'Optional bar color for composed charts.', aliases: ['bar-color'] },
433
- { name: 'lineColor', type: 'string', required: false, description: 'Optional line color for composed charts.', aliases: ['line-color'] },
434
- { name: 'colorBy', type: '"series" | "category" | "value" | "none"', required: false, description: 'Bar charts only: how bars are colored. Default "series" (single accent + one highlighted bar). "category" rotates the palette, "value" shades by magnitude, "none" is flat. Color should encode data, not decorate.', aliases: ['color-by'] },
435
- { name: 'highlight', type: 'number | "max" | "min"', required: false, description: 'Bar charts (colorBy="series") only: which bar gets the accent — "max" (default), "min", a 0-based index, or null for no emphasis.' },
436
- { name: 'labelKey', type: 'string', required: false, description: 'Category label key for dot-plot, bullet, and slopegraph rows.', aliases: ['label-key'] },
437
- { name: 'targetKey', type: 'string', required: false, description: 'Per-row target value key for bullet charts.', aliases: ['target-key'] },
438
- { name: 'rangesKey', type: 'string', required: false, description: 'Per-row qualitative band thresholds (number[]) key for bullet charts.', aliases: ['ranges-key'] },
439
- { name: 'beforeKey', type: 'string', required: false, description: 'Left-column value key for slopegraph.', aliases: ['before-key'] },
440
- { name: 'afterKey', type: 'string', required: false, description: 'Right-column value key for slopegraph.', aliases: ['after-key'] },
441
- { name: 'sort', type: '"asc" | "desc" | "none"', required: false, description: 'Row sort order for dot-plot (defaults to desc).' },
442
- { name: 'height', type: 'number', required: false, description: 'Optional chart content height.', aliases: ['chart-height'] },
443
- { name: 'showLegend', type: 'boolean', required: false, description: 'Show chart legend when supported; pass false for compact node layouts.', aliases: ['show-legend'] },
444
- { name: 'showLabels', type: 'boolean', required: false, description: 'Show direct labels when supported, such as pie slice labels; defaults to true.', aliases: ['show-labels'] },
583
+ {
584
+ name: 'xKey',
585
+ type: 'string',
586
+ required: false,
587
+ description: 'X-axis/category key for line, bar, area, scatter, stacked-bar, and composed charts.',
588
+ aliases: ['x-key'],
589
+ },
590
+ {
591
+ name: 'yKey',
592
+ type: 'string',
593
+ required: false,
594
+ description:
595
+ 'Y-axis value key for line, bar, area, and scatter charts. Also used as a fallback bar key for composed charts.',
596
+ aliases: ['y-key'],
597
+ },
598
+ {
599
+ name: 'zKey',
600
+ type: 'string',
601
+ required: false,
602
+ description: 'Optional bubble-size key for scatter charts.',
603
+ aliases: ['z-key'],
604
+ },
605
+ {
606
+ name: 'nameKey',
607
+ type: 'string',
608
+ required: false,
609
+ description: 'Slice name key for pie graphs.',
610
+ aliases: ['name-key'],
611
+ },
612
+ {
613
+ name: 'valueKey',
614
+ type: 'string',
615
+ required: false,
616
+ description: 'Value key for pie slices, sparkline, dot-plot, and the bullet measure.',
617
+ aliases: ['value-key'],
618
+ },
619
+ {
620
+ name: 'axisKey',
621
+ type: 'string',
622
+ required: false,
623
+ description: 'Category key for radar charts.',
624
+ aliases: ['axis-key'],
625
+ },
626
+ {
627
+ name: 'metrics',
628
+ type: 'string[]',
629
+ required: false,
630
+ description: 'Series keys to plot as radar polygons. Defaults to non-axis numeric columns.',
631
+ },
632
+ {
633
+ name: 'series',
634
+ type: 'string[]',
635
+ required: false,
636
+ description: 'Series keys for stacked-bar segments. Defaults to non-x numeric columns.',
637
+ },
638
+ {
639
+ name: 'barKey',
640
+ type: 'string',
641
+ required: false,
642
+ description: 'Bar series key for composed charts.',
643
+ aliases: ['bar-key'],
644
+ },
645
+ {
646
+ name: 'lineKey',
647
+ type: 'string',
648
+ required: false,
649
+ description: 'Line series key for composed charts.',
650
+ aliases: ['line-key'],
651
+ },
652
+ {
653
+ name: 'aggregate',
654
+ type: '"sum" | "count" | "avg"',
655
+ required: false,
656
+ description: 'Optional aggregation for repeated x-axis values in line, bar, area, and stacked-bar charts.',
657
+ },
658
+ {
659
+ name: 'color',
660
+ type: 'string',
661
+ required: false,
662
+ description: 'Optional series color for line, bar, area, and scatter charts.',
663
+ },
664
+ {
665
+ name: 'barColor',
666
+ type: 'string',
667
+ required: false,
668
+ description: 'Optional bar color for composed charts.',
669
+ aliases: ['bar-color'],
670
+ },
671
+ {
672
+ name: 'lineColor',
673
+ type: 'string',
674
+ required: false,
675
+ description: 'Optional line color for composed charts.',
676
+ aliases: ['line-color'],
677
+ },
678
+ {
679
+ name: 'colorBy',
680
+ type: '"series" | "category" | "value" | "none"',
681
+ required: false,
682
+ description:
683
+ 'Bar charts only: how bars are colored. Default "series" (single accent + one highlighted bar). "category" rotates the palette, "value" shades by magnitude, "none" is flat. Color should encode data, not decorate.',
684
+ aliases: ['color-by'],
685
+ },
686
+ {
687
+ name: 'highlight',
688
+ type: 'number | "max" | "min"',
689
+ required: false,
690
+ description:
691
+ 'Bar charts (colorBy="series") only: which bar gets the accent — "max" (default), "min", a 0-based index, or null for no emphasis.',
692
+ },
693
+ {
694
+ name: 'labelKey',
695
+ type: 'string',
696
+ required: false,
697
+ description: 'Category label key for dot-plot, bullet, and slopegraph rows.',
698
+ aliases: ['label-key'],
699
+ },
700
+ {
701
+ name: 'targetKey',
702
+ type: 'string',
703
+ required: false,
704
+ description: 'Per-row target value key for bullet charts.',
705
+ aliases: ['target-key'],
706
+ },
707
+ {
708
+ name: 'rangesKey',
709
+ type: 'string',
710
+ required: false,
711
+ description: 'Per-row qualitative band thresholds (number[]) key for bullet charts.',
712
+ aliases: ['ranges-key'],
713
+ },
714
+ {
715
+ name: 'beforeKey',
716
+ type: 'string',
717
+ required: false,
718
+ description: 'Left-column value key for slopegraph.',
719
+ aliases: ['before-key'],
720
+ },
721
+ {
722
+ name: 'afterKey',
723
+ type: 'string',
724
+ required: false,
725
+ description: 'Right-column value key for slopegraph.',
726
+ aliases: ['after-key'],
727
+ },
728
+ {
729
+ name: 'sort',
730
+ type: '"asc" | "desc" | "none"',
731
+ required: false,
732
+ description: 'Row sort order for dot-plot (defaults to desc).',
733
+ },
734
+ {
735
+ name: 'height',
736
+ type: 'number',
737
+ required: false,
738
+ description: 'Optional chart content height.',
739
+ aliases: ['chart-height'],
740
+ },
741
+ {
742
+ name: 'showLegend',
743
+ type: 'boolean',
744
+ required: false,
745
+ description: 'Show chart legend when supported; pass false for compact node layouts.',
746
+ aliases: ['show-legend'],
747
+ },
748
+ {
749
+ name: 'showLabels',
750
+ type: 'boolean',
751
+ required: false,
752
+ description: 'Show direct labels when supported, such as pie slice labels; defaults to true.',
753
+ aliases: ['show-labels'],
754
+ },
445
755
  { name: 'width', type: 'number', required: false, description: 'Optional node width.' },
446
- { name: 'nodeHeight', type: 'number', required: false, description: 'Optional node height (canvas frame). Distinct from `height`, which sets only the chart content height inside the node.', aliases: ['node-height'] },
447
- { name: 'strictSize', type: 'boolean', required: false, description: 'Keep explicit node size fixed and scroll overflowing content instead of browser auto-fitting.', aliases: ['strict-size', 'scroll-overflow'] },
756
+ {
757
+ name: 'nodeHeight',
758
+ type: 'number',
759
+ required: false,
760
+ description:
761
+ 'Optional node height (canvas frame). Distinct from `height`, which sets only the chart content height inside the node.',
762
+ aliases: ['node-height'],
763
+ },
764
+ {
765
+ name: 'strictSize',
766
+ type: 'boolean',
767
+ required: false,
768
+ description: 'Keep explicit node size fixed and scroll overflowing content instead of browser auto-fitting.',
769
+ aliases: ['strict-size', 'scroll-overflow'],
770
+ },
448
771
  ],
449
772
  example: {
450
773
  title: 'Deploy Trend',
@@ -470,16 +793,62 @@ const CANVAS_CREATE_TYPES: CanvasCreateTypeSchema[] = [
470
793
  mcpTool: 'canvas_app (action:"build-artifact")',
471
794
  fields: [
472
795
  { name: 'title', type: 'string', required: true, description: 'Artifact title used for default paths.' },
473
- { name: 'appTsx', type: 'string', required: true, description: 'Contents for src/App.tsx. The CLI also accepts piped contents via --stdin.', aliases: ['app-file', 'app-tsx'] },
474
- { name: 'indexCss', type: 'string', required: false, description: 'Optional src/index.css contents.', aliases: ['index-css-file', 'index-css'] },
475
- { name: 'mainTsx', type: 'string', required: false, description: 'Optional src/main.tsx contents.', aliases: ['main-file', 'main-tsx'] },
476
- { name: 'indexHtml', type: 'string', required: false, description: 'Optional index.html contents.', aliases: ['index-html-file', 'index-html'] },
796
+ {
797
+ name: 'appTsx',
798
+ type: 'string',
799
+ required: true,
800
+ description: 'Contents for src/App.tsx. The CLI also accepts piped contents via --stdin.',
801
+ aliases: ['app-file', 'app-tsx'],
802
+ },
803
+ {
804
+ name: 'indexCss',
805
+ type: 'string',
806
+ required: false,
807
+ description: 'Optional src/index.css contents.',
808
+ aliases: ['index-css-file', 'index-css'],
809
+ },
810
+ {
811
+ name: 'mainTsx',
812
+ type: 'string',
813
+ required: false,
814
+ description: 'Optional src/main.tsx contents.',
815
+ aliases: ['main-file', 'main-tsx'],
816
+ },
817
+ {
818
+ name: 'indexHtml',
819
+ type: 'string',
820
+ required: false,
821
+ description: 'Optional index.html contents.',
822
+ aliases: ['index-html-file', 'index-html'],
823
+ },
477
824
  { name: 'projectPath', type: 'string', required: false, description: 'Optional project directory.' },
478
825
  { name: 'outputPath', type: 'string', required: false, description: 'Optional output HTML path.' },
479
- { name: 'openInCanvas', type: 'boolean', required: false, description: 'Open the built artifact on the canvas (default true).' },
480
- { name: 'includeLogs', type: 'boolean', required: false, description: 'Include raw build stdout/stderr in the response (default false).' },
481
- { name: 'deps', type: 'string[]', required: false, description: 'Optional npm dependencies to add before bundling, e.g. recharts.', aliases: ['deps'] },
482
- { name: 'timeoutMs', type: 'number', required: false, description: 'Build command timeout in milliseconds. This controls subprocess timeout, not the MCP client request timeout.' },
826
+ {
827
+ name: 'openInCanvas',
828
+ type: 'boolean',
829
+ required: false,
830
+ description: 'Open the built artifact on the canvas (default true).',
831
+ },
832
+ {
833
+ name: 'includeLogs',
834
+ type: 'boolean',
835
+ required: false,
836
+ description: 'Include raw build stdout/stderr in the response (default false).',
837
+ },
838
+ {
839
+ name: 'deps',
840
+ type: 'string[]',
841
+ required: false,
842
+ description: 'Optional npm dependencies to add before bundling, e.g. recharts.',
843
+ aliases: ['deps'],
844
+ },
845
+ {
846
+ name: 'timeoutMs',
847
+ type: 'number',
848
+ required: false,
849
+ description:
850
+ 'Build command timeout in milliseconds. This controls subprocess timeout, not the MCP client request timeout.',
851
+ },
483
852
  ],
484
853
  example: {
485
854
  title: 'Dashboard Artifact',
@@ -540,9 +909,21 @@ export function describeCanvasSchema(): {
540
909
  },
541
910
  components: clone(describeJsonRenderCatalog()),
542
911
  directives: [
543
- { name: '$state', usage: '{ "$state": "/path/to/value" } — read a value from the state model by path (one-way). Use this to bind a value by path; there is no $path directive.' },
544
- { name: '$format', usage: '{ "$format": "currency"|"number"|"percent"|"date", "value": <num|state-ref>, "currency"?: "USD", "locale"?, "style"?, "options"? } — Intl-formatted string' },
545
- { name: '$math', usage: '{ "$math": "add"|"subtract"|"multiply"|"divide"|"mod"|"min"|"max"|"round"|"floor"|"ceil"|"abs", "a": <num>, "b"?: <num> }' },
912
+ {
913
+ name: '$state',
914
+ usage:
915
+ '{ "$state": "/path/to/value" } — read a value from the state model by path (one-way). Use this to bind a value by path; there is no $path directive.',
916
+ },
917
+ {
918
+ name: '$format',
919
+ usage:
920
+ '{ "$format": "currency"|"number"|"percent"|"date", "value": <num|state-ref>, "currency"?: "USD", "locale"?, "style"?, "options"? } — Intl-formatted string',
921
+ },
922
+ {
923
+ name: '$math',
924
+ usage:
925
+ '{ "$math": "add"|"subtract"|"multiply"|"divide"|"mod"|"min"|"max"|"round"|"floor"|"ceil"|"abs", "a": <num>, "b"?: <num> }',
926
+ },
546
927
  { name: '$concat', usage: '{ "$concat": [<value>, <value>, ...] } — join values into one string' },
547
928
  { name: '$count', usage: '{ "$count": <array|state-ref> } — length of an array' },
548
929
  { name: '$truncate', usage: '{ "$truncate": <string>, "length": <num>, "suffix"?: "…" }' },