@pinepaper.studio/mcp-server 1.5.1 → 1.5.4

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 (96) hide show
  1. package/README.md +6 -4
  2. package/dist/agent/types.d.ts +16 -16
  3. package/dist/browser/puppeteer-controller.d.ts +5 -1
  4. package/dist/browser/puppeteer-controller.d.ts.map +1 -1
  5. package/dist/browser/puppeteer-controller.js +11 -3
  6. package/dist/browser/puppeteer-controller.js.map +1 -1
  7. package/dist/browser/url-target.d.ts +26 -0
  8. package/dist/browser/url-target.d.ts.map +1 -0
  9. package/dist/browser/url-target.js +50 -0
  10. package/dist/browser/url-target.js.map +1 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +128 -109
  13. package/dist/index.js.map +1 -1
  14. package/dist/ontology/design-graph.d.ts +85 -0
  15. package/dist/ontology/design-graph.d.ts.map +1 -0
  16. package/dist/ontology/design-graph.js +944 -0
  17. package/dist/ontology/design-graph.js.map +1 -0
  18. package/dist/ontology/hints.d.ts +71 -0
  19. package/dist/ontology/hints.d.ts.map +1 -0
  20. package/dist/ontology/hints.js +189 -0
  21. package/dist/ontology/hints.js.map +1 -0
  22. package/dist/ontology/index.d.ts +11 -0
  23. package/dist/ontology/index.d.ts.map +1 -0
  24. package/dist/ontology/index.js +14 -0
  25. package/dist/ontology/index.js.map +1 -0
  26. package/dist/ontology/semantic-vocabulary.d.ts +12 -0
  27. package/dist/ontology/semantic-vocabulary.d.ts.map +1 -0
  28. package/dist/ontology/semantic-vocabulary.js +26 -0
  29. package/dist/ontology/semantic-vocabulary.js.map +1 -0
  30. package/dist/ontology/types.d.ts +255 -0
  31. package/dist/ontology/types.d.ts.map +1 -0
  32. package/dist/ontology/types.js +10 -0
  33. package/dist/ontology/types.js.map +1 -0
  34. package/dist/ontology/validator.d.ts +36 -0
  35. package/dist/ontology/validator.d.ts.map +1 -0
  36. package/dist/ontology/validator.js +374 -0
  37. package/dist/ontology/validator.js.map +1 -0
  38. package/dist/ontology/vocabulary.d.ts +34 -0
  39. package/dist/ontology/vocabulary.d.ts.map +1 -0
  40. package/dist/ontology/vocabulary.js +429 -0
  41. package/dist/ontology/vocabulary.js.map +1 -0
  42. package/dist/prompts/index.d.ts.map +1 -1
  43. package/dist/prompts/index.js +146 -0
  44. package/dist/prompts/index.js.map +1 -1
  45. package/dist/tools/compact-descriptions.d.ts +5 -2
  46. package/dist/tools/compact-descriptions.d.ts.map +1 -1
  47. package/dist/tools/compact-descriptions.js +56 -235
  48. package/dist/tools/compact-descriptions.js.map +1 -1
  49. package/dist/tools/definitions.d.ts +1 -1
  50. package/dist/tools/definitions.d.ts.map +1 -1
  51. package/dist/tools/definitions.js +1842 -1784
  52. package/dist/tools/definitions.js.map +1 -1
  53. package/dist/tools/handlers/camera.d.ts +19 -0
  54. package/dist/tools/handlers/camera.d.ts.map +1 -0
  55. package/dist/tools/handlers/camera.js +94 -0
  56. package/dist/tools/handlers/camera.js.map +1 -0
  57. package/dist/tools/handlers/export.d.ts +12 -0
  58. package/dist/tools/handlers/export.d.ts.map +1 -0
  59. package/dist/tools/handlers/export.js +30 -0
  60. package/dist/tools/handlers/export.js.map +1 -0
  61. package/dist/tools/handlers/font.d.ts +12 -0
  62. package/dist/tools/handlers/font.d.ts.map +1 -0
  63. package/dist/tools/handlers/font.js +135 -0
  64. package/dist/tools/handlers/font.js.map +1 -0
  65. package/dist/tools/handlers/maps.d.ts +19 -0
  66. package/dist/tools/handlers/maps.d.ts.map +1 -0
  67. package/dist/tools/handlers/maps.js +184 -0
  68. package/dist/tools/handlers/maps.js.map +1 -0
  69. package/dist/tools/handlers/ontology.d.ts +20 -0
  70. package/dist/tools/handlers/ontology.d.ts.map +1 -0
  71. package/dist/tools/handlers/ontology.js +185 -0
  72. package/dist/tools/handlers/ontology.js.map +1 -0
  73. package/dist/tools/handlers/tool-guide.d.ts +14 -0
  74. package/dist/tools/handlers/tool-guide.d.ts.map +1 -0
  75. package/dist/tools/handlers/tool-guide.js +52 -0
  76. package/dist/tools/handlers/tool-guide.js.map +1 -0
  77. package/dist/tools/handlers.d.ts +18 -0
  78. package/dist/tools/handlers.d.ts.map +1 -1
  79. package/dist/tools/handlers.js +321 -574
  80. package/dist/tools/handlers.js.map +1 -1
  81. package/dist/tools/minimal-descriptions.d.ts +4 -0
  82. package/dist/tools/minimal-descriptions.d.ts.map +1 -1
  83. package/dist/tools/minimal-descriptions.js +65 -54
  84. package/dist/tools/minimal-descriptions.js.map +1 -1
  85. package/dist/tools/toolkits.d.ts.map +1 -1
  86. package/dist/tools/toolkits.js +67 -46
  87. package/dist/tools/toolkits.js.map +1 -1
  88. package/dist/types/code-generator.d.ts +49 -2
  89. package/dist/types/code-generator.d.ts.map +1 -1
  90. package/dist/types/code-generator.js +1456 -39
  91. package/dist/types/code-generator.js.map +1 -1
  92. package/dist/types/schemas.d.ts +1381 -404
  93. package/dist/types/schemas.d.ts.map +1 -1
  94. package/dist/types/schemas.js +426 -20
  95. package/dist/types/schemas.js.map +1 -1
  96. package/package.json +2 -2
@@ -9,10 +9,28 @@
9
9
  */
10
10
  import { COMPACT_DESCRIPTIONS } from './compact-descriptions.js';
11
11
  import { MINIMAL_DESCRIPTIONS } from './minimal-descriptions.js';
12
+ import { EffectTypeSchema, SimpleAnimationTypeSchema, } from '../types/schemas.js';
13
+ /**
14
+ * Vocabulary lists derived from Zod schemas so tool descriptions stay in
15
+ * sync automatically. The description-schema-parity test
16
+ * (src/__tests__/unit/description-schema-parity.test.ts) fails CI if any
17
+ * tool description that names a vocabulary slot drops or invents values
18
+ * relative to the source-of-truth schema.
19
+ */
20
+ const EFFECT_TYPES_LIST = EffectTypeSchema.options.join(', ');
21
+ const SIMPLE_ANIMATION_TYPES_LIST = SimpleAnimationTypeSchema.options.join(', ');
12
22
  // =============================================================================
13
23
  // AI AGENT GUIDE (exported for pinepaper_tool_guide)
14
24
  // =============================================================================
15
- export const AI_AGENT_GUIDE = `WORKFLOW — Create → Validate → Iterate:
25
+ export const AI_AGENT_GUIDE = `⚠️ You are connected to PinePaper Studio via MCP tools. ALWAYS use these tools to create visual content.
26
+ NEVER create standalone HTML pages, React components, or web apps as a substitute. Do NOT use frontend design skills or CSS-only animations instead of PinePaper.
27
+ PinePaper tools ARE the implementation — they generate Paper.js/JavaScript code that runs on the canvas and produce Canvas 2D, SVG, MP4, GIF, PNG exports.
28
+ If a tool fails, report the error — do NOT fall back to generating HTML pages.
29
+ The generated code is shown in tool responses and can be copied into PinePaper's Code Console.
30
+
31
+ ⚠️ KNOWN CONFLICT: The "frontend-design" plugin instructs agents to generate HTML/CSS pages for visual content. This conflicts with PinePaper. If you keep generating HTML instead of calling PinePaper tools, the user should disable the frontend-design plugin.
32
+
33
+ WORKFLOW — Create → Validate → Iterate:
16
34
 
17
35
  1. pinepaper_agent_start_job (clearCanvas: true, canvasPreset)
18
36
  2. pinepaper_agent_batch_execute — ONE call with ALL operations:
@@ -39,7 +57,7 @@ RULES:
39
57
  CANVAS: set_canvas_size (width/height or preset) → set_background (color) → execute_generator (procedural art)
40
58
  ITEMS: create (itemType, position, properties) → modify (itemId, properties) → delete (itemId)
41
59
  ANIMATE: animate (loop presets) → keyframe_animate (timed reveals) → relation (behavioral links)
42
- EFFECTS: apply_mask (reveal animations) → apply_effect (sparkle/blast)
60
+ EFFECTS: apply_mask (reveal animations) → apply_effect (sparkle/blast/bubbles/fireflies/trail...)
43
61
  PLAY: play_timeline (start playback)
44
62
 
45
63
  ─── GENERATORS (prefer these for backgrounds) ───
@@ -56,6 +74,7 @@ Choose based on mood:
56
74
 
57
75
  Shapes: circle, rectangle, star, ellipse, triangle, polygon, line, arc, path
58
76
  Text: text (content, fontSize, fontFamily, color, fontWeight)
77
+ Dynamic text: set contentType on text items → clock (live time), timer (elapsed), countdown (from N seconds), stopwatch (pauseable)
59
78
  All items: opacity, shadowColor, shadowBlur, blendMode, strokeColor, strokeWidth
60
79
 
61
80
  SVG imports for recognizable objects (planes, cars, animals, buildings):
@@ -65,7 +84,7 @@ SVG imports for recognizable objects (planes, cars, animals, buildings):
65
84
 
66
85
  Loop presets (animate): pulse, rotate, bounce, fade, wobble, slide, typewriter
67
86
  Keyframe (keyframe_animate): [{time, properties, easing}] → opacity, scale, scaleX, scaleY, x, y, rotation, fillColor, strokeColor, fontSize
68
- Relations (relation): orbits, follows, attached_to, points_at, mirrors, parallax, wave_through, morphs_to (+ 9 more in batch_execute schema)
87
+ Relations (relation): orbits, follows, attached_to, points_at, mirrors, parallax, wave_through, morphs_to, group_morphs_to, moves_along_path (+ 9 more in batch_execute schema)
69
88
  Masks (apply_mask): wipeLeft, wipeRight, wipeUp, wipeDown, iris, irisOut, star, heart, curtainHorizontal, curtainVertical, cinematic, diagonalWipe, revealUp, revealDown
70
89
  Effects (apply_effect): sparkle, blast
71
90
 
@@ -103,10 +122,38 @@ Shapes: process (rect), decision (diamond), terminal (rounded), data, document,
103
122
  Workflow: create shapes with positions → connect with arrows → optional auto_layout
104
123
  See pinepaper://docs/diagrams for full examples.
105
124
 
125
+ ─── STANDALONE TOOLS (not batch — call directly) ───
126
+
127
+ Deformation: pinepaper_deform — vertex-level presets (fold, squeeze, twist, ripple, wave, breathe, wobble...)
128
+ Phase-driven animation: sin, blink, pingpong, elastic, heartbeat, stepped
129
+ Use for organic motion that keyframes can't achieve.
130
+
131
+ Sprite Sheets: pinepaper_sprite_sheet — generate from skeleton poses, play, export (PNG + atlas)
132
+ For character animation and game sprite pipelines.
133
+
134
+ Interaction: pinepaper_interaction — continuous physics behaviors (repel, attract, follow, orbit, slingshot)
135
+ For interactive storytelling, quizzes, games. trigger_action for state changes (incrementScore, navigate, showFeedback).
136
+
137
+ Storage: pinepaper_storage — save/load/list/delete projects (IndexedDB persistence)
138
+ For multi-project workflows and session recovery.
139
+
140
+ Data Viz: pinepaper_create_chart — create/update/reconfigure/remove charts (bar, line, scatter, area)
141
+ Pass data as array of objects + options. Auto-animated with expression-driven oscillation.
142
+
143
+ Magic: pinepaper_magic — ontology-aware auto-animation + style remix
144
+ One-click animate (mood: calm/professional/energetic/dramatic/whimsical) or remix (cycle colors/fonts).
145
+
146
+ Physics: pinepaper_physics — rigid body simulation (init, add_body, apply_force, create_joint)
147
+ For interactive simulations, gravity, collisions. Based on Box2D/Planck.js.
148
+
149
+ Measurement: pinepaper_measurement — rulers, grid, snap-to-grid, get item dimensions
150
+ For precise layouts and alignment.
151
+
106
152
  ─── CANVAS & EXPORT ───
107
153
 
108
154
  Presets: instagram (1080x1080), youtube (1920x1080), tiktok (1080x1920), twitter (1200x675)
109
- Export: pinepaper_agent_export (SVG/PNG/GIF/MP4/WebM/PDF), pinepaper_export_svg`;
155
+ Export: pinepaper_agent_export (SVG/PNG/GIF/MP4/WebM/PDF), pinepaper_export_svg
156
+ Widget: pinepaper_export_widget (pp:PinePaper ontology JSON), pinepaper_export_widget_html (self-contained HTML with tree-shaken runtime)`;
110
157
  /*
111
158
  * The AI_AGENT_GUIDE constant above is included as a comment in verbose/compact modes
112
159
  * and served on-demand via pinepaper_tool_guide in minimal mode.
@@ -282,7 +329,7 @@ USE WHEN:
282
329
  IMPORTANT:
283
330
  - Save the returned itemId! You need it for pinepaper_add_relation, pinepaper_modify_item, pinepaper_delete_item, etc.
284
331
  - If there's a welcome template on the canvas, use pinepaper_clear_canvas first
285
- - Position defaults to canvas center (400, 300). Use position: {x, y} to place elsewhere.
332
+ - Position defaults to canvas center (400, 300). Use position: {x, y} or [x, y] (both forms accepted) to place elsewhere.
286
333
  - DO NOT take screenshots after every create operation. Trust the API response - if it returns success, the item was created. Take ONE screenshot at the end to verify the final result.
287
334
 
288
335
  ⚠️ COMPLEX CHARACTERS/ILLUSTRATIONS:
@@ -344,12 +391,23 @@ For glossy 3D spheres, use pinepaper_create_glossy_sphere instead. For diagonal
344
391
  description: 'Type of item to create',
345
392
  },
346
393
  position: {
347
- type: 'object',
348
- properties: {
349
- x: { type: 'number', description: 'X coordinate (default: 400)' },
350
- y: { type: 'number', description: 'Y coordinate (default: 300)' },
351
- },
352
- description: 'Position on canvas',
394
+ oneOf: [
395
+ {
396
+ type: 'object',
397
+ properties: {
398
+ x: { type: 'number', description: 'X coordinate (default: 400)' },
399
+ y: { type: 'number', description: 'Y coordinate (default: 300)' },
400
+ },
401
+ },
402
+ {
403
+ type: 'array',
404
+ items: { type: 'number' },
405
+ minItems: 2,
406
+ maxItems: 2,
407
+ description: '[x, y] tuple — array shorthand for position',
408
+ },
409
+ ],
410
+ description: 'Position on canvas. Either {x, y} object or [x, y] array.',
353
411
  },
354
412
  properties: {
355
413
  type: 'object',
@@ -427,7 +485,15 @@ MODIFIABLE PROPERTIES:
427
485
  - blendMode: Blend mode (normal, multiply, screen, overlay, etc.)
428
486
 
429
487
  GRADIENT OBJECT FORMAT:
430
- {type: "linear"|"radial", stops: [{color: "#fff", offset: 0}, {color: "#000", offset: 1}], origin: [x,y], destination: [x,y]}`,
488
+ {type: "linear"|"radial", stops: [{color: "#fff", offset: 0}, {color: "#000", offset: 1}], origin: [x,y], destination: [x,y]}
489
+
490
+ LETTER-COLLAGE PROPS (non-destructive — registry ids, animations, relations, effects, deformations all preserved):
491
+ - palette (collage group): Swap palette name in-place. e.g. "wordle", "spring", "sunset", "magazine". Walks existing letters, rewrites tile + text fills. No geometry change.
492
+ - collageStyle (collage group): Swap visual style — "tile" | "magazine" | "paperCut" | "fold" | "gradient" | "image". Geometry rebuilds; every registryId is preserved via graft.
493
+ - palette + collageStyle (collage group): Combine in one call to apply both atomically.
494
+ - bgColor (single letter group, child of a collage): Tile/background fill for that one letter.
495
+ - textColor (single letter group): PointText fill for that one letter.
496
+ Use the collage group's id for palette/collageStyle; use a child letter's id for bgColor/textColor. Prefer this over destructive recreation.`,
431
497
  inputSchema: {
432
498
  type: 'object',
433
499
  properties: {
@@ -437,7 +503,7 @@ GRADIENT OBJECT FORMAT:
437
503
  },
438
504
  properties: {
439
505
  type: 'object',
440
- description: 'Properties to update: x, y, width, height, scale, scaleX, scaleY, rotation, opacity, color, strokeColor, strokeWidth, fontSize, content. DO NOT pass animationType here — use pinepaper_animate or pinepaper_keyframe_animate instead.',
506
+ description: 'Properties to update: x, y, width, height, scale, scaleX, scaleY, rotation, opacity, color, strokeColor, strokeWidth, fontSize, content. Letter-collage non-destructive props (preserve ids/animations/relations): palette, collageStyle (collage group); bgColor, textColor (single letter). DO NOT pass animationType here — use pinepaper_animate or pinepaper_keyframe_animate instead.',
441
507
  additionalProperties: true,
442
508
  },
443
509
  data: {
@@ -699,6 +765,65 @@ Returns the itemId of the imported SVG group, which can be used with pinepaper_a
699
765
  },
700
766
  },
701
767
  },
768
+ {
769
+ name: 'pinepaper_import_mermaid',
770
+ annotations: {
771
+ title: 'Import Mermaid Diagram',
772
+ readOnlyHint: false,
773
+ destructiveHint: false,
774
+ idempotentHint: false,
775
+ openWorldHint: false,
776
+ },
777
+ description: `Import a Mermaid diagram source string and render it onto the canvas as native diagram shapes + connectors. Faster than building a flowchart shape-by-shape with pinepaper_create_diagram_shape + pinepaper_connect.
778
+
779
+ USE WHEN:
780
+ - User asks for a flowchart, sequence diagram, ER diagram, class diagram, or state machine
781
+ - You have Mermaid source from another tool / docs / the user's clipboard
782
+ - You want to author multi-node diagrams in one call instead of N create+connect operations
783
+
784
+ SUPPORTED DIAGRAM TYPES (auto-detected from the first non-blank line):
785
+ - flowchart / graph: shapes + edges + subgraphs + chained edges (TD, LR, RL, BT directions)
786
+ - stateDiagram(-v2): states, transitions, [*] start/end, stereotypes, nested states
787
+ - sequenceDiagram: participants, messages, activations / lifelines
788
+ - erDiagram: entities + relationships + attributes
789
+ - classDiagram: classes, fields, methods, visibility, inheritance / association
790
+
791
+ OPTIONS:
792
+ - autoLayout (default true): run hierarchical/force layout after import. Set false to keep coordinates exactly as parsed.
793
+ - clearExisting (default false): remove existing canvas items first. Default is additive — diagram is appended.
794
+
795
+ EXAMPLE (flowchart):
796
+ {
797
+ "mermaidText": "flowchart TD\\n A[Start] --> B{Decision}\\n B -->|Yes| C[Action]\\n B -->|No| D[End]"
798
+ }
799
+
800
+ EXAMPLE (sequenceDiagram):
801
+ {
802
+ "mermaidText": "sequenceDiagram\\n Alice->>Bob: Hello\\n Bob-->>Alice: Hi back\\n Note right of Bob: Thinking..."
803
+ }
804
+
805
+ Returns { success, nodeCount, edgeCount, nodes, edges, errors }. The created shapes participate in the relation/animation systems just like natively created items — you can grab their ids from \`nodes\` and feed them into pinepaper_add_relation, pinepaper_animate, etc.
806
+
807
+ NOTE: Import-only — there is no MCP equivalent of FxTool's exportMermaid. Mermaid lacks animation primitives, so a round-trip would silently drop animations.`,
808
+ inputSchema: {
809
+ type: 'object',
810
+ properties: {
811
+ mermaidText: {
812
+ type: 'string',
813
+ description: 'Mermaid diagram source. First line picks the type (flowchart, stateDiagram, sequenceDiagram, erDiagram, classDiagram).',
814
+ },
815
+ autoLayout: {
816
+ type: 'boolean',
817
+ description: 'Run auto-layout after import (default: true).',
818
+ },
819
+ clearExisting: {
820
+ type: 'boolean',
821
+ description: 'Clear existing canvas items first (default: false).',
822
+ },
823
+ },
824
+ required: ['mermaidText'],
825
+ },
826
+ },
702
827
  {
703
828
  name: 'pinepaper_import_image',
704
829
  annotations: {
@@ -1143,6 +1268,8 @@ RELATION COMPATIBILITY:
1143
1268
  Circle→Circle: radius interpolation
1144
1269
  Text→Text: font blend
1145
1270
  Cross-type: particle denoising transition
1271
+ - group_morphs_to: pair-by-index morph between two paper.Groups (any two — graph vertices+edges, letter collages, dashboard clusters). Path.Line children deform via endpoints; other children translate; excess children fade. Params: duration, hold, loop, easing (linear|easeIn|easeOut|easeInOut), deformLines.
1272
+ - moves_along_path: self-relation (targetId=null); item is driven along a custom-drawn path stored in params.path (array of {x,y} or [x,y]). Params: path, speed, closed, phase, easing (linear|easeIn|easeOut|easeInOut|sine|bounce|pingpong).
1146
1273
 
1147
1274
  VERIFYING ANIMATION WORKS:
1148
1275
  After adding a relation, verify the animation is running:
@@ -1164,7 +1291,7 @@ Relations are COMPOSITIONAL - an item can have multiple relations that work toge
1164
1291
  },
1165
1292
  relationType: {
1166
1293
  type: 'string',
1167
- enum: ['orbits', 'follows', 'attached_to', 'maintains_distance', 'points_at', 'mirrors', 'parallax', 'bounds_to', 'animates', 'grows_from', 'staggered_with', 'indicates', 'circumscribes', 'wave_through', 'camera_follows', 'camera_animates', 'morphs_to'],
1294
+ enum: ['orbits', 'follows', 'attached_to', 'maintains_distance', 'points_at', 'mirrors', 'parallax', 'bounds_to', 'animates', 'grows_from', 'staggered_with', 'indicates', 'circumscribes', 'wave_through', 'camera_follows', 'camera_animates', 'morphs_to', 'group_morphs_to', 'moves_along_path'],
1168
1295
  description: 'Type of relationship',
1169
1296
  },
1170
1297
  params: {
@@ -1198,7 +1325,7 @@ USE WHEN:
1198
1325
  targetId: { type: 'string', description: 'Target item ID' },
1199
1326
  relationType: {
1200
1327
  type: 'string',
1201
- enum: ['orbits', 'follows', 'attached_to', 'maintains_distance', 'points_at', 'mirrors', 'parallax', 'bounds_to', 'animates', 'grows_from', 'staggered_with', 'indicates', 'circumscribes', 'wave_through', 'camera_follows', 'camera_animates', 'morphs_to'],
1328
+ enum: ['orbits', 'follows', 'attached_to', 'maintains_distance', 'points_at', 'mirrors', 'parallax', 'bounds_to', 'animates', 'grows_from', 'staggered_with', 'indicates', 'circumscribes', 'wave_through', 'camera_follows', 'camera_animates', 'morphs_to', 'group_morphs_to', 'moves_along_path'],
1202
1329
  description: 'Specific relation type to remove (optional - removes all if not specified)',
1203
1330
  },
1204
1331
  },
@@ -1226,7 +1353,7 @@ USE WHEN:
1226
1353
  itemId: { type: 'string', description: 'Item to query relations for' },
1227
1354
  relationType: {
1228
1355
  type: 'string',
1229
- enum: ['orbits', 'follows', 'attached_to', 'maintains_distance', 'points_at', 'mirrors', 'parallax', 'bounds_to', 'animates', 'grows_from', 'staggered_with', 'indicates', 'circumscribes', 'wave_through', 'camera_follows', 'camera_animates', 'morphs_to'],
1356
+ enum: ['orbits', 'follows', 'attached_to', 'maintains_distance', 'points_at', 'mirrors', 'parallax', 'bounds_to', 'animates', 'grows_from', 'staggered_with', 'indicates', 'circumscribes', 'wave_through', 'camera_follows', 'camera_animates', 'morphs_to', 'group_morphs_to', 'moves_along_path'],
1230
1357
  description: 'Filter by relation type (optional)',
1231
1358
  },
1232
1359
  direction: {
@@ -1445,7 +1572,17 @@ EASING OPTIONS:
1445
1572
  - easeOut: Slow end
1446
1573
  - easeInOut: Slow start and end
1447
1574
  - bounce: Bounce effect
1448
- - elastic: Elastic overshoot`,
1575
+ - elastic: Elastic overshoot
1576
+
1577
+ CLIP WINDOW (optional — Premiere/Canva-style clip behavior):
1578
+ - timeOffset: Shift the whole clip in canvas time (seconds). The animation only runs while canvas time is in [timeOffset, timeOffset + (clipOutPoint - clipInPoint)].
1579
+ - clipInPoint: Skip the first N seconds of keyframe data (head trim).
1580
+ - clipOutPoint: Stop at N seconds into the keyframe data (tail trim). Default: lastKeyframeTime.
1581
+ Outside the clip window the item is hidden via item.visible=false (opacity is left alone, so opacity-keyframes still work inside the window).
1582
+
1583
+ EXAMPLE — Reveal at 2s, skip first second of keyframe data, end at 4s of keyframe data:
1584
+ { itemId, timeOffset: 2, clipInPoint: 1, clipOutPoint: 4, keyframes: [...] }
1585
+ // Item visible during canvas time 2..5s; keyframes shifted so kf time=1 plays at canvas 2s.`,
1449
1586
  inputSchema: {
1450
1587
  type: 'object',
1451
1588
  properties: {
@@ -1478,6 +1615,18 @@ EASING OPTIONS:
1478
1615
  type: 'boolean',
1479
1616
  description: 'Whether to loop the animation',
1480
1617
  },
1618
+ timeOffset: {
1619
+ type: 'number',
1620
+ description: 'Shift the whole clip in canvas time (seconds). Item is hidden outside [timeOffset, timeOffset+window].',
1621
+ },
1622
+ clipInPoint: {
1623
+ type: 'number',
1624
+ description: 'Skip the first N seconds of keyframe data (head trim).',
1625
+ },
1626
+ clipOutPoint: {
1627
+ type: 'number',
1628
+ description: 'Stop at N seconds into the keyframe data (tail trim). Default: lastKeyframeTime.',
1629
+ },
1481
1630
  },
1482
1631
  required: ['itemId', 'keyframes'],
1483
1632
  },
@@ -1494,7 +1643,7 @@ EASING OPTIONS:
1494
1643
  description: `Control keyframe animation playback.
1495
1644
 
1496
1645
  USE WHEN:
1497
- - Starting/stopping timeline playback
1646
+ - Starting/stopping/pausing timeline playback
1498
1647
  - Seeking to specific time
1499
1648
  - Controlling animation state`,
1500
1649
  inputSchema: {
@@ -1502,7 +1651,7 @@ USE WHEN:
1502
1651
  properties: {
1503
1652
  action: {
1504
1653
  type: 'string',
1505
- enum: ['play', 'stop', 'seek'],
1654
+ enum: ['play', 'pause', 'stop', 'seek'],
1506
1655
  description: 'Playback action',
1507
1656
  },
1508
1657
  duration: {
@@ -1746,29 +1895,60 @@ Requires maskType and keyframes array.`,
1746
1895
  idempotentHint: false,
1747
1896
  openWorldHint: false,
1748
1897
  },
1749
- description: `Animate camera with keyframe-based zoom and pan sequence for cinematic effects.
1898
+ description: `Animate camera with keyframe-based zoom, pan, and 3D tilt sequence for cinematic effects.
1750
1899
 
1751
1900
  USE WHEN:
1752
1901
  - Creating cinematic camera movements
1753
1902
  - Building presentation zoom sequences
1754
1903
  - Making dramatic reveals with camera motion
1755
1904
  - Tour animations showing different parts of canvas
1905
+ - 3D perspective effects (pitch/yaw tilt via equirectangular projection)
1906
+
1907
+ The camera follows a keyframe sequence. For an orbit-style camera (revolving
1908
+ around a subject), add 4-8 keyframes around the pivot using pathMode: "arc"
1909
+ with pivot + arcDirection on each segment. There is no separate "orbit" mode
1910
+ — it is expressible as keyframes + arc paths.
1756
1911
 
1757
1912
  KEYFRAME PROPERTIES:
1758
1913
  - time: Time in seconds
1759
1914
  - zoom: Zoom level (1=normal, 2=2x zoom in, 0.5=zoom out)
1760
- - center: View center [x, y]
1915
+ - focus: Camera target, resolved live against the scene graph. Accepts:
1916
+ [x, y] literal position
1917
+ 'item-id' itemRegistry lookup → item bounds center (tracks the item as it moves)
1918
+ { item: 'id', offset: [dx, dy] } item center + offset
1919
+ - center: [x, y] — legacy alias, honored only when focus is absent
1920
+ - pitch: 3D tilt in degrees (0=flat, positive=tilt forward). Uses equirectangular projection
1921
+ - yaw: 3D rotation in degrees. Uses equirectangular projection
1761
1922
  - easing: Timing function (linear, easeIn, easeOut, easeInOut, bounce, elastic)
1762
1923
 
1763
- EXAMPLE:
1924
+ CURVED INTER-KEYFRAME PATHS (optional; default is linear):
1925
+ - pathOut: [dx, dy] — bezier tangent handle when LEAVING this keyframe
1926
+ - pathIn: [dx, dy] — bezier tangent handle when ARRIVING at this keyframe
1927
+ Either handle alone promotes the segment to a cubic bezier.
1928
+ - pathMode: 'arc' — arc around a pivot. Requires pivot: [x, y]; optional arcDirection: 'ccw'|'cw'
1929
+ - pathMode: 'custom' + path: 'M x y C ...' — sample any SVG path string (falls back to linear when Paper.js is unavailable)
1930
+ Endpoints always match the resolved focus of each keyframe — handles only shape the curve between them.
1931
+
1932
+ EXAMPLE (with 3D tilt):
1764
1933
  {
1765
1934
  "duration": 6,
1766
1935
  "loop": true,
1936
+ "fov": 60,
1937
+ "keyframes": [
1938
+ { "time": 0, "zoom": 1, "focus": [400, 300], "pitch": 0, "yaw": 0 },
1939
+ { "time": 2, "zoom": 2, "focus": "hero-character", "pitch": 12, "yaw": -5, "easing": "easeInOut" },
1940
+ { "time": 4, "zoom": 2, "focus": { "item": "villain", "offset": [0, -40] }, "pitch": 8, "yaw": 3, "easing": "easeOut" },
1941
+ { "time": 6, "zoom": 1, "focus": [400, 300], "pitch": 0, "yaw": 0, "easing": "easeInOut" }
1942
+ ]
1943
+ }
1944
+
1945
+ EXAMPLE (curved arc between waypoints):
1946
+ {
1947
+ "duration": 4,
1767
1948
  "keyframes": [
1768
- { "time": 0, "zoom": 1, "center": [400, 300] },
1769
- { "time": 2, "zoom": 2, "center": [400, 300], "easing": "easeInOut" },
1770
- { "time": 4, "zoom": 2, "center": [600, 300], "easing": "easeOut" },
1771
- { "time": 6, "zoom": 1, "center": [400, 300], "easing": "easeInOut" }
1949
+ { "time": 0, "zoom": 1, "focus": [200, 300], "pathOut": [120, -60] },
1950
+ { "time": 2, "zoom": 1.5, "focus": [800, 300], "pathIn": [-120, -60], "pathMode": "arc", "pivot": [500, 450], "arcDirection": "ccw" },
1951
+ { "time": 4, "zoom": 1, "focus": [200, 300] }
1772
1952
  ]
1773
1953
  }`,
1774
1954
  inputSchema: {
@@ -1782,183 +1962,111 @@ EXAMPLE:
1782
1962
  properties: {
1783
1963
  time: { type: 'number', description: 'Time in seconds' },
1784
1964
  zoom: { type: 'number', description: 'Zoom level (1=normal, 2=2x zoom in)' },
1965
+ focus: {
1966
+ description: 'Camera target, resolved live against the scene graph. Accepts [x, y], an item id string, or { item: "id", offset: [dx, dy] }. Takes precedence over center.',
1967
+ },
1785
1968
  center: {
1786
1969
  type: 'array',
1787
1970
  items: { type: 'number' },
1788
- description: 'View center [x, y]',
1971
+ description: 'Legacy view center [x, y] — honored only when focus is absent',
1789
1972
  },
1973
+ pitch: { type: 'number', description: '3D tilt in degrees (0=flat, positive=forward tilt)' },
1974
+ yaw: { type: 'number', description: '3D rotation in degrees' },
1790
1975
  easing: {
1791
1976
  type: 'string',
1792
1977
  enum: ['linear', 'easeIn', 'easeOut', 'easeInOut', 'bounce', 'elastic'],
1793
1978
  },
1979
+ pathOut: {
1980
+ type: 'array',
1981
+ items: { type: 'number' },
1982
+ description: 'Bezier tangent handle [dx, dy] when leaving this keyframe. Promotes segment to cubic bezier.',
1983
+ },
1984
+ pathIn: {
1985
+ type: 'array',
1986
+ items: { type: 'number' },
1987
+ description: 'Bezier tangent handle [dx, dy] when arriving at this keyframe. Promotes segment to cubic bezier.',
1988
+ },
1989
+ pathMode: {
1990
+ type: 'string',
1991
+ enum: ['arc', 'custom'],
1992
+ description: 'arc: curve around pivot (requires pivot). custom: sample an SVG path (requires path).',
1993
+ },
1994
+ pivot: {
1995
+ type: 'array',
1996
+ items: { type: 'number' },
1997
+ description: 'Arc center [x, y] when pathMode is "arc"',
1998
+ },
1999
+ arcDirection: {
2000
+ type: 'string',
2001
+ enum: ['ccw', 'cw'],
2002
+ description: 'Arc sweep direction when pathMode is "arc" (default: ccw)',
2003
+ },
2004
+ path: {
2005
+ type: 'string',
2006
+ description: 'SVG path string (e.g. "M 100 200 C 150 100 350 100 400 200") when pathMode is "custom"',
2007
+ },
1794
2008
  },
1795
2009
  },
1796
2010
  },
1797
2011
  duration: { type: 'number', description: 'Total animation duration in seconds' },
1798
2012
  loop: { type: 'boolean', description: 'Loop the animation' },
1799
2013
  delay: { type: 'number', description: 'Delay before animation starts' },
2014
+ fov: { type: 'number', description: 'Field of view in degrees for 3D perspective (default: 60)' },
1800
2015
  },
1801
2016
  required: ['keyframes', 'duration'],
1802
2017
  },
1803
2018
  },
1804
2019
  {
1805
- name: 'pinepaper_camera_zoom',
1806
- annotations: {
1807
- title: 'Camera Zoom',
1808
- readOnlyHint: false,
1809
- destructiveHint: false,
1810
- idempotentHint: false,
1811
- openWorldHint: false,
1812
- },
1813
- description: `Simple camera zoom animation.
1814
-
1815
- USE WHEN:
1816
- - Quick zoom in to focus on something
1817
- - Zoom out to show full canvas
1818
- - Simple zoom effects without complex keyframes`,
1819
- inputSchema: {
1820
- type: 'object',
1821
- properties: {
1822
- direction: {
1823
- type: 'string',
1824
- enum: ['in', 'out'],
1825
- description: 'Zoom direction',
1826
- },
1827
- level: {
1828
- type: 'number',
1829
- description: 'Target zoom level (default: 2 for in, 0.5 for out)',
1830
- },
1831
- duration: {
1832
- type: 'number',
1833
- description: 'Animation duration in seconds (default: 0.5)',
1834
- },
1835
- },
1836
- required: ['direction'],
1837
- },
1838
- },
1839
- {
1840
- name: 'pinepaper_camera_pan',
2020
+ name: 'pinepaper_camera',
1841
2021
  annotations: {
1842
- title: 'Camera Pan',
2022
+ title: 'Camera Control',
1843
2023
  readOnlyHint: false,
1844
2024
  destructiveHint: false,
1845
2025
  idempotentHint: false,
1846
2026
  openWorldHint: false,
1847
2027
  },
1848
- description: `Pan camera in a direction or to specific coordinates.
2028
+ description: `Camera control: zoom, pan, move, reset, stop, get state. Single action-dispatched tool replaces six thin wrappers. For keyframe walkthroughs / 3D pitch+yaw / curved paths, use pinepaper_camera_animate (a separate, richer tool).
1849
2029
 
1850
- USE WHEN:
1851
- - Moving view to different part of canvas
1852
- - Directional panning (left, right, up, down)
1853
- - Centering on specific coordinates
2030
+ ACTIONS:
2031
+ - zoom — { direction: "in"|"out", level?: number, duration?: number }
2032
+ level defaults to 2 (in) or 0.5 (out). duration default 0.5s.
2033
+ - pan — { direction?: "left"|"right"|"up"|"down", amount?: number, x?: number, y?: number, duration?: number }
2034
+ Either direction+amount (default 100px) OR x+y for panTo.
2035
+ - move_to — { x, y, zoom, duration?: number }
2036
+ Combined zoom + pan in one motion.
2037
+ - reset — { duration?: number }
2038
+ Back to center + zoom 1.
2039
+ - stop — {}
2040
+ Cancel any active animation.
2041
+ - state — {}
2042
+ Returns { zoom, center, isAnimating }.
1854
2043
 
1855
2044
  EXAMPLES:
1856
- // Pan left 200 pixels
1857
- { "direction": "left", "amount": 200 }
1858
-
1859
- // Pan to specific coordinates
1860
- { "x": 200, "y": 200, "duration": 1 }`,
2045
+ { action: "zoom", direction: "in", level: 2.5 }
2046
+ { action: "pan", x: 200, y: 200, duration: 1 }
2047
+ { action: "move_to", x: 600, y: 400, zoom: 2 }
2048
+ { action: "reset" }
2049
+ { action: "state" }`,
1861
2050
  inputSchema: {
1862
2051
  type: 'object',
1863
2052
  properties: {
1864
- direction: {
2053
+ action: {
1865
2054
  type: 'string',
1866
- enum: ['left', 'right', 'up', 'down'],
1867
- description: 'Pan direction (use with amount)',
1868
- },
1869
- amount: {
1870
- type: 'number',
1871
- description: 'Pixels to pan (default: 100)',
2055
+ enum: ['zoom', 'pan', 'move_to', 'reset', 'stop', 'state'],
2056
+ description: 'Camera action to perform',
1872
2057
  },
1873
- x: {
1874
- type: 'number',
1875
- description: 'Target X coordinate (use with y for panTo)',
1876
- },
1877
- y: {
1878
- type: 'number',
1879
- description: 'Target Y coordinate (use with x for panTo)',
1880
- },
1881
- duration: {
1882
- type: 'number',
1883
- description: 'Animation duration in seconds (default: 0.5)',
1884
- },
1885
- },
1886
- },
1887
- },
1888
- {
1889
- name: 'pinepaper_camera_move_to',
1890
- annotations: {
1891
- title: 'Camera Move To',
1892
- readOnlyHint: false,
1893
- destructiveHint: false,
1894
- idempotentHint: false,
1895
- openWorldHint: false,
1896
- },
1897
- description: `Combined camera zoom and pan to a specific location.
1898
-
1899
- USE WHEN:
1900
- - Moving to and zooming on a specific point in one motion
1901
- - Focusing on an item with appropriate zoom level`,
1902
- inputSchema: {
1903
- type: 'object',
1904
- properties: {
1905
- x: { type: 'number', description: 'Target X coordinate' },
1906
- y: { type: 'number', description: 'Target Y coordinate' },
1907
- zoom: { type: 'number', description: 'Target zoom level' },
1908
- duration: { type: 'number', description: 'Animation duration in seconds (default: 0.5)' },
1909
- },
1910
- required: ['x', 'y', 'zoom'],
1911
- },
1912
- },
1913
- {
1914
- name: 'pinepaper_camera_reset',
1915
- annotations: {
1916
- title: 'Camera Reset',
1917
- readOnlyHint: false,
1918
- destructiveHint: false,
1919
- idempotentHint: false,
1920
- openWorldHint: false,
1921
- },
1922
- description: `Reset camera to default state (center of canvas, zoom 1).
1923
-
1924
- USE WHEN:
1925
- - Returning to default view after camera movements
1926
- - Resetting before starting new sequence`,
1927
- inputSchema: {
1928
- type: 'object',
1929
- properties: {
1930
- duration: { type: 'number', description: 'Animation duration in seconds (default: 0.5)' },
2058
+ direction: {
2059
+ type: 'string',
2060
+ description: 'For zoom: "in"|"out". For pan: "left"|"right"|"up"|"down".',
2061
+ },
2062
+ level: { type: 'number', description: 'Zoom level (zoom action; default 2 for in, 0.5 for out)' },
2063
+ amount: { type: 'number', description: 'Pixels to pan (pan action with direction; default 100)' },
2064
+ x: { type: 'number', description: 'Target X coordinate (pan with x+y, or move_to)' },
2065
+ y: { type: 'number', description: 'Target Y coordinate (pan with x+y, or move_to)' },
2066
+ zoom: { type: 'number', description: 'Target zoom level (move_to)' },
2067
+ duration: { type: 'number', description: 'Animation duration in seconds (default 0.5)' },
1931
2068
  },
1932
- },
1933
- },
1934
- {
1935
- name: 'pinepaper_camera_stop',
1936
- annotations: {
1937
- title: 'Camera Stop',
1938
- readOnlyHint: false,
1939
- destructiveHint: false,
1940
- idempotentHint: true,
1941
- openWorldHint: false,
1942
- },
1943
- description: `Stop current camera animation.`,
1944
- inputSchema: {
1945
- type: 'object',
1946
- properties: {},
1947
- },
1948
- },
1949
- {
1950
- name: 'pinepaper_camera_state',
1951
- annotations: {
1952
- title: 'Camera State',
1953
- readOnlyHint: true,
1954
- destructiveHint: false,
1955
- idempotentHint: true,
1956
- openWorldHint: false,
1957
- },
1958
- description: `Get current camera state (zoom level, center position, animation status).`,
1959
- inputSchema: {
1960
- type: 'object',
1961
- properties: {},
2069
+ required: ['action'],
1962
2070
  },
1963
2071
  },
1964
2072
  // ---------------------------------------------------------------------------
@@ -2026,7 +2134,7 @@ EXAMPLE - Bouncing Balls:
2026
2134
  }
2027
2135
 
2028
2136
  SUPPORTED ITEM TYPES: text, circle, star, rectangle, triangle, polygon, ellipse, path, line, arc
2029
- SUPPORTED RELATIONS: orbits, follows, attached_to, maintains_distance, points_at, mirrors, parallax, bounds_to, animates, grows_from, staggered_with, indicates, circumscribes, wave_through, camera_follows, camera_animates, morphs_to
2137
+ SUPPORTED RELATIONS: orbits, follows, attached_to, maintains_distance, points_at, mirrors, parallax, bounds_to, animates, grows_from, staggered_with, indicates, circumscribes, wave_through, camera_follows, camera_animates, morphs_to, group_morphs_to, moves_along_path
2030
2138
  SUPPORTED ANIMATIONS: pulse, rotate, bounce, fade, wobble, slide, typewriter`,
2031
2139
  inputSchema: {
2032
2140
  type: 'object',
@@ -2072,7 +2180,7 @@ SUPPORTED ANIMATIONS: pulse, rotate, bounce, fade, wobble, slide, typewriter`,
2072
2180
  target: { type: 'string', description: 'Name of target item' },
2073
2181
  type: {
2074
2182
  type: 'string',
2075
- enum: ['orbits', 'follows', 'attached_to', 'maintains_distance', 'points_at', 'mirrors', 'parallax', 'bounds_to', 'animates', 'grows_from', 'staggered_with', 'indicates', 'circumscribes', 'wave_through', 'camera_follows', 'camera_animates', 'morphs_to'],
2183
+ enum: ['orbits', 'follows', 'attached_to', 'maintains_distance', 'points_at', 'mirrors', 'parallax', 'bounds_to', 'animates', 'grows_from', 'staggered_with', 'indicates', 'circumscribes', 'wave_through', 'camera_follows', 'camera_animates', 'morphs_to', 'group_morphs_to', 'moves_along_path'],
2076
2184
  },
2077
2185
  params: {
2078
2186
  type: 'object',
@@ -2121,2152 +2229,1670 @@ SUPPORTED ANIMATIONS: pulse, rotate, bounce, fade, wobble, slide, typewriter`,
2121
2229
  required: ['items'],
2122
2230
  },
2123
2231
  },
2124
- // ---------------------------------------------------------------------------
2125
- // LAYER 5 — BLUEPRINTS: TEMPLATE TOOLS
2126
- // ---------------------------------------------------------------------------
2232
+ // --- Scene Management ---
2127
2233
  {
2128
- name: 'pinepaper_apply_template',
2234
+ name: 'pinepaper_manage_scenes',
2129
2235
  annotations: {
2130
- title: 'Apply Template',
2236
+ title: 'Manage Scenes',
2131
2237
  readOnlyHint: false,
2132
- destructiveHint: true,
2238
+ destructiveHint: false,
2133
2239
  idempotentHint: false,
2134
2240
  openWorldHint: false,
2135
2241
  },
2136
- description: `Load a pre-built template design onto the canvas, or list available templates.
2242
+ description: `Manage multiple saved scenes (canvas snapshots). Save, load, organize, and transfer scenes for multi-scene storyboards and presentations.
2137
2243
 
2138
- USE WHEN:
2139
- - User wants to start from a pre-made design
2140
- - User asks for a template, preset, or starter layout
2141
- - User wants to see what templates are available
2142
- - Need a quick starting point for social media, presentations, etc.
2143
-
2144
- ⚠️ DESTRUCTIVE: Loading a template replaces the current canvas content.
2145
-
2146
- MODES:
2147
- 1. LIST MODE: Set listOnly: true (or omit templateId) to browse available templates
2148
- - Optionally filter by category
2149
- 2. LOAD MODE: Provide a templateId to apply that template
2150
-
2151
- TEMPLATE CATEGORIES (13):
2152
- - social-media: Social media post/story layouts
2153
- - meme: Meme templates and formats
2154
- - business: Business cards, letterheads, presentations
2155
- - education: Educational diagrams, worksheets
2156
- - creative: Artistic and creative compositions
2157
- - tech: Technology-themed designs
2158
- - global: International and multicultural designs
2159
- - indigenous: Indigenous art-inspired patterns
2160
- - seasonal: Holiday and seasonal themes
2161
- - masking: Mask reveal effect demonstrations
2162
- - scenes: Pre-built animated scenes
2163
- - diagrams: Flowchart and diagram starters
2164
- - maps: Geographic visualization templates
2165
-
2166
- EXAMPLES:
2167
- - List all templates: { "listOnly": true }
2168
- - List by category: { "category": "social-media", "listOnly": true }
2169
- - Load template: { "templateId": "solar-system" }`,
2244
+ ACTIONS:
2245
+ - save: Save current canvas state as a named scene. Params: name (string)
2246
+ - load: Load a saved scene onto canvas. Params: sceneId, transition (none|fade|zoom-in|zoom-out)
2247
+ - list: List all saved scenes with metadata
2248
+ - delete: Delete a scene. Params: sceneId
2249
+ - rename: Rename a scene. Params: sceneId, name
2250
+ - duplicate: Clone a scene. Params: sceneId
2251
+ - reorder: Reorder scenes. Params: sceneIds (ordered array)
2252
+ - info: Get scene details. Params: sceneId
2253
+ - export: Export all scenes as JSON
2254
+ - import: Import scenes from JSON. Params: scenesJson, merge (boolean)
2255
+
2256
+ WORKFLOW — Multi-Scene Storyboard:
2257
+ 1. Create your first scene → save(name: "Intro")
2258
+ 2. Clear canvas, create second scene → save(name: "Chapter 1")
2259
+ 3. Repeat for all scenes
2260
+ 4. Use pinepaper_scene_playback to play them as a slideshow`,
2170
2261
  inputSchema: {
2171
2262
  type: 'object',
2172
2263
  properties: {
2173
- templateId: {
2264
+ action: {
2174
2265
  type: 'string',
2175
- description: 'Template ID to load (omit to list templates)',
2266
+ enum: ['save', 'load', 'list', 'delete', 'rename', 'duplicate', 'reorder', 'info', 'export', 'import'],
2267
+ description: 'Scene management action',
2176
2268
  },
2177
- category: {
2269
+ name: { type: 'string', description: 'Scene name (for save, rename)' },
2270
+ sceneId: { type: 'string', description: 'Scene identifier (for load, delete, rename, duplicate, info)' },
2271
+ transition: {
2178
2272
  type: 'string',
2179
- enum: ['social-media', 'meme', 'business', 'education', 'creative', 'tech', 'global', 'indigenous', 'seasonal', 'masking', 'scenes', 'diagrams', 'maps'],
2180
- description: 'Filter templates by category',
2273
+ enum: ['none', 'fade', 'zoom-in', 'zoom-out'],
2274
+ description: 'Transition effect when loading a scene',
2181
2275
  },
2182
- listOnly: {
2183
- type: 'boolean',
2184
- description: 'If true, only list available templates without loading (default: false)',
2276
+ sceneIds: {
2277
+ type: 'array',
2278
+ items: { type: 'string' },
2279
+ description: 'Ordered array of scene IDs (for reorder)',
2185
2280
  },
2281
+ scenesJson: { type: 'string', description: 'JSON string of scenes to import' },
2282
+ merge: { type: 'boolean', description: 'Merge with existing scenes on import (default: replace)' },
2186
2283
  },
2284
+ required: ['action'],
2187
2285
  },
2188
2286
  },
2189
- // ---------------------------------------------------------------------------
2190
- // DOMAIN: DIAGRAM TOOLS
2191
- // ---------------------------------------------------------------------------
2192
2287
  {
2193
- name: 'pinepaper_create_diagram_shape',
2288
+ name: 'pinepaper_scene_playback',
2194
2289
  annotations: {
2195
- title: 'Create Diagram Shape',
2290
+ title: 'Scene Playback',
2196
2291
  readOnlyHint: false,
2197
2292
  destructiveHint: false,
2198
2293
  idempotentHint: false,
2199
2294
  openWorldHint: false,
2200
2295
  },
2201
- description: `Create a diagram shape on the canvas. Diagram shapes are specialized shapes for flowcharts, UML diagrams, network diagrams, and similar technical drawings.
2202
-
2203
- USE WHEN:
2204
- - Creating flowcharts, process diagrams, or workflows
2205
- - Building UML class diagrams, use case diagrams, or sequence diagrams
2206
- - Designing network topology diagrams
2207
- - Making organizational charts or decision trees
2208
- - Any technical or architectural diagram
2209
-
2210
- SHAPE TYPES:
2296
+ description: `Control sequential scene chain playback — play saved scenes as a slideshow presentation.
2211
2297
 
2212
- Flowchart shapes:
2213
- - process: Rectangle for process steps (default: 120x60)
2214
- - decision: Diamond for yes/no decisions (default: 100x100)
2215
- - terminal: Rounded rectangle for start/end (default: 120x40)
2216
- - data: Parallelogram for data I/O (default: 120x60)
2217
- - document: Wavy-bottom rectangle for documents (default: 100x80)
2218
- - database: Cylinder for database/storage (default: 80x100)
2219
- - preparation: Hexagon for preparation steps (default: 120x60)
2220
-
2221
- UML shapes:
2222
- - uml-class: Class box with name/attributes/methods sections (default: 150x120)
2223
- - uml-usecase: Ellipse for use case (default: 140x80)
2224
- - uml-actor: Stick figure for actor (default: 60x100)
2225
-
2226
- Network shapes:
2227
- - cloud: Cloud shape for cloud services (default: 140x90)
2228
- - server: Server rack shape (default: 80x100)
2229
-
2230
- Basic shapes (same as pinepaper_create_item but diagram-optimized):
2231
- - rectangle, circle, triangle, star
2232
-
2233
- All shapes:
2234
- - Have connection ports for connectors
2235
- - Support labels inside the shape
2236
- - Can be connected using pinepaper_connect or pinepaper_connect_ports
2237
-
2238
- EXAMPLES:
2239
- - Flowchart start: {shapeType: "terminal", label: "Start", position: {x: 400, y: 100}}
2240
- - Decision node: {shapeType: "decision", label: "Is valid?", position: {x: 400, y: 200}}
2241
- - Database: {shapeType: "database", label: "Users DB", position: {x: 600, y: 200}}
2242
- - UML Class: {shapeType: "uml-class", label: "User", width: 180, height: 150}
2243
-
2244
- WORKFLOW TIP:
2245
- After creating shapes, use pinepaper_connect to draw connectors between them.
2246
- Use pinepaper_auto_layout to automatically arrange shapes in a clean layout.`,
2298
+ ACTIONS:
2299
+ - create_chain: Create a playback chain from scene IDs. Params: sceneIds (array), loop (bool), autoPlay (bool), defaultDuration (seconds), defaultTransition (none|fade|zoom-in|zoom-out), transitionDuration (seconds)
2300
+ - play: Start playing the chain
2301
+ - pause: Pause playback
2302
+ - resume: Resume paused playback
2303
+ - stop: Stop playback and reset
2304
+ - toggle_loop: Enable/disable looping. Params: enabled (bool)
2305
+ - jump: Jump to specific scene index. Params: index (0-based)
2306
+
2307
+ NOTE: defaultDuration and transitionDuration are in SECONDS (converted to ms internally).
2308
+
2309
+ EXAMPLE — Slideshow:
2310
+ 1. Save 3 scenes with pinepaper_manage_scenes
2311
+ 2. create_chain with sceneIds, defaultDuration: 5, loop: true
2312
+ 3. play`,
2247
2313
  inputSchema: {
2248
2314
  type: 'object',
2249
2315
  properties: {
2250
- shapeType: {
2316
+ action: {
2251
2317
  type: 'string',
2252
- enum: ['process', 'decision', 'terminal', 'data', 'document', 'database', 'preparation', 'uml-class', 'uml-usecase', 'uml-actor', 'cloud', 'server', 'rectangle', 'circle', 'triangle', 'star'],
2253
- description: 'Type of diagram shape to create',
2254
- },
2255
- position: {
2256
- type: 'object',
2257
- properties: {
2258
- x: { type: 'number', description: 'X coordinate (default: 400)' },
2259
- y: { type: 'number', description: 'Y coordinate (default: 300)' },
2260
- },
2261
- description: 'Position on canvas',
2262
- },
2263
- width: {
2264
- type: 'number',
2265
- description: 'Shape width in pixels (uses type-specific default if not specified)',
2318
+ enum: ['create_chain', 'play', 'pause', 'resume', 'stop', 'toggle_loop', 'jump'],
2319
+ description: 'Playback control action',
2266
2320
  },
2267
- height: {
2268
- type: 'number',
2269
- description: 'Shape height in pixels (uses type-specific default if not specified)',
2321
+ sceneIds: {
2322
+ type: 'array',
2323
+ items: { type: 'string' },
2324
+ description: 'Scene IDs for the chain (create_chain)',
2270
2325
  },
2271
- label: {
2326
+ loop: { type: 'boolean', description: 'Loop the chain (create_chain)' },
2327
+ autoPlay: { type: 'boolean', description: 'Start playing immediately (create_chain)' },
2328
+ defaultDuration: { type: 'number', description: 'Duration per scene in seconds (create_chain)' },
2329
+ defaultTransition: {
2272
2330
  type: 'string',
2273
- description: 'Text label inside the shape',
2274
- },
2275
- style: {
2276
- type: 'object',
2277
- properties: {
2278
- fillColor: { type: 'string', description: 'Fill color' },
2279
- strokeColor: { type: 'string', description: 'Stroke color' },
2280
- strokeWidth: { type: 'number', description: 'Stroke width' },
2281
- },
2282
- description: 'Visual styling options',
2331
+ enum: ['none', 'fade', 'zoom-in', 'zoom-out'],
2332
+ description: 'Default transition between scenes',
2283
2333
  },
2334
+ transitionDuration: { type: 'number', description: 'Transition duration in seconds (create_chain)' },
2335
+ enabled: { type: 'boolean', description: 'Enable/disable loop (toggle_loop)' },
2336
+ index: { type: 'number', description: '0-based scene index (jump)' },
2284
2337
  },
2285
- required: ['shapeType'],
2338
+ required: ['action'],
2286
2339
  },
2287
2340
  },
2341
+ // ---------------------------------------------------------------------------
2342
+ // LAYER 4 — COMPOSITIONS: SELECTION, TRANSFORM & HISTORY TOOLS
2343
+ // ---------------------------------------------------------------------------
2288
2344
  {
2289
- name: 'pinepaper_connect',
2345
+ name: 'pinepaper_selection',
2290
2346
  annotations: {
2291
- title: 'Connect Items',
2347
+ title: 'Selection',
2292
2348
  readOnlyHint: false,
2293
- destructiveHint: false,
2349
+ destructiveHint: true,
2294
2350
  idempotentHint: false,
2295
2351
  openWorldHint: false,
2296
2352
  },
2297
- description: `Connect two items with a smart connector. This is the primary way to draw lines/arrows between diagram shapes.
2298
-
2299
- USE WHEN:
2300
- - Drawing arrows between flowchart steps
2301
- - Connecting UML classes with associations
2302
- - Creating network connections between nodes
2303
- - Any diagram that needs lines/arrows between elements
2304
-
2305
- CONNECTOR FEATURES:
2306
- - Automatic port selection (finds nearest ports)
2307
- - Smart routing to avoid overlapping shapes
2308
- - Animated "bolt" effect for data flow visualization
2309
- - Arrow heads on either or both ends
2310
- - Labels on connectors
2311
-
2312
- ROUTING TYPES:
2313
- - orthogonal: Right-angle turns only (default, best for flowcharts)
2314
- - direct: Straight line between points
2315
- - curved: Bezier curve with adjustable curvature
2316
-
2317
- ARROW STYLES:
2318
- - classic: Standard filled arrow (default for head)
2319
- - stealth: Narrow sharp arrow
2320
- - sharp: Simple pointed arrow
2321
- - open: Outline arrow (not filled)
2322
- - diamond: Diamond shape (for UML aggregation)
2323
- - circle: Circle (for UML composition)
2324
- - none: No arrowhead (default for tail)
2325
-
2326
- LINE STYLES:
2327
- - solid: Continuous line (default)
2328
- - dashed: Dashed line (for optional relationships)
2329
- - dotted: Dotted line (for dependencies)
2330
-
2331
- ANIMATED BOLT:
2332
- Enable boltEnabled: true to show an animated particle traveling along the connector.
2333
- Useful for showing data flow, process direction, or network traffic.
2334
-
2335
- EXAMPLES:
2336
- - Simple arrow: {sourceItemId: "shape_1", targetItemId: "shape_2"}
2337
- - Curved line: {sourceItemId: "a", targetItemId: "b", routing: "curved", curvature: 0.7}
2338
- - Dashed dependency: {sourceItemId: "a", targetItemId: "b", lineStyle: "dashed", headStyle: "open"}
2339
- - Two-way arrow: {sourceItemId: "a", targetItemId: "b", headStyle: "classic", tailStyle: "classic"}
2340
- - Labeled connection: {sourceItemId: "a", targetItemId: "b", label: "1..*"}
2353
+ description: `Manage item selection on canvas.
2341
2354
 
2342
- RETURNS:
2343
- - connectorId: ID of the connector (use for updates/removal)
2344
- - sourceItemId, targetItemId: Connected items`,
2355
+ ACTIONS:
2356
+ - select: Select items by ID. Params: itemIds (string[]), mode (replace|add|remove)
2357
+ - select_all: Select all items on canvas
2358
+ - deselect_all: Clear selection
2359
+ - get: Get currently selected items with bounds
2360
+ - delete_selected: Delete all selected items`,
2345
2361
  inputSchema: {
2346
2362
  type: 'object',
2347
2363
  properties: {
2348
- sourceItemId: {
2349
- type: 'string',
2350
- description: 'Registry ID of the source item (where arrow starts)',
2351
- },
2352
- targetItemId: {
2353
- type: 'string',
2354
- description: 'Registry ID of the target item (where arrow points)',
2355
- },
2356
- routing: {
2357
- type: 'string',
2358
- enum: ['direct', 'orthogonal', 'curved'],
2359
- description: 'Connector routing style (default: orthogonal)',
2360
- },
2361
- lineColor: {
2362
- type: 'string',
2363
- description: 'Line color (default: #4B5563)',
2364
- },
2365
- lineWidth: {
2366
- type: 'number',
2367
- description: 'Line width in pixels (default: 2)',
2368
- },
2369
- lineStyle: {
2370
- type: 'string',
2371
- enum: ['solid', 'dashed', 'dotted'],
2372
- description: 'Line style (default: solid)',
2373
- },
2374
- headStyle: {
2375
- type: 'string',
2376
- enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'],
2377
- description: 'Arrow head style at target (default: classic)',
2378
- },
2379
- tailStyle: {
2380
- type: 'string',
2381
- enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'],
2382
- description: 'Arrow style at source (default: none)',
2383
- },
2384
- label: {
2364
+ action: {
2385
2365
  type: 'string',
2386
- description: 'Text label on the connector',
2387
- },
2388
- curvature: {
2389
- type: 'number',
2390
- description: 'Curve intensity for curved routing (0.1-1.0, default: 0.5)',
2366
+ enum: ['select', 'select_all', 'deselect_all', 'get', 'delete_selected'],
2367
+ description: 'Selection action',
2391
2368
  },
2392
- boltEnabled: {
2393
- type: 'boolean',
2394
- description: 'Enable animated bolt effect (default: true)',
2369
+ itemIds: {
2370
+ type: 'array',
2371
+ items: { type: 'string' },
2372
+ description: 'Item IDs to select (for select action)',
2395
2373
  },
2396
- boltColor: {
2374
+ mode: {
2397
2375
  type: 'string',
2398
- description: 'Bolt animation color (default: #fbbf24)',
2376
+ enum: ['replace', 'add', 'remove'],
2377
+ description: 'Selection mode: replace (default), add to, or remove from current selection',
2399
2378
  },
2400
2379
  },
2401
- required: ['sourceItemId', 'targetItemId'],
2380
+ required: ['action'],
2402
2381
  },
2403
2382
  },
2404
2383
  {
2405
- name: 'pinepaper_connect_ports',
2384
+ name: 'pinepaper_transform',
2406
2385
  annotations: {
2407
- title: 'Connect Specific Ports',
2386
+ title: 'Transform',
2408
2387
  readOnlyHint: false,
2409
2388
  destructiveHint: false,
2410
2389
  idempotentHint: false,
2411
2390
  openWorldHint: false,
2412
2391
  },
2413
- description: `Connect two specific ports on items. Use this when you need precise control over which ports the connector attaches to.
2414
-
2415
- USE WHEN:
2416
- - Need connector to attach to specific side of shape
2417
- - Creating complex diagrams where automatic port selection isn't ideal
2418
- - Building circuit-like diagrams with specific entry/exit points
2419
- - Connecting specific input/output ports
2420
-
2421
- PORT POSITIONS:
2422
- Standard positions:
2423
- - top, bottom, left, right: Center of each edge
2424
- - top-left, top-right, bottom-left, bottom-right: Corners
2425
- - center: Center of the shape
2426
-
2427
- Line/path specific:
2428
- - start: Beginning of path
2429
- - end: End of path
2430
-
2431
- EXAMPLES:
2432
- - Top to bottom: {sourceItemId: "a", sourcePort: "bottom", targetItemId: "b", targetPort: "top"}
2433
- - Left to right: {sourceItemId: "a", sourcePort: "right", targetItemId: "b", targetPort: "left"}
2434
- - Corner connection: {sourceItemId: "a", sourcePort: "bottom-right", targetItemId: "b", targetPort: "top-left"}
2392
+ description: `Transform items: nudge position, flip, or change z-order.
2435
2393
 
2436
- CONFIG OPTIONS:
2437
- Same as pinepaper_connect: routing, lineColor, lineWidth, lineStyle, headStyle, tailStyle, label, curvature, boltEnabled, boltColor`,
2394
+ ACTIONS:
2395
+ - nudge: Move item by dx/dy offset. Params: itemId, dx, dy
2396
+ - flip: Mirror item. Params: itemId, direction (horizontal|vertical)
2397
+ - reorder: Change z-order. Params: itemId, order (bringToFront|sendToBack|moveUp|moveDown)`,
2438
2398
  inputSchema: {
2439
2399
  type: 'object',
2440
2400
  properties: {
2441
- sourceItemId: {
2401
+ action: {
2442
2402
  type: 'string',
2443
- description: 'Registry ID of the source item',
2403
+ enum: ['nudge', 'flip', 'reorder'],
2404
+ description: 'Transform action',
2444
2405
  },
2445
- sourcePort: {
2406
+ itemId: { type: 'string', description: 'Target item ID' },
2407
+ dx: { type: 'number', description: 'Horizontal offset (for nudge)' },
2408
+ dy: { type: 'number', description: 'Vertical offset (for nudge)' },
2409
+ direction: {
2446
2410
  type: 'string',
2447
- enum: ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'center', 'start', 'end'],
2448
- description: 'Port position on source item',
2411
+ enum: ['horizontal', 'vertical'],
2412
+ description: 'Flip direction',
2449
2413
  },
2450
- targetItemId: {
2414
+ order: {
2451
2415
  type: 'string',
2452
- description: 'Registry ID of the target item',
2416
+ enum: ['bringToFront', 'sendToBack', 'moveUp', 'moveDown'],
2417
+ description: 'Z-order operation',
2453
2418
  },
2454
- targetPort: {
2419
+ },
2420
+ required: ['action'],
2421
+ },
2422
+ },
2423
+ {
2424
+ name: 'pinepaper_history',
2425
+ annotations: {
2426
+ title: 'History',
2427
+ readOnlyHint: false,
2428
+ destructiveHint: false,
2429
+ idempotentHint: false,
2430
+ openWorldHint: false,
2431
+ },
2432
+ description: `Undo/redo and history state inspection.
2433
+
2434
+ ACTIONS:
2435
+ - undo: Undo last canvas action
2436
+ - redo: Redo last undone action
2437
+ - get_state: Get history stack state (canUndo, canRedo, count)`,
2438
+ inputSchema: {
2439
+ type: 'object',
2440
+ properties: {
2441
+ action: {
2455
2442
  type: 'string',
2456
- enum: ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'center', 'start', 'end'],
2457
- description: 'Port position on target item',
2458
- },
2459
- config: {
2460
- type: 'object',
2461
- properties: {
2462
- routing: { type: 'string', enum: ['direct', 'orthogonal', 'curved'] },
2463
- lineColor: { type: 'string' },
2464
- lineWidth: { type: 'number' },
2465
- lineStyle: { type: 'string', enum: ['solid', 'dashed', 'dotted'] },
2466
- headStyle: { type: 'string', enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'] },
2467
- tailStyle: { type: 'string', enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'] },
2468
- label: { type: 'string' },
2469
- curvature: { type: 'number' },
2470
- boltEnabled: { type: 'boolean' },
2471
- boltColor: { type: 'string' },
2472
- },
2473
- description: 'Connector configuration options',
2443
+ enum: ['undo', 'redo', 'get_state'],
2444
+ description: 'History action',
2474
2445
  },
2475
2446
  },
2476
- required: ['sourceItemId', 'sourcePort', 'targetItemId', 'targetPort'],
2447
+ required: ['action'],
2477
2448
  },
2478
2449
  },
2450
+ // ---------------------------------------------------------------------------
2451
+ // LAYER 4 — COMPOSITIONS: IMAGE PROCESSING TOOLS
2452
+ // ---------------------------------------------------------------------------
2479
2453
  {
2480
- name: 'pinepaper_add_ports',
2454
+ name: 'pinepaper_image_filter',
2481
2455
  annotations: {
2482
- title: 'Add Ports to Item',
2456
+ title: 'Image Filter',
2483
2457
  readOnlyHint: false,
2484
2458
  destructiveHint: false,
2485
2459
  idempotentHint: false,
2486
2460
  openWorldHint: false,
2487
2461
  },
2488
- description: `Add connection ports to an existing item. Ports are anchor points where connectors can attach.
2462
+ description: `Apply GPU-accelerated image filters to raster items.
2489
2463
 
2490
- USE WHEN:
2491
- - Adding custom port positions to shapes
2492
- - Enabling connections on items that don't have ports
2493
- - Creating specialized connection points for complex diagrams
2494
-
2495
- PORT TYPES:
2496
- - standard: Standard 4 ports (top, bottom, left, right)
2497
- - line: 2 ports (start, end) for line-like items
2498
- - path: N ports distributed along a path
2499
- - custom: User-defined port positions
2500
-
2501
- CUSTOM PORTS:
2502
- Define specific ports with position and type:
2503
- - position: where on the item (top, bottom, left, right, corners)
2504
- - type: input (accept incoming), output (start outgoing), or both
2464
+ ACTIONS:
2465
+ - apply: Apply a single filter. Params: itemId, filterName, params
2466
+ - chain: Apply multiple filters in sequence. Params: itemId, filters (array of {name, params})
2505
2467
 
2506
- EXAMPLES:
2507
- - Standard 4 ports: {itemId: "shape_1", portType: "standard"}
2508
- - Line endpoints: {itemId: "line_1", portType: "line"}
2509
- - Path with 5 ports: {itemId: "path_1", portType: "path", count: 5}
2510
- - Custom ports: {itemId: "shape_1", portType: "custom", ports: [{position: "top", type: "input"}, {position: "bottom", type: "output"}]}`,
2468
+ Available filters: blur, brightness, contrast, saturate, grayscale, sepia, invert, hue-rotate, sharpen, emboss, edge-detect.`,
2511
2469
  inputSchema: {
2512
2470
  type: 'object',
2513
2471
  properties: {
2514
- itemId: {
2472
+ action: {
2515
2473
  type: 'string',
2516
- description: 'Registry ID of the item to add ports to',
2474
+ enum: ['apply', 'chain'],
2475
+ description: 'Filter action',
2517
2476
  },
2518
- portType: {
2519
- type: 'string',
2520
- enum: ['standard', 'line', 'path', 'custom'],
2521
- description: 'Type of port configuration (default: standard)',
2477
+ itemId: { type: 'string', description: 'Target raster item ID' },
2478
+ filterName: { type: 'string', description: 'Filter name (for apply)' },
2479
+ params: {
2480
+ type: 'object',
2481
+ description: 'Filter parameters (e.g. {amount: 5} for blur)',
2522
2482
  },
2523
- ports: {
2483
+ filters: {
2524
2484
  type: 'array',
2525
2485
  items: {
2526
2486
  type: 'object',
2527
2487
  properties: {
2528
- position: {
2529
- type: 'string',
2530
- enum: ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'center', 'start', 'end'],
2531
- },
2532
- type: {
2533
- type: 'string',
2534
- enum: ['input', 'output', 'both'],
2535
- },
2488
+ name: { type: 'string' },
2489
+ params: { type: 'object' },
2536
2490
  },
2491
+ required: ['name'],
2537
2492
  },
2538
- description: 'Custom port definitions (for portType: "custom")',
2539
- },
2540
- count: {
2541
- type: 'number',
2542
- description: 'Number of ports for path type',
2493
+ description: 'Filter chain (for chain action)',
2543
2494
  },
2544
2495
  },
2545
- required: ['itemId'],
2496
+ required: ['action', 'itemId'],
2546
2497
  },
2547
2498
  },
2548
2499
  {
2549
- name: 'pinepaper_auto_layout',
2500
+ name: 'pinepaper_lasso',
2550
2501
  annotations: {
2551
- title: 'Auto Layout',
2502
+ title: 'Lasso',
2552
2503
  readOnlyHint: false,
2553
2504
  destructiveHint: false,
2554
2505
  idempotentHint: false,
2555
2506
  openWorldHint: false,
2556
2507
  },
2557
- description: `Automatically arrange diagram items using a layout algorithm. This reorganizes items for cleaner, more readable diagrams.
2558
-
2559
- USE WHEN:
2560
- - Diagram items are messy or overlapping
2561
- - Want to create a professional-looking layout automatically
2562
- - After adding many items, need to organize them
2563
- - Creating hierarchical structures (org charts, trees)
2564
-
2565
- LAYOUT TYPES:
2566
-
2567
- hierarchical:
2568
- - Best for: flowcharts, org charts, dependency graphs
2569
- - Arranges items in levels from top to bottom (or other directions)
2570
- - Respects connector direction for parent-child relationships
2571
- - Options: direction (TB/BT/LR/RL), levelSpacing, nodeSpacing
2572
-
2573
- force-directed:
2574
- - Best for: network diagrams, relationship graphs
2575
- - Uses physics simulation (attraction/repulsion)
2576
- - Good for showing clusters and relationships
2577
- - Options: iterations, attraction, repulsion
2578
-
2579
- tree:
2580
- - Best for: hierarchies, file systems, family trees
2581
- - Similar to hierarchical but optimized for tree structures
2582
- - Options: direction, levelSpacing, nodeSpacing
2583
-
2584
- radial:
2585
- - Best for: mind maps, hub-and-spoke diagrams
2586
- - Places items in concentric circles around a center
2587
- - Options: centerX, centerY, startRadius, radiusStep
2588
-
2589
- grid:
2590
- - Best for: equal-importance items, component libraries
2591
- - Arranges items in rows and columns
2592
- - Options: columns, cellWidth, cellHeight
2508
+ description: `Freeform lasso selection for image items.
2593
2509
 
2594
- ANIMATION:
2595
- By default, items animate smoothly to their new positions.
2596
- Set animate: false for instant repositioning.
2597
-
2598
- EXAMPLES:
2599
- - Flowchart layout: {layoutType: "hierarchical", options: {direction: "TB", levelSpacing: 100}}
2600
- - Network diagram: {layoutType: "force-directed", options: {iterations: 200, repulsion: 2000}}
2601
- - Mind map: {layoutType: "radial", options: {centerX: 400, centerY: 300}}
2602
- - Grid of icons: {layoutType: "grid", options: {columns: 4, cellWidth: 120}}
2603
-
2604
- PARTIAL LAYOUT:
2605
- Pass itemIds array to only layout specific items, leaving others in place.`,
2510
+ ACTIONS:
2511
+ - activate: Start lasso mode on an image item. Params: itemId
2512
+ - apply: Confirm and apply the lasso selection`,
2606
2513
  inputSchema: {
2607
2514
  type: 'object',
2608
2515
  properties: {
2609
- layoutType: {
2516
+ action: {
2610
2517
  type: 'string',
2611
- enum: ['hierarchical', 'force-directed', 'tree', 'radial', 'grid'],
2612
- description: 'Layout algorithm to use',
2613
- },
2614
- itemIds: {
2615
- type: 'array',
2616
- items: { type: 'string' },
2617
- description: 'Specific items to layout (default: all diagram items)',
2618
- },
2619
- options: {
2620
- type: 'object',
2621
- properties: {
2622
- direction: {
2623
- type: 'string',
2624
- enum: ['TB', 'BT', 'LR', 'RL'],
2625
- description: 'Layout direction (TB=top-to-bottom, LR=left-to-right, etc.)',
2626
- },
2627
- levelSpacing: {
2628
- type: 'number',
2629
- description: 'Vertical spacing between levels (default: 100)',
2630
- },
2631
- nodeSpacing: {
2632
- type: 'number',
2633
- description: 'Horizontal spacing between nodes (default: 80)',
2634
- },
2635
- iterations: {
2636
- type: 'number',
2637
- description: 'Iterations for force-directed layout (default: 100)',
2638
- },
2639
- attraction: {
2640
- type: 'number',
2641
- description: 'Attraction force for connected nodes (default: 0.01)',
2642
- },
2643
- repulsion: {
2644
- type: 'number',
2645
- description: 'Repulsion force between all nodes (default: 1000)',
2646
- },
2647
- columns: {
2648
- type: 'number',
2649
- description: 'Number of columns for grid layout',
2650
- },
2651
- cellWidth: {
2652
- type: 'number',
2653
- description: 'Cell width for grid layout (default: 150)',
2654
- },
2655
- cellHeight: {
2656
- type: 'number',
2657
- description: 'Cell height for grid layout (default: 100)',
2658
- },
2659
- centerX: {
2660
- type: 'number',
2661
- description: 'Center X for radial layout',
2662
- },
2663
- centerY: {
2664
- type: 'number',
2665
- description: 'Center Y for radial layout',
2666
- },
2667
- startRadius: {
2668
- type: 'number',
2669
- description: 'Starting radius for radial layout (default: 100)',
2670
- },
2671
- radiusStep: {
2672
- type: 'number',
2673
- description: 'Radius increment per level for radial layout (default: 80)',
2674
- },
2675
- animate: {
2676
- type: 'boolean',
2677
- description: 'Animate transition to new positions (default: true)',
2678
- },
2679
- animationDuration: {
2680
- type: 'number',
2681
- description: 'Animation duration in ms (default: 300)',
2682
- },
2683
- },
2684
- description: 'Layout-specific options',
2518
+ enum: ['activate', 'apply'],
2519
+ description: 'Lasso action',
2685
2520
  },
2521
+ itemId: { type: 'string', description: 'Target image item ID (for activate)' },
2686
2522
  },
2687
- required: ['layoutType'],
2523
+ required: ['action'],
2688
2524
  },
2689
2525
  },
2690
2526
  {
2691
- name: 'pinepaper_get_diagram_shapes',
2527
+ name: 'pinepaper_cutout_style',
2692
2528
  annotations: {
2693
- title: 'Get Diagram Shapes',
2694
- readOnlyHint: true,
2529
+ title: 'Cutout Style',
2530
+ readOnlyHint: false,
2695
2531
  destructiveHint: false,
2696
- idempotentHint: true,
2532
+ idempotentHint: false,
2697
2533
  openWorldHint: false,
2698
2534
  },
2699
- description: `[Utility] Get a list of available diagram shapes with their properties.
2700
-
2701
- USE WHEN:
2702
- - Need to see what diagram shapes are available
2703
- - Want to know default sizes and styling for shapes
2704
- - Building dynamic UI that shows shape options
2705
-
2706
- CATEGORIES:
2707
- - flowchart: process, decision, terminal, data, document, database, preparation
2708
- - uml: uml-class, uml-usecase, uml-actor
2709
- - network: cloud, server
2710
- - basic: rectangle, circle, triangle, star
2535
+ description: `Apply decorative cutout styles to image items (sticker effects, torn edges, etc.).
2711
2536
 
2712
- RETURNS:
2713
- Array of shape definitions including:
2714
- - name: Shape identifier
2715
- - category: Category it belongs to
2716
- - defaultWidth, defaultHeight: Default dimensions
2717
- - defaultStyle: Default colors and stroke
2718
- - description: What the shape represents`,
2537
+ ACTIONS:
2538
+ - apply: Apply a cutout preset. Params: itemId, preset, options
2539
+ - list: List available cutout style presets`,
2719
2540
  inputSchema: {
2720
2541
  type: 'object',
2721
2542
  properties: {
2722
- category: {
2543
+ action: {
2723
2544
  type: 'string',
2724
- enum: ['flowchart', 'uml', 'network', 'basic'],
2725
- description: 'Filter by category (optional - returns all if not specified)',
2545
+ enum: ['apply', 'list'],
2546
+ description: 'Cutout style action',
2726
2547
  },
2548
+ itemId: { type: 'string', description: 'Target image item ID (for apply)' },
2549
+ preset: { type: 'string', description: 'Cutout style preset name' },
2550
+ options: { type: 'object', description: 'Additional style options' },
2727
2551
  },
2552
+ required: ['action'],
2728
2553
  },
2729
2554
  },
2555
+ // ---------------------------------------------------------------------------
2556
+ // LAYER 4 — COMPOSITIONS: PRECOMP, VIEW & BACKGROUND TOOLS
2557
+ // ---------------------------------------------------------------------------
2730
2558
  {
2731
- name: 'pinepaper_update_connector',
2559
+ name: 'pinepaper_precomp',
2732
2560
  annotations: {
2733
- title: 'Update Connector',
2561
+ title: 'Precomp',
2734
2562
  readOnlyHint: false,
2735
2563
  destructiveHint: false,
2736
- idempotentHint: true,
2564
+ idempotentHint: false,
2737
2565
  openWorldHint: false,
2738
2566
  },
2739
- description: `Update the style or label of an existing connector.
2740
-
2741
- USE WHEN:
2742
- - Changing connector appearance after creation
2743
- - Updating connector labels
2744
- - Changing arrow styles or colors
2745
-
2746
- UPDATABLE PROPERTIES:
2747
- - style: lineColor, lineWidth, headStyle, tailStyle, routing, lineStyle
2748
- - label: Text label on the connector
2749
- - labelPosition: Position along path (0-1, where 0.5 is middle)
2567
+ description: `Nested compositions — group items into reusable animated precomps.
2750
2568
 
2751
- EXAMPLES:
2752
- - Change color: {connectorId: "conn_1", style: {lineColor: "#ef4444"}}
2753
- - Add label: {connectorId: "conn_1", label: "data flow"}
2754
- - Change to dashed: {connectorId: "conn_1", style: {lineStyle: "dashed"}}
2755
- - Move label: {connectorId: "conn_1", labelPosition: 0.25}`,
2569
+ ACTIONS:
2570
+ - create: Create precomp from items. Params: itemIds (string[]), name, loop (bool), duration (seconds)
2571
+ - add: Add item to existing precomp. Params: precompId, itemId
2572
+ - remove: Remove item from precomp. Params: precompId, itemId`,
2756
2573
  inputSchema: {
2757
2574
  type: 'object',
2758
2575
  properties: {
2759
- connectorId: {
2760
- type: 'string',
2761
- description: 'ID of the connector to update',
2762
- },
2763
- style: {
2764
- type: 'object',
2765
- properties: {
2766
- lineColor: { type: 'string' },
2767
- lineWidth: { type: 'number' },
2768
- headStyle: { type: 'string', enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'] },
2769
- tailStyle: { type: 'string', enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'] },
2770
- routing: { type: 'string', enum: ['direct', 'orthogonal', 'curved'] },
2771
- lineStyle: { type: 'string', enum: ['solid', 'dashed', 'dotted'] },
2772
- },
2773
- description: 'Style properties to update',
2774
- },
2775
- label: {
2576
+ action: {
2776
2577
  type: 'string',
2777
- description: 'New label text',
2578
+ enum: ['create', 'add', 'remove'],
2579
+ description: 'Precomp action',
2778
2580
  },
2779
- labelPosition: {
2780
- type: 'number',
2781
- description: 'Label position along path (0-1)',
2581
+ itemIds: {
2582
+ type: 'array',
2583
+ items: { type: 'string' },
2584
+ description: 'Item IDs to group (for create)',
2782
2585
  },
2586
+ name: { type: 'string', description: 'Precomp name' },
2587
+ loop: { type: 'boolean', description: 'Loop precomp animation' },
2588
+ duration: { type: 'number', description: 'Precomp duration in seconds' },
2589
+ precompId: { type: 'string', description: 'Target precomp ID (for add/remove)' },
2590
+ itemId: { type: 'string', description: 'Item to add/remove' },
2783
2591
  },
2784
- required: ['connectorId'],
2592
+ required: ['action'],
2785
2593
  },
2786
2594
  },
2787
2595
  {
2788
- name: 'pinepaper_remove_connector',
2596
+ name: 'pinepaper_view',
2789
2597
  annotations: {
2790
- title: 'Remove Connector',
2598
+ title: 'View',
2791
2599
  readOnlyHint: false,
2792
- destructiveHint: true,
2793
- idempotentHint: true,
2600
+ destructiveHint: false,
2601
+ idempotentHint: false,
2794
2602
  openWorldHint: false,
2795
2603
  },
2796
- description: `Remove a connector from the canvas.
2604
+ description: `View control — fit view to content or get current view state.
2797
2605
 
2798
- USE WHEN:
2799
- - Deleting a connection between items
2800
- - Removing incorrect links
2801
- - Restructuring diagram connections`,
2606
+ ACTIONS:
2607
+ - fit: Fit view to content or canvas bounds. Params: mode (content|canvas), padding (number)
2608
+ - get_state: Get current view state (zoom, center, bounds)`,
2802
2609
  inputSchema: {
2803
2610
  type: 'object',
2804
2611
  properties: {
2805
- connectorId: {
2612
+ action: {
2806
2613
  type: 'string',
2807
- description: 'ID of the connector to remove',
2614
+ enum: ['fit', 'get_state'],
2615
+ description: 'View action',
2616
+ },
2617
+ mode: {
2618
+ type: 'string',
2619
+ enum: ['content', 'canvas'],
2620
+ description: 'Fit mode (for fit action)',
2808
2621
  },
2622
+ padding: { type: 'number', description: 'Padding around content in pixels (default: 20)' },
2809
2623
  },
2810
- required: ['connectorId'],
2624
+ required: ['action'],
2811
2625
  },
2812
2626
  },
2813
2627
  {
2814
- name: 'pinepaper_diagram_mode',
2628
+ name: 'pinepaper_background',
2815
2629
  annotations: {
2816
- title: 'Diagram Mode',
2630
+ title: 'Background',
2817
2631
  readOnlyHint: false,
2818
2632
  destructiveHint: false,
2819
- idempotentHint: true,
2633
+ idempotentHint: false,
2820
2634
  openWorldHint: false,
2821
2635
  },
2822
- description: `Control the diagram mode for interactive editing.
2823
-
2824
- USE WHEN:
2825
- - Switching between drawing and selection modes
2826
- - Enabling/disabling diagram-specific UI
2827
- - Setting up the canvas for diagram creation
2636
+ description: `Set, clear, or query the canvas background.
2828
2637
 
2829
2638
  ACTIONS:
2830
- - activate: Enable diagram mode (shows grid, snap, port indicators)
2831
- - deactivate: Return to normal canvas mode
2832
- - toggle: Switch between diagram and normal mode
2833
- - setMode: Set specific tool mode (select, connect, shape, pan)
2834
-
2835
- TOOL MODES (for setMode action):
2836
- - select: Selection and moving items
2837
- - connect: Drawing connectors between items
2838
- - shape: Drawing new shapes (optionally specify shapeType)
2839
- - pan: Panning the canvas
2840
-
2841
- EXAMPLES:
2842
- - Enter diagram mode: {action: "activate"}
2843
- - Exit diagram mode: {action: "deactivate"}
2844
- - Set to connect mode: {action: "setMode", mode: "connect"}
2845
- - Set to draw rectangles: {action: "setMode", mode: "shape", shapeType: "process"}`,
2639
+ - set: Set background. Params: mode (color|pattern|generator), color, pattern, generator, generatorParams
2640
+ - clear: Remove background entirely
2641
+ - get: Get current background settings`,
2846
2642
  inputSchema: {
2847
2643
  type: 'object',
2848
2644
  properties: {
2849
2645
  action: {
2850
2646
  type: 'string',
2851
- enum: ['activate', 'deactivate', 'toggle', 'setMode'],
2852
- description: 'Action to perform',
2647
+ enum: ['set', 'clear', 'get'],
2648
+ description: 'Background action',
2853
2649
  },
2854
2650
  mode: {
2855
2651
  type: 'string',
2856
- enum: ['select', 'connect', 'shape', 'pan'],
2857
- description: 'Tool mode (for setMode action)',
2858
- },
2859
- shapeType: {
2860
- type: 'string',
2861
- enum: ['process', 'decision', 'terminal', 'data', 'document', 'database', 'preparation', 'uml-class', 'uml-usecase', 'uml-actor', 'cloud', 'server', 'rectangle', 'circle', 'triangle', 'star'],
2862
- description: 'Shape type for shape mode',
2652
+ enum: ['color', 'pattern', 'generator'],
2653
+ description: 'Background type (for set)',
2863
2654
  },
2655
+ color: { type: 'string', description: 'Hex color (for color mode)' },
2656
+ pattern: { type: 'string', description: 'Pattern name (for pattern mode)' },
2657
+ generator: { type: 'string', description: 'Generator name (for generator mode)' },
2658
+ generatorParams: { type: 'object', description: 'Generator parameters' },
2864
2659
  },
2865
2660
  required: ['action'],
2866
2661
  },
2867
2662
  },
2868
2663
  // ---------------------------------------------------------------------------
2869
- // DOMAIN: MAP TOOLS
2664
+ // LAYER 4 — COMPOSITIONS: CANVAS QUERY TOOLS
2870
2665
  // ---------------------------------------------------------------------------
2871
2666
  {
2872
- name: 'pinepaper_load_map',
2667
+ name: 'pinepaper_query',
2873
2668
  annotations: {
2874
- title: 'Load Map',
2875
- readOnlyHint: false,
2669
+ title: 'Canvas Query',
2670
+ readOnlyHint: true,
2876
2671
  destructiveHint: false,
2877
- idempotentHint: false,
2672
+ idempotentHint: true,
2878
2673
  openWorldHint: false,
2879
2674
  },
2880
- description: `Load a geographic map onto the canvas with specified projection and styling.
2881
-
2882
- USE WHEN:
2883
- - Creating world maps or country visualizations
2884
- - Building choropleth data visualizations
2885
- - Making infographics with geographic data
2886
- - Creating animated map reveals
2887
-
2888
- AVAILABLE MAPS:
2889
- - world: World countries (110m resolution, faster)
2890
- - worldHighRes: World countries (50m resolution, more detailed)
2891
- - usa: US states map
2892
-
2893
- PROJECTIONS:
2894
- - naturalEarth: Natural Earth projection (recommended for world maps)
2895
- - mercator: Standard web mercator
2896
- - equalEarth: Equal-area projection
2897
- - orthographic: Globe/3D sphere view
2898
- - albers: Conic projection (good for USA)
2899
- - stereographic: Stereographic projection
2900
-
2901
- QUALITY SETTINGS:
2902
- - fast: Aggressive simplification (prototyping)
2903
- - balanced: Moderate detail (most uses)
2904
- - professional: No simplification (publications)
2905
-
2906
- EXAMPLES:
2907
- - World map: {mapId: "world", projection: "naturalEarth", quality: "balanced"}
2908
- - USA map: {mapId: "usa", projection: "albers", quality: "professional"}
2909
- - Globe view: {mapId: "worldHighRes", projection: "orthographic", rotate: [0, -30, 0]}
2675
+ description: `Query canvas items and spatial information.
2910
2676
 
2911
- RETURNS:
2912
- - mapId: Reference ID for the loaded map
2913
- - group: Paper.js group containing all regions
2914
- - regions: Array of region info
2915
- - bounds: Map bounding box`,
2677
+ ACTIONS:
2678
+ - get_by_id: Get detailed item info. Params: itemId
2679
+ - hit_test: Find items at coordinates. Params: x, y, tolerance, all (bool)
2680
+ - is_empty: Check if canvas has any items`,
2916
2681
  inputSchema: {
2917
2682
  type: 'object',
2918
2683
  properties: {
2919
- mapId: {
2920
- type: 'string',
2921
- enum: ['world', 'worldHighRes', 'usa'],
2922
- description: 'Map to load (world=110m, worldHighRes=50m professional quality, usa=US states)',
2923
- },
2924
- projection: {
2925
- type: 'string',
2926
- enum: ['mercator', 'equalEarth', 'naturalEarth', 'orthographic', 'albers', 'stereographic'],
2927
- description: 'Map projection type',
2928
- },
2929
- quality: {
2684
+ action: {
2930
2685
  type: 'string',
2931
- enum: ['fast', 'balanced', 'professional'],
2932
- description: 'Rendering quality (professional=no simplification)',
2933
- },
2934
- fillColor: { type: 'string', description: 'Default fill color for regions' },
2935
- strokeColor: { type: 'string', description: 'Border/stroke color' },
2936
- strokeWidth: { type: 'number', description: 'Border width in pixels' },
2937
- scale: { type: 'number', description: 'Scale multiplier' },
2938
- center: {
2939
- type: 'array',
2940
- items: { type: 'number' },
2941
- description: 'Center coordinates [longitude, latitude]',
2942
- },
2943
- rotate: {
2944
- type: 'array',
2945
- items: { type: 'number' },
2946
- description: 'Rotation angles [x, y, z]',
2947
- },
2948
- enableHover: { type: 'boolean', description: 'Enable hover effects on regions' },
2949
- enableClick: { type: 'boolean', description: 'Enable click events on regions' },
2950
- hoverFill: { type: 'string', description: 'Fill color on hover' },
2951
- hoverStroke: { type: 'string', description: 'Stroke color on hover' },
2686
+ enum: ['get_by_id', 'hit_test', 'is_empty'],
2687
+ description: 'Query action',
2688
+ },
2689
+ itemId: { type: 'string', description: 'Item ID (for get_by_id)' },
2690
+ x: { type: 'number', description: 'X coordinate (for hit_test)' },
2691
+ y: { type: 'number', description: 'Y coordinate (for hit_test)' },
2692
+ all: { type: 'boolean', description: 'Return all hits (default: first only)' },
2693
+ tolerance: { type: 'number', description: 'Hit test tolerance in pixels (default: 5)' },
2952
2694
  },
2953
- required: ['mapId'],
2695
+ required: ['action'],
2954
2696
  },
2955
2697
  },
2698
+ // ---------------------------------------------------------------------------
2699
+ // DEFORMATION, SPRITE SHEETS, STORAGE, INTERACTION
2700
+ // ---------------------------------------------------------------------------
2956
2701
  {
2957
- name: 'pinepaper_highlight_regions',
2702
+ name: 'pinepaper_deform',
2958
2703
  annotations: {
2959
- title: 'Highlight Regions',
2704
+ title: 'Deformation',
2960
2705
  readOnlyHint: false,
2961
2706
  destructiveHint: false,
2962
- idempotentHint: true,
2707
+ idempotentHint: false,
2963
2708
  openWorldHint: false,
2964
2709
  },
2965
- description: `Highlight specific regions on a loaded map with custom styling.
2966
-
2967
- USE WHEN:
2968
- - Emphasizing specific countries or states
2969
- - Creating interactive map highlights
2970
- - Building step-by-step map reveals
2971
- - Showing geographic data points
2710
+ description: `Apply vertex deformation presets to items for organic motion effects.
2972
2711
 
2973
- REGION ID FORMATS:
2974
- - World maps: Full country names ("United States of America", "France", "Japan")
2975
- - USA map: State codes ("CA", "TX", "NY", "FL")
2712
+ ACTIONS:
2713
+ - apply: Apply looping deformation. Params: itemId, preset, frequency, amplitude (0-1), phase, loop, axis, turns, waves, maxDisplacement, speed, steps
2714
+ - trigger: One-shot deformation (auto-removes). Params: itemId, preset, amplitude, speed
2715
+ - remove: Restore original geometry. Params: itemId
2976
2716
 
2977
- STYLING OPTIONS:
2978
- - fillColor: Highlight fill color
2979
- - strokeColor: Highlight stroke color
2980
- - strokeWidth: Border width for highlighted regions
2981
- - animate: Whether to animate the highlight transition
2717
+ PRESETS: fold, squeeze, squash, pinch, bulge, twist, ripple, wave, breathe, melt, shear, inflate, wobble
2982
2718
 
2983
- EXAMPLES:
2984
- - Highlight countries: {regionIds: ["United States of America", "Canada", "Mexico"], options: {fillColor: "#3b82f6"}}
2985
- - Highlight US states: {regionIds: ["CA", "TX", "NY"], options: {fillColor: "#22c55e", animate: true}}
2986
- - Custom styling: {regionIds: ["Japan"], options: {fillColor: "#ef4444", strokeColor: "#dc2626", strokeWidth: 2}}`,
2719
+ PHASES: sin, blink, linear, pingpong, once, elastic, heartbeat, stepped`,
2987
2720
  inputSchema: {
2988
2721
  type: 'object',
2989
2722
  properties: {
2990
- regionIds: {
2991
- type: 'array',
2992
- items: { type: 'string' },
2993
- description: 'Array of region IDs to highlight (country names or state codes)',
2723
+ action: {
2724
+ type: 'string',
2725
+ enum: ['apply', 'trigger', 'remove'],
2726
+ description: 'Deformation action',
2994
2727
  },
2995
- options: {
2996
- type: 'object',
2997
- properties: {
2998
- fillColor: { type: 'string', description: 'Highlight fill color' },
2999
- strokeColor: { type: 'string', description: 'Highlight stroke color' },
3000
- strokeWidth: { type: 'number', description: 'Highlight stroke width' },
3001
- animate: { type: 'boolean', description: 'Animate the highlight transition' },
3002
- },
3003
- description: 'Highlight styling options',
2728
+ itemId: { type: 'string', description: 'Target item ID' },
2729
+ preset: {
2730
+ type: 'string',
2731
+ enum: ['fold', 'squeeze', 'squash', 'pinch', 'bulge', 'twist', 'ripple', 'wave', 'breathe', 'melt', 'shear', 'inflate', 'wobble'],
2732
+ description: 'Deformation preset name',
3004
2733
  },
2734
+ frequency: { type: 'number', description: 'Oscillation speed (default: 1)' },
2735
+ amplitude: { type: 'number', description: 'Deformation strength 0-1 (default: 1)' },
2736
+ phase: {
2737
+ type: 'string',
2738
+ enum: ['sin', 'blink', 'linear', 'pingpong', 'once', 'elastic', 'heartbeat', 'stepped'],
2739
+ description: 'Phase driver for animation timing',
2740
+ },
2741
+ loop: { type: 'boolean', description: 'Loop the deformation (default: true)' },
2742
+ axis: { type: 'string', enum: ['horizontal', 'vertical'], description: 'Axis for fold/wave presets' },
2743
+ turns: { type: 'number', description: 'Rotation amount for twist preset' },
2744
+ waves: { type: 'number', description: 'Wave count for ripple/wave presets' },
2745
+ maxDisplacement: { type: 'number', description: 'Maximum displacement in pixels' },
2746
+ speed: { type: 'number', description: 'Animation speed multiplier' },
2747
+ steps: { type: 'number', description: 'Quantization levels for stepped phase' },
3005
2748
  },
3006
- required: ['regionIds'],
2749
+ required: ['action'],
3007
2750
  },
3008
2751
  },
3009
2752
  {
3010
- name: 'pinepaper_unhighlight_regions',
2753
+ name: 'pinepaper_sprite_sheet',
3011
2754
  annotations: {
3012
- title: 'Unhighlight Regions',
2755
+ title: 'Sprite Sheet',
3013
2756
  readOnlyHint: false,
3014
2757
  destructiveHint: false,
3015
- idempotentHint: true,
2758
+ idempotentHint: false,
3016
2759
  openWorldHint: false,
3017
2760
  },
3018
- description: `Remove highlights from specific regions or all regions on the map.
2761
+ description: `Generate, play, and export sprite sheets from skeleton poses.
3019
2762
 
3020
- USE WHEN:
3021
- - Resetting map to original state
3022
- - Removing specific region highlights
3023
- - Cycling through different highlight states
3024
-
3025
- EXAMPLES:
3026
- - Remove all highlights: {regionIds: "all"}
3027
- - Remove specific: {regionIds: ["CA", "TX"]}`,
2763
+ ACTIONS:
2764
+ - generate: Create sprite sheet from skeleton. Params: skeletonId, poses, transition, bakedAnimation, animations, padding, name
2765
+ - play: Play sprite animation on canvas. Params: spriteSheetId, x, y, animation, fps, scale
2766
+ - export: Export sprite sheet as image + metadata. Params: spriteSheetId, format (png|webp)`,
3028
2767
  inputSchema: {
3029
2768
  type: 'object',
3030
2769
  properties: {
3031
- regionIds: {
3032
- oneOf: [
3033
- { type: 'array', items: { type: 'string' } },
3034
- { type: 'string', enum: ['all'] },
3035
- ],
3036
- description: 'Region IDs to unhighlight, or "all" for all regions',
2770
+ action: {
2771
+ type: 'string',
2772
+ enum: ['generate', 'play', 'export'],
2773
+ description: 'Sprite sheet action',
3037
2774
  },
3038
- },
3039
- required: ['regionIds'],
3040
- },
3041
- },
3042
- {
3043
- name: 'pinepaper_apply_data_colors',
3044
- annotations: {
3045
- title: 'Apply Data Colors',
3046
- readOnlyHint: false,
3047
- destructiveHint: false,
3048
- idempotentHint: true,
3049
- openWorldHint: false,
3050
- },
3051
- description: `Apply data-driven coloring to map regions (choropleth visualization).
3052
-
3053
- USE WHEN:
3054
- - Visualizing statistics by region (population, GDP, etc.)
3055
- - Creating heat maps
3056
- - Showing data distribution across geography
3057
- - Building infographics with data overlays
3058
-
3059
- COLOR SCALES:
3060
- - blues: Light to dark blue gradient
3061
- - greens: Light to dark green gradient
3062
- - reds: Light to dark red gradient
3063
- - oranges: Light to dark orange gradient
3064
- - purples: Light to dark purple gradient
3065
- - heat: Yellow to red heat map gradient
3066
-
3067
- DATA FORMAT:
3068
- Keys must match region IDs exactly (country names for world maps, state codes for USA).
3069
-
3070
- EXAMPLES:
3071
- - Population data: {data: {"California": 39538223, "Texas": 29145505, "New York": 20201249}, options: {colorScale: "blues", showLegend: true}}
3072
- - GDP heat map: {data: {"United States of America": 21000, "China": 15000, "Japan": 5000}, options: {colorScale: "heat"}}
3073
- - Custom range: {data: {"CA": 85, "TX": 72}, options: {colorScale: "greens", minValue: 0, maxValue: 100}}`,
3074
- inputSchema: {
3075
- type: 'object',
3076
- properties: {
3077
- data: {
2775
+ skeletonId: { type: 'string', description: 'Skeleton ID (for generate)' },
2776
+ spriteSheetId: { type: 'string', description: 'Sprite sheet ID (for play/export)' },
2777
+ name: { type: 'string', description: 'Sheet name' },
2778
+ poses: {
2779
+ type: 'array',
2780
+ items: { type: 'object', properties: { name: { type: 'string' }, poseId: { type: 'string' } }, required: ['name', 'poseId'] },
2781
+ description: 'Explicit pose list',
2782
+ },
2783
+ transition: {
3078
2784
  type: 'object',
3079
- additionalProperties: { type: 'number' },
3080
- description: 'Object mapping region IDs to numeric values',
2785
+ properties: { poseIdA: { type: 'string' }, poseIdB: { type: 'string' }, frameCount: { type: 'number' }, name: { type: 'string' } },
2786
+ description: 'Interpolate between two poses',
3081
2787
  },
3082
- options: {
2788
+ bakedAnimation: {
3083
2789
  type: 'object',
3084
- properties: {
3085
- colorScale: {
3086
- type: 'string',
3087
- enum: ['blues', 'greens', 'reds', 'oranges', 'purples', 'heat'],
3088
- description: 'Color scale to use',
3089
- },
3090
- minValue: { type: 'number', description: 'Minimum value for scale' },
3091
- maxValue: { type: 'number', description: 'Maximum value for scale' },
3092
- showLegend: { type: 'boolean', description: 'Display color legend' },
3093
- legendPosition: {
3094
- type: 'string',
3095
- enum: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
3096
- description: 'Legend position',
3097
- },
3098
- legendTitle: { type: 'string', description: 'Title for the legend' },
3099
- },
3100
- description: 'Choropleth styling options',
2790
+ properties: { duration: { type: 'number' }, fps: { type: 'number' }, name: { type: 'string' } },
2791
+ description: 'Bake timeline animation into frames',
3101
2792
  },
2793
+ animations: {
2794
+ type: 'object',
2795
+ additionalProperties: { type: 'object', properties: { frames: { type: 'array', items: { type: 'string' } }, fps: { type: 'number' }, loop: { type: 'boolean' } } },
2796
+ description: 'Animation definitions mapping name to frame sequences',
2797
+ },
2798
+ padding: { type: 'number', description: 'Padding between frames (default: 1)' },
2799
+ x: { type: 'number', description: 'X position for playback' },
2800
+ y: { type: 'number', description: 'Y position for playback' },
2801
+ animation: { type: 'string', description: 'Animation name to play' },
2802
+ fps: { type: 'number', description: 'Frame rate (default: 12)' },
2803
+ scale: { type: 'number', description: 'Scale factor (default: 1)' },
2804
+ format: { type: 'string', enum: ['png', 'webp'], description: 'Export format (default: png)' },
3102
2805
  },
3103
- required: ['data'],
2806
+ required: ['action'],
3104
2807
  },
3105
2808
  },
3106
2809
  {
3107
- name: 'pinepaper_add_marker',
2810
+ name: 'pinepaper_storage',
3108
2811
  annotations: {
3109
- title: 'Add Map Marker',
2812
+ title: 'Storage',
3110
2813
  readOnlyHint: false,
3111
- destructiveHint: false,
2814
+ destructiveHint: true,
3112
2815
  idempotentHint: false,
3113
2816
  openWorldHint: false,
3114
2817
  },
3115
- description: `Add a marker to the map at specified coordinates.
2818
+ description: `Persistent project storage via IndexedDB.
3116
2819
 
3117
- USE WHEN:
3118
- - Marking cities or points of interest
3119
- - Creating location-based visualizations
3120
- - Adding data points with geographic coordinates
3121
- - Building interactive map annotations
3122
-
3123
- MARKER OPTIONS:
3124
- - lat, lon: Geographic coordinates (required)
3125
- - label: Text label for the marker
3126
- - color: Marker color
3127
- - size: Marker size in pixels
3128
- - pulse: Enable animated pulse effect
3129
- - shape: Marker shape (circle, pin, star)
3130
-
3131
- EXAMPLES:
3132
- - City marker: {lat: 37.7749, lon: -122.4194, label: "San Francisco", color: "#ef4444", pulse: true}
3133
- - Simple point: {lat: 40.7128, lon: -74.0060, size: 8, color: "#3b82f6"}
3134
- - Pin marker: {lat: 51.5074, lon: -0.1278, label: "London", shape: "pin"}`,
2820
+ ACTIONS:
2821
+ - save: Save current project. Params: name, thumbnail (bool)
2822
+ - load: Load project onto canvas. Params: projectId
2823
+ - list: List all saved projects
2824
+ - delete: Delete a saved project. Params: projectId`,
3135
2825
  inputSchema: {
3136
2826
  type: 'object',
3137
2827
  properties: {
3138
- lat: { type: 'number', description: 'Latitude' },
3139
- lon: { type: 'number', description: 'Longitude' },
3140
- label: { type: 'string', description: 'Marker label text' },
3141
- color: { type: 'string', description: 'Marker color' },
3142
- size: { type: 'number', description: 'Marker size in pixels' },
3143
- pulse: { type: 'boolean', description: 'Enable pulse animation' },
3144
- shape: {
2828
+ action: {
3145
2829
  type: 'string',
3146
- enum: ['circle', 'pin', 'star'],
3147
- description: 'Marker shape',
2830
+ enum: ['save', 'load', 'list', 'delete'],
2831
+ description: 'Storage action',
3148
2832
  },
2833
+ projectId: { type: 'string', description: 'Project ID (for load/delete)' },
2834
+ name: { type: 'string', description: 'Project name (for save)' },
2835
+ thumbnail: { type: 'boolean', description: 'Auto-capture thumbnail on save' },
3149
2836
  },
3150
- required: ['lat', 'lon'],
2837
+ required: ['action'],
3151
2838
  },
3152
2839
  },
3153
2840
  {
3154
- name: 'pinepaper_add_map_labels',
2841
+ name: 'pinepaper_interaction',
3155
2842
  annotations: {
3156
- title: 'Add Map Labels',
2843
+ title: 'Interaction',
3157
2844
  readOnlyHint: false,
3158
2845
  destructiveHint: false,
3159
- idempotentHint: true,
2846
+ idempotentHint: false,
3160
2847
  openWorldHint: false,
3161
2848
  },
3162
- description: `Add text labels to map regions.
2849
+ description: `Add continuous physics behaviors and trigger interaction actions.
3163
2850
 
3164
- USE WHEN:
3165
- - Labeling countries or states
3166
- - Adding region names to visualizations
3167
- - Creating annotated maps
3168
- - Showing data values on regions
2851
+ ACTIONS:
2852
+ - add_behavior: Attach a continuous behavior. Params: itemId, behaviorType, params
2853
+ - remove_behavior: Remove a behavior. Params: itemId, behaviorId
2854
+ - trigger_action: Fire an interaction action. Params: actionType, params
2855
+ - get_state: Get interaction state (score, progress, step)
3169
2856
 
3170
- LABEL TYPES:
3171
- - name: Full region name
3172
- - code: Region code (e.g., "CA" for California)
3173
- - value: Data value (if applyDataColors was used)
2857
+ BEHAVIOR TYPES: repel, attract, follow, orbit, slingshot, physics_body, draggable_constrained
3174
2858
 
3175
- EXAMPLES:
3176
- - Label all visible: {options: {fontSize: 10, fontColor: "#374151"}}
3177
- - Label specific regions: {regions: ["California", "Texas"], options: {labelType: "code"}}
3178
- - Show data values: {options: {labelType: "value", fontSize: 12}}`,
2859
+ ACTION TYPES: navigate, show, hide, animate, stopAnimation, setState, incrementScore, playTimeline, pauseTimeline, seekTimeline, showFeedback, complete`,
3179
2860
  inputSchema: {
3180
2861
  type: 'object',
3181
2862
  properties: {
3182
- regions: {
3183
- type: 'array',
3184
- items: { type: 'string' },
3185
- description: 'Specific regions to label (null for all visible)',
2863
+ action: {
2864
+ type: 'string',
2865
+ enum: ['add_behavior', 'remove_behavior', 'trigger_action', 'get_state'],
2866
+ description: 'Interaction action',
3186
2867
  },
3187
- options: {
2868
+ itemId: { type: 'string', description: 'Target item ID' },
2869
+ behaviorType: {
2870
+ type: 'string',
2871
+ enum: ['repel', 'attract', 'follow', 'orbit', 'slingshot', 'physics_body', 'draggable_constrained'],
2872
+ description: 'Continuous behavior type',
2873
+ },
2874
+ behaviorId: { type: 'string', description: 'Behavior ID (for remove_behavior)' },
2875
+ actionType: {
2876
+ type: 'string',
2877
+ enum: ['navigate', 'show', 'hide', 'animate', 'stopAnimation', 'setState', 'incrementScore', 'playTimeline', 'pauseTimeline', 'seekTimeline', 'showFeedback', 'complete'],
2878
+ description: 'Interaction action type (for trigger_action)',
2879
+ },
2880
+ params: {
3188
2881
  type: 'object',
3189
- properties: {
3190
- fontSize: { type: 'number', description: 'Label font size' },
3191
- fontColor: { type: 'string', description: 'Label text color' },
3192
- labelType: {
3193
- type: 'string',
3194
- enum: ['name', 'code', 'value'],
3195
- description: 'Type of label content',
3196
- },
3197
- backgroundColor: { type: 'string', description: 'Label background color' },
3198
- },
3199
- description: 'Label styling options',
2882
+ description: 'Action-specific or behavior-specific parameters',
3200
2883
  },
3201
2884
  },
2885
+ required: ['action'],
3202
2886
  },
3203
2887
  },
2888
+ // ---------------------------------------------------------------------------
2889
+ // WIDGET EXPORT
2890
+ // ---------------------------------------------------------------------------
3204
2891
  {
3205
- name: 'pinepaper_pan_map',
2892
+ name: 'pinepaper_export_widget',
3206
2893
  annotations: {
3207
- title: 'Pan Map',
3208
- readOnlyHint: false,
2894
+ title: 'Export Widget',
2895
+ readOnlyHint: true,
3209
2896
  destructiveHint: false,
3210
2897
  idempotentHint: true,
3211
2898
  openWorldHint: false,
3212
2899
  },
3213
- description: `Pan the map view to center on specific coordinates.
2900
+ description: `Export current scene as a PineWidget (pp:PinePaper ontology JSON v0.4.3).
3214
2901
 
3215
- USE WHEN:
3216
- - Navigating to a specific location
3217
- - Creating animated map transitions
3218
- - Focusing on a region of interest
2902
+ Returns portable scene data with items, relations, animations, masks, and interactions serialized in the pp:PinePaper semantic format. Includes embed code snippet for external sites.
3219
2903
 
3220
- EXAMPLES:
3221
- - Pan to New York: {lat: 40.7128, lon: -74.0060}
3222
- - Pan to Europe: {lat: 50, lon: 10}`,
2904
+ Params: download (bool), filename, includeInteractions (bool, default true), minify (bool)`,
3223
2905
  inputSchema: {
3224
2906
  type: 'object',
3225
2907
  properties: {
3226
- lat: { type: 'number', description: 'Target latitude' },
3227
- lon: { type: 'number', description: 'Target longitude' },
3228
- animate: { type: 'boolean', description: 'Animate the pan transition' },
3229
- duration: { type: 'number', description: 'Animation duration in seconds' },
2908
+ download: { type: 'boolean', description: 'Trigger browser download (default: false)' },
2909
+ filename: { type: 'string', description: 'Output filename (default: widget-scene.json)' },
2910
+ includeInteractions: { type: 'boolean', description: 'Include interaction triggers (default: true)' },
2911
+ minify: { type: 'boolean', description: 'Minify JSON output (default: false)' },
3230
2912
  },
3231
- required: ['lat', 'lon'],
3232
2913
  },
3233
2914
  },
3234
2915
  {
3235
- name: 'pinepaper_zoom_map',
2916
+ name: 'pinepaper_export_widget_html',
3236
2917
  annotations: {
3237
- title: 'Zoom Map',
3238
- readOnlyHint: false,
2918
+ title: 'Export Widget HTML',
2919
+ readOnlyHint: true,
3239
2920
  destructiveHint: false,
3240
2921
  idempotentHint: true,
3241
2922
  openWorldHint: false,
3242
2923
  },
3243
- description: `Set the map zoom level.
3244
-
3245
- USE WHEN:
3246
- - Zooming in on specific areas
3247
- - Creating zoom animations
3248
- - Adjusting map scale
2924
+ description: `Export current scene as a self-contained HTML page with tree-shaken PineWidget runtime.
3249
2925
 
3250
- ZOOM LEVELS:
3251
- - 1: Full view (default)
3252
- - 2-5: Moderate zoom
3253
- - 5+: Close-up view
2926
+ Generates a single HTML file (<20KB typical) with inline scene data and only the JavaScript code needed for the specific items, relations, and features used. No external dependencies.
3254
2927
 
3255
- EXAMPLES:
3256
- - Zoom in: {level: 2}
3257
- - Animated zoom: {level: 3, animate: true, duration: 1}`,
2928
+ Params: title (page title), download (bool)`,
3258
2929
  inputSchema: {
3259
2930
  type: 'object',
3260
2931
  properties: {
3261
- level: { type: 'number', description: 'Zoom level (1 = full view)' },
3262
- animate: { type: 'boolean', description: 'Animate the zoom transition' },
3263
- duration: { type: 'number', description: 'Animation duration in seconds' },
2932
+ title: { type: 'string', description: 'HTML page title (default: PinePaper Widget)' },
2933
+ download: { type: 'boolean', description: 'Trigger browser download (default: false)' },
3264
2934
  },
3265
- required: ['level'],
3266
- },
3267
- },
3268
- {
3269
- name: 'pinepaper_export_map',
3270
- annotations: {
3271
- title: 'Export Map',
3272
- readOnlyHint: true,
3273
- destructiveHint: false,
3274
- idempotentHint: true,
3275
- openWorldHint: false,
3276
- },
3277
- description: `Export the current map configuration and state.
3278
-
3279
- USE WHEN:
3280
- - Saving map state for later restoration
3281
- - Exporting map data for external use
3282
- - Creating shareable map configurations
3283
-
3284
- RETURNS:
3285
- - mapId: Current map identifier
3286
- - projection: Active projection
3287
- - regions: Region states and highlights
3288
- - markers: All added markers
3289
- - dataColors: Applied data coloring configuration`,
3290
- inputSchema: {
3291
- type: 'object',
3292
- properties: {},
3293
2935
  },
3294
2936
  },
2937
+ // ---------------------------------------------------------------------------
2938
+ // LAYER 5 — BLUEPRINTS: TEMPLATE TOOLS
2939
+ // ---------------------------------------------------------------------------
3295
2940
  {
3296
- name: 'pinepaper_import_custom_map',
2941
+ name: 'pinepaper_apply_template',
3297
2942
  annotations: {
3298
- title: 'Import Custom Map',
2943
+ title: 'Apply Template',
3299
2944
  readOnlyHint: false,
3300
- destructiveHint: false,
2945
+ destructiveHint: true,
3301
2946
  idempotentHint: false,
3302
- openWorldHint: true,
2947
+ openWorldHint: false,
3303
2948
  },
3304
- description: `Import a custom GeoJSON or TopoJSON map.
2949
+ description: `Load a pre-built template design onto the canvas, or list available templates.
3305
2950
 
3306
2951
  USE WHEN:
3307
- - Loading custom geographic boundaries
3308
- - Using detailed country/region maps from GADM
3309
- - Importing custom shapes or territories
3310
- - Working with non-standard geographic data
2952
+ - User wants to start from a pre-made design
2953
+ - User asks for a template, preset, or starter layout
2954
+ - User wants to see what templates are available
2955
+ - Need a quick starting point for social media, presentations, etc.
2956
+
2957
+ ⚠️ DESTRUCTIVE: Loading a template replaces the current canvas content.
3311
2958
 
3312
- SUPPORTED FORMATS:
3313
- - GeoJSON: Standard geographic JSON format
3314
- - TopoJSON: Compressed topology format
2959
+ MODES:
2960
+ 1. LIST MODE: Set listOnly: true (or omit templateId) to browse available templates
2961
+ - Optionally filter by category
2962
+ 2. LOAD MODE: Provide a templateId to apply that template
3315
2963
 
3316
- SOURCES:
3317
- - GADM: Detailed country subdivisions (gadm.org)
3318
- - Natural Earth: Public domain maps (naturalearthdata.com)
3319
- - Census: Official boundary files
3320
- - Custom: Your own GeoJSON files
2964
+ TEMPLATE CATEGORIES (13):
2965
+ - social-media: Social media post/story layouts
2966
+ - meme: Meme templates and formats
2967
+ - business: Business cards, letterheads, presentations
2968
+ - education: Educational diagrams, worksheets
2969
+ - creative: Artistic and creative compositions
2970
+ - tech: Technology-themed designs
2971
+ - global: International and multicultural designs
2972
+ - indigenous: Indigenous art-inspired patterns
2973
+ - seasonal: Holiday and seasonal themes
2974
+ - masking: Mask reveal effect demonstrations
2975
+ - scenes: Pre-built animated scenes
2976
+ - diagrams: Flowchart and diagram starters
2977
+ - maps: Geographic visualization templates
3321
2978
 
3322
2979
  EXAMPLES:
3323
- - Import from URL: {url: "https://example.com/custom.geojson", options: {projection: "mercator"}}
3324
- - Import GeoJSON object: {geoJson: {...}, options: {projection: "naturalEarth"}}`,
2980
+ - List all templates: { "listOnly": true }
2981
+ - List by category: { "category": "social-media", "listOnly": true }
2982
+ - Load template: { "templateId": "solar-system" }`,
3325
2983
  inputSchema: {
3326
2984
  type: 'object',
3327
2985
  properties: {
3328
- url: { type: 'string', description: 'URL to GeoJSON/TopoJSON file' },
3329
- geoJson: {
3330
- type: 'object',
3331
- description: 'GeoJSON object to import directly',
2986
+ templateId: {
2987
+ type: 'string',
2988
+ description: 'Template ID to load (omit to list templates)',
3332
2989
  },
3333
- options: {
3334
- type: 'object',
3335
- properties: {
3336
- projection: {
3337
- type: 'string',
3338
- enum: ['mercator', 'equalEarth', 'naturalEarth', 'orthographic', 'albers', 'stereographic'],
3339
- description: 'Projection to use for rendering',
3340
- },
3341
- fillColor: { type: 'string' },
3342
- strokeColor: { type: 'string' },
3343
- strokeWidth: { type: 'number' },
3344
- },
3345
- description: 'Import options',
2990
+ category: {
2991
+ type: 'string',
2992
+ enum: ['social-media', 'meme', 'business', 'education', 'creative', 'tech', 'global', 'indigenous', 'seasonal', 'masking', 'scenes', 'diagrams', 'maps'],
2993
+ description: 'Filter templates by category',
2994
+ },
2995
+ listOnly: {
2996
+ type: 'boolean',
2997
+ description: 'If true, only list available templates without loading (default: false)',
3346
2998
  },
3347
2999
  },
3348
3000
  },
3349
3001
  },
3002
+ // ---------------------------------------------------------------------------
3003
+ // DOMAIN: DIAGRAM TOOLS
3004
+ // ---------------------------------------------------------------------------
3350
3005
  {
3351
- name: 'pinepaper_get_region_at_point',
3006
+ name: 'pinepaper_create_diagram_shape',
3352
3007
  annotations: {
3353
- title: 'Get Region at Point',
3354
- readOnlyHint: true,
3008
+ title: 'Create Diagram Shape',
3009
+ readOnlyHint: false,
3355
3010
  destructiveHint: false,
3356
- idempotentHint: true,
3011
+ idempotentHint: false,
3357
3012
  openWorldHint: false,
3358
3013
  },
3359
- description: `[Utility] Get the region at a specific canvas point (hit testing).
3014
+ description: `Create a diagram shape on the canvas. Diagram shapes are specialized shapes for flowcharts, UML diagrams, network diagrams, and similar technical drawings.
3360
3015
 
3361
3016
  USE WHEN:
3362
- - Implementing click interactions
3363
- - Finding which region is at a coordinate
3364
- - Building interactive map features
3365
-
3366
- EXAMPLES:
3367
- - Check point: {x: 400, y: 300}
3017
+ - Creating flowcharts, process diagrams, or workflows
3018
+ - Building UML class diagrams, use case diagrams, or sequence diagrams
3019
+ - Designing network topology diagrams
3020
+ - Making organizational charts or decision trees
3021
+ - Any technical or architectural diagram
3368
3022
 
3369
- RETURNS:
3370
- - regionId: ID of the region at point (or null)
3371
- - regionName: Display name
3372
- - properties: Region properties from GeoJSON`,
3373
- inputSchema: {
3374
- type: 'object',
3375
- properties: {
3376
- x: { type: 'number', description: 'Canvas X coordinate' },
3377
- y: { type: 'number', description: 'Canvas Y coordinate' },
3378
- },
3379
- required: ['x', 'y'],
3380
- },
3381
- },
3382
- {
3383
- name: 'pinepaper_animate_map_regions',
3384
- annotations: {
3385
- title: 'Animate Map Regions',
3386
- readOnlyHint: false,
3387
- destructiveHint: false,
3388
- idempotentHint: false,
3389
- openWorldHint: false,
3390
- },
3391
- description: `Animate specific map regions with timeline-integrated keyframe color animations.
3023
+ SHAPE TYPES:
3392
3024
 
3393
- USE WHEN:
3394
- - Creating animated choropleth transitions
3395
- - Showing data changes over time
3396
- - Building story-based map visualizations
3397
- - Adding visual emphasis to regions
3025
+ Flowchart shapes:
3026
+ - process: Rectangle for process steps (default: 120x60)
3027
+ - decision: Diamond for yes/no decisions (default: 100x100)
3028
+ - terminal: Rounded rectangle for start/end (default: 120x40)
3029
+ - data: Parallelogram for data I/O (default: 120x60)
3030
+ - document: Wavy-bottom rectangle for documents (default: 100x80)
3031
+ - database: Cylinder for database/storage (default: 80x100)
3032
+ - preparation: Hexagon for preparation steps (default: 120x60)
3398
3033
 
3399
- KEYFRAME PROPERTIES:
3400
- - time: Time in seconds for this keyframe
3401
- - fillColor: Fill color at this keyframe (required)
3402
- - strokeColor: Optional stroke color
3403
- - opacity: Optional opacity (0-1)
3034
+ UML shapes:
3035
+ - uml-class: Class box with name/attributes/methods sections (default: 150x120)
3036
+ - uml-usecase: Ellipse for use case (default: 140x80)
3037
+ - uml-actor: Stick figure for actor (default: 60x100)
3038
+
3039
+ Network shapes:
3040
+ - cloud: Cloud shape for cloud services (default: 140x90)
3041
+ - server: Server rack shape (default: 80x100)
3042
+
3043
+ Basic shapes (same as pinepaper_create_item but diagram-optimized):
3044
+ - rectangle, circle, triangle, star
3045
+
3046
+ All shapes:
3047
+ - Have connection ports for connectors
3048
+ - Support labels inside the shape
3049
+ - Can be connected using pinepaper_connect or pinepaper_connect_ports
3404
3050
 
3405
3051
  EXAMPLES:
3406
- - Simple color transition: {duration: 5, loop: true, regions: {"USA": [{"time": 0, "fillColor": "#ef4444"}, {"time": 5, "fillColor": "#22c55e"}]}}
3407
- - Multi-region animation: {duration: 8, regions: {"USA": [...], "France": [...], "Japan": [...]}}`,
3052
+ - Flowchart start: {shapeType: "terminal", label: "Start", position: {x: 400, y: 100}}
3053
+ - Decision node: {shapeType: "decision", label: "Is valid?", position: {x: 400, y: 200}}
3054
+ - Database: {shapeType: "database", label: "Users DB", position: {x: 600, y: 200}}
3055
+ - UML Class: {shapeType: "uml-class", label: "User", width: 180, height: 150}
3056
+
3057
+ WORKFLOW TIP:
3058
+ After creating shapes, use pinepaper_connect to draw connectors between them.
3059
+ Use pinepaper_auto_layout to automatically arrange shapes in a clean layout.`,
3408
3060
  inputSchema: {
3409
3061
  type: 'object',
3410
3062
  properties: {
3411
- duration: {
3063
+ shapeType: {
3064
+ type: 'string',
3065
+ enum: ['process', 'decision', 'terminal', 'data', 'document', 'database', 'preparation', 'uml-class', 'uml-usecase', 'uml-actor', 'cloud', 'server', 'rectangle', 'circle', 'triangle', 'star'],
3066
+ description: 'Type of diagram shape to create',
3067
+ },
3068
+ position: {
3069
+ type: 'object',
3070
+ properties: {
3071
+ x: { type: 'number', description: 'X coordinate (default: 400)' },
3072
+ y: { type: 'number', description: 'Y coordinate (default: 300)' },
3073
+ },
3074
+ description: 'Position on canvas',
3075
+ },
3076
+ width: {
3412
3077
  type: 'number',
3413
- description: 'Total animation duration in seconds (default: 5)',
3078
+ description: 'Shape width in pixels (uses type-specific default if not specified)',
3414
3079
  },
3415
- loop: {
3416
- type: 'boolean',
3417
- description: 'Loop the animation (default: true)',
3080
+ height: {
3081
+ type: 'number',
3082
+ description: 'Shape height in pixels (uses type-specific default if not specified)',
3083
+ },
3084
+ label: {
3085
+ type: 'string',
3086
+ description: 'Text label inside the shape',
3418
3087
  },
3419
- regions: {
3088
+ style: {
3420
3089
  type: 'object',
3421
- additionalProperties: {
3422
- type: 'array',
3423
- items: {
3424
- type: 'object',
3425
- properties: {
3426
- time: { type: 'number', description: 'Time in seconds' },
3427
- fillColor: { type: 'string', description: 'Fill color at this keyframe' },
3428
- strokeColor: { type: 'string', description: 'Stroke color (optional)' },
3429
- opacity: { type: 'number', description: 'Opacity 0-1 (optional)' },
3430
- },
3431
- required: ['time', 'fillColor'],
3432
- },
3090
+ properties: {
3091
+ fillColor: { type: 'string', description: 'Fill color' },
3092
+ strokeColor: { type: 'string', description: 'Stroke color' },
3093
+ strokeWidth: { type: 'number', description: 'Stroke width' },
3433
3094
  },
3434
- description: 'Object mapping region IDs to arrays of keyframes',
3095
+ description: 'Visual styling options',
3435
3096
  },
3436
3097
  },
3437
- required: ['regions'],
3098
+ required: ['shapeType'],
3438
3099
  },
3439
3100
  },
3440
3101
  {
3441
- name: 'pinepaper_animate_map_wave',
3102
+ name: 'pinepaper_connect',
3442
3103
  annotations: {
3443
- title: 'Animate Map Wave',
3104
+ title: 'Connect Items',
3444
3105
  readOnlyHint: false,
3445
3106
  destructiveHint: false,
3446
3107
  idempotentHint: false,
3447
3108
  openWorldHint: false,
3448
3109
  },
3449
- description: `Create a wave animation across all map regions based on geographic position.
3110
+ description: `Connect two items with a smart connector. This is the primary way to draw lines/arrows between diagram shapes.
3450
3111
 
3451
3112
  USE WHEN:
3452
- - Creating dramatic visual effects
3453
- - Showing global spread patterns
3454
- - Adding ambient map animations
3455
- - Building attention-grabbing transitions
3113
+ - Drawing arrows between flowchart steps
3114
+ - Connecting UML classes with associations
3115
+ - Creating network connections between nodes
3116
+ - Any diagram that needs lines/arrows between elements
3117
+
3118
+ CONNECTOR FEATURES:
3119
+ - Automatic port selection (finds nearest ports)
3120
+ - Smart routing to avoid overlapping shapes
3121
+ - Animated "bolt" effect for data flow visualization
3122
+ - Arrow heads on either or both ends
3123
+ - Labels on connectors
3124
+
3125
+ ROUTING TYPES:
3126
+ - orthogonal: Right-angle turns only (default, best for flowcharts)
3127
+ - direct: Straight line between points
3128
+ - curved: Bezier curve with adjustable curvature
3129
+
3130
+ ARROW STYLES:
3131
+ - classic: Standard filled arrow (default for head)
3132
+ - stealth: Narrow sharp arrow
3133
+ - sharp: Simple pointed arrow
3134
+ - open: Outline arrow (not filled)
3135
+ - diamond: Diamond shape (for UML aggregation)
3136
+ - circle: Circle (for UML composition)
3137
+ - none: No arrowhead (default for tail)
3138
+
3139
+ LINE STYLES:
3140
+ - solid: Continuous line (default)
3141
+ - dashed: Dashed line (for optional relationships)
3142
+ - dotted: Dotted line (for dependencies)
3456
3143
 
3457
- WAVE DIRECTIONS:
3458
- - horizontal: Wave sweeps left to right
3459
- - vertical: Wave sweeps top to bottom
3460
- - radial: Wave radiates from center outward
3144
+ ANIMATED BOLT:
3145
+ Enable boltEnabled: true to show an animated particle traveling along the connector.
3146
+ Useful for showing data flow, process direction, or network traffic.
3461
3147
 
3462
3148
  EXAMPLES:
3463
- - Rainbow wave: {duration: 10, colors: ["#ef4444", "#fbbf24", "#22c55e", "#3b82f6"], waveDirection: "horizontal"}
3464
- - Fast radial pulse: {duration: 3, colors: ["#ffffff", "#3b82f6"], waveDirection: "radial", loop: true}`,
3149
+ - Simple arrow: {sourceItemId: "shape_1", targetItemId: "shape_2"}
3150
+ - Curved line: {sourceItemId: "a", targetItemId: "b", routing: "curved", curvature: 0.7}
3151
+ - Dashed dependency: {sourceItemId: "a", targetItemId: "b", lineStyle: "dashed", headStyle: "open"}
3152
+ - Two-way arrow: {sourceItemId: "a", targetItemId: "b", headStyle: "classic", tailStyle: "classic"}
3153
+ - Labeled connection: {sourceItemId: "a", targetItemId: "b", label: "1..*"}
3154
+
3155
+ RETURNS:
3156
+ - connectorId: ID of the connector (use for updates/removal)
3157
+ - sourceItemId, targetItemId: Connected items`,
3465
3158
  inputSchema: {
3466
3159
  type: 'object',
3467
3160
  properties: {
3468
- duration: {
3469
- type: 'number',
3470
- description: 'Total wave duration in seconds (default: 10)',
3161
+ sourceItemId: {
3162
+ type: 'string',
3163
+ description: 'Registry ID of the source item (where arrow starts)',
3471
3164
  },
3472
- loop: {
3473
- type: 'boolean',
3474
- description: 'Loop the animation (default: true)',
3165
+ targetItemId: {
3166
+ type: 'string',
3167
+ description: 'Registry ID of the target item (where arrow points)',
3475
3168
  },
3476
- colors: {
3477
- type: 'array',
3478
- items: { type: 'string' },
3479
- description: 'Array of colors for the wave (default: red, yellow, green, blue)',
3169
+ routing: {
3170
+ type: 'string',
3171
+ enum: ['direct', 'orthogonal', 'curved'],
3172
+ description: 'Connector routing style (default: orthogonal)',
3480
3173
  },
3481
- waveDirection: {
3174
+ lineColor: {
3482
3175
  type: 'string',
3483
- enum: ['horizontal', 'vertical', 'radial'],
3484
- description: 'Direction of the wave effect (default: horizontal)',
3176
+ description: 'Line color (default: #4B5563)',
3485
3177
  },
3486
- },
3487
- },
3488
- },
3489
- {
3490
- name: 'pinepaper_stop_map_animations',
3491
- annotations: {
3492
- title: 'Stop Map Animations',
3493
- readOnlyHint: false,
3494
- destructiveHint: false,
3495
- idempotentHint: true,
3496
- openWorldHint: false,
3497
- },
3498
- description: `Stop all or specific map region animations.
3499
-
3500
- USE WHEN:
3501
- - Ending animated sequences
3502
- - Resetting map to static state
3503
- - Pausing for user interaction
3504
- - Transitioning to different visualization
3505
-
3506
- EXAMPLES:
3507
- - Stop all: {}
3508
- - Stop specific regions: {regions: ["USA", "France"]}
3509
- - Stop and reset colors: {resetColors: true}`,
3510
- inputSchema: {
3511
- type: 'object',
3512
- properties: {
3513
- regions: {
3514
- type: 'array',
3515
- items: { type: 'string' },
3516
- description: 'Specific region IDs to stop (omit for all)',
3178
+ lineWidth: {
3179
+ type: 'number',
3180
+ description: 'Line width in pixels (default: 2)',
3517
3181
  },
3518
- resetColors: {
3519
- type: 'boolean',
3520
- description: 'Reset regions to default colors (default: true)',
3182
+ lineStyle: {
3183
+ type: 'string',
3184
+ enum: ['solid', 'dashed', 'dotted'],
3185
+ description: 'Line style (default: solid)',
3521
3186
  },
3522
- },
3523
- },
3524
- },
3525
- {
3526
- name: 'pinepaper_get_animated_map_regions',
3527
- annotations: {
3528
- title: 'Get Animated Map Regions',
3529
- readOnlyHint: true,
3530
- destructiveHint: false,
3531
- idempotentHint: true,
3532
- openWorldHint: false,
3533
- },
3534
- description: `[Utility] Get list of currently animated map regions with their animation data.
3535
-
3536
- USE WHEN:
3537
- - Debugging animations
3538
- - Checking animation state
3539
- - Building animation controls
3540
- - Inspecting current timeline
3541
-
3542
- RETURNS:
3543
- - animatedRegions: Array of region animation info
3544
- - count: Total number of animated regions`,
3545
- inputSchema: {
3546
- type: 'object',
3547
- properties: {},
3548
- },
3549
- },
3550
- {
3551
- name: 'pinepaper_export_map_region_csv',
3552
- annotations: {
3553
- title: 'Export Map Region CSV',
3554
- readOnlyHint: true,
3555
- destructiveHint: false,
3556
- idempotentHint: true,
3557
- openWorldHint: false,
3558
- },
3559
- description: `Export map region data as CSV including colors, highlight, and selection status.
3560
-
3561
- USE WHEN:
3562
- - Saving map state for later
3563
- - Creating data-driven workflows
3564
- - Integrating with spreadsheet tools
3565
- - Building export features
3566
-
3567
- CSV COLUMNS:
3568
- - regionId: Region identifier
3569
- - name: Display name
3570
- - highlighted: 1 or 0
3571
- - selected: 1 or 0
3572
- - fillColor: Current fill color
3573
- - strokeColor: Current stroke color
3574
-
3575
- EXAMPLES:
3576
- - Full export: {}
3577
- - Colors only: {includeHighlighted: false, includeSelected: false}
3578
- - Auto-download: {download: true, filename: "map-export.csv"}`,
3579
- inputSchema: {
3580
- type: 'object',
3581
- properties: {
3582
- includeHighlighted: {
3583
- type: 'boolean',
3584
- description: 'Include highlight status column (default: true)',
3187
+ headStyle: {
3188
+ type: 'string',
3189
+ enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'],
3190
+ description: 'Arrow head style at target (default: classic)',
3585
3191
  },
3586
- includeSelected: {
3587
- type: 'boolean',
3588
- description: 'Include selection status column (default: true)',
3192
+ tailStyle: {
3193
+ type: 'string',
3194
+ enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'],
3195
+ description: 'Arrow style at source (default: none)',
3589
3196
  },
3590
- includeColors: {
3591
- type: 'boolean',
3592
- description: 'Include fill/stroke color columns (default: true)',
3197
+ label: {
3198
+ type: 'string',
3199
+ description: 'Text label on the connector',
3200
+ },
3201
+ curvature: {
3202
+ type: 'number',
3203
+ description: 'Curve intensity for curved routing (0.1-1.0, default: 0.5)',
3593
3204
  },
3594
- download: {
3205
+ boltEnabled: {
3595
3206
  type: 'boolean',
3596
- description: 'Auto-download the CSV file (default: false)',
3207
+ description: 'Enable animated bolt effect (default: true)',
3597
3208
  },
3598
- filename: {
3209
+ boltColor: {
3599
3210
  type: 'string',
3600
- description: 'Filename for download (default: map-regions.csv)',
3211
+ description: 'Bolt animation color (default: #fbbf24)',
3601
3212
  },
3602
3213
  },
3214
+ required: ['sourceItemId', 'targetItemId'],
3603
3215
  },
3604
3216
  },
3605
3217
  {
3606
- name: 'pinepaper_import_map_region_csv',
3218
+ name: 'pinepaper_connect_ports',
3607
3219
  annotations: {
3608
- title: 'Import Map Region CSV',
3220
+ title: 'Connect Specific Ports',
3609
3221
  readOnlyHint: false,
3610
3222
  destructiveHint: false,
3611
- idempotentHint: true,
3223
+ idempotentHint: false,
3612
3224
  openWorldHint: false,
3613
3225
  },
3614
- description: `Import CSV data to update map region states (colors, highlight, selection).
3226
+ description: `Connect two specific ports on items. Use this when you need precise control over which ports the connector attaches to.
3615
3227
 
3616
3228
  USE WHEN:
3617
- - Restoring saved map state
3618
- - Applying data from spreadsheets
3619
- - Batch updating region properties
3620
- - Building data-driven visualizations
3621
-
3622
- CSV FORMAT:
3623
- Must have 'regionId' column. Optional columns:
3624
- - fillColor: Hex color for fill
3625
- - strokeColor: Hex color for stroke
3626
- - highlighted: 1 or 0
3627
- - selected: 1 or 0
3229
+ - Need connector to attach to specific side of shape
3230
+ - Creating complex diagrams where automatic port selection isn't ideal
3231
+ - Building circuit-like diagrams with specific entry/exit points
3232
+ - Connecting specific input/output ports
3233
+
3234
+ PORT POSITIONS:
3235
+ Standard positions:
3236
+ - top, bottom, left, right: Center of each edge
3237
+ - top-left, top-right, bottom-left, bottom-right: Corners
3238
+ - center: Center of the shape
3239
+
3240
+ Line/path specific:
3241
+ - start: Beginning of path
3242
+ - end: End of path
3628
3243
 
3629
3244
  EXAMPLES:
3630
- - Import full CSV: {csvText: "regionId,fillColor,highlighted\\nUSA,#22c55e,1\\nFrance,#3b82f6,0"}
3631
- - Colors only: {csvText: "...", applyHighlight: false, applySelection: false}`,
3245
+ - Top to bottom: {sourceItemId: "a", sourcePort: "bottom", targetItemId: "b", targetPort: "top"}
3246
+ - Left to right: {sourceItemId: "a", sourcePort: "right", targetItemId: "b", targetPort: "left"}
3247
+ - Corner connection: {sourceItemId: "a", sourcePort: "bottom-right", targetItemId: "b", targetPort: "top-left"}
3248
+
3249
+ CONFIG OPTIONS:
3250
+ Same as pinepaper_connect: routing, lineColor, lineWidth, lineStyle, headStyle, tailStyle, label, curvature, boltEnabled, boltColor`,
3632
3251
  inputSchema: {
3633
3252
  type: 'object',
3634
3253
  properties: {
3635
- csvText: {
3254
+ sourceItemId: {
3636
3255
  type: 'string',
3637
- description: 'CSV text content to import',
3256
+ description: 'Registry ID of the source item',
3638
3257
  },
3639
- applyColors: {
3640
- type: 'boolean',
3641
- description: 'Apply fill/stroke colors from CSV (default: true)',
3258
+ sourcePort: {
3259
+ type: 'string',
3260
+ enum: ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'center', 'start', 'end'],
3261
+ description: 'Port position on source item',
3642
3262
  },
3643
- applyHighlight: {
3644
- type: 'boolean',
3645
- description: 'Update highlight status from CSV (default: true)',
3263
+ targetItemId: {
3264
+ type: 'string',
3265
+ description: 'Registry ID of the target item',
3646
3266
  },
3647
- applySelection: {
3648
- type: 'boolean',
3649
- description: 'Update selection status from CSV (default: true)',
3267
+ targetPort: {
3268
+ type: 'string',
3269
+ enum: ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'center', 'start', 'end'],
3270
+ description: 'Port position on target item',
3650
3271
  },
3651
- },
3652
- required: ['csvText'],
3653
- },
3654
- },
3655
- {
3656
- name: 'pinepaper_select_map_regions',
3657
- annotations: {
3658
- title: 'Select Map Regions',
3659
- readOnlyHint: false,
3660
- destructiveHint: false,
3661
- idempotentHint: true,
3662
- openWorldHint: false,
3663
- },
3664
- description: `Programmatically select map regions.
3665
-
3666
- USE WHEN:
3667
- - Building interactive map features
3668
- - Responding to user input
3669
- - Creating selection-based workflows
3670
- - Highlighting user choices
3671
-
3672
- EXAMPLES:
3673
- - Select countries: {regionIds: ["USA", "Canada", "Mexico"]}
3674
- - Select US states: {regionIds: ["CA", "TX", "NY"]}`,
3675
- inputSchema: {
3676
- type: 'object',
3677
- properties: {
3678
- regionIds: {
3679
- type: 'array',
3680
- items: { type: 'string' },
3681
- description: 'Array of region IDs to select',
3272
+ config: {
3273
+ type: 'object',
3274
+ properties: {
3275
+ routing: { type: 'string', enum: ['direct', 'orthogonal', 'curved'] },
3276
+ lineColor: { type: 'string' },
3277
+ lineWidth: { type: 'number' },
3278
+ lineStyle: { type: 'string', enum: ['solid', 'dashed', 'dotted'] },
3279
+ headStyle: { type: 'string', enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'] },
3280
+ tailStyle: { type: 'string', enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'] },
3281
+ label: { type: 'string' },
3282
+ curvature: { type: 'number' },
3283
+ boltEnabled: { type: 'boolean' },
3284
+ boltColor: { type: 'string' },
3285
+ },
3286
+ description: 'Connector configuration options',
3682
3287
  },
3683
3288
  },
3684
- required: ['regionIds'],
3289
+ required: ['sourceItemId', 'sourcePort', 'targetItemId', 'targetPort'],
3685
3290
  },
3686
3291
  },
3687
3292
  {
3688
- name: 'pinepaper_deselect_map_regions',
3293
+ name: 'pinepaper_add_ports',
3689
3294
  annotations: {
3690
- title: 'Deselect Map Regions',
3295
+ title: 'Add Ports to Item',
3691
3296
  readOnlyHint: false,
3692
3297
  destructiveHint: false,
3693
- idempotentHint: true,
3694
- openWorldHint: false,
3695
- },
3696
- description: `Programmatically deselect map regions.
3697
-
3698
- USE WHEN:
3699
- - Clearing user selections
3700
- - Resetting map state
3701
- - Implementing toggle behavior
3702
- - Building selection management
3703
-
3704
- EXAMPLES:
3705
- - Deselect specific: {regionIds: ["USA", "France"]}
3706
- - Deselect all: {} (omit regionIds)`,
3707
- inputSchema: {
3708
- type: 'object',
3709
- properties: {
3710
- regionIds: {
3711
- type: 'array',
3712
- items: { type: 'string' },
3713
- description: 'Array of region IDs to deselect (omit for all)',
3714
- },
3715
- },
3716
- },
3717
- },
3718
- {
3719
- name: 'pinepaper_get_highlighted_map_regions',
3720
- annotations: {
3721
- title: 'Get Highlighted Map Regions',
3722
- readOnlyHint: true,
3723
- destructiveHint: false,
3724
- idempotentHint: true,
3298
+ idempotentHint: false,
3725
3299
  openWorldHint: false,
3726
3300
  },
3727
- description: `[Utility] Get list of currently highlighted map regions.
3301
+ description: `Add connection ports to an existing item. Ports are anchor points where connectors can attach.
3728
3302
 
3729
3303
  USE WHEN:
3730
- - Checking current highlight state
3731
- - Building conditional logic
3732
- - Creating highlight summaries
3733
- - Debugging map state
3304
+ - Adding custom port positions to shapes
3305
+ - Enabling connections on items that don't have ports
3306
+ - Creating specialized connection points for complex diagrams
3734
3307
 
3735
- RETURNS:
3736
- - highlighted: Array of highlighted region IDs
3737
- - count: Total number of highlighted regions`,
3738
- inputSchema: {
3739
- type: 'object',
3740
- properties: {},
3741
- },
3742
- },
3743
- {
3744
- name: 'pinepaper_export_map_geojson',
3745
- annotations: {
3746
- title: 'Export Map GeoJSON',
3747
- readOnlyHint: true,
3748
- destructiveHint: false,
3749
- idempotentHint: true,
3750
- openWorldHint: false,
3751
- },
3752
- description: `Export the current map as GeoJSON (with current colors/modifications).
3308
+ PORT TYPES:
3309
+ - standard: Standard 4 ports (top, bottom, left, right)
3310
+ - line: 2 ports (start, end) for line-like items
3311
+ - path: N ports distributed along a path
3312
+ - custom: User-defined port positions
3753
3313
 
3754
- USE WHEN:
3755
- - Saving map state with custom styling
3756
- - Exporting for use in other mapping tools
3757
- - Creating styled GeoJSON for external applications
3758
- - Archiving map customizations
3314
+ CUSTOM PORTS:
3315
+ Define specific ports with position and type:
3316
+ - position: where on the item (top, bottom, left, right, corners)
3317
+ - type: input (accept incoming), output (start outgoing), or both
3759
3318
 
3760
3319
  EXAMPLES:
3761
- - Export with styles: {includeStyles: true}
3762
- - Selected regions only: {selectedOnly: true}
3763
- - Auto-download: {download: true, filename: "my-map.geojson"}`,
3320
+ - Standard 4 ports: {itemId: "shape_1", portType: "standard"}
3321
+ - Line endpoints: {itemId: "line_1", portType: "line"}
3322
+ - Path with 5 ports: {itemId: "path_1", portType: "path", count: 5}
3323
+ - Custom ports: {itemId: "shape_1", portType: "custom", ports: [{position: "top", type: "input"}, {position: "bottom", type: "output"}]}`,
3764
3324
  inputSchema: {
3765
3325
  type: 'object',
3766
3326
  properties: {
3767
- includeStyles: {
3768
- type: 'boolean',
3769
- description: 'Include fill/stroke colors as properties (default: true)',
3770
- },
3771
- includeMetadata: {
3772
- type: 'boolean',
3773
- description: 'Include region names and IDs (default: true)',
3327
+ itemId: {
3328
+ type: 'string',
3329
+ description: 'Registry ID of the item to add ports to',
3774
3330
  },
3775
- selectedOnly: {
3776
- type: 'boolean',
3777
- description: 'Only export selected regions (default: false)',
3331
+ portType: {
3332
+ type: 'string',
3333
+ enum: ['standard', 'line', 'path', 'custom'],
3334
+ description: 'Type of port configuration (default: standard)',
3778
3335
  },
3779
- download: {
3780
- type: 'boolean',
3781
- description: 'Auto-download the file (default: false)',
3336
+ ports: {
3337
+ type: 'array',
3338
+ items: {
3339
+ type: 'object',
3340
+ properties: {
3341
+ position: {
3342
+ type: 'string',
3343
+ enum: ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'center', 'start', 'end'],
3344
+ },
3345
+ type: {
3346
+ type: 'string',
3347
+ enum: ['input', 'output', 'both'],
3348
+ },
3349
+ },
3350
+ },
3351
+ description: 'Custom port definitions (for portType: "custom")',
3782
3352
  },
3783
- filename: {
3784
- type: 'string',
3785
- description: 'Filename for download (default: "map-export.geojson")',
3353
+ count: {
3354
+ type: 'number',
3355
+ description: 'Number of ports for path type',
3786
3356
  },
3787
3357
  },
3358
+ required: ['itemId'],
3788
3359
  },
3789
3360
  },
3790
3361
  {
3791
- name: 'pinepaper_export_original_map_geojson',
3362
+ name: 'pinepaper_auto_layout',
3792
3363
  annotations: {
3793
- title: 'Export Original Map GeoJSON',
3794
- readOnlyHint: true,
3364
+ title: 'Auto Layout',
3365
+ readOnlyHint: false,
3795
3366
  destructiveHint: false,
3796
- idempotentHint: true,
3367
+ idempotentHint: false,
3797
3368
  openWorldHint: false,
3798
3369
  },
3799
- description: `Export the original source GeoJSON (unmodified boundaries). Returns the exact data used to load the map, allowing users to edit boundaries externally and re-import.
3370
+ description: `Automatically arrange diagram items using a layout algorithm. This reorganizes items for cleaner, more readable diagrams.
3800
3371
 
3801
3372
  USE WHEN:
3802
- - Extracting original map data for external editing
3803
- - Getting clean boundaries without customizations
3804
- - Creating a baseline for map modifications
3805
- - Re-importing after external boundary edits
3373
+ - Diagram items are messy or overlapping
3374
+ - Want to create a professional-looking layout automatically
3375
+ - After adding many items, need to organize them
3376
+ - Creating hierarchical structures (org charts, trees)
3806
3377
 
3807
- EXAMPLES:
3808
- - Get original data: {}
3809
- - Auto-download: {download: true, filename: "map-source.geojson"}`,
3810
- inputSchema: {
3811
- type: 'object',
3812
- properties: {
3813
- download: {
3814
- type: 'boolean',
3815
- description: 'Auto-download the file (default: false)',
3816
- },
3817
- filename: {
3818
- type: 'string',
3819
- description: 'Filename for download (default: "map-source.geojson")',
3820
- },
3821
- },
3822
- },
3823
- },
3824
- {
3825
- name: 'pinepaper_get_map_source_info',
3826
- annotations: {
3827
- title: 'Get Map Source Info',
3828
- readOnlyHint: true,
3829
- destructiveHint: false,
3830
- idempotentHint: true,
3831
- openWorldHint: false,
3832
- },
3833
- description: `[Utility] Get information about the currently loaded map source.
3378
+ LAYOUT TYPES:
3834
3379
 
3835
- USE WHEN:
3836
- - Checking what map is currently loaded
3837
- - Debugging map loading issues
3838
- - Getting map metadata
3839
- - Verifying map configuration
3380
+ hierarchical:
3381
+ - Best for: flowcharts, org charts, dependency graphs
3382
+ - Arranges items in levels from top to bottom (or other directions)
3383
+ - Respects connector direction for parent-child relationships
3384
+ - Options: direction (TB/BT/LR/RL), levelSpacing, nodeSpacing
3840
3385
 
3841
- RETURNS:
3842
- - source: Map source identifier (e.g., "world", "worldHighRes", "usa", or custom)
3843
- - projection: Current projection type
3844
- - quality: Rendering quality setting
3845
- - regionCount: Total number of regions
3846
- - hasOriginalGeoJSON: Whether original GeoJSON is available
3847
- - isCustomImport: Whether this is a custom imported map`,
3848
- inputSchema: {
3849
- type: 'object',
3850
- properties: {},
3851
- },
3852
- },
3853
- // ---------------------------------------------------------------------------
3854
- // DOMAIN: FONT TOOLS
3855
- // ---------------------------------------------------------------------------
3856
- {
3857
- name: 'pinepaper_font_show_studio',
3858
- annotations: {
3859
- title: 'Font Show Studio',
3860
- readOnlyHint: false,
3861
- destructiveHint: false,
3862
- idempotentHint: true,
3863
- openWorldHint: false,
3864
- },
3865
- description: `Open the Font Studio UI for interactive font creation.
3386
+ force-directed:
3387
+ - Best for: network diagrams, relationship graphs
3388
+ - Uses physics simulation (attraction/repulsion)
3389
+ - Good for showing clusters and relationships
3390
+ - Options: iterations, attraction, repulsion
3866
3391
 
3867
- USE WHEN:
3868
- - Starting a custom font creation workflow
3869
- - Need the interactive Font Studio interface with guide lines
3870
- - Want to create a hand-drawn font from scratch
3392
+ tree:
3393
+ - Best for: hierarchies, file systems, family trees
3394
+ - Similar to hierarchical but optimized for tree structures
3395
+ - Options: direction, levelSpacing, nodeSpacing
3871
3396
 
3872
- WORKFLOW:
3873
- 1. Open Font Studio → pinepaper_font_show_studio
3874
- 2. Set font name → pinepaper_font_set_name
3875
- 3. Check required chars → pinepaper_font_get_required_chars
3876
- 4. For each character: draw path, cleanup, create glyph
3877
- 5. Check progress → pinepaper_font_get_status
3878
- 6. Export when complete → pinepaper_font_export`,
3879
- inputSchema: {
3880
- type: 'object',
3881
- properties: {},
3882
- },
3883
- },
3884
- {
3885
- name: 'pinepaper_font_set_name',
3886
- annotations: {
3887
- title: 'Font Set Name',
3888
- readOnlyHint: false,
3889
- destructiveHint: false,
3890
- idempotentHint: true,
3891
- openWorldHint: false,
3892
- },
3893
- description: `Set the font family name for the current font being created.`,
3894
- inputSchema: {
3895
- type: 'object',
3896
- properties: {
3897
- name: {
3898
- type: 'string',
3899
- description: "Font family name (e.g., 'MyHandwriting')",
3900
- },
3901
- },
3902
- required: ['name'],
3903
- },
3904
- },
3905
- {
3906
- name: 'pinepaper_font_get_required_chars',
3907
- annotations: {
3908
- title: 'Font Get Required Chars',
3909
- readOnlyHint: true,
3910
- destructiveHint: false,
3911
- idempotentHint: true,
3912
- openWorldHint: false,
3913
- },
3914
- description: `Get the list of characters needed for a complete font.
3397
+ radial:
3398
+ - Best for: mind maps, hub-and-spoke diagrams
3399
+ - Places items in concentric circles around a center
3400
+ - Options: centerX, centerY, startRadius, radiusStep
3401
+
3402
+ grid:
3403
+ - Best for: equal-importance items, component libraries
3404
+ - Arranges items in rows and columns
3405
+ - Options: columns, cellWidth, cellHeight
3406
+
3407
+ ANIMATION:
3408
+ By default, items animate smoothly to their new positions.
3409
+ Set animate: false for instant repositioning.
3410
+
3411
+ EXAMPLES:
3412
+ - Flowchart layout: {layoutType: "hierarchical", options: {direction: "TB", levelSpacing: 100}}
3413
+ - Network diagram: {layoutType: "force-directed", options: {iterations: 200, repulsion: 2000}}
3414
+ - Mind map: {layoutType: "radial", options: {centerX: 400, centerY: 300}}
3415
+ - Grid of icons: {layoutType: "grid", options: {columns: 4, cellWidth: 120}}
3915
3416
 
3916
- CHARACTER SETS:
3917
- - minimum: A-Z, a-z, 0-9, space (63 chars) - enough for basic text
3918
- - standard: adds punctuation and symbols (90+ chars) - full typography`,
3417
+ PARTIAL LAYOUT:
3418
+ Pass itemIds array to only layout specific items, leaving others in place.`,
3919
3419
  inputSchema: {
3920
3420
  type: 'object',
3921
3421
  properties: {
3922
- set: {
3422
+ layoutType: {
3923
3423
  type: 'string',
3924
- enum: ['minimum', 'standard'],
3925
- description: 'minimum: A-Z, a-z, 0-9, space (63 chars). standard: adds punctuation (90+ chars)',
3424
+ enum: ['hierarchical', 'force-directed', 'tree', 'radial', 'grid'],
3425
+ description: 'Layout algorithm to use',
3426
+ },
3427
+ itemIds: {
3428
+ type: 'array',
3429
+ items: { type: 'string' },
3430
+ description: 'Specific items to layout (default: all diagram items)',
3431
+ },
3432
+ options: {
3433
+ type: 'object',
3434
+ properties: {
3435
+ direction: {
3436
+ type: 'string',
3437
+ enum: ['TB', 'BT', 'LR', 'RL'],
3438
+ description: 'Layout direction (TB=top-to-bottom, LR=left-to-right, etc.)',
3439
+ },
3440
+ levelSpacing: {
3441
+ type: 'number',
3442
+ description: 'Vertical spacing between levels (default: 100)',
3443
+ },
3444
+ nodeSpacing: {
3445
+ type: 'number',
3446
+ description: 'Horizontal spacing between nodes (default: 80)',
3447
+ },
3448
+ iterations: {
3449
+ type: 'number',
3450
+ description: 'Iterations for force-directed layout (default: 100)',
3451
+ },
3452
+ attraction: {
3453
+ type: 'number',
3454
+ description: 'Attraction force for connected nodes (default: 0.01)',
3455
+ },
3456
+ repulsion: {
3457
+ type: 'number',
3458
+ description: 'Repulsion force between all nodes (default: 1000)',
3459
+ },
3460
+ columns: {
3461
+ type: 'number',
3462
+ description: 'Number of columns for grid layout',
3463
+ },
3464
+ cellWidth: {
3465
+ type: 'number',
3466
+ description: 'Cell width for grid layout (default: 150)',
3467
+ },
3468
+ cellHeight: {
3469
+ type: 'number',
3470
+ description: 'Cell height for grid layout (default: 100)',
3471
+ },
3472
+ centerX: {
3473
+ type: 'number',
3474
+ description: 'Center X for radial layout',
3475
+ },
3476
+ centerY: {
3477
+ type: 'number',
3478
+ description: 'Center Y for radial layout',
3479
+ },
3480
+ startRadius: {
3481
+ type: 'number',
3482
+ description: 'Starting radius for radial layout (default: 100)',
3483
+ },
3484
+ radiusStep: {
3485
+ type: 'number',
3486
+ description: 'Radius increment per level for radial layout (default: 80)',
3487
+ },
3488
+ animate: {
3489
+ type: 'boolean',
3490
+ description: 'Animate transition to new positions (default: true)',
3491
+ },
3492
+ animationDuration: {
3493
+ type: 'number',
3494
+ description: 'Animation duration in ms (default: 300)',
3495
+ },
3496
+ },
3497
+ description: 'Layout-specific options',
3926
3498
  },
3927
3499
  },
3500
+ required: ['layoutType'],
3928
3501
  },
3929
3502
  },
3930
3503
  {
3931
- name: 'pinepaper_font_get_status',
3504
+ name: 'pinepaper_get_diagram_shapes',
3932
3505
  annotations: {
3933
- title: 'Font Get Status',
3506
+ title: 'Get Diagram Shapes',
3934
3507
  readOnlyHint: true,
3935
3508
  destructiveHint: false,
3936
3509
  idempotentHint: true,
3937
3510
  openWorldHint: false,
3938
3511
  },
3939
- description: `Get font completion status including progress percentage, completed/pending characters.
3512
+ description: `[Utility] Get a list of available diagram shapes with their properties.
3940
3513
 
3941
3514
  USE WHEN:
3942
- - Checking progress during font creation
3943
- - Determining which characters still need to be drawn
3944
- - Verifying font is complete before export`,
3945
- inputSchema: {
3946
- type: 'object',
3947
- properties: {},
3948
- },
3949
- },
3950
- {
3951
- name: 'pinepaper_font_create_glyph',
3952
- annotations: {
3953
- title: 'Font Create Glyph',
3954
- readOnlyHint: false,
3955
- destructiveHint: false,
3956
- idempotentHint: false,
3957
- openWorldHint: false,
3958
- },
3959
- description: `Create a glyph from a Paper.js path. Converts a drawn path into an OpenType glyph with calculated advance width.
3515
+ - Need to see what diagram shapes are available
3516
+ - Want to know default sizes and styling for shapes
3517
+ - Building dynamic UI that shows shape options
3960
3518
 
3961
- USE WHEN:
3962
- - Converting a drawn character path to a font glyph
3963
- - Adding a new character to the font
3519
+ CATEGORIES:
3520
+ - flowchart: process, decision, terminal, data, document, database, preparation
3521
+ - uml: uml-class, uml-usecase, uml-actor
3522
+ - network: cloud, server
3523
+ - basic: rectangle, circle, triangle, star
3964
3524
 
3965
- WORKFLOW:
3966
- 1. Draw the character as a Paper.js path on the canvas
3967
- 2. Optionally clean up the path (pinepaper_font_cleanup_path)
3968
- 3. Use the path's registry ID to create the glyph`,
3525
+ RETURNS:
3526
+ Array of shape definitions including:
3527
+ - name: Shape identifier
3528
+ - category: Category it belongs to
3529
+ - defaultWidth, defaultHeight: Default dimensions
3530
+ - defaultStyle: Default colors and stroke
3531
+ - description: What the shape represents`,
3969
3532
  inputSchema: {
3970
3533
  type: 'object',
3971
3534
  properties: {
3972
- character: {
3973
- type: 'string',
3974
- description: "Single character (e.g., 'A', 'a', '1', ' ')",
3975
- },
3976
- pathId: {
3535
+ category: {
3977
3536
  type: 'string',
3978
- description: 'Registry ID of the Paper.js path to use as glyph shape',
3537
+ enum: ['flowchart', 'uml', 'network', 'basic'],
3538
+ description: 'Filter by category (optional - returns all if not specified)',
3979
3539
  },
3980
3540
  },
3981
- required: ['character', 'pathId'],
3982
3541
  },
3983
3542
  },
3984
3543
  {
3985
- name: 'pinepaper_font_create_space',
3544
+ name: 'pinepaper_update_connector',
3986
3545
  annotations: {
3987
- title: 'Font Create Space',
3546
+ title: 'Update Connector',
3988
3547
  readOnlyHint: false,
3989
3548
  destructiveHint: false,
3990
3549
  idempotentHint: true,
3991
3550
  openWorldHint: false,
3992
3551
  },
3993
- description: `Create the space glyph (no visible shape, just advance width).
3552
+ description: `Update the style or label of an existing connector.
3994
3553
 
3995
3554
  USE WHEN:
3996
- - Adding the space character to the font
3997
- - Space needs no drawn path, only a width value`,
3998
- inputSchema: {
3999
- type: 'object',
4000
- properties: {
4001
- width: {
4002
- type: 'number',
4003
- description: 'Space width in font units (default: 250)',
4004
- },
4005
- },
4006
- },
4007
- },
4008
- {
4009
- name: 'pinepaper_font_remove_glyph',
4010
- annotations: {
4011
- title: 'Font Remove Glyph',
4012
- readOnlyHint: false,
4013
- destructiveHint: true,
4014
- idempotentHint: true,
4015
- openWorldHint: false,
4016
- },
4017
- description: `Remove a glyph from the font. Use when a character needs to be redrawn.`,
4018
- inputSchema: {
4019
- type: 'object',
4020
- properties: {
4021
- character: {
4022
- type: 'string',
4023
- description: 'Character to remove',
4024
- },
4025
- },
4026
- required: ['character'],
4027
- },
4028
- },
4029
- {
4030
- name: 'pinepaper_font_set_metrics',
4031
- annotations: {
4032
- title: 'Font Set Metrics',
4033
- readOnlyHint: false,
4034
- destructiveHint: false,
4035
- idempotentHint: true,
4036
- openWorldHint: false,
4037
- },
4038
- description: `Set font metrics (advanced). Controls the coordinate grid and vertical measurements.
3555
+ - Changing connector appearance after creation
3556
+ - Updating connector labels
3557
+ - Changing arrow styles or colors
3558
+
3559
+ UPDATABLE PROPERTIES:
3560
+ - style: lineColor, lineWidth, headStyle, tailStyle, routing, lineStyle
3561
+ - label: Text label on the connector
3562
+ - labelPosition: Position along path (0-1, where 0.5 is middle)
4039
3563
 
4040
- METRICS:
4041
- - unitsPerEm: Coordinate grid size (default: 1000)
4042
- - ascender: Height above baseline (default: 800)
4043
- - descender: Depth below baseline, negative (default: -200)
4044
- - xHeight: Lowercase letter height (default: 500)
4045
- - capHeight: Capital letter height (default: 700)`,
3564
+ EXAMPLES:
3565
+ - Change color: {connectorId: "conn_1", style: {lineColor: "#ef4444"}}
3566
+ - Add label: {connectorId: "conn_1", label: "data flow"}
3567
+ - Change to dashed: {connectorId: "conn_1", style: {lineStyle: "dashed"}}
3568
+ - Move label: {connectorId: "conn_1", labelPosition: 0.25}`,
4046
3569
  inputSchema: {
4047
3570
  type: 'object',
4048
3571
  properties: {
4049
- unitsPerEm: {
4050
- type: 'number',
4051
- description: 'Coordinate grid size (default: 1000)',
4052
- },
4053
- ascender: {
4054
- type: 'number',
4055
- description: 'Height above baseline (default: 800)',
3572
+ connectorId: {
3573
+ type: 'string',
3574
+ description: 'ID of the connector to update',
4056
3575
  },
4057
- descender: {
4058
- type: 'number',
4059
- description: 'Depth below baseline, negative (default: -200)',
3576
+ style: {
3577
+ type: 'object',
3578
+ properties: {
3579
+ lineColor: { type: 'string' },
3580
+ lineWidth: { type: 'number' },
3581
+ headStyle: { type: 'string', enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'] },
3582
+ tailStyle: { type: 'string', enum: ['classic', 'stealth', 'sharp', 'open', 'diamond', 'circle', 'none'] },
3583
+ routing: { type: 'string', enum: ['direct', 'orthogonal', 'curved'] },
3584
+ lineStyle: { type: 'string', enum: ['solid', 'dashed', 'dotted'] },
3585
+ },
3586
+ description: 'Style properties to update',
4060
3587
  },
4061
- xHeight: {
4062
- type: 'number',
4063
- description: 'Lowercase letter height (default: 500)',
3588
+ label: {
3589
+ type: 'string',
3590
+ description: 'New label text',
4064
3591
  },
4065
- capHeight: {
3592
+ labelPosition: {
4066
3593
  type: 'number',
4067
- description: 'Capital letter height (default: 700)',
3594
+ description: 'Label position along path (0-1)',
4068
3595
  },
4069
3596
  },
3597
+ required: ['connectorId'],
4070
3598
  },
4071
3599
  },
4072
3600
  {
4073
- name: 'pinepaper_font_export',
3601
+ name: 'pinepaper_remove_connector',
4074
3602
  annotations: {
4075
- title: 'Font Export',
4076
- readOnlyHint: true,
4077
- destructiveHint: false,
3603
+ title: 'Remove Connector',
3604
+ readOnlyHint: false,
3605
+ destructiveHint: true,
4078
3606
  idempotentHint: true,
4079
3607
  openWorldHint: false,
4080
3608
  },
4081
- description: `Export the font as an OTF file. Triggers browser download of the completed font.
3609
+ description: `Remove a connector from the canvas.
4082
3610
 
4083
3611
  USE WHEN:
4084
- - Font is complete and ready for download
4085
- - User wants to save the font as a file`,
3612
+ - Deleting a connection between items
3613
+ - Removing incorrect links
3614
+ - Restructuring diagram connections`,
4086
3615
  inputSchema: {
4087
3616
  type: 'object',
4088
3617
  properties: {
4089
- download: {
4090
- type: 'boolean',
4091
- description: 'Trigger browser download (default: true)',
3618
+ connectorId: {
3619
+ type: 'string',
3620
+ description: 'ID of the connector to remove',
4092
3621
  },
4093
3622
  },
3623
+ required: ['connectorId'],
4094
3624
  },
4095
3625
  },
4096
3626
  {
4097
- name: 'pinepaper_font_load_into_document',
3627
+ name: 'pinepaper_diagram_mode',
4098
3628
  annotations: {
4099
- title: 'Font Load Into Document',
3629
+ title: 'Diagram Mode',
4100
3630
  readOnlyHint: false,
4101
3631
  destructiveHint: false,
4102
3632
  idempotentHint: true,
4103
3633
  openWorldHint: false,
4104
3634
  },
4105
- description: `Load the custom font into the document for immediate use in PinePaper text items.
3635
+ description: `Control the diagram mode for interactive editing.
4106
3636
 
4107
3637
  USE WHEN:
4108
- - Want to use the created font immediately in the current document
4109
- - Testing how the font looks in actual text items`,
4110
- inputSchema: {
4111
- type: 'object',
4112
- properties: {},
4113
- },
4114
- },
4115
- {
4116
- name: 'pinepaper_font_export_data',
4117
- annotations: {
4118
- title: 'Font Export Data',
4119
- readOnlyHint: true,
4120
- destructiveHint: false,
4121
- idempotentHint: true,
4122
- openWorldHint: false,
4123
- },
4124
- description: `Export font data as JSON for saving progress. Use to save work-in-progress fonts.
3638
+ - Switching between drawing and selection modes
3639
+ - Enabling/disabling diagram-specific UI
3640
+ - Setting up the canvas for diagram creation
4125
3641
 
4126
- USE WHEN:
4127
- - Saving font progress for later continuation
4128
- - Backing up font data`,
3642
+ ACTIONS:
3643
+ - activate: Enable diagram mode (shows grid, snap, port indicators)
3644
+ - deactivate: Return to normal canvas mode
3645
+ - toggle: Switch between diagram and normal mode
3646
+ - setMode: Set specific tool mode (select, connect, shape, pan)
3647
+
3648
+ TOOL MODES (for setMode action):
3649
+ - select: Selection and moving items
3650
+ - connect: Drawing connectors between items
3651
+ - shape: Drawing new shapes (optionally specify shapeType)
3652
+ - pan: Panning the canvas
3653
+
3654
+ EXAMPLES:
3655
+ - Enter diagram mode: {action: "activate"}
3656
+ - Exit diagram mode: {action: "deactivate"}
3657
+ - Set to connect mode: {action: "setMode", mode: "connect"}
3658
+ - Set to draw rectangles: {action: "setMode", mode: "shape", shapeType: "process"}`,
4129
3659
  inputSchema: {
4130
3660
  type: 'object',
4131
3661
  properties: {
4132
- download: {
4133
- type: 'boolean',
4134
- description: 'Trigger browser download (default: true)',
3662
+ action: {
3663
+ type: 'string',
3664
+ enum: ['activate', 'deactivate', 'toggle', 'setMode'],
3665
+ description: 'Action to perform',
3666
+ },
3667
+ mode: {
3668
+ type: 'string',
3669
+ enum: ['select', 'connect', 'shape', 'pan'],
3670
+ description: 'Tool mode (for setMode action)',
3671
+ },
3672
+ shapeType: {
3673
+ type: 'string',
3674
+ enum: ['process', 'decision', 'terminal', 'data', 'document', 'database', 'preparation', 'uml-class', 'uml-usecase', 'uml-actor', 'cloud', 'server', 'rectangle', 'circle', 'triangle', 'star'],
3675
+ description: 'Shape type for shape mode',
4135
3676
  },
4136
3677
  },
3678
+ required: ['action'],
4137
3679
  },
4138
3680
  },
3681
+ // ---------------------------------------------------------------------------
3682
+ // DOMAIN: MAP TOOLS — four action-dispatched tools replace 23 wrappers
3683
+ // ---------------------------------------------------------------------------
4139
3684
  {
4140
- name: 'pinepaper_font_import_data',
3685
+ name: 'pinepaper_map',
4141
3686
  annotations: {
4142
- title: 'Font Import Data',
3687
+ title: 'Map: Load + Viewport',
4143
3688
  readOnlyHint: false,
4144
3689
  destructiveHint: false,
4145
3690
  idempotentHint: false,
4146
3691
  openWorldHint: false,
4147
3692
  },
4148
- description: `Import font data from previously saved JSON. Restores a font from exported data.
3693
+ description: `Load a map and control its viewport. Call action: "load" first to set up; subsequent calls control pan / zoom / config import-export.
4149
3694
 
4150
- USE WHEN:
4151
- - Resuming work on a previously saved font
4152
- - Loading font data exported with pinepaper_font_export_data`,
3695
+ ACTIONS:
3696
+ - load — { mapId: "usa"|"world"|"worldHighRes"|<custom>, projection?, options? }
3697
+ - pan — { lat, lon, duration? }
3698
+ - zoom — { level, duration? }
3699
+ - export_config — {}
3700
+ - import_custom — { url? | geojson?, projection? }
3701
+
3702
+ For region styling/selection use pinepaper_map_regions; for animations use pinepaper_map_animation; for CSV/GeoJSON/source-info use pinepaper_map_data.`,
4153
3703
  inputSchema: {
4154
3704
  type: 'object',
4155
3705
  properties: {
4156
- data: {
4157
- type: 'object',
4158
- description: 'Font data object from pinepaper_font_export_data',
4159
- },
3706
+ action: { type: 'string', enum: ['load', 'pan', 'zoom', 'export_config', 'import_custom'], description: 'Map action' },
3707
+ mapId: { type: 'string', description: 'Map identifier (load)' },
3708
+ projection: { type: 'string', description: 'Projection (load / import_custom)' },
3709
+ options: { type: 'object', description: 'Map options (load)', additionalProperties: true },
3710
+ lat: { type: 'number', description: 'Latitude (pan)' },
3711
+ lon: { type: 'number', description: 'Longitude (pan)' },
3712
+ level: { type: 'number', description: 'Zoom level (zoom)' },
3713
+ duration: { type: 'number', description: 'Animation duration (pan, zoom; default 0.5)' },
3714
+ url: { type: 'string', description: 'GeoJSON/TopoJSON URL (import_custom)' },
3715
+ geojson: { type: 'object', description: 'Inline GeoJSON (import_custom)' },
4160
3716
  },
4161
- required: ['data'],
3717
+ required: ['action'],
4162
3718
  },
4163
3719
  },
4164
3720
  {
4165
- name: 'pinepaper_font_clear',
3721
+ name: 'pinepaper_map_regions',
4166
3722
  annotations: {
4167
- title: 'Font Clear',
3723
+ title: 'Map: Region Styling + Selection',
4168
3724
  readOnlyHint: false,
4169
- destructiveHint: true,
4170
- idempotentHint: true,
3725
+ destructiveHint: false,
3726
+ idempotentHint: false,
4171
3727
  openWorldHint: false,
4172
3728
  },
4173
- description: `Clear all glyphs and reset the font. Removes all drawn characters.
3729
+ description: `Highlight, color, label, and select map regions. Requires a map loaded via pinepaper_map { action: "load" } first.
4174
3730
 
4175
- WARNING: This is destructive - all glyph progress will be lost.`,
3731
+ ACTIONS:
3732
+ - highlight — { regionIds: string[], color?, opacity? }
3733
+ - unhighlight — { regionIds?: string[] } omit to clear all
3734
+ - apply_colors — { data: Record<regionId, value>, options? } choropleth coloring
3735
+ - add_marker — { lat, lon, label?, color?, size? }
3736
+ - add_labels — { regions?: string[], style?, formatter? }
3737
+ - get_at_point — { x, y } region at canvas coords
3738
+ - select — { regionIds: string[] }
3739
+ - deselect — { regionIds?: string[] } omit to deselect all
3740
+ - get_highlighted — {}`,
4176
3741
  inputSchema: {
4177
3742
  type: 'object',
4178
- properties: {},
3743
+ properties: {
3744
+ action: { type: 'string', enum: ['highlight', 'unhighlight', 'apply_colors', 'add_marker', 'add_labels', 'get_at_point', 'select', 'deselect', 'get_highlighted'], description: 'Region action' },
3745
+ regionIds: { type: 'array', items: { type: 'string' } },
3746
+ color: { type: 'string' },
3747
+ opacity: { type: 'number' },
3748
+ data: { type: 'object', description: 'Region → value (apply_colors)', additionalProperties: true },
3749
+ options: { type: 'object', additionalProperties: true },
3750
+ lat: { type: 'number' },
3751
+ lon: { type: 'number' },
3752
+ label: { type: 'string' },
3753
+ size: { type: 'number' },
3754
+ regions: { type: 'array', items: { type: 'string' } },
3755
+ style: { type: 'object', additionalProperties: true },
3756
+ formatter: { type: 'string' },
3757
+ x: { type: 'number' },
3758
+ y: { type: 'number' },
3759
+ },
3760
+ required: ['action'],
4179
3761
  },
4180
3762
  },
4181
3763
  {
4182
- name: 'pinepaper_font_remove_overlap',
3764
+ name: 'pinepaper_map_animation',
4183
3765
  annotations: {
4184
- title: 'Font Remove Overlap',
3766
+ title: 'Map: Region Animations',
4185
3767
  readOnlyHint: false,
4186
3768
  destructiveHint: false,
4187
- idempotentHint: true,
3769
+ idempotentHint: false,
4188
3770
  openWorldHint: false,
4189
3771
  },
4190
- description: `Remove overlapping areas from a path (like FontForge's RemoveOverlap). Merges multiple overlapping paths into a single clean outline.
3772
+ description: `Animate map regions with keyframes or wave effects.
4191
3773
 
4192
- USE WHEN:
4193
- - Path has overlapping strokes that need merging
4194
- - Preparing a glyph path for clean font output`,
3774
+ ACTIONS:
3775
+ - animate_regions — { regions: Record<regionId, keyframes[]>, duration?, loop? }
3776
+ - animate_wave — { regions?: string[], waveDirection?, speed?, color?, duration?, loop? }
3777
+ - stop — { regionIds?: string[] }
3778
+ - get_animated — {}`,
4195
3779
  inputSchema: {
4196
3780
  type: 'object',
4197
3781
  properties: {
4198
- pathId: {
4199
- type: 'string',
4200
- description: 'Registry ID of the Paper.js path to process',
4201
- },
3782
+ action: { type: 'string', enum: ['animate_regions', 'animate_wave', 'stop', 'get_animated'], description: 'Animation action' },
3783
+ regions: { type: 'object', description: 'Keyframes per region (animate_regions) or list (animate_wave)', additionalProperties: true },
3784
+ regionIds: { type: 'array', items: { type: 'string' } },
3785
+ waveDirection: { type: 'string', enum: ['horizontal', 'vertical', 'radial'] },
3786
+ speed: { type: 'number' },
3787
+ color: { type: 'string' },
3788
+ duration: { type: 'number' },
3789
+ loop: { type: 'boolean' },
4202
3790
  },
4203
- required: ['pathId'],
3791
+ required: ['action'],
4204
3792
  },
4205
3793
  },
4206
3794
  {
4207
- name: 'pinepaper_font_correct_direction',
3795
+ name: 'pinepaper_map_data',
4208
3796
  annotations: {
4209
- title: 'Font Correct Direction',
3797
+ title: 'Map: Data Import + Export',
4210
3798
  readOnlyHint: false,
4211
3799
  destructiveHint: false,
4212
3800
  idempotentHint: true,
4213
3801
  openWorldHint: false,
4214
3802
  },
4215
- description: `Correct path winding direction for proper fill rendering (like FontForge's CorrectDirection). Ensures outer contours are clockwise and inner holes are counter-clockwise.
3803
+ description: `CSV / GeoJSON import-export and source-info introspection.
4216
3804
 
4217
- USE WHEN:
4218
- - Glyph fills are rendering incorrectly (holes appear filled)
4219
- - Preparing paths for font export`,
3805
+ ACTIONS:
3806
+ - export_csv — { regionIds?, columns?, download?, filename? }
3807
+ - import_csv — { csv: string, mapping?: { region?, value?, color? } }
3808
+ - export_geojson — { includeStyles?, includeMetadata?, selectedOnly?, download?, filename? }
3809
+ - export_original_geojson — { download?, filename? } source GeoJSON before styling
3810
+ - source_info — {} { source, projection, quality, regionCount, hasOriginalGeoJSON, isCustomImport }`,
4220
3811
  inputSchema: {
4221
3812
  type: 'object',
4222
3813
  properties: {
4223
- pathId: {
4224
- type: 'string',
4225
- description: 'Registry ID of the Paper.js path to process',
4226
- },
3814
+ action: { type: 'string', enum: ['export_csv', 'import_csv', 'export_geojson', 'export_original_geojson', 'source_info'], description: 'Data action' },
3815
+ regionIds: { type: 'array', items: { type: 'string' } },
3816
+ columns: { type: 'array', items: { type: 'string' } },
3817
+ csv: { type: 'string' },
3818
+ mapping: { type: 'object', additionalProperties: true },
3819
+ includeStyles: { type: 'boolean' },
3820
+ includeMetadata: { type: 'boolean' },
3821
+ selectedOnly: { type: 'boolean' },
3822
+ download: { type: 'boolean' },
3823
+ filename: { type: 'string' },
4227
3824
  },
4228
- required: ['pathId'],
3825
+ required: ['action'],
4229
3826
  },
4230
3827
  },
3828
+ // ---------------------------------------------------------------------------
3829
+ // DOMAIN: FONT TOOLS — single action-dispatched tool replaces 16 wrappers
3830
+ // ---------------------------------------------------------------------------
4231
3831
  {
4232
- name: 'pinepaper_font_cleanup_path',
3832
+ name: 'pinepaper_font',
4233
3833
  annotations: {
4234
- title: 'Font Cleanup Path',
3834
+ title: 'Font Studio',
4235
3835
  readOnlyHint: false,
4236
3836
  destructiveHint: false,
4237
- idempotentHint: true,
3837
+ idempotentHint: false,
4238
3838
  openWorldHint: false,
4239
3839
  },
4240
- description: `Apply all path cleanup operations in the correct order: removeOverlap -> correctDirection -> smooth. Convenience tool that combines all path preparation steps.
3840
+ description: `Font Studio control — single action-dispatched tool covering the full Studio API. Sixteen previous thin wrappers collapse into this one entry to reduce the tool list footprint without losing capability.
4241
3841
 
4242
- USE WHEN:
4243
- - Preparing a drawn path before creating a glyph
4244
- - Quick one-step path cleanup instead of calling individual operations`,
3842
+ ACTIONS:
3843
+ - show_studio — {} open the Font Studio UI
3844
+ - set_name — { name } name the in-progress font
3845
+ - get_required_chars — { set?: string } list chars to draw (default: minimum)
3846
+ - get_status — {} completion status
3847
+ - create_glyph — { character, pathId } attach a path as a glyph
3848
+ - create_space — { width? } create a space glyph
3849
+ - remove_glyph — { character }
3850
+ - set_metrics — { metrics: { unitsPerEm?, ascender?, descender?, xHeight?, capHeight? } } (or top-level keys)
3851
+ - export — { download?: boolean } export as OTF
3852
+ - load_into_document — {} load the font for use in this canvas
3853
+ - export_data — { download?: boolean } export as JSON
3854
+ - import_data — { data: object } import from JSON
3855
+ - clear — {} reset everything
3856
+ - remove_overlap — { pathId } path cleanup
3857
+ - correct_direction — { pathId } path cleanup
3858
+ - cleanup_path — { pathId, removeOverlap?, correctDirection?, smooth?, smoothTolerance? }`,
4245
3859
  inputSchema: {
4246
3860
  type: 'object',
4247
3861
  properties: {
4248
- pathId: {
3862
+ action: {
4249
3863
  type: 'string',
4250
- description: 'Registry ID of the Paper.js path to process',
4251
- },
4252
- removeOverlap: {
4253
- type: 'boolean',
4254
- description: 'Merge overlapping strokes (default: true)',
4255
- },
4256
- correctDirection: {
4257
- type: 'boolean',
4258
- description: 'Fix winding direction for fills (default: true)',
4259
- },
4260
- smooth: {
4261
- type: 'boolean',
4262
- description: 'Apply path smoothing (default: true)',
4263
- },
4264
- smoothTolerance: {
4265
- type: 'number',
4266
- description: 'Smoothing tolerance - higher = more simplification (default: 2.5)',
3864
+ enum: [
3865
+ 'show_studio', 'set_name', 'get_required_chars', 'get_status',
3866
+ 'create_glyph', 'create_space', 'remove_glyph', 'set_metrics',
3867
+ 'export', 'load_into_document', 'export_data', 'import_data',
3868
+ 'clear', 'remove_overlap', 'correct_direction', 'cleanup_path',
3869
+ ],
3870
+ description: 'Font Studio action',
3871
+ },
3872
+ name: { type: 'string', description: 'Font name (set_name)' },
3873
+ set: { type: 'string', description: 'Character set name (get_required_chars; default "minimum")' },
3874
+ character: { type: 'string', description: 'Single-character glyph identifier (create_glyph, remove_glyph)' },
3875
+ pathId: { type: 'string', description: 'Item id of the path source (create_glyph, remove_overlap, correct_direction, cleanup_path)' },
3876
+ width: { type: 'number', description: 'Space-glyph width (create_space)' },
3877
+ download: { type: 'boolean', description: 'Trigger browser download (export, export_data); default true' },
3878
+ metrics: {
3879
+ type: 'object',
3880
+ description: 'Font metrics (set_metrics)',
3881
+ properties: {
3882
+ unitsPerEm: { type: 'number' },
3883
+ ascender: { type: 'number' },
3884
+ descender: { type: 'number' },
3885
+ xHeight: { type: 'number' },
3886
+ capHeight: { type: 'number' },
3887
+ },
4267
3888
  },
3889
+ data: { type: 'object', description: 'Font JSON payload (import_data)' },
3890
+ removeOverlap: { type: 'boolean', description: 'cleanup_path option' },
3891
+ correctDirection: { type: 'boolean', description: 'cleanup_path option' },
3892
+ smooth: { type: 'boolean', description: 'cleanup_path option (default true)' },
3893
+ smoothTolerance: { type: 'number', description: 'cleanup_path tolerance (default 2.5)' },
4268
3894
  },
4269
- required: ['pathId'],
3895
+ required: ['action'],
4270
3896
  },
4271
3897
  },
4272
3898
  // ---------------------------------------------------------------------------
@@ -4486,7 +4112,7 @@ USE WHEN:
4486
4112
  - "grid background", "geometric abstract", "noise texture"
4487
4113
  - Creating dynamic procedural backgrounds
4488
4114
 
4489
- GENERATORS (14 total):
4115
+ GENERATORS (15 total):
4490
4116
 
4491
4117
  Classic:
4492
4118
  - drawSunburst: Radial rays from center (rayCount, colors, bgColor, opacity, rayGap, gradientRays)
@@ -4512,7 +4138,22 @@ New — Particles:
4512
4138
  - drawWindField: Directional wind particles with noise turbulence (particleCount, colors, direction, turbulence, trailLength, speed)
4513
4139
 
4514
4140
  New — Textures:
4515
- - drawNoiseTexture: Perlin/grain/stipple noise (noiseType: perlin|grain|stipple, colors, scale, density, animated)`,
4141
+ - drawNoiseTexture: Perlin/grain/stipple noise (noiseType: perlin|grain|stipple, colors, scale, density, animated)
4142
+
4143
+ New — Tech:
4144
+ - drawGlobeWireframe: Vercel-style wireframe globe (bgColor, wireColor, glowColor, highlightColor, meridianCount, latitudeCount, globeRadius, nodeCount, nodeSize, animationEnabled, animationSpeed, strokeWidth, gridOpacity)
4145
+
4146
+ PineMath — Math/Science:
4147
+ - drawFunctionPlot: Plot y=f(x) (expression, xMin, xMax, yMin, yMax, color, lineWidth, showAxes, showGrid, steps, animate: none|scroll-right|scroll-left|oscillate|bounce|wipe|custom)
4148
+ - drawParametricCurve: Plot (x(t),y(t)) Lissajous/spirals/roses (xExpression, yExpression, tMin, tMax, color, steps, scale, animate: none|linear|slow|fast|wave|bounce, trailFade)
4149
+ - drawSimulation: Dynamic systems with ODE solvers (preset: pendulum|springMass|lorenz|doublePendulum|vanderpol, solver: euler|rk4|rk45, timeScale, showTrail, trailLength, trailColor, objectColor)
4150
+ - drawSpectrumAnalyzer: FFT signal visualization (waveform: sine|square|sawtooth|triangle|noise|composite, frequency, amplitude, sampleRate, window: none|hann|hamming|blackman, waveColor, spectrumColor)
4151
+ - draw3DSurface: 3D surfaces from equations (preset: torus|sphere|wave|klein|mobius|custom, xExpr, yExpr, zExpr, uSteps, vSteps, scale, rotateSpeed)
4152
+
4153
+ COMMON PARAMS (all generators):
4154
+ - bgColor: Background color ("none"/"transparent" for no background)
4155
+ - interactive: Make generated items selectable/draggable (default false)
4156
+ - clipToCanvas: Clip output to canvas bounds (default true, set false for overflow)`,
4516
4157
  inputSchema: {
4517
4158
  type: 'object',
4518
4159
  properties: {
@@ -4523,6 +4164,9 @@ New — Textures:
4523
4164
  'drawCircuit', 'drawWaves', 'drawPattern',
4524
4165
  'drawBokeh', 'drawGradientMesh', 'drawGeometricAbstract', 'drawWindField',
4525
4166
  'drawFluidFlow', 'drawOrganicFlow', 'drawNoiseTexture',
4167
+ 'drawGlobeWireframe',
4168
+ 'drawFunctionPlot', 'drawParametricCurve', 'drawSimulation',
4169
+ 'drawSpectrumAnalyzer', 'draw3DSurface',
4526
4170
  ],
4527
4171
  description: 'Generator name',
4528
4172
  },
@@ -4571,19 +4215,37 @@ USE WHEN:
4571
4215
 
4572
4216
  USE WHEN:
4573
4217
  - Adding sparkle/glitter effects
4574
- - Creating burst/explosion effects
4575
- - Enhancing visual impact
4218
+ - Creating burst/explosion, fire, smoke effects
4219
+ - Weather effects (rain, snow)
4220
+ - Celebration effects (confetti)
4221
+ - Enhancing visual impact (ripple, glow, electric)
4576
4222
 
4577
- EFFECTS:
4223
+ EFFECTS (15 total):
4578
4224
  - sparkle: Glitter/sparkle particles (color, speed, size)
4579
- - blast: Explosion burst effect (color, radius, count)`,
4225
+ - blast: Explosion burst effect (color, radius, count)
4226
+ - smoke: Rising smoke plumes (color, speed, size, drift, height, growthRate)
4227
+ - fire: Animated fire/flames (color, colors, speed, size, height, turbulence)
4228
+ - rain: Falling rain drops (color, count, speed, angle, spread)
4229
+ - snow: Falling snowflakes (color, count, speed, spread, particleLife)
4230
+ - confetti: Celebration confetti (colors, count, radius, gravity, size, spread, interval, repeat)
4231
+ - ripple: Expanding ring ripples (color, speed, maxRadius, ringCount, strokeWidth)
4232
+ - glow: Pulsing glow aura (color drives the shadow halo; speed, intensity, size; optional fill — interior tint decoupled from color; fillOpacity 0..1 multiplies intensity opacity)
4233
+ - electric: Lightning bolts (color, speed, boltCount, length, flickerRate)
4234
+ - bubbles: Rising transparent bubbles (color drives the rim; count, speed, size, spread; optional fill — interior tint, default null = outlined-only; fillOpacity 0..1, default 0.25 when fill is set)
4235
+ - dust: Ambient drifting motes (color, count, speed, size, spread)
4236
+ - fireflies: Glowing wandering dots (color, count, speed, size, spread)
4237
+ - shockwave: Expanding concentric rings — burst type (speed, maxRadius, count, thickness)
4238
+ - trail: Fading afterimages following movement (speed, count, size, fadeRate)
4239
+
4240
+ EXAMPLE — bubbles with magenta interior over a blue rim:
4241
+ { effectType: "bubbles", params: { color: "#93c5fd", fill: "#ff00aa", fillOpacity: 0.4 } }`,
4580
4242
  inputSchema: {
4581
4243
  type: 'object',
4582
4244
  properties: {
4583
4245
  itemId: { type: 'string', description: 'Registry ID of the item' },
4584
4246
  effectType: {
4585
4247
  type: 'string',
4586
- enum: ['sparkle', 'blast'],
4248
+ enum: ['sparkle', 'blast', 'smoke', 'fire', 'rain', 'snow', 'confetti', 'ripple', 'glow', 'electric', 'bubbles', 'dust', 'fireflies', 'shockwave', 'trail'],
4587
4249
  description: 'Type of effect',
4588
4250
  },
4589
4251
  params: {
@@ -5227,24 +4889,17 @@ RETURNS:
5227
4889
  idempotentHint: true,
5228
4890
  openWorldHint: true,
5229
4891
  },
5230
- description: `Connect to PinePaper Studio Editor in a browser.
5231
-
5232
- ⚠️ USUALLY NOT NEEDED — the browser auto-connects on the first tool call. Do NOT call this tool unless you need custom settings.
5233
-
5234
- Call this ONLY when: you need a custom URL, or you need headless: false to see the browser window.
5235
- Call this AT MOST once — never call it again after connected.
5236
-
5237
- For normal workflows, skip this tool and go directly to pinepaper_agent_start_job.`,
4892
+ description: `Connect to PinePaper Studio in a browser. Auto-connects headless on first tool call. Call with headless: false to show the browser window, or headless: true to hide it. Can be called mid-session to toggle visibility.`,
5238
4893
  inputSchema: {
5239
4894
  type: 'object',
5240
4895
  properties: {
5241
- url: {
5242
- type: 'string',
5243
- description: 'Custom PinePaper Studio URL (default: https://pinepaper.studio/editor)',
5244
- },
5245
4896
  headless: {
5246
4897
  type: 'boolean',
5247
- description: 'Run browser in headless mode - no visible window (default: false - browser window is visible)',
4898
+ description: 'Run in headless mode (default: false when explicitly called)',
4899
+ },
4900
+ url: {
4901
+ type: 'string',
4902
+ description: 'Studio URL to connect to (e.g. "http://localhost:3000" for local dev). Must be http:// or https:// — file:/data:/javascript: are rejected. Overrides the PINEPAPER_STUDIO_URL env var and the prod default. "/editor" and agent-mode params are added automatically. Passing a URL with a different origin/pathname reconnects.',
5248
4903
  },
5249
4904
  },
5250
4905
  },
@@ -5468,19 +5123,19 @@ PRIVACY: No screenshots, no tool call arguments, no user content — only struct
5468
5123
  {
5469
5124
  name: 'pinepaper_agent_start_job',
5470
5125
  annotations: {
5471
- title: 'Start Agent Job',
5126
+ title: 'Create Animation/Video/Graphic — Start Here',
5472
5127
  readOnlyHint: false,
5473
5128
  destructiveHint: false,
5474
5129
  idempotentHint: false,
5475
5130
  openWorldHint: false,
5476
5131
  },
5477
- description: `Start a new agent job. Then batch_execute ALL operations, then end_job to get a screenshot for user validation.
5132
+ description: `Start a new agent job for creating animations, videos, graphics, or any visual content. Do NOT generate HTML or React — use PinePaper tools instead.
5478
5133
 
5479
5134
  ⚠️ Call ONCE per pipeline. NEVER restart — creates duplicates.
5480
5135
 
5481
5136
  WORKFLOW: start_job → batch_execute (everything in ONE call) → end_job (screenshot) → show user → iterate if needed.
5482
5137
 
5483
- RETURNS: canvasSize {width, height} — use this to position items within bounds.
5138
+ RETURNS: canvasSize {width, height} — use this to position items within bounds. Also returns ontology: a pp: triples + item summary snapshot of the (typically empty) canvas. Reuse this baseline across the same agent turn instead of calling pinepaper_get_canvas_ontology unless you've mutated the canvas. When clearCanvas is false, the ontology captures whatever's already on the canvas.
5484
5139
 
5485
5140
  CANVAS PRESETS: instagram (1080x1080), instagram-story (1080x1920), tiktok (1080x1920), youtube (1920x1080), youtube-thumbnail (1280x720), twitter (1200x675), linkedin (1200x627), web, print-a4, print-letter`,
5486
5141
  inputSchema: {
@@ -5492,7 +5147,7 @@ CANVAS PRESETS: instagram (1080x1080), instagram-story (1080x1920), tiktok (1080
5492
5147
  },
5493
5148
  description: {
5494
5149
  type: 'string',
5495
- description: 'Pass the user\'s request/prompt here — the server returns contextual design guidance when the prompt is vague',
5150
+ description: 'Pass the user\'s request/prompt here for creative direction',
5496
5151
  },
5497
5152
  screenshotPolicy: {
5498
5153
  type: 'string',
@@ -5508,13 +5163,17 @@ CANVAS PRESETS: instagram (1080x1080), instagram-story (1080x1920), tiktok (1080
5508
5163
  type: 'boolean',
5509
5164
  description: 'Clear canvas when starting job (default: true)',
5510
5165
  },
5166
+ includeOntology: {
5167
+ type: 'boolean',
5168
+ description: 'Include canvas ontology snapshot in the result (default: true). Pre-bundles a pp: triples baseline so the agent can reason about composition without a follow-up pinepaper_get_canvas_ontology call.',
5169
+ },
5511
5170
  },
5512
5171
  },
5513
5172
  },
5514
5173
  {
5515
5174
  name: 'pinepaper_agent_end_job',
5516
5175
  annotations: {
5517
- title: 'End Agent Job',
5176
+ title: 'Finish & Show Screenshot to User',
5518
5177
  readOnlyHint: false,
5519
5178
  destructiveHint: false,
5520
5179
  idempotentHint: false,
@@ -5621,7 +5280,7 @@ EXAMPLES:
5621
5280
  {
5622
5281
  name: 'pinepaper_agent_batch_execute',
5623
5282
  annotations: {
5624
- title: 'Batch Execute Operations',
5283
+ title: 'Build Scene — Items, Animations, Effects in One Call',
5625
5284
  readOnlyHint: false,
5626
5285
  destructiveHint: false,
5627
5286
  idempotentHint: false,
@@ -5635,6 +5294,8 @@ NOTE: For diagrams (flowcharts, UML), use pinepaper_create_diagram_shape + pinep
5635
5294
 
5636
5295
  ⚠️ SIZING: All positions/sizes MUST fit within the canvas. start_job returns canvasSize. Keep items within 5%-95% of canvas width/height. Max canvas: 4096x4096.
5637
5296
 
5297
+ ONTOLOGY PREFLIGHT: Before code generation, this tool validates itemType, relationType, effectType, and generatorName against the canonical PinePaper vocabulary. A typo (e.g. "circel") returns a structured VALIDATION_ERROR with the operation index, the offending field, the canonical valid list, and a suggested fix — fix and retry rather than guessing. Pass skipValidation: true to bypass when intentionally using experimental vocabulary.
5298
+
5638
5299
  WORKFLOW:
5639
5300
  1. pinepaper_agent_start_job → 2. pinepaper_agent_batch_execute (everything) → 3. pinepaper_agent_end_job (screenshot for validation)
5640
5301
  After validation: user reviews screenshot → feedback → modify/recreate as needed.
@@ -5645,7 +5306,8 @@ CANVAS SETUP:
5645
5306
  set_canvas_size — {width, height} or {preset: "instagram"|"youtube"|"tiktok"|...}
5646
5307
  set_background — {backgroundColor: "#hex"}
5647
5308
  execute_generator — {generatorName, generatorParams} → fills canvas with procedural art
5648
- Generators: drawBokeh, drawGradientMesh, drawWaves, drawSunburst, drawSunsetScene, drawGrid, drawCircuit, drawPattern, drawStackedCircles, drawGeometricAbstract, drawWindField, drawFluidFlow, drawOrganicFlow, drawNoiseTexture
5309
+ Generators: drawBokeh, drawGradientMesh, drawWaves, drawSunburst, drawSunsetScene, drawGrid, drawCircuit, drawPattern, drawStackedCircles, drawGeometricAbstract, drawWindField, drawFluidFlow, drawOrganicFlow, drawNoiseTexture, drawGlobeWireframe
5310
+ PineMath: drawFunctionPlot (y=f(x) plots), drawParametricCurve (x(t),y(t)), drawSimulation (pendulum, Lorenz, spring-mass), drawSpectrumAnalyzer (FFT), draw3DSurface (torus, sphere, Klein bottle)
5649
5311
 
5650
5312
  ITEMS:
5651
5313
  create — {itemType, position: {x,y}, properties}
@@ -5663,18 +5325,18 @@ ITEMS:
5663
5325
 
5664
5326
  ANIMATION:
5665
5327
  animate — Loop animation: {itemId, animationType, animationOptions}
5666
- animationType: pulse, rotate, bounce, fade, wobble, slide, typewriter
5328
+ animationType: ${SIMPLE_ANIMATION_TYPES_LIST}
5667
5329
  keyframe_animate — Timed animation: {itemId, keyframes: [{time, properties, easing}], duration, loop}
5668
5330
  Animatable properties: opacity, scale, scaleX, scaleY, x, y, rotation, fillColor, strokeColor, fontSize
5669
5331
  Easing: easeInOut, easeIn, easeOut, easeInCubic, easeOutCubic, easeOutBounce, linear
5670
5332
  relation — Behavioral link: {sourceId, targetId, relationType, relationOptions}
5671
- relationType: orbits, follows, attached_to, points_at, mirrors, parallax, wave_through, morphs_to (+ 9 more in schema)
5333
+ relationType: orbits, follows, attached_to, points_at, mirrors, parallax, wave_through, morphs_to, group_morphs_to, moves_along_path (+ 9 more in schema)
5672
5334
 
5673
5335
  EFFECTS:
5674
5336
  apply_mask — Reveal effect: {itemId, maskPreset, maskOptions}
5675
5337
  maskPreset: wipeLeft, wipeRight, wipeUp, wipeDown, iris, irisOut, star, heart, curtainHorizontal, curtainVertical, cinematic, diagonalWipe, revealUp, revealDown
5676
5338
  apply_effect — Visual effect: {itemId, effectType, effectParams}
5677
- effectType: sparkle, blast
5339
+ effectType: ${EFFECT_TYPES_LIST}
5678
5340
 
5679
5341
  PLAYBACK:
5680
5342
  play_timeline — {action: "play"|"stop"|"seek", duration, loop}
@@ -5716,7 +5378,7 @@ EXAMPLE — Animated sky scene with timed reveals:
5716
5378
  backgroundColor: { type: 'string', description: 'For set_background: hex color' },
5717
5379
  generatorName: {
5718
5380
  type: 'string',
5719
- enum: ['drawSunburst', 'drawSunsetScene', 'drawGrid', 'drawWaves', 'drawCircuit', 'drawStackedCircles', 'drawPattern', 'drawBokeh', 'drawGradientMesh', 'drawGeometricAbstract', 'drawWindField', 'drawFluidFlow', 'drawOrganicFlow', 'drawNoiseTexture'],
5381
+ enum: ['drawSunburst', 'drawSunsetScene', 'drawGrid', 'drawWaves', 'drawCircuit', 'drawStackedCircles', 'drawPattern', 'drawBokeh', 'drawGradientMesh', 'drawGeometricAbstract', 'drawWindField', 'drawFluidFlow', 'drawOrganicFlow', 'drawNoiseTexture', 'drawGlobeWireframe'],
5720
5382
  description: 'For execute_generator: generator name',
5721
5383
  },
5722
5384
  generatorParams: { type: 'object', description: 'For execute_generator: parameters' },
@@ -5760,7 +5422,7 @@ EXAMPLE — Animated sky scene with timed reveals:
5760
5422
  targetId: { type: 'string', description: 'For relation: target item ID or $N' },
5761
5423
  relationType: {
5762
5424
  type: 'string',
5763
- enum: ['orbits', 'follows', 'attached_to', 'points_at', 'mirrors', 'parallax', 'animates', 'grows_from', 'staggered_with', 'wave_through', 'circumscribes', 'morphs_to', 'maintains_distance', 'bounds_to', 'indicates', 'camera_follows', 'camera_animates'],
5425
+ enum: ['orbits', 'follows', 'attached_to', 'points_at', 'mirrors', 'parallax', 'animates', 'grows_from', 'staggered_with', 'wave_through', 'circumscribes', 'morphs_to', 'group_morphs_to', 'moves_along_path', 'maintains_distance', 'bounds_to', 'indicates', 'camera_follows', 'camera_animates'],
5764
5426
  description: 'For relation: type',
5765
5427
  },
5766
5428
  relationOptions: { type: 'object', description: 'For relation: options' },
@@ -5775,7 +5437,7 @@ EXAMPLE — Animated sky scene with timed reveals:
5775
5437
  // Effects
5776
5438
  effectType: {
5777
5439
  type: 'string',
5778
- enum: ['sparkle', 'blast'],
5440
+ enum: ['sparkle', 'blast', 'smoke', 'fire', 'rain', 'snow', 'confetti', 'ripple', 'glow', 'electric', 'bubbles', 'dust', 'fireflies', 'shockwave', 'trail'],
5779
5441
  description: 'For apply_effect: effect type',
5780
5442
  },
5781
5443
  effectParams: { type: 'object', description: 'For apply_effect: parameters' },
@@ -5795,6 +5457,10 @@ EXAMPLE — Animated sky scene with timed reveals:
5795
5457
  type: 'boolean',
5796
5458
  description: 'If true, all operations succeed or all fail (default: true)',
5797
5459
  },
5460
+ skipValidation: {
5461
+ type: 'boolean',
5462
+ description: 'Skip the ontology preflight that catches vocabulary typos before browser execution (default: false). Only set true when knowingly using experimental values.',
5463
+ },
5798
5464
  },
5799
5465
  required: ['operations'],
5800
5466
  },
@@ -5802,7 +5468,7 @@ EXAMPLE — Animated sky scene with timed reveals:
5802
5468
  {
5803
5469
  name: 'pinepaper_agent_export',
5804
5470
  annotations: {
5805
- title: 'Smart Export',
5471
+ title: 'Export as MP4 Video, GIF, PNG, SVG, or PDF',
5806
5472
  readOnlyHint: true,
5807
5473
  destructiveHint: false,
5808
5474
  idempotentHint: true,
@@ -5822,6 +5488,7 @@ PLATFORMS & OPTIMAL FORMATS:
5822
5488
 
5823
5489
  FORMATS: svg, png, gif, mp4, webm, pdf.
5824
5490
  QUALITY: draft, standard, high.
5491
+ FRAMING: canvas (default, full canvas) | camera (camera_animates first-keyframe viewport — video formats only, requires a keyframe-mode walkthrough on the canvas; camera animation still drives motion within the fixed output frame).
5825
5492
 
5826
5493
  ⚠️ If export fails, do NOT retry with different formats — report the error to the user.
5827
5494
  ⚠️ When user asks for "video", always use format: "mp4".
@@ -5829,7 +5496,8 @@ QUALITY: draft, standard, high.
5829
5496
  EXAMPLES:
5830
5497
  - {platform: "instagram"} — auto-selects best format
5831
5498
  - {platform: "instagram", format: "mp4"} — force MP4
5832
- - {platform: "web", format: "svg"} — animated SVG`,
5499
+ - {platform: "web", format: "svg"} — animated SVG
5500
+ - {platform: "youtube", format: "mp4", framing: "camera"} — render only what the camera frames during the walkthrough`,
5833
5501
  inputSchema: {
5834
5502
  type: 'object',
5835
5503
  properties: {
@@ -5848,6 +5516,11 @@ EXAMPLES:
5848
5516
  enum: ['draft', 'standard', 'high'],
5849
5517
  description: 'Export quality level (default: standard)',
5850
5518
  },
5519
+ framing: {
5520
+ type: 'string',
5521
+ enum: ['canvas', 'camera'],
5522
+ description: 'Output framing. "canvas" (default) renders the full canvas. "camera" renders only the first-keyframe viewport of a camera_animates walkthrough — video formats only.',
5523
+ },
5851
5524
  },
5852
5525
  required: ['platform'],
5853
5526
  },
@@ -6105,6 +5778,171 @@ EXAMPLES:
6105
5778
  },
6106
5779
  },
6107
5780
  // ---------------------------------------------------------------------------
5781
+ // ONTOLOGY TOOLS (Design Knowledge Graph)
5782
+ // ---------------------------------------------------------------------------
5783
+ {
5784
+ name: 'pinepaper_get_canvas_ontology',
5785
+ annotations: {
5786
+ title: 'Get Canvas Ontology',
5787
+ readOnlyHint: true,
5788
+ destructiveHint: false,
5789
+ idempotentHint: true,
5790
+ openWorldHint: false,
5791
+ },
5792
+ description: `Capture the live canvas as compact pp: ontology triples + a structured item summary.
5793
+
5794
+ USE THIS instead of pinepaper_get_items when you need to REASON about composition (what's on the canvas, how items relate, what's animated). Typical scenes shrink 3-10× compared to a raw item dump while preserving relations, animations, effects, masks, and collage styling.
5795
+
5796
+ OUTPUT (a snapshot of FxTool's canvas state):
5797
+ - canvasWidth, canvasHeight, canvasPreset
5798
+ - itemCount, itemTypes ([unique]), hasAnimations, relationCount
5799
+ - items: capped item summaries with positions, colors, group structure, collage metadata, keyframes, effects, deformations
5800
+ - triples: a TripleLanguage-serialized pp: triple block (compact tokenized form). Read this for structural reasoning.
5801
+ - viewport (when includeViewport: true): zoom + center + hasCameraAnimation flag
5802
+
5803
+ OPTIONS:
5804
+ - maxItems (default 50): cap on item summaries. Larger scenes are truncated, not paginated — pinepaper_query_ontology and pinepaper_get_items remain available for full enumeration.
5805
+ - maxChildren (default 10): cap on per-group child summaries.
5806
+ - includeViewport (default false): include zoom/pan/camera-animation flag.
5807
+
5808
+ NOTE: Requires FxTool with the canvas-ontology promotion. Returns { success: false, error } with a clear hint when running against an older build.`,
5809
+ inputSchema: {
5810
+ type: 'object',
5811
+ properties: {
5812
+ maxItems: { type: 'number', description: 'Cap on item summaries (default 50, max 500).' },
5813
+ maxChildren: { type: 'number', description: 'Cap on per-group child summaries (default 10, max 50).' },
5814
+ includeViewport: { type: 'boolean', description: 'Include zoom/pan/camera-animation state (default false).' },
5815
+ },
5816
+ },
5817
+ },
5818
+ {
5819
+ name: 'pinepaper_analyze_design',
5820
+ annotations: {
5821
+ title: 'Analyze Design',
5822
+ readOnlyHint: true,
5823
+ destructiveHint: false,
5824
+ idempotentHint: true,
5825
+ openWorldHint: false,
5826
+ },
5827
+ description: `Analyze a template or scene definition using the PinePaper Design Knowledge Graph.
5828
+
5829
+ Extracts a typed graph with pp: namespace nodes, edges, patterns, math functions, semantic metadata, and a structural fingerprint. Also produces a JSON-LD export.
5830
+
5831
+ INPUT: A template definition object with { id, name, category, data: { items: [...], relations: [...] } }
5832
+
5833
+ RETURNS: Graph analysis including node/edge type counts, detected patterns (orbitalComposition, staggeredReveal, maskReveal, etc.), math functions used, semantic inference (mood, intent, audience, contentType), and JSON-LD.
5834
+
5835
+ USE WHEN:
5836
+ - Understanding the structural composition of a design
5837
+ - Comparing design complexity before/after changes
5838
+ - Generating metadata for design catalogs`,
5839
+ inputSchema: {
5840
+ type: 'object',
5841
+ properties: {
5842
+ definition: {
5843
+ type: 'object',
5844
+ description: 'Template or scene definition object',
5845
+ },
5846
+ },
5847
+ required: ['definition'],
5848
+ },
5849
+ },
5850
+ {
5851
+ name: 'pinepaper_validate_design',
5852
+ annotations: {
5853
+ title: 'Validate Design',
5854
+ readOnlyHint: true,
5855
+ destructiveHint: false,
5856
+ idempotentHint: true,
5857
+ openWorldHint: false,
5858
+ },
5859
+ description: `Validate and score a template definition against the PinePaper ontology.
5860
+
5861
+ Two-phase analysis:
5862
+ 1. Schema validation — checks required fields, known item/relation types, keyframe structure, semantic vocabulary compliance
5863
+ 2. Quality scoring — rates across 5 dimensions: completeness (0.20), animationDesign (0.25), semanticRichness (0.20), compositionUse (0.15), structuralDepth (0.20)
5864
+
5865
+ Quality tiers: basic (<0.4), fair (0.4-0.6), good (0.6-0.8), excellent (>=0.8)
5866
+
5867
+ USE WHEN:
5868
+ - Checking a template for structural issues before publishing
5869
+ - Comparing quality scores between template variants
5870
+ - Validating that all item/relation types are in the vocabulary`,
5871
+ inputSchema: {
5872
+ type: 'object',
5873
+ properties: {
5874
+ definition: {
5875
+ type: 'object',
5876
+ description: 'Template or scene definition object to validate',
5877
+ },
5878
+ },
5879
+ required: ['definition'],
5880
+ },
5881
+ },
5882
+ {
5883
+ name: 'pinepaper_query_ontology',
5884
+ annotations: {
5885
+ title: 'Query Ontology',
5886
+ readOnlyHint: true,
5887
+ destructiveHint: false,
5888
+ idempotentHint: true,
5889
+ openWorldHint: false,
5890
+ },
5891
+ description: `Query the PinePaper design knowledge graph — explore types, properties, edges, hierarchy, and patterns.
5892
+
5893
+ USE WHEN:
5894
+ - Discovering available item types, relation types, or generators
5895
+ - Checking what properties a type supports and which are animatable
5896
+ - Navigating the type hierarchy (parent/child relationships)
5897
+ - Understanding how types relate to each other
5898
+
5899
+ QUERIES (14):
5900
+ Listing:
5901
+ - list_types: All item types (filter by category, includeAbstract)
5902
+ - list_edges: All relation/edge types (filter by category)
5903
+ - list_generators: All background generators (filter by category)
5904
+ - list_effects: All visual effect types
5905
+ - list_patterns: All detected design patterns
5906
+ - list_math_functions: All math functions used in animations
5907
+
5908
+ Hierarchy:
5909
+ - type_hierarchy: Ancestry chain for a ppType (e.g. pp:Circle → pp:CanvasShape → pp:CanvasElement)
5910
+ - type_children: Direct subtypes of a ppType
5911
+ - is_subtype: Check if typeA is a subtype of typeB
5912
+
5913
+ Properties:
5914
+ - type_properties: All properties for a ppType (inherited + direct)
5915
+ - animatable_properties: Only animatable properties for a ppType
5916
+
5917
+ Lookup:
5918
+ - node_type: Map an itemType string (e.g. "circle") to its pp: type
5919
+ - edge_type: Map a relationName string (e.g. "orbits") to its pp: edge
5920
+ - edge_info: Full metadata for an edge type`,
5921
+ inputSchema: {
5922
+ type: 'object',
5923
+ properties: {
5924
+ query: {
5925
+ type: 'string',
5926
+ enum: [
5927
+ 'list_types', 'list_edges', 'list_generators', 'list_effects',
5928
+ 'list_patterns', 'list_math_functions',
5929
+ 'type_hierarchy', 'type_children', 'type_properties', 'animatable_properties',
5930
+ 'is_subtype', 'edge_info', 'node_type', 'edge_type',
5931
+ ],
5932
+ description: 'Query type',
5933
+ },
5934
+ ppType: { type: 'string', description: 'pp: namespaced type (e.g. "pp:Circle") — for hierarchy/property queries' },
5935
+ itemType: { type: 'string', description: 'PinePaper item type string (e.g. "circle") — for node_type lookup' },
5936
+ relationName: { type: 'string', description: 'Relation name (e.g. "orbits") — for edge_type/edge_info lookup' },
5937
+ typeA: { type: 'string', description: 'First type for is_subtype check' },
5938
+ typeB: { type: 'string', description: 'Second type (ancestor) for is_subtype check' },
5939
+ category: { type: 'string', description: 'Filter by category for list queries' },
5940
+ includeAbstract: { type: 'boolean', description: 'Include abstract types in list_types (default: false)' },
5941
+ },
5942
+ required: ['query'],
5943
+ },
5944
+ },
5945
+ // ---------------------------------------------------------------------------
6108
5946
  // ON-DEMAND TOOL GUIDE (RLM-inspired — query detailed docs in minimal mode)
6109
5947
  // ---------------------------------------------------------------------------
6110
5948
  {
@@ -6120,8 +5958,10 @@ EXAMPLES:
6120
5958
 
6121
5959
  USE WHEN: You need full parameter docs, examples, or workflow guidance — especially in minimal verbosity mode where tool descriptions are short summaries.
6122
5960
 
5961
+ PREFER RESOURCES WHERE POSSIBLE: The full AI Agent Guide is also available via the MCP resources API at pinepaper://docs/agent-guide — clients that support resources should pull it that way rather than calling this tool. Per-domain references live at pinepaper://docs/{generators,relations,masks,diagrams,maps,effects-and-filters,fonts,custom-paths,paperjs-in-pinepaper,templates,customization,getting-started}. Use this tool when the client doesn't support resources or when you want a specific tool's verbose description.
5962
+
6123
5963
  MODES:
6124
- - No args → returns the full AI Agent Guide (workflow, rules, batch operations, visual composition tips)
5964
+ - No args → returns the full AI Agent Guide (same content as pinepaper://docs/agent-guide)
6125
5965
  - tool: "pinepaper_agent_batch_execute" → returns that tool's full verbose description
6126
5966
  - category: "animation" → returns all tools in that category with full descriptions
6127
5967
 
@@ -6187,6 +6027,224 @@ VERBOSITY:
6187
6027
  },
6188
6028
  },
6189
6029
  },
6030
+ // ---------------------------------------------------------------------------
6031
+ // DATA VISUALIZATION (CHARTS)
6032
+ // ---------------------------------------------------------------------------
6033
+ {
6034
+ name: 'pinepaper_create_chart',
6035
+ annotations: {
6036
+ title: 'Create Chart',
6037
+ readOnlyHint: false,
6038
+ destructiveHint: false,
6039
+ idempotentHint: false,
6040
+ openWorldHint: false,
6041
+ },
6042
+ description: `Create and manage data visualizations on the canvas.
6043
+
6044
+ ACTIONS:
6045
+ - create: Create a chart. Params: chartType, data (array of objects), options
6046
+ - update: Update chart data. Params: chartId, data, options
6047
+ - reconfigure: Change chart styling. Params: chartId, options
6048
+ - remove: Delete a chart. Params: chartId
6049
+
6050
+ CHART TYPES: bar, line, scatter, area
6051
+
6052
+ DATA FORMAT: Array of objects, e.g. [{category: "A", value: 10}, {category: "B", value: 20}]
6053
+
6054
+ OPTIONS (vary by chart type):
6055
+ - Common: title, width, height, x, y, colors, animation, axisColor, labelColor, labelFontSize
6056
+ - Bar: barWidth, barGap, xLabel, yLabel
6057
+ orient: 'horizontal' flips bars to grow rightward from a left Y-axis — best for long category names
6058
+ labelArrangement: 'auto'|'horizontal'|'slanted'|'vertical'|'truncate'|'wrap'
6059
+ auto — smart: measures widest label and picks horizontal → slanted (−45°) → vertical (−90°) by slot width
6060
+ slanted — force −45° rotation
6061
+ vertical — force −90° rotation
6062
+ truncate — ellipsis when label exceeds slot (uses ctx.measureText; override char cap with labelTruncateMaxChars)
6063
+ wrap — split on last space before midpoint, up to two lines
6064
+ Bottom-margin is capped at 25% (slanted) / 35% (vertical) of chart height, so changing labelFontSize shifts labels inside a stable budget rather than shrinking the bars.
6065
+ - Line: lineColor, lineWidth, xLabel, yLabel
6066
+ - Scatter: dotColor, dotRadius
6067
+ - Area: fillColor, lineColor, lineWidth
6068
+
6069
+ Data field mapping: use xField/yField in options to specify which data keys to use for axes.`,
6070
+ inputSchema: {
6071
+ type: 'object',
6072
+ properties: {
6073
+ action: {
6074
+ type: 'string',
6075
+ enum: ['create', 'update', 'reconfigure', 'remove'],
6076
+ description: 'Chart action',
6077
+ },
6078
+ chartType: {
6079
+ type: 'string',
6080
+ enum: ['bar', 'line', 'scatter', 'area'],
6081
+ description: 'Chart type (for create)',
6082
+ },
6083
+ chartId: { type: 'string', description: 'Chart ID (for update/reconfigure/remove)' },
6084
+ data: {
6085
+ type: 'array',
6086
+ items: { type: 'object' },
6087
+ description: 'Data array of objects (for create/update)',
6088
+ },
6089
+ options: {
6090
+ type: 'object',
6091
+ description: 'Chart options (colors, title, dimensions, field mapping, animation)',
6092
+ },
6093
+ },
6094
+ required: ['action'],
6095
+ },
6096
+ },
6097
+ // ---------------------------------------------------------------------------
6098
+ // MAGIC SYSTEM
6099
+ // ---------------------------------------------------------------------------
6100
+ {
6101
+ name: 'pinepaper_magic',
6102
+ annotations: {
6103
+ title: 'Magic',
6104
+ readOnlyHint: false,
6105
+ destructiveHint: false,
6106
+ idempotentHint: false,
6107
+ openWorldHint: false,
6108
+ },
6109
+ description: `Ontology-aware auto-animation and style remixing.
6110
+
6111
+ ACTIONS:
6112
+ - animate: Apply mood-driven animations, effects, and deformations. Params: mood, selectionOnly
6113
+ - remix: Non-destructive style cycling (colors, fonts, shadows). Params: selectionOnly
6114
+
6115
+ MOODS: calm, professional, energetic, dramatic, whimsical
6116
+
6117
+ The magic system analyzes canvas content via the design graph, selects type-appropriate treatments (animations for shapes, collage for text, filters for images), and tracks provenance.`,
6118
+ inputSchema: {
6119
+ type: 'object',
6120
+ properties: {
6121
+ action: {
6122
+ type: 'string',
6123
+ enum: ['animate', 'remix'],
6124
+ description: 'Magic action',
6125
+ },
6126
+ mood: {
6127
+ type: 'string',
6128
+ enum: ['calm', 'professional', 'energetic', 'dramatic', 'whimsical'],
6129
+ description: 'Energy/mood for animation selection',
6130
+ },
6131
+ selectionOnly: { type: 'boolean', description: 'Only affect selected items (default: false)' },
6132
+ },
6133
+ required: ['action'],
6134
+ },
6135
+ },
6136
+ // ---------------------------------------------------------------------------
6137
+ // PHYSICS (RIGID BODY SIMULATION)
6138
+ // ---------------------------------------------------------------------------
6139
+ {
6140
+ name: 'pinepaper_physics',
6141
+ annotations: {
6142
+ title: 'Physics',
6143
+ readOnlyHint: false,
6144
+ destructiveHint: false,
6145
+ idempotentHint: false,
6146
+ openWorldHint: false,
6147
+ },
6148
+ description: `Rigid body physics simulation (Box2D/Planck.js).
6149
+
6150
+ ACTIONS:
6151
+ - init: Start physics world. Params: gravity ({x, y}, default {x:0, y:980})
6152
+ - add_body: Register item as physics body. Params: itemId, bodyType (static|dynamic|kinematic), mass, friction, restitution, fixedRotation, shape (auto|circle|rect)
6153
+ - remove_body: Remove from physics. Params: itemId
6154
+ - apply_force: Continuous force in px/s². Params: itemId, force ({x, y})
6155
+ - apply_impulse: Instant velocity change. Params: itemId, impulse ({x, y})
6156
+ - set_velocity: Set linear velocity. Params: itemId, velocity ({x, y})
6157
+ - get_state: Get body position/velocity/rotation. Params: itemId
6158
+ - create_ground: Static floor plane. Params: y, width
6159
+ - create_joint: Connect two bodies. Params: itemId, targetItemId, jointType (revolute|distance|weld|prismatic), jointParams`,
6160
+ inputSchema: {
6161
+ type: 'object',
6162
+ properties: {
6163
+ action: {
6164
+ type: 'string',
6165
+ enum: ['init', 'add_body', 'remove_body', 'apply_force', 'apply_impulse', 'set_velocity', 'get_state', 'create_ground', 'create_joint'],
6166
+ description: 'Physics action',
6167
+ },
6168
+ itemId: { type: 'string', description: 'Target item ID' },
6169
+ gravity: {
6170
+ type: 'object',
6171
+ properties: { x: { type: 'number' }, y: { type: 'number' } },
6172
+ description: 'Gravity vector (for init)',
6173
+ },
6174
+ bodyType: {
6175
+ type: 'string',
6176
+ enum: ['static', 'dynamic', 'kinematic'],
6177
+ description: 'Physics body type',
6178
+ },
6179
+ mass: { type: 'number', description: 'Body mass (default: 1)' },
6180
+ friction: { type: 'number', description: 'Surface friction (default: 0.3)' },
6181
+ restitution: { type: 'number', description: 'Bounciness 0-1 (default: 0.3)' },
6182
+ fixedRotation: { type: 'boolean', description: 'Prevent rotation' },
6183
+ shape: { type: 'string', enum: ['auto', 'circle', 'rect'], description: 'Collision shape (default: auto)' },
6184
+ force: {
6185
+ type: 'object',
6186
+ properties: { x: { type: 'number' }, y: { type: 'number' } },
6187
+ description: 'Force vector in px/s²',
6188
+ },
6189
+ impulse: {
6190
+ type: 'object',
6191
+ properties: { x: { type: 'number' }, y: { type: 'number' } },
6192
+ description: 'Impulse vector',
6193
+ },
6194
+ velocity: {
6195
+ type: 'object',
6196
+ properties: { x: { type: 'number' }, y: { type: 'number' } },
6197
+ description: 'Velocity vector',
6198
+ },
6199
+ y: { type: 'number', description: 'Ground Y position' },
6200
+ width: { type: 'number', description: 'Ground width' },
6201
+ targetItemId: { type: 'string', description: 'Second item for joint' },
6202
+ jointType: {
6203
+ type: 'string',
6204
+ enum: ['revolute', 'distance', 'weld', 'prismatic'],
6205
+ description: 'Joint type',
6206
+ },
6207
+ jointParams: {
6208
+ type: 'object',
6209
+ description: 'Joint-specific parameters (anchor, enableMotor, motorSpeed, etc.)',
6210
+ },
6211
+ },
6212
+ required: ['action'],
6213
+ },
6214
+ },
6215
+ // ---------------------------------------------------------------------------
6216
+ // MEASUREMENT SYSTEM
6217
+ // ---------------------------------------------------------------------------
6218
+ {
6219
+ name: 'pinepaper_measurement',
6220
+ annotations: {
6221
+ title: 'Measurement',
6222
+ readOnlyHint: false,
6223
+ destructiveHint: false,
6224
+ idempotentHint: true,
6225
+ openWorldHint: false,
6226
+ },
6227
+ description: `Rulers, grid overlay, snap-to-grid, and dimension readout.
6228
+
6229
+ ACTIONS:
6230
+ - set_rulers: Show/hide rulers. Params: enabled (bool)
6231
+ - set_grid: Show/hide unit grid. Params: enabled (bool)
6232
+ - get_dimensions: Get item bounds. Params: itemId → returns {x, y, width, height, rotation}
6233
+ - set_snap: Enable/disable snap-to-grid. Params: enabled (bool)`,
6234
+ inputSchema: {
6235
+ type: 'object',
6236
+ properties: {
6237
+ action: {
6238
+ type: 'string',
6239
+ enum: ['set_rulers', 'set_grid', 'get_dimensions', 'set_snap'],
6240
+ description: 'Measurement action',
6241
+ },
6242
+ enabled: { type: 'boolean', description: 'Enable/disable (for set_rulers, set_grid, set_snap)' },
6243
+ itemId: { type: 'string', description: 'Item ID (for get_dimensions)' },
6244
+ },
6245
+ required: ['action'],
6246
+ },
6247
+ },
6190
6248
  ];
6191
6249
  /**
6192
6250
  * Get a tool definition by name