@pinepaper.studio/mcp-server 1.5.3 → 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 (71) hide show
  1. package/README.md +6 -4
  2. package/dist/agent/types.d.ts +16 -16
  3. package/dist/browser/url-target.d.ts +26 -0
  4. package/dist/browser/url-target.d.ts.map +1 -0
  5. package/dist/browser/url-target.js +50 -0
  6. package/dist/browser/url-target.js.map +1 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +47 -2
  9. package/dist/index.js.map +1 -1
  10. package/dist/ontology/hints.d.ts +71 -0
  11. package/dist/ontology/hints.d.ts.map +1 -0
  12. package/dist/ontology/hints.js +189 -0
  13. package/dist/ontology/hints.js.map +1 -0
  14. package/dist/ontology/vocabulary.d.ts.map +1 -1
  15. package/dist/ontology/vocabulary.js +34 -0
  16. package/dist/ontology/vocabulary.js.map +1 -1
  17. package/dist/prompts/index.d.ts.map +1 -1
  18. package/dist/prompts/index.js +146 -0
  19. package/dist/prompts/index.js.map +1 -1
  20. package/dist/tools/compact-descriptions.d.ts +3 -0
  21. package/dist/tools/compact-descriptions.d.ts.map +1 -1
  22. package/dist/tools/compact-descriptions.js +17 -8
  23. package/dist/tools/compact-descriptions.js.map +1 -1
  24. package/dist/tools/definitions.d.ts +1 -1
  25. package/dist/tools/definitions.d.ts.map +1 -1
  26. package/dist/tools/definitions.js +1090 -1639
  27. package/dist/tools/definitions.js.map +1 -1
  28. package/dist/tools/handlers/camera.d.ts +19 -0
  29. package/dist/tools/handlers/camera.d.ts.map +1 -0
  30. package/dist/tools/handlers/camera.js +94 -0
  31. package/dist/tools/handlers/camera.js.map +1 -0
  32. package/dist/tools/handlers/export.d.ts +12 -0
  33. package/dist/tools/handlers/export.d.ts.map +1 -0
  34. package/dist/tools/handlers/export.js +30 -0
  35. package/dist/tools/handlers/export.js.map +1 -0
  36. package/dist/tools/handlers/font.d.ts +12 -0
  37. package/dist/tools/handlers/font.d.ts.map +1 -0
  38. package/dist/tools/handlers/font.js +135 -0
  39. package/dist/tools/handlers/font.js.map +1 -0
  40. package/dist/tools/handlers/maps.d.ts +19 -0
  41. package/dist/tools/handlers/maps.d.ts.map +1 -0
  42. package/dist/tools/handlers/maps.js +184 -0
  43. package/dist/tools/handlers/maps.js.map +1 -0
  44. package/dist/tools/handlers/ontology.d.ts +20 -0
  45. package/dist/tools/handlers/ontology.d.ts.map +1 -0
  46. package/dist/tools/handlers/ontology.js +185 -0
  47. package/dist/tools/handlers/ontology.js.map +1 -0
  48. package/dist/tools/handlers/tool-guide.d.ts +14 -0
  49. package/dist/tools/handlers/tool-guide.d.ts.map +1 -0
  50. package/dist/tools/handlers/tool-guide.js +52 -0
  51. package/dist/tools/handlers/tool-guide.js.map +1 -0
  52. package/dist/tools/handlers.d.ts +18 -0
  53. package/dist/tools/handlers.d.ts.map +1 -1
  54. package/dist/tools/handlers.js +205 -603
  55. package/dist/tools/handlers.js.map +1 -1
  56. package/dist/tools/minimal-descriptions.d.ts +4 -0
  57. package/dist/tools/minimal-descriptions.d.ts.map +1 -1
  58. package/dist/tools/minimal-descriptions.js +45 -54
  59. package/dist/tools/minimal-descriptions.js.map +1 -1
  60. package/dist/tools/toolkits.d.ts.map +1 -1
  61. package/dist/tools/toolkits.js +36 -45
  62. package/dist/tools/toolkits.js.map +1 -1
  63. package/dist/types/code-generator.d.ts +36 -1
  64. package/dist/types/code-generator.d.ts.map +1 -1
  65. package/dist/types/code-generator.js +823 -35
  66. package/dist/types/code-generator.js.map +1 -1
  67. package/dist/types/schemas.d.ts +1116 -444
  68. package/dist/types/schemas.d.ts.map +1 -1
  69. package/dist/types/schemas.js +290 -18
  70. package/dist/types/schemas.js.map +1 -1
  71. package/package.json +1 -1
@@ -9,6 +9,16 @@
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
  // =============================================================================
@@ -47,7 +57,7 @@ RULES:
47
57
  CANVAS: set_canvas_size (width/height or preset) → set_background (color) → execute_generator (procedural art)
48
58
  ITEMS: create (itemType, position, properties) → modify (itemId, properties) → delete (itemId)
49
59
  ANIMATE: animate (loop presets) → keyframe_animate (timed reveals) → relation (behavioral links)
50
- EFFECTS: apply_mask (reveal animations) → apply_effect (sparkle/blast)
60
+ EFFECTS: apply_mask (reveal animations) → apply_effect (sparkle/blast/bubbles/fireflies/trail...)
51
61
  PLAY: play_timeline (start playback)
52
62
 
53
63
  ─── GENERATORS (prefer these for backgrounds) ───
@@ -64,6 +74,7 @@ Choose based on mood:
64
74
 
65
75
  Shapes: circle, rectangle, star, ellipse, triangle, polygon, line, arc, path
66
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)
67
78
  All items: opacity, shadowColor, shadowBlur, blendMode, strokeColor, strokeWidth
68
79
 
69
80
  SVG imports for recognizable objects (planes, cars, animals, buildings):
@@ -73,7 +84,7 @@ SVG imports for recognizable objects (planes, cars, animals, buildings):
73
84
 
74
85
  Loop presets (animate): pulse, rotate, bounce, fade, wobble, slide, typewriter
75
86
  Keyframe (keyframe_animate): [{time, properties, easing}] → opacity, scale, scaleX, scaleY, x, y, rotation, fillColor, strokeColor, fontSize
76
- 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)
77
88
  Masks (apply_mask): wipeLeft, wipeRight, wipeUp, wipeDown, iris, irisOut, star, heart, curtainHorizontal, curtainVertical, cinematic, diagonalWipe, revealUp, revealDown
78
89
  Effects (apply_effect): sparkle, blast
79
90
 
@@ -111,10 +122,38 @@ Shapes: process (rect), decision (diamond), terminal (rounded), data, document,
111
122
  Workflow: create shapes with positions → connect with arrows → optional auto_layout
112
123
  See pinepaper://docs/diagrams for full examples.
113
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
+
114
152
  ─── CANVAS & EXPORT ───
115
153
 
116
154
  Presets: instagram (1080x1080), youtube (1920x1080), tiktok (1080x1920), twitter (1200x675)
117
- 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)`;
118
157
  /*
119
158
  * The AI_AGENT_GUIDE constant above is included as a comment in verbose/compact modes
120
159
  * and served on-demand via pinepaper_tool_guide in minimal mode.
@@ -290,7 +329,7 @@ USE WHEN:
290
329
  IMPORTANT:
291
330
  - Save the returned itemId! You need it for pinepaper_add_relation, pinepaper_modify_item, pinepaper_delete_item, etc.
292
331
  - If there's a welcome template on the canvas, use pinepaper_clear_canvas first
293
- - 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.
294
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.
295
334
 
296
335
  ⚠️ COMPLEX CHARACTERS/ILLUSTRATIONS:
@@ -352,12 +391,23 @@ For glossy 3D spheres, use pinepaper_create_glossy_sphere instead. For diagonal
352
391
  description: 'Type of item to create',
353
392
  },
354
393
  position: {
355
- type: 'object',
356
- properties: {
357
- x: { type: 'number', description: 'X coordinate (default: 400)' },
358
- y: { type: 'number', description: 'Y coordinate (default: 300)' },
359
- },
360
- 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.',
361
411
  },
362
412
  properties: {
363
413
  type: 'object',
@@ -435,7 +485,15 @@ MODIFIABLE PROPERTIES:
435
485
  - blendMode: Blend mode (normal, multiply, screen, overlay, etc.)
436
486
 
437
487
  GRADIENT OBJECT FORMAT:
438
- {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.`,
439
497
  inputSchema: {
440
498
  type: 'object',
441
499
  properties: {
@@ -445,7 +503,7 @@ GRADIENT OBJECT FORMAT:
445
503
  },
446
504
  properties: {
447
505
  type: 'object',
448
- 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.',
449
507
  additionalProperties: true,
450
508
  },
451
509
  data: {
@@ -707,6 +765,65 @@ Returns the itemId of the imported SVG group, which can be used with pinepaper_a
707
765
  },
708
766
  },
709
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
+ },
710
827
  {
711
828
  name: 'pinepaper_import_image',
712
829
  annotations: {
@@ -1151,6 +1268,8 @@ RELATION COMPATIBILITY:
1151
1268
  Circle→Circle: radius interpolation
1152
1269
  Text→Text: font blend
1153
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).
1154
1273
 
1155
1274
  VERIFYING ANIMATION WORKS:
1156
1275
  After adding a relation, verify the animation is running:
@@ -1172,7 +1291,7 @@ Relations are COMPOSITIONAL - an item can have multiple relations that work toge
1172
1291
  },
1173
1292
  relationType: {
1174
1293
  type: 'string',
1175
- 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'],
1176
1295
  description: 'Type of relationship',
1177
1296
  },
1178
1297
  params: {
@@ -1206,7 +1325,7 @@ USE WHEN:
1206
1325
  targetId: { type: 'string', description: 'Target item ID' },
1207
1326
  relationType: {
1208
1327
  type: 'string',
1209
- 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'],
1210
1329
  description: 'Specific relation type to remove (optional - removes all if not specified)',
1211
1330
  },
1212
1331
  },
@@ -1234,7 +1353,7 @@ USE WHEN:
1234
1353
  itemId: { type: 'string', description: 'Item to query relations for' },
1235
1354
  relationType: {
1236
1355
  type: 'string',
1237
- 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'],
1238
1357
  description: 'Filter by relation type (optional)',
1239
1358
  },
1240
1359
  direction: {
@@ -1453,7 +1572,17 @@ EASING OPTIONS:
1453
1572
  - easeOut: Slow end
1454
1573
  - easeInOut: Slow start and end
1455
1574
  - bounce: Bounce effect
1456
- - 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.`,
1457
1586
  inputSchema: {
1458
1587
  type: 'object',
1459
1588
  properties: {
@@ -1486,6 +1615,18 @@ EASING OPTIONS:
1486
1615
  type: 'boolean',
1487
1616
  description: 'Whether to loop the animation',
1488
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
+ },
1489
1630
  },
1490
1631
  required: ['itemId', 'keyframes'],
1491
1632
  },
@@ -1754,29 +1895,60 @@ Requires maskType and keyframes array.`,
1754
1895
  idempotentHint: false,
1755
1896
  openWorldHint: false,
1756
1897
  },
1757
- 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.
1758
1899
 
1759
1900
  USE WHEN:
1760
1901
  - Creating cinematic camera movements
1761
1902
  - Building presentation zoom sequences
1762
1903
  - Making dramatic reveals with camera motion
1763
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.
1764
1911
 
1765
1912
  KEYFRAME PROPERTIES:
1766
1913
  - time: Time in seconds
1767
1914
  - zoom: Zoom level (1=normal, 2=2x zoom in, 0.5=zoom out)
1768
- - 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
1769
1922
  - easing: Timing function (linear, easeIn, easeOut, easeInOut, bounce, elastic)
1770
1923
 
1771
- 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):
1772
1933
  {
1773
1934
  "duration": 6,
1774
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,
1775
1948
  "keyframes": [
1776
- { "time": 0, "zoom": 1, "center": [400, 300] },
1777
- { "time": 2, "zoom": 2, "center": [400, 300], "easing": "easeInOut" },
1778
- { "time": 4, "zoom": 2, "center": [600, 300], "easing": "easeOut" },
1779
- { "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] }
1780
1952
  ]
1781
1953
  }`,
1782
1954
  inputSchema: {
@@ -1790,183 +1962,111 @@ EXAMPLE:
1790
1962
  properties: {
1791
1963
  time: { type: 'number', description: 'Time in seconds' },
1792
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
+ },
1793
1968
  center: {
1794
1969
  type: 'array',
1795
1970
  items: { type: 'number' },
1796
- description: 'View center [x, y]',
1971
+ description: 'Legacy view center [x, y] — honored only when focus is absent',
1797
1972
  },
1973
+ pitch: { type: 'number', description: '3D tilt in degrees (0=flat, positive=forward tilt)' },
1974
+ yaw: { type: 'number', description: '3D rotation in degrees' },
1798
1975
  easing: {
1799
1976
  type: 'string',
1800
1977
  enum: ['linear', 'easeIn', 'easeOut', 'easeInOut', 'bounce', 'elastic'],
1801
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
+ },
1802
2008
  },
1803
2009
  },
1804
2010
  },
1805
2011
  duration: { type: 'number', description: 'Total animation duration in seconds' },
1806
2012
  loop: { type: 'boolean', description: 'Loop the animation' },
1807
2013
  delay: { type: 'number', description: 'Delay before animation starts' },
2014
+ fov: { type: 'number', description: 'Field of view in degrees for 3D perspective (default: 60)' },
1808
2015
  },
1809
2016
  required: ['keyframes', 'duration'],
1810
2017
  },
1811
2018
  },
1812
2019
  {
1813
- name: 'pinepaper_camera_zoom',
1814
- annotations: {
1815
- title: 'Camera Zoom',
1816
- readOnlyHint: false,
1817
- destructiveHint: false,
1818
- idempotentHint: false,
1819
- openWorldHint: false,
1820
- },
1821
- description: `Simple camera zoom animation.
1822
-
1823
- USE WHEN:
1824
- - Quick zoom in to focus on something
1825
- - Zoom out to show full canvas
1826
- - Simple zoom effects without complex keyframes`,
1827
- inputSchema: {
1828
- type: 'object',
1829
- properties: {
1830
- direction: {
1831
- type: 'string',
1832
- enum: ['in', 'out'],
1833
- description: 'Zoom direction',
1834
- },
1835
- level: {
1836
- type: 'number',
1837
- description: 'Target zoom level (default: 2 for in, 0.5 for out)',
1838
- },
1839
- duration: {
1840
- type: 'number',
1841
- description: 'Animation duration in seconds (default: 0.5)',
1842
- },
1843
- },
1844
- required: ['direction'],
1845
- },
1846
- },
1847
- {
1848
- name: 'pinepaper_camera_pan',
2020
+ name: 'pinepaper_camera',
1849
2021
  annotations: {
1850
- title: 'Camera Pan',
2022
+ title: 'Camera Control',
1851
2023
  readOnlyHint: false,
1852
2024
  destructiveHint: false,
1853
2025
  idempotentHint: false,
1854
2026
  openWorldHint: false,
1855
2027
  },
1856
- 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).
1857
2029
 
1858
- USE WHEN:
1859
- - Moving view to different part of canvas
1860
- - Directional panning (left, right, up, down)
1861
- - 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 }.
1862
2043
 
1863
2044
  EXAMPLES:
1864
- // Pan left 200 pixels
1865
- { "direction": "left", "amount": 200 }
1866
-
1867
- // Pan to specific coordinates
1868
- { "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" }`,
1869
2050
  inputSchema: {
1870
2051
  type: 'object',
1871
2052
  properties: {
1872
- direction: {
2053
+ action: {
1873
2054
  type: 'string',
1874
- enum: ['left', 'right', 'up', 'down'],
1875
- description: 'Pan direction (use with amount)',
1876
- },
1877
- amount: {
1878
- type: 'number',
1879
- description: 'Pixels to pan (default: 100)',
1880
- },
1881
- x: {
1882
- type: 'number',
1883
- description: 'Target X coordinate (use with y for panTo)',
1884
- },
1885
- y: {
1886
- type: 'number',
1887
- description: 'Target Y coordinate (use with x for panTo)',
2055
+ enum: ['zoom', 'pan', 'move_to', 'reset', 'stop', 'state'],
2056
+ description: 'Camera action to perform',
1888
2057
  },
1889
- duration: {
1890
- type: 'number',
1891
- 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".',
1892
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)' },
1893
2068
  },
1894
- },
1895
- },
1896
- {
1897
- name: 'pinepaper_camera_move_to',
1898
- annotations: {
1899
- title: 'Camera Move To',
1900
- readOnlyHint: false,
1901
- destructiveHint: false,
1902
- idempotentHint: false,
1903
- openWorldHint: false,
1904
- },
1905
- description: `Combined camera zoom and pan to a specific location.
1906
-
1907
- USE WHEN:
1908
- - Moving to and zooming on a specific point in one motion
1909
- - Focusing on an item with appropriate zoom level`,
1910
- inputSchema: {
1911
- type: 'object',
1912
- properties: {
1913
- x: { type: 'number', description: 'Target X coordinate' },
1914
- y: { type: 'number', description: 'Target Y coordinate' },
1915
- zoom: { type: 'number', description: 'Target zoom level' },
1916
- duration: { type: 'number', description: 'Animation duration in seconds (default: 0.5)' },
1917
- },
1918
- required: ['x', 'y', 'zoom'],
1919
- },
1920
- },
1921
- {
1922
- name: 'pinepaper_camera_reset',
1923
- annotations: {
1924
- title: 'Camera Reset',
1925
- readOnlyHint: false,
1926
- destructiveHint: false,
1927
- idempotentHint: false,
1928
- openWorldHint: false,
1929
- },
1930
- description: `Reset camera to default state (center of canvas, zoom 1).
1931
-
1932
- USE WHEN:
1933
- - Returning to default view after camera movements
1934
- - Resetting before starting new sequence`,
1935
- inputSchema: {
1936
- type: 'object',
1937
- properties: {
1938
- duration: { type: 'number', description: 'Animation duration in seconds (default: 0.5)' },
1939
- },
1940
- },
1941
- },
1942
- {
1943
- name: 'pinepaper_camera_stop',
1944
- annotations: {
1945
- title: 'Camera Stop',
1946
- readOnlyHint: false,
1947
- destructiveHint: false,
1948
- idempotentHint: true,
1949
- openWorldHint: false,
1950
- },
1951
- description: `Stop current camera animation.`,
1952
- inputSchema: {
1953
- type: 'object',
1954
- properties: {},
1955
- },
1956
- },
1957
- {
1958
- name: 'pinepaper_camera_state',
1959
- annotations: {
1960
- title: 'Camera State',
1961
- readOnlyHint: true,
1962
- destructiveHint: false,
1963
- idempotentHint: true,
1964
- openWorldHint: false,
1965
- },
1966
- description: `Get current camera state (zoom level, center position, animation status).`,
1967
- inputSchema: {
1968
- type: 'object',
1969
- properties: {},
2069
+ required: ['action'],
1970
2070
  },
1971
2071
  },
1972
2072
  // ---------------------------------------------------------------------------
@@ -2034,7 +2134,7 @@ EXAMPLE - Bouncing Balls:
2034
2134
  }
2035
2135
 
2036
2136
  SUPPORTED ITEM TYPES: text, circle, star, rectangle, triangle, polygon, ellipse, path, line, arc
2037
- 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
2038
2138
  SUPPORTED ANIMATIONS: pulse, rotate, bounce, fade, wobble, slide, typewriter`,
2039
2139
  inputSchema: {
2040
2140
  type: 'object',
@@ -2080,7 +2180,7 @@ SUPPORTED ANIMATIONS: pulse, rotate, bounce, fade, wobble, slide, typewriter`,
2080
2180
  target: { type: 'string', description: 'Name of target item' },
2081
2181
  type: {
2082
2182
  type: 'string',
2083
- 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'],
2084
2184
  },
2085
2185
  params: {
2086
2186
  type: 'object',
@@ -2596,101 +2696,340 @@ ACTIONS:
2596
2696
  },
2597
2697
  },
2598
2698
  // ---------------------------------------------------------------------------
2599
- // LAYER 5 — BLUEPRINTS: TEMPLATE TOOLS
2699
+ // DEFORMATION, SPRITE SHEETS, STORAGE, INTERACTION
2600
2700
  // ---------------------------------------------------------------------------
2601
2701
  {
2602
- name: 'pinepaper_apply_template',
2702
+ name: 'pinepaper_deform',
2603
2703
  annotations: {
2604
- title: 'Apply Template',
2704
+ title: 'Deformation',
2605
2705
  readOnlyHint: false,
2606
- destructiveHint: true,
2706
+ destructiveHint: false,
2607
2707
  idempotentHint: false,
2608
2708
  openWorldHint: false,
2609
2709
  },
2610
- description: `Load a pre-built template design onto the canvas, or list available templates.
2611
-
2612
- USE WHEN:
2613
- - User wants to start from a pre-made design
2614
- - User asks for a template, preset, or starter layout
2615
- - User wants to see what templates are available
2616
- - Need a quick starting point for social media, presentations, etc.
2617
-
2618
- ⚠️ DESTRUCTIVE: Loading a template replaces the current canvas content.
2710
+ description: `Apply vertex deformation presets to items for organic motion effects.
2619
2711
 
2620
- MODES:
2621
- 1. LIST MODE: Set listOnly: true (or omit templateId) to browse available templates
2622
- - Optionally filter by category
2623
- 2. LOAD MODE: Provide a templateId to apply that template
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
2624
2716
 
2625
- TEMPLATE CATEGORIES (13):
2626
- - social-media: Social media post/story layouts
2627
- - meme: Meme templates and formats
2628
- - business: Business cards, letterheads, presentations
2629
- - education: Educational diagrams, worksheets
2630
- - creative: Artistic and creative compositions
2631
- - tech: Technology-themed designs
2632
- - global: International and multicultural designs
2633
- - indigenous: Indigenous art-inspired patterns
2634
- - seasonal: Holiday and seasonal themes
2635
- - masking: Mask reveal effect demonstrations
2636
- - scenes: Pre-built animated scenes
2637
- - diagrams: Flowchart and diagram starters
2638
- - maps: Geographic visualization templates
2717
+ PRESETS: fold, squeeze, squash, pinch, bulge, twist, ripple, wave, breathe, melt, shear, inflate, wobble
2639
2718
 
2640
- EXAMPLES:
2641
- - List all templates: { "listOnly": true }
2642
- - List by category: { "category": "social-media", "listOnly": true }
2643
- - Load template: { "templateId": "solar-system" }`,
2719
+ PHASES: sin, blink, linear, pingpong, once, elastic, heartbeat, stepped`,
2644
2720
  inputSchema: {
2645
2721
  type: 'object',
2646
2722
  properties: {
2647
- templateId: {
2723
+ action: {
2648
2724
  type: 'string',
2649
- description: 'Template ID to load (omit to list templates)',
2725
+ enum: ['apply', 'trigger', 'remove'],
2726
+ description: 'Deformation action',
2650
2727
  },
2651
- category: {
2728
+ itemId: { type: 'string', description: 'Target item ID' },
2729
+ preset: {
2652
2730
  type: 'string',
2653
- enum: ['social-media', 'meme', 'business', 'education', 'creative', 'tech', 'global', 'indigenous', 'seasonal', 'masking', 'scenes', 'diagrams', 'maps'],
2654
- description: 'Filter templates by category',
2731
+ enum: ['fold', 'squeeze', 'squash', 'pinch', 'bulge', 'twist', 'ripple', 'wave', 'breathe', 'melt', 'shear', 'inflate', 'wobble'],
2732
+ description: 'Deformation preset name',
2655
2733
  },
2656
- listOnly: {
2657
- type: 'boolean',
2658
- description: 'If true, only list available templates without loading (default: false)',
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',
2659
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' },
2660
2748
  },
2749
+ required: ['action'],
2661
2750
  },
2662
2751
  },
2663
- // ---------------------------------------------------------------------------
2664
- // DOMAIN: DIAGRAM TOOLS
2665
- // ---------------------------------------------------------------------------
2666
2752
  {
2667
- name: 'pinepaper_create_diagram_shape',
2753
+ name: 'pinepaper_sprite_sheet',
2668
2754
  annotations: {
2669
- title: 'Create Diagram Shape',
2755
+ title: 'Sprite Sheet',
2670
2756
  readOnlyHint: false,
2671
2757
  destructiveHint: false,
2672
2758
  idempotentHint: false,
2673
2759
  openWorldHint: false,
2674
2760
  },
2675
- description: `Create a diagram shape on the canvas. Diagram shapes are specialized shapes for flowcharts, UML diagrams, network diagrams, and similar technical drawings.
2676
-
2677
- USE WHEN:
2678
- - Creating flowcharts, process diagrams, or workflows
2679
- - Building UML class diagrams, use case diagrams, or sequence diagrams
2680
- - Designing network topology diagrams
2681
- - Making organizational charts or decision trees
2682
- - Any technical or architectural diagram
2683
-
2684
- SHAPE TYPES:
2761
+ description: `Generate, play, and export sprite sheets from skeleton poses.
2685
2762
 
2686
- Flowchart shapes:
2687
- - process: Rectangle for process steps (default: 120x60)
2688
- - decision: Diamond for yes/no decisions (default: 100x100)
2689
- - terminal: Rounded rectangle for start/end (default: 120x40)
2690
- - data: Parallelogram for data I/O (default: 120x60)
2691
- - document: Wavy-bottom rectangle for documents (default: 100x80)
2692
- - database: Cylinder for database/storage (default: 80x100)
2693
- - preparation: Hexagon for preparation steps (default: 120x60)
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)`,
2767
+ inputSchema: {
2768
+ type: 'object',
2769
+ properties: {
2770
+ action: {
2771
+ type: 'string',
2772
+ enum: ['generate', 'play', 'export'],
2773
+ description: 'Sprite sheet action',
2774
+ },
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: {
2784
+ type: 'object',
2785
+ properties: { poseIdA: { type: 'string' }, poseIdB: { type: 'string' }, frameCount: { type: 'number' }, name: { type: 'string' } },
2786
+ description: 'Interpolate between two poses',
2787
+ },
2788
+ bakedAnimation: {
2789
+ type: 'object',
2790
+ properties: { duration: { type: 'number' }, fps: { type: 'number' }, name: { type: 'string' } },
2791
+ description: 'Bake timeline animation into frames',
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)' },
2805
+ },
2806
+ required: ['action'],
2807
+ },
2808
+ },
2809
+ {
2810
+ name: 'pinepaper_storage',
2811
+ annotations: {
2812
+ title: 'Storage',
2813
+ readOnlyHint: false,
2814
+ destructiveHint: true,
2815
+ idempotentHint: false,
2816
+ openWorldHint: false,
2817
+ },
2818
+ description: `Persistent project storage via IndexedDB.
2819
+
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`,
2825
+ inputSchema: {
2826
+ type: 'object',
2827
+ properties: {
2828
+ action: {
2829
+ type: 'string',
2830
+ enum: ['save', 'load', 'list', 'delete'],
2831
+ description: 'Storage action',
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' },
2836
+ },
2837
+ required: ['action'],
2838
+ },
2839
+ },
2840
+ {
2841
+ name: 'pinepaper_interaction',
2842
+ annotations: {
2843
+ title: 'Interaction',
2844
+ readOnlyHint: false,
2845
+ destructiveHint: false,
2846
+ idempotentHint: false,
2847
+ openWorldHint: false,
2848
+ },
2849
+ description: `Add continuous physics behaviors and trigger interaction actions.
2850
+
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)
2856
+
2857
+ BEHAVIOR TYPES: repel, attract, follow, orbit, slingshot, physics_body, draggable_constrained
2858
+
2859
+ ACTION TYPES: navigate, show, hide, animate, stopAnimation, setState, incrementScore, playTimeline, pauseTimeline, seekTimeline, showFeedback, complete`,
2860
+ inputSchema: {
2861
+ type: 'object',
2862
+ properties: {
2863
+ action: {
2864
+ type: 'string',
2865
+ enum: ['add_behavior', 'remove_behavior', 'trigger_action', 'get_state'],
2866
+ description: 'Interaction action',
2867
+ },
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: {
2881
+ type: 'object',
2882
+ description: 'Action-specific or behavior-specific parameters',
2883
+ },
2884
+ },
2885
+ required: ['action'],
2886
+ },
2887
+ },
2888
+ // ---------------------------------------------------------------------------
2889
+ // WIDGET EXPORT
2890
+ // ---------------------------------------------------------------------------
2891
+ {
2892
+ name: 'pinepaper_export_widget',
2893
+ annotations: {
2894
+ title: 'Export Widget',
2895
+ readOnlyHint: true,
2896
+ destructiveHint: false,
2897
+ idempotentHint: true,
2898
+ openWorldHint: false,
2899
+ },
2900
+ description: `Export current scene as a PineWidget (pp:PinePaper ontology JSON v0.4.3).
2901
+
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.
2903
+
2904
+ Params: download (bool), filename, includeInteractions (bool, default true), minify (bool)`,
2905
+ inputSchema: {
2906
+ type: 'object',
2907
+ properties: {
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)' },
2912
+ },
2913
+ },
2914
+ },
2915
+ {
2916
+ name: 'pinepaper_export_widget_html',
2917
+ annotations: {
2918
+ title: 'Export Widget HTML',
2919
+ readOnlyHint: true,
2920
+ destructiveHint: false,
2921
+ idempotentHint: true,
2922
+ openWorldHint: false,
2923
+ },
2924
+ description: `Export current scene as a self-contained HTML page with tree-shaken PineWidget runtime.
2925
+
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.
2927
+
2928
+ Params: title (page title), download (bool)`,
2929
+ inputSchema: {
2930
+ type: 'object',
2931
+ properties: {
2932
+ title: { type: 'string', description: 'HTML page title (default: PinePaper Widget)' },
2933
+ download: { type: 'boolean', description: 'Trigger browser download (default: false)' },
2934
+ },
2935
+ },
2936
+ },
2937
+ // ---------------------------------------------------------------------------
2938
+ // LAYER 5 — BLUEPRINTS: TEMPLATE TOOLS
2939
+ // ---------------------------------------------------------------------------
2940
+ {
2941
+ name: 'pinepaper_apply_template',
2942
+ annotations: {
2943
+ title: 'Apply Template',
2944
+ readOnlyHint: false,
2945
+ destructiveHint: true,
2946
+ idempotentHint: false,
2947
+ openWorldHint: false,
2948
+ },
2949
+ description: `Load a pre-built template design onto the canvas, or list available templates.
2950
+
2951
+ USE WHEN:
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.
2958
+
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
2963
+
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
2978
+
2979
+ EXAMPLES:
2980
+ - List all templates: { "listOnly": true }
2981
+ - List by category: { "category": "social-media", "listOnly": true }
2982
+ - Load template: { "templateId": "solar-system" }`,
2983
+ inputSchema: {
2984
+ type: 'object',
2985
+ properties: {
2986
+ templateId: {
2987
+ type: 'string',
2988
+ description: 'Template ID to load (omit to list templates)',
2989
+ },
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)',
2998
+ },
2999
+ },
3000
+ },
3001
+ },
3002
+ // ---------------------------------------------------------------------------
3003
+ // DOMAIN: DIAGRAM TOOLS
3004
+ // ---------------------------------------------------------------------------
3005
+ {
3006
+ name: 'pinepaper_create_diagram_shape',
3007
+ annotations: {
3008
+ title: 'Create Diagram Shape',
3009
+ readOnlyHint: false,
3010
+ destructiveHint: false,
3011
+ idempotentHint: false,
3012
+ openWorldHint: false,
3013
+ },
3014
+ description: `Create a diagram shape on the canvas. Diagram shapes are specialized shapes for flowcharts, UML diagrams, network diagrams, and similar technical drawings.
3015
+
3016
+ USE WHEN:
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
3022
+
3023
+ SHAPE TYPES:
3024
+
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)
2694
3033
 
2695
3034
  UML shapes:
2696
3035
  - uml-class: Class box with name/attributes/methods sections (default: 150x120)
@@ -3259,1488 +3598,301 @@ EXAMPLES:
3259
3598
  },
3260
3599
  },
3261
3600
  {
3262
- name: 'pinepaper_remove_connector',
3263
- annotations: {
3264
- title: 'Remove Connector',
3265
- readOnlyHint: false,
3266
- destructiveHint: true,
3267
- idempotentHint: true,
3268
- openWorldHint: false,
3269
- },
3270
- description: `Remove a connector from the canvas.
3271
-
3272
- USE WHEN:
3273
- - Deleting a connection between items
3274
- - Removing incorrect links
3275
- - Restructuring diagram connections`,
3276
- inputSchema: {
3277
- type: 'object',
3278
- properties: {
3279
- connectorId: {
3280
- type: 'string',
3281
- description: 'ID of the connector to remove',
3282
- },
3283
- },
3284
- required: ['connectorId'],
3285
- },
3286
- },
3287
- {
3288
- name: 'pinepaper_diagram_mode',
3289
- annotations: {
3290
- title: 'Diagram Mode',
3291
- readOnlyHint: false,
3292
- destructiveHint: false,
3293
- idempotentHint: true,
3294
- openWorldHint: false,
3295
- },
3296
- description: `Control the diagram mode for interactive editing.
3297
-
3298
- USE WHEN:
3299
- - Switching between drawing and selection modes
3300
- - Enabling/disabling diagram-specific UI
3301
- - Setting up the canvas for diagram creation
3302
-
3303
- ACTIONS:
3304
- - activate: Enable diagram mode (shows grid, snap, port indicators)
3305
- - deactivate: Return to normal canvas mode
3306
- - toggle: Switch between diagram and normal mode
3307
- - setMode: Set specific tool mode (select, connect, shape, pan)
3308
-
3309
- TOOL MODES (for setMode action):
3310
- - select: Selection and moving items
3311
- - connect: Drawing connectors between items
3312
- - shape: Drawing new shapes (optionally specify shapeType)
3313
- - pan: Panning the canvas
3314
-
3315
- EXAMPLES:
3316
- - Enter diagram mode: {action: "activate"}
3317
- - Exit diagram mode: {action: "deactivate"}
3318
- - Set to connect mode: {action: "setMode", mode: "connect"}
3319
- - Set to draw rectangles: {action: "setMode", mode: "shape", shapeType: "process"}`,
3320
- inputSchema: {
3321
- type: 'object',
3322
- properties: {
3323
- action: {
3324
- type: 'string',
3325
- enum: ['activate', 'deactivate', 'toggle', 'setMode'],
3326
- description: 'Action to perform',
3327
- },
3328
- mode: {
3329
- type: 'string',
3330
- enum: ['select', 'connect', 'shape', 'pan'],
3331
- description: 'Tool mode (for setMode action)',
3332
- },
3333
- shapeType: {
3334
- type: 'string',
3335
- enum: ['process', 'decision', 'terminal', 'data', 'document', 'database', 'preparation', 'uml-class', 'uml-usecase', 'uml-actor', 'cloud', 'server', 'rectangle', 'circle', 'triangle', 'star'],
3336
- description: 'Shape type for shape mode',
3337
- },
3338
- },
3339
- required: ['action'],
3340
- },
3341
- },
3342
- // ---------------------------------------------------------------------------
3343
- // DOMAIN: MAP TOOLS
3344
- // ---------------------------------------------------------------------------
3345
- {
3346
- name: 'pinepaper_load_map',
3347
- annotations: {
3348
- title: 'Load Map',
3349
- readOnlyHint: false,
3350
- destructiveHint: false,
3351
- idempotentHint: false,
3352
- openWorldHint: false,
3353
- },
3354
- description: `Load a geographic map onto the canvas with specified projection and styling.
3355
-
3356
- USE WHEN:
3357
- - Creating world maps or country visualizations
3358
- - Building choropleth data visualizations
3359
- - Making infographics with geographic data
3360
- - Creating animated map reveals
3361
-
3362
- AVAILABLE MAPS:
3363
- - world: World countries (110m resolution, faster)
3364
- - worldHighRes: World countries (50m resolution, more detailed)
3365
- - usa: US states map
3366
-
3367
- PROJECTIONS:
3368
- - naturalEarth: Natural Earth projection (recommended for world maps)
3369
- - mercator: Standard web mercator
3370
- - equalEarth: Equal-area projection
3371
- - orthographic: Globe/3D sphere view
3372
- - albers: Conic projection (good for USA)
3373
- - stereographic: Stereographic projection
3374
-
3375
- QUALITY SETTINGS:
3376
- - fast: Aggressive simplification (prototyping)
3377
- - balanced: Moderate detail (most uses)
3378
- - professional: No simplification (publications)
3379
-
3380
- EXAMPLES:
3381
- - World map: {mapId: "world", projection: "naturalEarth", quality: "balanced"}
3382
- - USA map: {mapId: "usa", projection: "albers", quality: "professional"}
3383
- - Globe view: {mapId: "worldHighRes", projection: "orthographic", rotate: [0, -30, 0]}
3384
-
3385
- RETURNS:
3386
- - mapId: Reference ID for the loaded map
3387
- - group: Paper.js group containing all regions
3388
- - regions: Array of region info
3389
- - bounds: Map bounding box`,
3390
- inputSchema: {
3391
- type: 'object',
3392
- properties: {
3393
- mapId: {
3394
- type: 'string',
3395
- enum: ['world', 'worldHighRes', 'usa'],
3396
- description: 'Map to load (world=110m, worldHighRes=50m professional quality, usa=US states)',
3397
- },
3398
- projection: {
3399
- type: 'string',
3400
- enum: ['mercator', 'equalEarth', 'naturalEarth', 'orthographic', 'albers', 'stereographic'],
3401
- description: 'Map projection type',
3402
- },
3403
- quality: {
3404
- type: 'string',
3405
- enum: ['fast', 'balanced', 'professional'],
3406
- description: 'Rendering quality (professional=no simplification)',
3407
- },
3408
- fillColor: { type: 'string', description: 'Default fill color for regions' },
3409
- strokeColor: { type: 'string', description: 'Border/stroke color' },
3410
- strokeWidth: { type: 'number', description: 'Border width in pixels' },
3411
- scale: { type: 'number', description: 'Scale multiplier' },
3412
- center: {
3413
- type: 'array',
3414
- items: { type: 'number' },
3415
- description: 'Center coordinates [longitude, latitude]',
3416
- },
3417
- rotate: {
3418
- type: 'array',
3419
- items: { type: 'number' },
3420
- description: 'Rotation angles [x, y, z]',
3421
- },
3422
- enableHover: { type: 'boolean', description: 'Enable hover effects on regions' },
3423
- enableClick: { type: 'boolean', description: 'Enable click events on regions' },
3424
- hoverFill: { type: 'string', description: 'Fill color on hover' },
3425
- hoverStroke: { type: 'string', description: 'Stroke color on hover' },
3426
- },
3427
- required: ['mapId'],
3428
- },
3429
- },
3430
- {
3431
- name: 'pinepaper_highlight_regions',
3432
- annotations: {
3433
- title: 'Highlight Regions',
3434
- readOnlyHint: false,
3435
- destructiveHint: false,
3436
- idempotentHint: true,
3437
- openWorldHint: false,
3438
- },
3439
- description: `Highlight specific regions on a loaded map with custom styling.
3440
-
3441
- USE WHEN:
3442
- - Emphasizing specific countries or states
3443
- - Creating interactive map highlights
3444
- - Building step-by-step map reveals
3445
- - Showing geographic data points
3446
-
3447
- REGION ID FORMATS:
3448
- - World maps: Full country names ("United States of America", "France", "Japan")
3449
- - USA map: State codes ("CA", "TX", "NY", "FL")
3450
-
3451
- STYLING OPTIONS:
3452
- - fillColor: Highlight fill color
3453
- - strokeColor: Highlight stroke color
3454
- - strokeWidth: Border width for highlighted regions
3455
- - animate: Whether to animate the highlight transition
3456
-
3457
- EXAMPLES:
3458
- - Highlight countries: {regionIds: ["United States of America", "Canada", "Mexico"], options: {fillColor: "#3b82f6"}}
3459
- - Highlight US states: {regionIds: ["CA", "TX", "NY"], options: {fillColor: "#22c55e", animate: true}}
3460
- - Custom styling: {regionIds: ["Japan"], options: {fillColor: "#ef4444", strokeColor: "#dc2626", strokeWidth: 2}}`,
3461
- inputSchema: {
3462
- type: 'object',
3463
- properties: {
3464
- regionIds: {
3465
- type: 'array',
3466
- items: { type: 'string' },
3467
- description: 'Array of region IDs to highlight (country names or state codes)',
3468
- },
3469
- options: {
3470
- type: 'object',
3471
- properties: {
3472
- fillColor: { type: 'string', description: 'Highlight fill color' },
3473
- strokeColor: { type: 'string', description: 'Highlight stroke color' },
3474
- strokeWidth: { type: 'number', description: 'Highlight stroke width' },
3475
- animate: { type: 'boolean', description: 'Animate the highlight transition' },
3476
- },
3477
- description: 'Highlight styling options',
3478
- },
3479
- },
3480
- required: ['regionIds'],
3481
- },
3482
- },
3483
- {
3484
- name: 'pinepaper_unhighlight_regions',
3485
- annotations: {
3486
- title: 'Unhighlight Regions',
3487
- readOnlyHint: false,
3488
- destructiveHint: false,
3489
- idempotentHint: true,
3490
- openWorldHint: false,
3491
- },
3492
- description: `Remove highlights from specific regions or all regions on the map.
3493
-
3494
- USE WHEN:
3495
- - Resetting map to original state
3496
- - Removing specific region highlights
3497
- - Cycling through different highlight states
3498
-
3499
- EXAMPLES:
3500
- - Remove all highlights: {regionIds: "all"}
3501
- - Remove specific: {regionIds: ["CA", "TX"]}`,
3502
- inputSchema: {
3503
- type: 'object',
3504
- properties: {
3505
- regionIds: {
3506
- oneOf: [
3507
- { type: 'array', items: { type: 'string' } },
3508
- { type: 'string', enum: ['all'] },
3509
- ],
3510
- description: 'Region IDs to unhighlight, or "all" for all regions',
3511
- },
3512
- },
3513
- required: ['regionIds'],
3514
- },
3515
- },
3516
- {
3517
- name: 'pinepaper_apply_data_colors',
3518
- annotations: {
3519
- title: 'Apply Data Colors',
3520
- readOnlyHint: false,
3521
- destructiveHint: false,
3522
- idempotentHint: true,
3523
- openWorldHint: false,
3524
- },
3525
- description: `Apply data-driven coloring to map regions (choropleth visualization).
3526
-
3527
- USE WHEN:
3528
- - Visualizing statistics by region (population, GDP, etc.)
3529
- - Creating heat maps
3530
- - Showing data distribution across geography
3531
- - Building infographics with data overlays
3532
-
3533
- COLOR SCALES:
3534
- - blues: Light to dark blue gradient
3535
- - greens: Light to dark green gradient
3536
- - reds: Light to dark red gradient
3537
- - oranges: Light to dark orange gradient
3538
- - purples: Light to dark purple gradient
3539
- - heat: Yellow to red heat map gradient
3540
-
3541
- DATA FORMAT:
3542
- Keys must match region IDs exactly (country names for world maps, state codes for USA).
3543
-
3544
- EXAMPLES:
3545
- - Population data: {data: {"California": 39538223, "Texas": 29145505, "New York": 20201249}, options: {colorScale: "blues", showLegend: true}}
3546
- - GDP heat map: {data: {"United States of America": 21000, "China": 15000, "Japan": 5000}, options: {colorScale: "heat"}}
3547
- - Custom range: {data: {"CA": 85, "TX": 72}, options: {colorScale: "greens", minValue: 0, maxValue: 100}}`,
3548
- inputSchema: {
3549
- type: 'object',
3550
- properties: {
3551
- data: {
3552
- type: 'object',
3553
- additionalProperties: { type: 'number' },
3554
- description: 'Object mapping region IDs to numeric values',
3555
- },
3556
- options: {
3557
- type: 'object',
3558
- properties: {
3559
- colorScale: {
3560
- type: 'string',
3561
- enum: ['blues', 'greens', 'reds', 'oranges', 'purples', 'heat'],
3562
- description: 'Color scale to use',
3563
- },
3564
- minValue: { type: 'number', description: 'Minimum value for scale' },
3565
- maxValue: { type: 'number', description: 'Maximum value for scale' },
3566
- showLegend: { type: 'boolean', description: 'Display color legend' },
3567
- legendPosition: {
3568
- type: 'string',
3569
- enum: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
3570
- description: 'Legend position',
3571
- },
3572
- legendTitle: { type: 'string', description: 'Title for the legend' },
3573
- },
3574
- description: 'Choropleth styling options',
3575
- },
3576
- },
3577
- required: ['data'],
3578
- },
3579
- },
3580
- {
3581
- name: 'pinepaper_add_marker',
3582
- annotations: {
3583
- title: 'Add Map Marker',
3584
- readOnlyHint: false,
3585
- destructiveHint: false,
3586
- idempotentHint: false,
3587
- openWorldHint: false,
3588
- },
3589
- description: `Add a marker to the map at specified coordinates.
3590
-
3591
- USE WHEN:
3592
- - Marking cities or points of interest
3593
- - Creating location-based visualizations
3594
- - Adding data points with geographic coordinates
3595
- - Building interactive map annotations
3596
-
3597
- MARKER OPTIONS:
3598
- - lat, lon: Geographic coordinates (required)
3599
- - label: Text label for the marker
3600
- - color: Marker color
3601
- - size: Marker size in pixels
3602
- - pulse: Enable animated pulse effect
3603
- - shape: Marker shape (circle, pin, star)
3604
-
3605
- EXAMPLES:
3606
- - City marker: {lat: 37.7749, lon: -122.4194, label: "San Francisco", color: "#ef4444", pulse: true}
3607
- - Simple point: {lat: 40.7128, lon: -74.0060, size: 8, color: "#3b82f6"}
3608
- - Pin marker: {lat: 51.5074, lon: -0.1278, label: "London", shape: "pin"}`,
3609
- inputSchema: {
3610
- type: 'object',
3611
- properties: {
3612
- lat: { type: 'number', description: 'Latitude' },
3613
- lon: { type: 'number', description: 'Longitude' },
3614
- label: { type: 'string', description: 'Marker label text' },
3615
- color: { type: 'string', description: 'Marker color' },
3616
- size: { type: 'number', description: 'Marker size in pixels' },
3617
- pulse: { type: 'boolean', description: 'Enable pulse animation' },
3618
- shape: {
3619
- type: 'string',
3620
- enum: ['circle', 'pin', 'star'],
3621
- description: 'Marker shape',
3622
- },
3623
- },
3624
- required: ['lat', 'lon'],
3625
- },
3626
- },
3627
- {
3628
- name: 'pinepaper_add_map_labels',
3629
- annotations: {
3630
- title: 'Add Map Labels',
3631
- readOnlyHint: false,
3632
- destructiveHint: false,
3633
- idempotentHint: true,
3634
- openWorldHint: false,
3635
- },
3636
- description: `Add text labels to map regions.
3637
-
3638
- USE WHEN:
3639
- - Labeling countries or states
3640
- - Adding region names to visualizations
3641
- - Creating annotated maps
3642
- - Showing data values on regions
3643
-
3644
- LABEL TYPES:
3645
- - name: Full region name
3646
- - code: Region code (e.g., "CA" for California)
3647
- - value: Data value (if applyDataColors was used)
3648
-
3649
- EXAMPLES:
3650
- - Label all visible: {options: {fontSize: 10, fontColor: "#374151"}}
3651
- - Label specific regions: {regions: ["California", "Texas"], options: {labelType: "code"}}
3652
- - Show data values: {options: {labelType: "value", fontSize: 12}}`,
3653
- inputSchema: {
3654
- type: 'object',
3655
- properties: {
3656
- regions: {
3657
- type: 'array',
3658
- items: { type: 'string' },
3659
- description: 'Specific regions to label (null for all visible)',
3660
- },
3661
- options: {
3662
- type: 'object',
3663
- properties: {
3664
- fontSize: { type: 'number', description: 'Label font size' },
3665
- fontColor: { type: 'string', description: 'Label text color' },
3666
- labelType: {
3667
- type: 'string',
3668
- enum: ['name', 'code', 'value'],
3669
- description: 'Type of label content',
3670
- },
3671
- backgroundColor: { type: 'string', description: 'Label background color' },
3672
- },
3673
- description: 'Label styling options',
3674
- },
3675
- },
3676
- },
3677
- },
3678
- {
3679
- name: 'pinepaper_pan_map',
3680
- annotations: {
3681
- title: 'Pan Map',
3682
- readOnlyHint: false,
3683
- destructiveHint: false,
3684
- idempotentHint: true,
3685
- openWorldHint: false,
3686
- },
3687
- description: `Pan the map view to center on specific coordinates.
3688
-
3689
- USE WHEN:
3690
- - Navigating to a specific location
3691
- - Creating animated map transitions
3692
- - Focusing on a region of interest
3693
-
3694
- EXAMPLES:
3695
- - Pan to New York: {lat: 40.7128, lon: -74.0060}
3696
- - Pan to Europe: {lat: 50, lon: 10}`,
3697
- inputSchema: {
3698
- type: 'object',
3699
- properties: {
3700
- lat: { type: 'number', description: 'Target latitude' },
3701
- lon: { type: 'number', description: 'Target longitude' },
3702
- animate: { type: 'boolean', description: 'Animate the pan transition' },
3703
- duration: { type: 'number', description: 'Animation duration in seconds' },
3704
- },
3705
- required: ['lat', 'lon'],
3706
- },
3707
- },
3708
- {
3709
- name: 'pinepaper_zoom_map',
3710
- annotations: {
3711
- title: 'Zoom Map',
3712
- readOnlyHint: false,
3713
- destructiveHint: false,
3714
- idempotentHint: true,
3715
- openWorldHint: false,
3716
- },
3717
- description: `Set the map zoom level.
3718
-
3719
- USE WHEN:
3720
- - Zooming in on specific areas
3721
- - Creating zoom animations
3722
- - Adjusting map scale
3723
-
3724
- ZOOM LEVELS:
3725
- - 1: Full view (default)
3726
- - 2-5: Moderate zoom
3727
- - 5+: Close-up view
3728
-
3729
- EXAMPLES:
3730
- - Zoom in: {level: 2}
3731
- - Animated zoom: {level: 3, animate: true, duration: 1}`,
3732
- inputSchema: {
3733
- type: 'object',
3734
- properties: {
3735
- level: { type: 'number', description: 'Zoom level (1 = full view)' },
3736
- animate: { type: 'boolean', description: 'Animate the zoom transition' },
3737
- duration: { type: 'number', description: 'Animation duration in seconds' },
3738
- },
3739
- required: ['level'],
3740
- },
3741
- },
3742
- {
3743
- name: 'pinepaper_export_map',
3744
- annotations: {
3745
- title: 'Export Map',
3746
- readOnlyHint: true,
3747
- destructiveHint: false,
3748
- idempotentHint: true,
3749
- openWorldHint: false,
3750
- },
3751
- description: `Export the current map configuration and state.
3752
-
3753
- USE WHEN:
3754
- - Saving map state for later restoration
3755
- - Exporting map data for external use
3756
- - Creating shareable map configurations
3757
-
3758
- RETURNS:
3759
- - mapId: Current map identifier
3760
- - projection: Active projection
3761
- - regions: Region states and highlights
3762
- - markers: All added markers
3763
- - dataColors: Applied data coloring configuration`,
3764
- inputSchema: {
3765
- type: 'object',
3766
- properties: {},
3767
- },
3768
- },
3769
- {
3770
- name: 'pinepaper_import_custom_map',
3771
- annotations: {
3772
- title: 'Import Custom Map',
3773
- readOnlyHint: false,
3774
- destructiveHint: false,
3775
- idempotentHint: false,
3776
- openWorldHint: true,
3777
- },
3778
- description: `Import a custom GeoJSON or TopoJSON map.
3779
-
3780
- USE WHEN:
3781
- - Loading custom geographic boundaries
3782
- - Using detailed country/region maps from GADM
3783
- - Importing custom shapes or territories
3784
- - Working with non-standard geographic data
3785
-
3786
- SUPPORTED FORMATS:
3787
- - GeoJSON: Standard geographic JSON format
3788
- - TopoJSON: Compressed topology format
3789
-
3790
- SOURCES:
3791
- - GADM: Detailed country subdivisions (gadm.org)
3792
- - Natural Earth: Public domain maps (naturalearthdata.com)
3793
- - Census: Official boundary files
3794
- - Custom: Your own GeoJSON files
3795
-
3796
- EXAMPLES:
3797
- - Import from URL: {url: "https://example.com/custom.geojson", options: {projection: "mercator"}}
3798
- - Import GeoJSON object: {geoJson: {...}, options: {projection: "naturalEarth"}}`,
3799
- inputSchema: {
3800
- type: 'object',
3801
- properties: {
3802
- url: { type: 'string', description: 'URL to GeoJSON/TopoJSON file' },
3803
- geoJson: {
3804
- type: 'object',
3805
- description: 'GeoJSON object to import directly',
3806
- },
3807
- options: {
3808
- type: 'object',
3809
- properties: {
3810
- projection: {
3811
- type: 'string',
3812
- enum: ['mercator', 'equalEarth', 'naturalEarth', 'orthographic', 'albers', 'stereographic'],
3813
- description: 'Projection to use for rendering',
3814
- },
3815
- fillColor: { type: 'string' },
3816
- strokeColor: { type: 'string' },
3817
- strokeWidth: { type: 'number' },
3818
- },
3819
- description: 'Import options',
3820
- },
3821
- },
3822
- },
3823
- },
3824
- {
3825
- name: 'pinepaper_get_region_at_point',
3826
- annotations: {
3827
- title: 'Get Region at Point',
3828
- readOnlyHint: true,
3829
- destructiveHint: false,
3830
- idempotentHint: true,
3831
- openWorldHint: false,
3832
- },
3833
- description: `[Utility] Get the region at a specific canvas point (hit testing).
3834
-
3835
- USE WHEN:
3836
- - Implementing click interactions
3837
- - Finding which region is at a coordinate
3838
- - Building interactive map features
3839
-
3840
- EXAMPLES:
3841
- - Check point: {x: 400, y: 300}
3842
-
3843
- RETURNS:
3844
- - regionId: ID of the region at point (or null)
3845
- - regionName: Display name
3846
- - properties: Region properties from GeoJSON`,
3847
- inputSchema: {
3848
- type: 'object',
3849
- properties: {
3850
- x: { type: 'number', description: 'Canvas X coordinate' },
3851
- y: { type: 'number', description: 'Canvas Y coordinate' },
3852
- },
3853
- required: ['x', 'y'],
3854
- },
3855
- },
3856
- {
3857
- name: 'pinepaper_animate_map_regions',
3858
- annotations: {
3859
- title: 'Animate Map Regions',
3860
- readOnlyHint: false,
3861
- destructiveHint: false,
3862
- idempotentHint: false,
3863
- openWorldHint: false,
3864
- },
3865
- description: `Animate specific map regions with timeline-integrated keyframe color animations.
3866
-
3867
- USE WHEN:
3868
- - Creating animated choropleth transitions
3869
- - Showing data changes over time
3870
- - Building story-based map visualizations
3871
- - Adding visual emphasis to regions
3872
-
3873
- KEYFRAME PROPERTIES:
3874
- - time: Time in seconds for this keyframe
3875
- - fillColor: Fill color at this keyframe (required)
3876
- - strokeColor: Optional stroke color
3877
- - opacity: Optional opacity (0-1)
3878
-
3879
- EXAMPLES:
3880
- - Simple color transition: {duration: 5, loop: true, regions: {"USA": [{"time": 0, "fillColor": "#ef4444"}, {"time": 5, "fillColor": "#22c55e"}]}}
3881
- - Multi-region animation: {duration: 8, regions: {"USA": [...], "France": [...], "Japan": [...]}}`,
3882
- inputSchema: {
3883
- type: 'object',
3884
- properties: {
3885
- duration: {
3886
- type: 'number',
3887
- description: 'Total animation duration in seconds (default: 5)',
3888
- },
3889
- loop: {
3890
- type: 'boolean',
3891
- description: 'Loop the animation (default: true)',
3892
- },
3893
- regions: {
3894
- type: 'object',
3895
- additionalProperties: {
3896
- type: 'array',
3897
- items: {
3898
- type: 'object',
3899
- properties: {
3900
- time: { type: 'number', description: 'Time in seconds' },
3901
- fillColor: { type: 'string', description: 'Fill color at this keyframe' },
3902
- strokeColor: { type: 'string', description: 'Stroke color (optional)' },
3903
- opacity: { type: 'number', description: 'Opacity 0-1 (optional)' },
3904
- },
3905
- required: ['time', 'fillColor'],
3906
- },
3907
- },
3908
- description: 'Object mapping region IDs to arrays of keyframes',
3909
- },
3910
- },
3911
- required: ['regions'],
3912
- },
3913
- },
3914
- {
3915
- name: 'pinepaper_animate_map_wave',
3916
- annotations: {
3917
- title: 'Animate Map Wave',
3918
- readOnlyHint: false,
3919
- destructiveHint: false,
3920
- idempotentHint: false,
3921
- openWorldHint: false,
3922
- },
3923
- description: `Create a wave animation across all map regions based on geographic position.
3924
-
3925
- USE WHEN:
3926
- - Creating dramatic visual effects
3927
- - Showing global spread patterns
3928
- - Adding ambient map animations
3929
- - Building attention-grabbing transitions
3930
-
3931
- WAVE DIRECTIONS:
3932
- - horizontal: Wave sweeps left to right
3933
- - vertical: Wave sweeps top to bottom
3934
- - radial: Wave radiates from center outward
3935
-
3936
- EXAMPLES:
3937
- - Rainbow wave: {duration: 10, colors: ["#ef4444", "#fbbf24", "#22c55e", "#3b82f6"], waveDirection: "horizontal"}
3938
- - Fast radial pulse: {duration: 3, colors: ["#ffffff", "#3b82f6"], waveDirection: "radial", loop: true}`,
3939
- inputSchema: {
3940
- type: 'object',
3941
- properties: {
3942
- duration: {
3943
- type: 'number',
3944
- description: 'Total wave duration in seconds (default: 10)',
3945
- },
3946
- loop: {
3947
- type: 'boolean',
3948
- description: 'Loop the animation (default: true)',
3949
- },
3950
- colors: {
3951
- type: 'array',
3952
- items: { type: 'string' },
3953
- description: 'Array of colors for the wave (default: red, yellow, green, blue)',
3954
- },
3955
- waveDirection: {
3956
- type: 'string',
3957
- enum: ['horizontal', 'vertical', 'radial'],
3958
- description: 'Direction of the wave effect (default: horizontal)',
3959
- },
3960
- },
3961
- },
3962
- },
3963
- {
3964
- name: 'pinepaper_stop_map_animations',
3965
- annotations: {
3966
- title: 'Stop Map Animations',
3967
- readOnlyHint: false,
3968
- destructiveHint: false,
3969
- idempotentHint: true,
3970
- openWorldHint: false,
3971
- },
3972
- description: `Stop all or specific map region animations.
3973
-
3974
- USE WHEN:
3975
- - Ending animated sequences
3976
- - Resetting map to static state
3977
- - Pausing for user interaction
3978
- - Transitioning to different visualization
3979
-
3980
- EXAMPLES:
3981
- - Stop all: {}
3982
- - Stop specific regions: {regions: ["USA", "France"]}
3983
- - Stop and reset colors: {resetColors: true}`,
3984
- inputSchema: {
3985
- type: 'object',
3986
- properties: {
3987
- regions: {
3988
- type: 'array',
3989
- items: { type: 'string' },
3990
- description: 'Specific region IDs to stop (omit for all)',
3991
- },
3992
- resetColors: {
3993
- type: 'boolean',
3994
- description: 'Reset regions to default colors (default: true)',
3995
- },
3996
- },
3997
- },
3998
- },
3999
- {
4000
- name: 'pinepaper_get_animated_map_regions',
4001
- annotations: {
4002
- title: 'Get Animated Map Regions',
4003
- readOnlyHint: true,
4004
- destructiveHint: false,
4005
- idempotentHint: true,
4006
- openWorldHint: false,
4007
- },
4008
- description: `[Utility] Get list of currently animated map regions with their animation data.
4009
-
4010
- USE WHEN:
4011
- - Debugging animations
4012
- - Checking animation state
4013
- - Building animation controls
4014
- - Inspecting current timeline
4015
-
4016
- RETURNS:
4017
- - animatedRegions: Array of region animation info
4018
- - count: Total number of animated regions`,
4019
- inputSchema: {
4020
- type: 'object',
4021
- properties: {},
4022
- },
4023
- },
4024
- {
4025
- name: 'pinepaper_export_map_region_csv',
4026
- annotations: {
4027
- title: 'Export Map Region CSV',
4028
- readOnlyHint: true,
4029
- destructiveHint: false,
4030
- idempotentHint: true,
4031
- openWorldHint: false,
4032
- },
4033
- description: `Export map region data as CSV including colors, highlight, and selection status.
4034
-
4035
- USE WHEN:
4036
- - Saving map state for later
4037
- - Creating data-driven workflows
4038
- - Integrating with spreadsheet tools
4039
- - Building export features
4040
-
4041
- CSV COLUMNS:
4042
- - regionId: Region identifier
4043
- - name: Display name
4044
- - highlighted: 1 or 0
4045
- - selected: 1 or 0
4046
- - fillColor: Current fill color
4047
- - strokeColor: Current stroke color
4048
-
4049
- EXAMPLES:
4050
- - Full export: {}
4051
- - Colors only: {includeHighlighted: false, includeSelected: false}
4052
- - Auto-download: {download: true, filename: "map-export.csv"}`,
4053
- inputSchema: {
4054
- type: 'object',
4055
- properties: {
4056
- includeHighlighted: {
4057
- type: 'boolean',
4058
- description: 'Include highlight status column (default: true)',
4059
- },
4060
- includeSelected: {
4061
- type: 'boolean',
4062
- description: 'Include selection status column (default: true)',
4063
- },
4064
- includeColors: {
4065
- type: 'boolean',
4066
- description: 'Include fill/stroke color columns (default: true)',
4067
- },
4068
- download: {
4069
- type: 'boolean',
4070
- description: 'Auto-download the CSV file (default: false)',
4071
- },
4072
- filename: {
4073
- type: 'string',
4074
- description: 'Filename for download (default: map-regions.csv)',
4075
- },
4076
- },
4077
- },
4078
- },
4079
- {
4080
- name: 'pinepaper_import_map_region_csv',
4081
- annotations: {
4082
- title: 'Import Map Region CSV',
4083
- readOnlyHint: false,
4084
- destructiveHint: false,
4085
- idempotentHint: true,
4086
- openWorldHint: false,
4087
- },
4088
- description: `Import CSV data to update map region states (colors, highlight, selection).
4089
-
4090
- USE WHEN:
4091
- - Restoring saved map state
4092
- - Applying data from spreadsheets
4093
- - Batch updating region properties
4094
- - Building data-driven visualizations
4095
-
4096
- CSV FORMAT:
4097
- Must have 'regionId' column. Optional columns:
4098
- - fillColor: Hex color for fill
4099
- - strokeColor: Hex color for stroke
4100
- - highlighted: 1 or 0
4101
- - selected: 1 or 0
4102
-
4103
- EXAMPLES:
4104
- - Import full CSV: {csvText: "regionId,fillColor,highlighted\\nUSA,#22c55e,1\\nFrance,#3b82f6,0"}
4105
- - Colors only: {csvText: "...", applyHighlight: false, applySelection: false}`,
4106
- inputSchema: {
4107
- type: 'object',
4108
- properties: {
4109
- csvText: {
4110
- type: 'string',
4111
- description: 'CSV text content to import',
4112
- },
4113
- applyColors: {
4114
- type: 'boolean',
4115
- description: 'Apply fill/stroke colors from CSV (default: true)',
4116
- },
4117
- applyHighlight: {
4118
- type: 'boolean',
4119
- description: 'Update highlight status from CSV (default: true)',
4120
- },
4121
- applySelection: {
4122
- type: 'boolean',
4123
- description: 'Update selection status from CSV (default: true)',
4124
- },
4125
- },
4126
- required: ['csvText'],
4127
- },
4128
- },
4129
- {
4130
- name: 'pinepaper_select_map_regions',
4131
- annotations: {
4132
- title: 'Select Map Regions',
4133
- readOnlyHint: false,
4134
- destructiveHint: false,
4135
- idempotentHint: true,
4136
- openWorldHint: false,
4137
- },
4138
- description: `Programmatically select map regions.
4139
-
4140
- USE WHEN:
4141
- - Building interactive map features
4142
- - Responding to user input
4143
- - Creating selection-based workflows
4144
- - Highlighting user choices
4145
-
4146
- EXAMPLES:
4147
- - Select countries: {regionIds: ["USA", "Canada", "Mexico"]}
4148
- - Select US states: {regionIds: ["CA", "TX", "NY"]}`,
4149
- inputSchema: {
4150
- type: 'object',
4151
- properties: {
4152
- regionIds: {
4153
- type: 'array',
4154
- items: { type: 'string' },
4155
- description: 'Array of region IDs to select',
4156
- },
4157
- },
4158
- required: ['regionIds'],
4159
- },
4160
- },
4161
- {
4162
- name: 'pinepaper_deselect_map_regions',
4163
- annotations: {
4164
- title: 'Deselect Map Regions',
4165
- readOnlyHint: false,
4166
- destructiveHint: false,
4167
- idempotentHint: true,
4168
- openWorldHint: false,
4169
- },
4170
- description: `Programmatically deselect map regions.
4171
-
4172
- USE WHEN:
4173
- - Clearing user selections
4174
- - Resetting map state
4175
- - Implementing toggle behavior
4176
- - Building selection management
4177
-
4178
- EXAMPLES:
4179
- - Deselect specific: {regionIds: ["USA", "France"]}
4180
- - Deselect all: {} (omit regionIds)`,
4181
- inputSchema: {
4182
- type: 'object',
4183
- properties: {
4184
- regionIds: {
4185
- type: 'array',
4186
- items: { type: 'string' },
4187
- description: 'Array of region IDs to deselect (omit for all)',
4188
- },
4189
- },
4190
- },
4191
- },
4192
- {
4193
- name: 'pinepaper_get_highlighted_map_regions',
4194
- annotations: {
4195
- title: 'Get Highlighted Map Regions',
4196
- readOnlyHint: true,
4197
- destructiveHint: false,
4198
- idempotentHint: true,
4199
- openWorldHint: false,
4200
- },
4201
- description: `[Utility] Get list of currently highlighted map regions.
4202
-
4203
- USE WHEN:
4204
- - Checking current highlight state
4205
- - Building conditional logic
4206
- - Creating highlight summaries
4207
- - Debugging map state
4208
-
4209
- RETURNS:
4210
- - highlighted: Array of highlighted region IDs
4211
- - count: Total number of highlighted regions`,
4212
- inputSchema: {
4213
- type: 'object',
4214
- properties: {},
4215
- },
4216
- },
4217
- {
4218
- name: 'pinepaper_export_map_geojson',
4219
- annotations: {
4220
- title: 'Export Map GeoJSON',
4221
- readOnlyHint: true,
4222
- destructiveHint: false,
4223
- idempotentHint: true,
4224
- openWorldHint: false,
4225
- },
4226
- description: `Export the current map as GeoJSON (with current colors/modifications).
4227
-
4228
- USE WHEN:
4229
- - Saving map state with custom styling
4230
- - Exporting for use in other mapping tools
4231
- - Creating styled GeoJSON for external applications
4232
- - Archiving map customizations
4233
-
4234
- EXAMPLES:
4235
- - Export with styles: {includeStyles: true}
4236
- - Selected regions only: {selectedOnly: true}
4237
- - Auto-download: {download: true, filename: "my-map.geojson"}`,
4238
- inputSchema: {
4239
- type: 'object',
4240
- properties: {
4241
- includeStyles: {
4242
- type: 'boolean',
4243
- description: 'Include fill/stroke colors as properties (default: true)',
4244
- },
4245
- includeMetadata: {
4246
- type: 'boolean',
4247
- description: 'Include region names and IDs (default: true)',
4248
- },
4249
- selectedOnly: {
4250
- type: 'boolean',
4251
- description: 'Only export selected regions (default: false)',
4252
- },
4253
- download: {
4254
- type: 'boolean',
4255
- description: 'Auto-download the file (default: false)',
4256
- },
4257
- filename: {
4258
- type: 'string',
4259
- description: 'Filename for download (default: "map-export.geojson")',
4260
- },
4261
- },
4262
- },
4263
- },
4264
- {
4265
- name: 'pinepaper_export_original_map_geojson',
4266
- annotations: {
4267
- title: 'Export Original Map GeoJSON',
4268
- readOnlyHint: true,
4269
- destructiveHint: false,
4270
- idempotentHint: true,
4271
- openWorldHint: false,
4272
- },
4273
- 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.
4274
-
4275
- USE WHEN:
4276
- - Extracting original map data for external editing
4277
- - Getting clean boundaries without customizations
4278
- - Creating a baseline for map modifications
4279
- - Re-importing after external boundary edits
4280
-
4281
- EXAMPLES:
4282
- - Get original data: {}
4283
- - Auto-download: {download: true, filename: "map-source.geojson"}`,
4284
- inputSchema: {
4285
- type: 'object',
4286
- properties: {
4287
- download: {
4288
- type: 'boolean',
4289
- description: 'Auto-download the file (default: false)',
4290
- },
4291
- filename: {
4292
- type: 'string',
4293
- description: 'Filename for download (default: "map-source.geojson")',
4294
- },
4295
- },
4296
- },
4297
- },
4298
- {
4299
- name: 'pinepaper_get_map_source_info',
4300
- annotations: {
4301
- title: 'Get Map Source Info',
4302
- readOnlyHint: true,
4303
- destructiveHint: false,
4304
- idempotentHint: true,
4305
- openWorldHint: false,
4306
- },
4307
- description: `[Utility] Get information about the currently loaded map source.
4308
-
4309
- USE WHEN:
4310
- - Checking what map is currently loaded
4311
- - Debugging map loading issues
4312
- - Getting map metadata
4313
- - Verifying map configuration
4314
-
4315
- RETURNS:
4316
- - source: Map source identifier (e.g., "world", "worldHighRes", "usa", or custom)
4317
- - projection: Current projection type
4318
- - quality: Rendering quality setting
4319
- - regionCount: Total number of regions
4320
- - hasOriginalGeoJSON: Whether original GeoJSON is available
4321
- - isCustomImport: Whether this is a custom imported map`,
4322
- inputSchema: {
4323
- type: 'object',
4324
- properties: {},
4325
- },
4326
- },
4327
- // ---------------------------------------------------------------------------
4328
- // DOMAIN: FONT TOOLS
4329
- // ---------------------------------------------------------------------------
4330
- {
4331
- name: 'pinepaper_font_show_studio',
4332
- annotations: {
4333
- title: 'Font Show Studio',
4334
- readOnlyHint: false,
4335
- destructiveHint: false,
4336
- idempotentHint: true,
4337
- openWorldHint: false,
4338
- },
4339
- description: `Open the Font Studio UI for interactive font creation.
4340
-
4341
- USE WHEN:
4342
- - Starting a custom font creation workflow
4343
- - Need the interactive Font Studio interface with guide lines
4344
- - Want to create a hand-drawn font from scratch
4345
-
4346
- WORKFLOW:
4347
- 1. Open Font Studio → pinepaper_font_show_studio
4348
- 2. Set font name → pinepaper_font_set_name
4349
- 3. Check required chars → pinepaper_font_get_required_chars
4350
- 4. For each character: draw path, cleanup, create glyph
4351
- 5. Check progress → pinepaper_font_get_status
4352
- 6. Export when complete → pinepaper_font_export`,
4353
- inputSchema: {
4354
- type: 'object',
4355
- properties: {},
4356
- },
4357
- },
4358
- {
4359
- name: 'pinepaper_font_set_name',
4360
- annotations: {
4361
- title: 'Font Set Name',
4362
- readOnlyHint: false,
4363
- destructiveHint: false,
4364
- idempotentHint: true,
4365
- openWorldHint: false,
4366
- },
4367
- description: `Set the font family name for the current font being created.`,
4368
- inputSchema: {
4369
- type: 'object',
4370
- properties: {
4371
- name: {
4372
- type: 'string',
4373
- description: "Font family name (e.g., 'MyHandwriting')",
4374
- },
4375
- },
4376
- required: ['name'],
4377
- },
4378
- },
4379
- {
4380
- name: 'pinepaper_font_get_required_chars',
4381
- annotations: {
4382
- title: 'Font Get Required Chars',
4383
- readOnlyHint: true,
4384
- destructiveHint: false,
4385
- idempotentHint: true,
4386
- openWorldHint: false,
4387
- },
4388
- description: `Get the list of characters needed for a complete font.
4389
-
4390
- CHARACTER SETS:
4391
- - minimum: A-Z, a-z, 0-9, space (63 chars) - enough for basic text
4392
- - standard: adds punctuation and symbols (90+ chars) - full typography`,
4393
- inputSchema: {
4394
- type: 'object',
4395
- properties: {
4396
- set: {
4397
- type: 'string',
4398
- enum: ['minimum', 'standard'],
4399
- description: 'minimum: A-Z, a-z, 0-9, space (63 chars). standard: adds punctuation (90+ chars)',
4400
- },
4401
- },
4402
- },
4403
- },
4404
- {
4405
- name: 'pinepaper_font_get_status',
4406
- annotations: {
4407
- title: 'Font Get Status',
4408
- readOnlyHint: true,
4409
- destructiveHint: false,
4410
- idempotentHint: true,
4411
- openWorldHint: false,
4412
- },
4413
- description: `Get font completion status including progress percentage, completed/pending characters.
4414
-
4415
- USE WHEN:
4416
- - Checking progress during font creation
4417
- - Determining which characters still need to be drawn
4418
- - Verifying font is complete before export`,
4419
- inputSchema: {
4420
- type: 'object',
4421
- properties: {},
4422
- },
4423
- },
4424
- {
4425
- name: 'pinepaper_font_create_glyph',
4426
- annotations: {
4427
- title: 'Font Create Glyph',
4428
- readOnlyHint: false,
4429
- destructiveHint: false,
4430
- idempotentHint: false,
4431
- openWorldHint: false,
4432
- },
4433
- description: `Create a glyph from a Paper.js path. Converts a drawn path into an OpenType glyph with calculated advance width.
4434
-
4435
- USE WHEN:
4436
- - Converting a drawn character path to a font glyph
4437
- - Adding a new character to the font
4438
-
4439
- WORKFLOW:
4440
- 1. Draw the character as a Paper.js path on the canvas
4441
- 2. Optionally clean up the path (pinepaper_font_cleanup_path)
4442
- 3. Use the path's registry ID to create the glyph`,
4443
- inputSchema: {
4444
- type: 'object',
4445
- properties: {
4446
- character: {
4447
- type: 'string',
4448
- description: "Single character (e.g., 'A', 'a', '1', ' ')",
4449
- },
4450
- pathId: {
4451
- type: 'string',
4452
- description: 'Registry ID of the Paper.js path to use as glyph shape',
4453
- },
4454
- },
4455
- required: ['character', 'pathId'],
4456
- },
4457
- },
4458
- {
4459
- name: 'pinepaper_font_create_space',
4460
- annotations: {
4461
- title: 'Font Create Space',
4462
- readOnlyHint: false,
4463
- destructiveHint: false,
4464
- idempotentHint: true,
4465
- openWorldHint: false,
4466
- },
4467
- description: `Create the space glyph (no visible shape, just advance width).
4468
-
4469
- USE WHEN:
4470
- - Adding the space character to the font
4471
- - Space needs no drawn path, only a width value`,
4472
- inputSchema: {
4473
- type: 'object',
4474
- properties: {
4475
- width: {
4476
- type: 'number',
4477
- description: 'Space width in font units (default: 250)',
4478
- },
4479
- },
4480
- },
4481
- },
4482
- {
4483
- name: 'pinepaper_font_remove_glyph',
4484
- annotations: {
4485
- title: 'Font Remove Glyph',
4486
- readOnlyHint: false,
4487
- destructiveHint: true,
4488
- idempotentHint: true,
4489
- openWorldHint: false,
4490
- },
4491
- description: `Remove a glyph from the font. Use when a character needs to be redrawn.`,
4492
- inputSchema: {
4493
- type: 'object',
4494
- properties: {
4495
- character: {
4496
- type: 'string',
4497
- description: 'Character to remove',
4498
- },
4499
- },
4500
- required: ['character'],
4501
- },
4502
- },
4503
- {
4504
- name: 'pinepaper_font_set_metrics',
4505
- annotations: {
4506
- title: 'Font Set Metrics',
4507
- readOnlyHint: false,
4508
- destructiveHint: false,
4509
- idempotentHint: true,
4510
- openWorldHint: false,
4511
- },
4512
- description: `Set font metrics (advanced). Controls the coordinate grid and vertical measurements.
4513
-
4514
- METRICS:
4515
- - unitsPerEm: Coordinate grid size (default: 1000)
4516
- - ascender: Height above baseline (default: 800)
4517
- - descender: Depth below baseline, negative (default: -200)
4518
- - xHeight: Lowercase letter height (default: 500)
4519
- - capHeight: Capital letter height (default: 700)`,
4520
- inputSchema: {
4521
- type: 'object',
4522
- properties: {
4523
- unitsPerEm: {
4524
- type: 'number',
4525
- description: 'Coordinate grid size (default: 1000)',
4526
- },
4527
- ascender: {
4528
- type: 'number',
4529
- description: 'Height above baseline (default: 800)',
4530
- },
4531
- descender: {
4532
- type: 'number',
4533
- description: 'Depth below baseline, negative (default: -200)',
4534
- },
4535
- xHeight: {
4536
- type: 'number',
4537
- description: 'Lowercase letter height (default: 500)',
4538
- },
4539
- capHeight: {
4540
- type: 'number',
4541
- description: 'Capital letter height (default: 700)',
4542
- },
4543
- },
4544
- },
4545
- },
4546
- {
4547
- name: 'pinepaper_font_export',
4548
- annotations: {
4549
- title: 'Font Export',
4550
- readOnlyHint: true,
4551
- destructiveHint: false,
4552
- idempotentHint: true,
4553
- openWorldHint: false,
4554
- },
4555
- description: `Export the font as an OTF file. Triggers browser download of the completed font.
4556
-
4557
- USE WHEN:
4558
- - Font is complete and ready for download
4559
- - User wants to save the font as a file`,
4560
- inputSchema: {
4561
- type: 'object',
4562
- properties: {
4563
- download: {
4564
- type: 'boolean',
4565
- description: 'Trigger browser download (default: true)',
4566
- },
4567
- },
4568
- },
4569
- },
4570
- {
4571
- name: 'pinepaper_font_load_into_document',
3601
+ name: 'pinepaper_remove_connector',
4572
3602
  annotations: {
4573
- title: 'Font Load Into Document',
3603
+ title: 'Remove Connector',
4574
3604
  readOnlyHint: false,
4575
- destructiveHint: false,
3605
+ destructiveHint: true,
4576
3606
  idempotentHint: true,
4577
3607
  openWorldHint: false,
4578
3608
  },
4579
- description: `Load the custom font into the document for immediate use in PinePaper text items.
3609
+ description: `Remove a connector from the canvas.
4580
3610
 
4581
3611
  USE WHEN:
4582
- - Want to use the created font immediately in the current document
4583
- - Testing how the font looks in actual text items`,
3612
+ - Deleting a connection between items
3613
+ - Removing incorrect links
3614
+ - Restructuring diagram connections`,
4584
3615
  inputSchema: {
4585
3616
  type: 'object',
4586
- properties: {},
3617
+ properties: {
3618
+ connectorId: {
3619
+ type: 'string',
3620
+ description: 'ID of the connector to remove',
3621
+ },
3622
+ },
3623
+ required: ['connectorId'],
4587
3624
  },
4588
3625
  },
4589
3626
  {
4590
- name: 'pinepaper_font_export_data',
3627
+ name: 'pinepaper_diagram_mode',
4591
3628
  annotations: {
4592
- title: 'Font Export Data',
4593
- readOnlyHint: true,
3629
+ title: 'Diagram Mode',
3630
+ readOnlyHint: false,
4594
3631
  destructiveHint: false,
4595
3632
  idempotentHint: true,
4596
3633
  openWorldHint: false,
4597
3634
  },
4598
- description: `Export font data as JSON for saving progress. Use to save work-in-progress fonts.
3635
+ description: `Control the diagram mode for interactive editing.
4599
3636
 
4600
3637
  USE WHEN:
4601
- - Saving font progress for later continuation
4602
- - Backing up font data`,
3638
+ - Switching between drawing and selection modes
3639
+ - Enabling/disabling diagram-specific UI
3640
+ - Setting up the canvas for diagram creation
3641
+
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"}`,
4603
3659
  inputSchema: {
4604
3660
  type: 'object',
4605
3661
  properties: {
4606
- download: {
4607
- type: 'boolean',
4608
- 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',
4609
3676
  },
4610
3677
  },
3678
+ required: ['action'],
4611
3679
  },
4612
3680
  },
3681
+ // ---------------------------------------------------------------------------
3682
+ // DOMAIN: MAP TOOLS — four action-dispatched tools replace 23 wrappers
3683
+ // ---------------------------------------------------------------------------
4613
3684
  {
4614
- name: 'pinepaper_font_import_data',
3685
+ name: 'pinepaper_map',
4615
3686
  annotations: {
4616
- title: 'Font Import Data',
3687
+ title: 'Map: Load + Viewport',
4617
3688
  readOnlyHint: false,
4618
3689
  destructiveHint: false,
4619
3690
  idempotentHint: false,
4620
3691
  openWorldHint: false,
4621
3692
  },
4622
- 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.
4623
3694
 
4624
- USE WHEN:
4625
- - Resuming work on a previously saved font
4626
- - 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.`,
4627
3703
  inputSchema: {
4628
3704
  type: 'object',
4629
3705
  properties: {
4630
- data: {
4631
- type: 'object',
4632
- description: 'Font data object from pinepaper_font_export_data',
4633
- },
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)' },
4634
3716
  },
4635
- required: ['data'],
3717
+ required: ['action'],
4636
3718
  },
4637
3719
  },
4638
3720
  {
4639
- name: 'pinepaper_font_clear',
3721
+ name: 'pinepaper_map_regions',
4640
3722
  annotations: {
4641
- title: 'Font Clear',
3723
+ title: 'Map: Region Styling + Selection',
4642
3724
  readOnlyHint: false,
4643
- destructiveHint: true,
4644
- idempotentHint: true,
3725
+ destructiveHint: false,
3726
+ idempotentHint: false,
4645
3727
  openWorldHint: false,
4646
3728
  },
4647
- 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.
4648
3730
 
4649
- 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 — {}`,
4650
3741
  inputSchema: {
4651
3742
  type: 'object',
4652
- 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'],
4653
3761
  },
4654
3762
  },
4655
3763
  {
4656
- name: 'pinepaper_font_remove_overlap',
3764
+ name: 'pinepaper_map_animation',
4657
3765
  annotations: {
4658
- title: 'Font Remove Overlap',
3766
+ title: 'Map: Region Animations',
4659
3767
  readOnlyHint: false,
4660
3768
  destructiveHint: false,
4661
- idempotentHint: true,
3769
+ idempotentHint: false,
4662
3770
  openWorldHint: false,
4663
3771
  },
4664
- 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.
4665
3773
 
4666
- USE WHEN:
4667
- - Path has overlapping strokes that need merging
4668
- - 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 — {}`,
4669
3779
  inputSchema: {
4670
3780
  type: 'object',
4671
3781
  properties: {
4672
- pathId: {
4673
- type: 'string',
4674
- description: 'Registry ID of the Paper.js path to process',
4675
- },
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' },
4676
3790
  },
4677
- required: ['pathId'],
3791
+ required: ['action'],
4678
3792
  },
4679
3793
  },
4680
3794
  {
4681
- name: 'pinepaper_font_correct_direction',
3795
+ name: 'pinepaper_map_data',
4682
3796
  annotations: {
4683
- title: 'Font Correct Direction',
3797
+ title: 'Map: Data Import + Export',
4684
3798
  readOnlyHint: false,
4685
3799
  destructiveHint: false,
4686
3800
  idempotentHint: true,
4687
3801
  openWorldHint: false,
4688
3802
  },
4689
- 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.
4690
3804
 
4691
- USE WHEN:
4692
- - Glyph fills are rendering incorrectly (holes appear filled)
4693
- - 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 }`,
4694
3811
  inputSchema: {
4695
3812
  type: 'object',
4696
3813
  properties: {
4697
- pathId: {
4698
- type: 'string',
4699
- description: 'Registry ID of the Paper.js path to process',
4700
- },
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' },
4701
3824
  },
4702
- required: ['pathId'],
3825
+ required: ['action'],
4703
3826
  },
4704
3827
  },
3828
+ // ---------------------------------------------------------------------------
3829
+ // DOMAIN: FONT TOOLS — single action-dispatched tool replaces 16 wrappers
3830
+ // ---------------------------------------------------------------------------
4705
3831
  {
4706
- name: 'pinepaper_font_cleanup_path',
3832
+ name: 'pinepaper_font',
4707
3833
  annotations: {
4708
- title: 'Font Cleanup Path',
3834
+ title: 'Font Studio',
4709
3835
  readOnlyHint: false,
4710
3836
  destructiveHint: false,
4711
- idempotentHint: true,
3837
+ idempotentHint: false,
4712
3838
  openWorldHint: false,
4713
3839
  },
4714
- 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.
4715
3841
 
4716
- USE WHEN:
4717
- - Preparing a drawn path before creating a glyph
4718
- - 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? }`,
4719
3859
  inputSchema: {
4720
3860
  type: 'object',
4721
3861
  properties: {
4722
- pathId: {
3862
+ action: {
4723
3863
  type: 'string',
4724
- description: 'Registry ID of the Paper.js path to process',
4725
- },
4726
- removeOverlap: {
4727
- type: 'boolean',
4728
- description: 'Merge overlapping strokes (default: true)',
4729
- },
4730
- correctDirection: {
4731
- type: 'boolean',
4732
- description: 'Fix winding direction for fills (default: true)',
4733
- },
4734
- smooth: {
4735
- type: 'boolean',
4736
- description: 'Apply path smoothing (default: true)',
4737
- },
4738
- smoothTolerance: {
4739
- type: 'number',
4740
- 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
+ },
4741
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)' },
4742
3894
  },
4743
- required: ['pathId'],
3895
+ required: ['action'],
4744
3896
  },
4745
3897
  },
4746
3898
  // ---------------------------------------------------------------------------
@@ -4989,7 +4141,19 @@ New — Textures:
4989
4141
  - drawNoiseTexture: Perlin/grain/stipple noise (noiseType: perlin|grain|stipple, colors, scale, density, animated)
4990
4142
 
4991
4143
  New — Tech:
4992
- - drawGlobeWireframe: Vercel-style wireframe globe (bgColor, wireColor, glowColor, highlightColor, meridianCount, latitudeCount, globeRadius, nodeCount, nodeSize, animationEnabled, animationSpeed, strokeWidth, gridOpacity)`,
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)`,
4993
4157
  inputSchema: {
4994
4158
  type: 'object',
4995
4159
  properties: {
@@ -5001,6 +4165,8 @@ New — Tech:
5001
4165
  'drawBokeh', 'drawGradientMesh', 'drawGeometricAbstract', 'drawWindField',
5002
4166
  'drawFluidFlow', 'drawOrganicFlow', 'drawNoiseTexture',
5003
4167
  'drawGlobeWireframe',
4168
+ 'drawFunctionPlot', 'drawParametricCurve', 'drawSimulation',
4169
+ 'drawSpectrumAnalyzer', 'draw3DSurface',
5004
4170
  ],
5005
4171
  description: 'Generator name',
5006
4172
  },
@@ -5054,7 +4220,7 @@ USE WHEN:
5054
4220
  - Celebration effects (confetti)
5055
4221
  - Enhancing visual impact (ripple, glow, electric)
5056
4222
 
5057
- EFFECTS (10 total):
4223
+ EFFECTS (15 total):
5058
4224
  - sparkle: Glitter/sparkle particles (color, speed, size)
5059
4225
  - blast: Explosion burst effect (color, radius, count)
5060
4226
  - smoke: Rising smoke plumes (color, speed, size, drift, height, growthRate)
@@ -5063,15 +4229,23 @@ EFFECTS (10 total):
5063
4229
  - snow: Falling snowflakes (color, count, speed, spread, particleLife)
5064
4230
  - confetti: Celebration confetti (colors, count, radius, gravity, size, spread, interval, repeat)
5065
4231
  - ripple: Expanding ring ripples (color, speed, maxRadius, ringCount, strokeWidth)
5066
- - glow: Pulsing glow aura (color, speed, intensity, size)
5067
- - electric: Lightning bolts (color, speed, boltCount, length, flickerRate)`,
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 } }`,
5068
4242
  inputSchema: {
5069
4243
  type: 'object',
5070
4244
  properties: {
5071
4245
  itemId: { type: 'string', description: 'Registry ID of the item' },
5072
4246
  effectType: {
5073
4247
  type: 'string',
5074
- enum: ['sparkle', 'blast', 'smoke', 'fire', 'rain', 'snow', 'confetti', 'ripple', 'glow', 'electric'],
4248
+ enum: ['sparkle', 'blast', 'smoke', 'fire', 'rain', 'snow', 'confetti', 'ripple', 'glow', 'electric', 'bubbles', 'dust', 'fireflies', 'shockwave', 'trail'],
5075
4249
  description: 'Type of effect',
5076
4250
  },
5077
4251
  params: {
@@ -5723,6 +4897,10 @@ RETURNS:
5723
4897
  type: 'boolean',
5724
4898
  description: 'Run in headless mode (default: false when explicitly called)',
5725
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.',
4903
+ },
5726
4904
  },
5727
4905
  },
5728
4906
  },
@@ -5957,7 +5135,7 @@ PRIVACY: No screenshots, no tool call arguments, no user content — only struct
5957
5135
 
5958
5136
  WORKFLOW: start_job → batch_execute (everything in ONE call) → end_job (screenshot) → show user → iterate if needed.
5959
5137
 
5960
- 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.
5961
5139
 
5962
5140
  CANVAS PRESETS: instagram (1080x1080), instagram-story (1080x1920), tiktok (1080x1920), youtube (1920x1080), youtube-thumbnail (1280x720), twitter (1200x675), linkedin (1200x627), web, print-a4, print-letter`,
5963
5141
  inputSchema: {
@@ -5985,6 +5163,10 @@ CANVAS PRESETS: instagram (1080x1080), instagram-story (1080x1920), tiktok (1080
5985
5163
  type: 'boolean',
5986
5164
  description: 'Clear canvas when starting job (default: true)',
5987
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
+ },
5988
5170
  },
5989
5171
  },
5990
5172
  },
@@ -6112,6 +5294,8 @@ NOTE: For diagrams (flowcharts, UML), use pinepaper_create_diagram_shape + pinep
6112
5294
 
6113
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.
6114
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
+
6115
5299
  WORKFLOW:
6116
5300
  1. pinepaper_agent_start_job → 2. pinepaper_agent_batch_execute (everything) → 3. pinepaper_agent_end_job (screenshot for validation)
6117
5301
  After validation: user reviews screenshot → feedback → modify/recreate as needed.
@@ -6122,7 +5306,8 @@ CANVAS SETUP:
6122
5306
  set_canvas_size — {width, height} or {preset: "instagram"|"youtube"|"tiktok"|...}
6123
5307
  set_background — {backgroundColor: "#hex"}
6124
5308
  execute_generator — {generatorName, generatorParams} → fills canvas with procedural art
6125
- 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)
6126
5311
 
6127
5312
  ITEMS:
6128
5313
  create — {itemType, position: {x,y}, properties}
@@ -6140,18 +5325,18 @@ ITEMS:
6140
5325
 
6141
5326
  ANIMATION:
6142
5327
  animate — Loop animation: {itemId, animationType, animationOptions}
6143
- animationType: pulse, rotate, bounce, fade, wobble, slide, typewriter
5328
+ animationType: ${SIMPLE_ANIMATION_TYPES_LIST}
6144
5329
  keyframe_animate — Timed animation: {itemId, keyframes: [{time, properties, easing}], duration, loop}
6145
5330
  Animatable properties: opacity, scale, scaleX, scaleY, x, y, rotation, fillColor, strokeColor, fontSize
6146
5331
  Easing: easeInOut, easeIn, easeOut, easeInCubic, easeOutCubic, easeOutBounce, linear
6147
5332
  relation — Behavioral link: {sourceId, targetId, relationType, relationOptions}
6148
- 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)
6149
5334
 
6150
5335
  EFFECTS:
6151
5336
  apply_mask — Reveal effect: {itemId, maskPreset, maskOptions}
6152
5337
  maskPreset: wipeLeft, wipeRight, wipeUp, wipeDown, iris, irisOut, star, heart, curtainHorizontal, curtainVertical, cinematic, diagonalWipe, revealUp, revealDown
6153
5338
  apply_effect — Visual effect: {itemId, effectType, effectParams}
6154
- effectType: sparkle, blast
5339
+ effectType: ${EFFECT_TYPES_LIST}
6155
5340
 
6156
5341
  PLAYBACK:
6157
5342
  play_timeline — {action: "play"|"stop"|"seek", duration, loop}
@@ -6237,7 +5422,7 @@ EXAMPLE — Animated sky scene with timed reveals:
6237
5422
  targetId: { type: 'string', description: 'For relation: target item ID or $N' },
6238
5423
  relationType: {
6239
5424
  type: 'string',
6240
- 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'],
6241
5426
  description: 'For relation: type',
6242
5427
  },
6243
5428
  relationOptions: { type: 'object', description: 'For relation: options' },
@@ -6252,7 +5437,7 @@ EXAMPLE — Animated sky scene with timed reveals:
6252
5437
  // Effects
6253
5438
  effectType: {
6254
5439
  type: 'string',
6255
- enum: ['sparkle', 'blast', 'smoke', 'fire', 'rain', 'snow', 'confetti', 'ripple', 'glow', 'electric'],
5440
+ enum: ['sparkle', 'blast', 'smoke', 'fire', 'rain', 'snow', 'confetti', 'ripple', 'glow', 'electric', 'bubbles', 'dust', 'fireflies', 'shockwave', 'trail'],
6256
5441
  description: 'For apply_effect: effect type',
6257
5442
  },
6258
5443
  effectParams: { type: 'object', description: 'For apply_effect: parameters' },
@@ -6272,6 +5457,10 @@ EXAMPLE — Animated sky scene with timed reveals:
6272
5457
  type: 'boolean',
6273
5458
  description: 'If true, all operations succeed or all fail (default: true)',
6274
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
+ },
6275
5464
  },
6276
5465
  required: ['operations'],
6277
5466
  },
@@ -6299,6 +5488,7 @@ PLATFORMS & OPTIMAL FORMATS:
6299
5488
 
6300
5489
  FORMATS: svg, png, gif, mp4, webm, pdf.
6301
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).
6302
5492
 
6303
5493
  ⚠️ If export fails, do NOT retry with different formats — report the error to the user.
6304
5494
  ⚠️ When user asks for "video", always use format: "mp4".
@@ -6306,7 +5496,8 @@ QUALITY: draft, standard, high.
6306
5496
  EXAMPLES:
6307
5497
  - {platform: "instagram"} — auto-selects best format
6308
5498
  - {platform: "instagram", format: "mp4"} — force MP4
6309
- - {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`,
6310
5501
  inputSchema: {
6311
5502
  type: 'object',
6312
5503
  properties: {
@@ -6325,6 +5516,11 @@ EXAMPLES:
6325
5516
  enum: ['draft', 'standard', 'high'],
6326
5517
  description: 'Export quality level (default: standard)',
6327
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
+ },
6328
5524
  },
6329
5525
  required: ['platform'],
6330
5526
  },
@@ -6584,6 +5780,41 @@ EXAMPLES:
6584
5780
  // ---------------------------------------------------------------------------
6585
5781
  // ONTOLOGY TOOLS (Design Knowledge Graph)
6586
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
+ },
6587
5818
  {
6588
5819
  name: 'pinepaper_analyze_design',
6589
5820
  annotations: {
@@ -6727,8 +5958,10 @@ Lookup:
6727
5958
 
6728
5959
  USE WHEN: You need full parameter docs, examples, or workflow guidance — especially in minimal verbosity mode where tool descriptions are short summaries.
6729
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
+
6730
5963
  MODES:
6731
- - 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)
6732
5965
  - tool: "pinepaper_agent_batch_execute" → returns that tool's full verbose description
6733
5966
  - category: "animation" → returns all tools in that category with full descriptions
6734
5967
 
@@ -6794,6 +6027,224 @@ VERBOSITY:
6794
6027
  },
6795
6028
  },
6796
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
+ },
6797
6248
  ];
6798
6249
  /**
6799
6250
  * Get a tool definition by name