PinePaper MCP Tools Specification

This document defines the MCP tools for PinePaper integration. These tools enable AI agents to create animated graphics and generate training data.

Tool Categories

  1. Canvas Tools - Set and get canvas dimensions (REQUIRED before creating items)
  2. Item Tools - Create, modify, delete canvas items
  3. Diagram Tools - Create flowcharts, UML diagrams, and network diagrams
  4. Relation Tools - Define behavior relationships (key for animation)
  5. Animation Tools - Apply and control animations
  6. Mask Tools - Apply clipping masks and animated reveal effects
  7. Generator Tools - Create procedural backgrounds
  8. Map Tools - Geographic visualizations (world maps, US states, choropleth)
  9. Font Tools - Create custom hand-drawn fonts with glyph management
  10. Text Design Tools - Create stylized text (Letter Collage with tile, magazine, gradient styles)
  11. Effect Tools - Apply visual effects (sparkle, blast)
  12. Query Tools - Find and inspect items
  13. Export Tools - Export graphics and training data
  14. Rigging Tools - Skeletal animation with bones, FK/IK solvers, and poses (v0.4)
  15. Blending Tools - Per-item and per-group compositing presets and transitions (v0.4)
  16. Image Filter Tools - GPU-accelerated image filters (grayscale, HSL, posterize, etc.)
  17. Lasso Tools - Freehand lasso selection for image region extraction
  18. Cutout Style Tools - Apply visual style presets to image cutouts
  19. View Tools - Zoom, pan, and fit canvas view
  20. Selection Tools - Select, deselect, and manage item selection
  21. Transform Tools - Nudge, flip, and reorder items in stacking order
  22. Background Tools - Set background color, pattern, or procedural generator
  23. History Tools - Undo, redo, and manage edit history
  24. Advanced Query Tools - Query items by name, type, or custom matcher
  25. Precomp Tools - Create and manage nested compositions
  26. Playback Tools - Control keyframe timeline playback
  27. 3D Projection Tools - Create and configure 3D objects with projection, camera, and lighting

Canvas Tools

IMPORTANT: AI agents MUST set the canvas size before creating items. The canvas defines the output dimensions and items should be positioned within these bounds.

pinepaper_get_canvas_size

Get the current canvas dimensions.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "width": 800,
  "height": 600,
  "preset": "default"
}

pinepaper_set_canvas_size

Set the canvas output dimensions. Agents SHOULD call this before creating items to ensure proper positioning.

Input Schema:

{
  "type": "object",
  "properties": {
    "preset": {
      "type": "string",
      "enum": [
        "youtube-thumbnail", "youtube-short", "tiktok",
        "instagram-story", "instagram-post", "instagram-landscape", "instagram-portrait",
        "facebook-post", "facebook-cover", "facebook-story",
        "twitter-post", "twitter-header",
        "linkedin-post", "linkedin-banner",
        "pinterest-pin",
        "presentation-16x9", "presentation-4x3",
        "hd-720p", "full-hd-1080p",
        "default"
      ],
      "description": "Predefined canvas size preset"
    },
    "width": {
      "type": "number",
      "description": "Custom canvas width in pixels (use with height for custom size)",
      "minimum": 100,
      "maximum": 7680
    },
    "height": {
      "type": "number",
      "description": "Custom canvas height in pixels (use with width for custom size)",
      "minimum": 100,
      "maximum": 4320
    }
  },
  "oneOf": [
    {"required": ["preset"]},
    {"required": ["width", "height"]}
  ]
}

Preset Dimensions:

Preset Dimensions Use Case
youtube-thumbnail 1280×720 YouTube video thumbnails
youtube-short 1080×1920 YouTube Shorts
tiktok 1080×1920 TikTok videos
instagram-story 1080×1920 Instagram Stories & Reels
instagram-post 1080×1080 Square Instagram posts
instagram-landscape 1080×566 Landscape Instagram posts
instagram-portrait 1080×1350 Portrait Instagram posts
facebook-post 1200×630 Facebook feed posts
facebook-cover 820×312 Facebook cover photos
facebook-story 1080×1920 Facebook Stories
twitter-post 1200×675 Twitter/X images
twitter-header 1500×500 Twitter/X profile headers
linkedin-post 1200×627 LinkedIn posts
linkedin-banner 1584×396 LinkedIn banners
pinterest-pin 1000×1500 Pinterest pins
presentation-16x9 1920×1080 16:9 presentations
presentation-4x3 1024×768 4:3 presentations
hd-720p 1280×720 HD video
full-hd-1080p 1920×1080 Full HD video
default 800×600 Default canvas

Output:

{
  "success": true,
  "width": 1080,
  "height": 1080,
  "preset": "instagram-post"
}

pinepaper_get_canvas_presets

List all available canvas presets with their dimensions.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "presets": [
    {
      "key": "instagram-post",
      "name": "Instagram Post (Square)",
      "width": 1080,
      "height": 1080,
      "aspectRatio": "1:1",
      "category": "social"
    }
  ]
}

Item Tools

pinepaper_create_item

Create an item on the canvas.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemType": {
      "type": "string",
      "enum": ["text", "circle", "star", "rectangle", "triangle", "polygon", "ellipse", "path", "line", "arc"],
      "description": "Type of item to create"
    },
    "position": {
      "type": "object",
      "properties": {
        "x": { "type": "number" },
        "y": { "type": "number" }
      },
      "description": "Position on canvas"
    },
    "properties": {
      "type": "object",
      "description": "Type-specific properties"
    },
    "data": {
      "type": "object",
      "description": "Item data flags for selection and behavior control",
      "properties": {
        "selectable": { "type": "boolean", "description": "Whether item can be selected (default: true for text layer items)" },
        "isDraggable": { "type": "boolean", "description": "Whether item can be dragged (default: true for text layer items)" },
        "isDecorative": { "type": "boolean", "description": "Mark as decorative/non-interactive (skipped by selection)" }
      }
    },
    "animationType": {
      "type": "string",
      "description": "Animation type to apply on creation (e.g., 'pulse', 'bounce', 'keyframe')"
    },
    "animationSpeed": {
      "type": "number",
      "description": "Animation speed multiplier (for simple animations)"
    },
    "keyframes": {
      "type": "array",
      "description": "Keyframe array for inline keyframe animation (requires animationType: 'keyframe')",
      "items": {
        "type": "object",
        "properties": {
          "time": { "type": "number", "description": "Time in seconds" },
          "properties": { "type": "object", "description": "Animatable properties (x, y, scale, opacity, rotation, fillColor, etc.)" },
          "easing": { "type": "string", "description": "Easing function: linear, easeIn, easeOut, easeInOut, bounce, elastic" }
        }
      }
    }
  },
  "required": ["itemType"]
}

Type-Specific Properties:

Type Properties
text content, fontSize, fontFamily, color
circle radius, color, strokeColor, strokeWidth
star radius1, radius2, color
rectangle width, height, color
polygon sides, radius, color
path segments or pathData, strokeColor, strokeWidth, closed, smooth
line from, to, strokeColor, strokeWidth
arc from, through, to, strokeColor

Data Flags for Selection Control:

Flag Type Description
selectable boolean Allow item to be selected (even in background layer). Default: true for text layer items
isDraggable boolean Allow item to be dragged when selected. Default: true for text layer items
isDecorative boolean Mark as non-interactive decoration (never selectable). Useful for orbit paths, guidelines, etc.

Layer and Selection Priority:

  1. Items in textItemGroup (text layer) are always selectable by default
  2. Items in patternGroup (background) are NOT selectable unless marked with selectable: true
  3. Items with isDecorative: true are never selectable (overrides all)
  4. Items with selectable: true can be selected even if in background layer

Output:

{
  "success": true,
  "itemId": "item_1",
  "type": "circle",
  "position": { "x": 400, "y": 300 }
}

pinepaper_modify_item

Modify an existing item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Registry ID of the item"
    },
    "properties": {
      "type": "object",
      "description": "Properties to update",
      "properties": {
        "x": { "type": "number", "description": "X position in pixels" },
        "y": { "type": "number", "description": "Y position in pixels" },
        "width": { "type": "number", "description": "Width in pixels (absolute sizing)" },
        "height": { "type": "number", "description": "Height in pixels (absolute sizing)" },
        "scale": { "type": "number", "description": "Uniform scale (1.0 = 100%)" },
        "scaleX": { "type": "number", "description": "Horizontal scale" },
        "scaleY": { "type": "number", "description": "Vertical scale" },
        "rotation": { "type": "number", "description": "Rotation in degrees" },
        "opacity": { "type": "number", "description": "Opacity (0-1)" },
        "color": { "type": "string", "description": "Fill color" },
        "strokeColor": { "type": "string", "description": "Stroke color" },
        "strokeWidth": { "type": "number", "description": "Stroke width in pixels" },
        "fontSize": { "type": "number", "description": "Font size (text items only)" },
        "content": { "type": "string", "description": "Text content (text items only)" },
        "animationType": { "type": "string", "description": "Animation type" },
        "animationSpeed": { "type": "number", "description": "Animation speed multiplier" }
      }
    },
    "data": {
      "type": "object",
      "description": "Update item data flags",
      "properties": {
        "selectable": { "type": "boolean" },
        "isDraggable": { "type": "boolean" },
        "isDecorative": { "type": "boolean" }
      }
    }
  },
  "required": ["itemId", "properties"]
}

Sizing: width/height vs scale:

Property Type Description
width pixels Set exact width in pixels (absolute, predictable)
height pixels Set exact height in pixels (absolute, predictable)
scale ratio Multiply current size (relative, compounds on repeated use)

Recommendation: Use width/height for precise sizing. Use scale only for proportional adjustments.

pinepaper_delete_item

Delete an item from the canvas.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Registry ID of the item to delete"
    }
  },
  "required": ["itemId"]
}

Diagram Tools

Tools for creating flowcharts, UML diagrams, network diagrams, and connecting any visual elements with smart arrows.

Key Capabilities:

  • Flowcharts & UML - Standard diagram shapes (process, decision, terminal, etc.)
  • Network Diagrams - Server, cloud, and infrastructure symbols
  • Visual Sequences - Connect any items (images, SVGs, shapes) with stylish arrows
  • Smart Connectors - Auto-routing with orthogonal, curved, or direct paths
  • Arrow Styles - Multiple head styles (classic, stealth, sharp, open, diamond, circle)
  • Animated Flow - Bolt effect shows connection direction

Works With Any Item: Diagram connectors aren’t limited to diagram shapes. Connect any canvas items:

  • Images and imported SVGs
  • Text elements
  • Custom paths and shapes
  • Generator-created elements

This enables creative visual storytelling, infographics, and animated sequences.

pinepaper_create_diagram_shape

Create a diagram shape (flowchart, UML, network, or basic shape).

Input Schema:

{
  "type": "object",
  "properties": {
    "shapeType": {
      "type": "string",
      "enum": [
        "process", "decision", "terminal", "data", "document", "database", "preparation",
        "uml-class", "uml-usecase", "uml-actor",
        "cloud", "server",
        "rectangle", "circle", "triangle", "star"
      ],
      "description": "Type of diagram shape to create"
    },
    "position": {
      "type": "object",
      "properties": {
        "x": { "type": "number" },
        "y": { "type": "number" }
      },
      "description": "Position on canvas"
    },
    "width": {
      "type": "number",
      "description": "Shape width in pixels (optional, uses default for shape type)"
    },
    "height": {
      "type": "number",
      "description": "Shape height in pixels (optional, uses default for shape type)"
    },
    "label": {
      "type": "string",
      "description": "Text label to display inside the shape"
    },
    "style": {
      "type": "object",
      "properties": {
        "fillColor": { "type": "string", "description": "Fill color (hex, rgb, or named)" },
        "strokeColor": { "type": "string", "description": "Border/stroke color" },
        "strokeWidth": { "type": "number", "description": "Border width in pixels" }
      }
    }
  },
  "required": ["shapeType"]
}

Shape Types by Category:

Category Shapes Description
Flowchart process, decision, terminal, data, document, database, preparation Standard flowchart symbols
UML uml-class, uml-usecase, uml-actor UML diagram elements
Network cloud, server Network architecture symbols
Basic rectangle, circle, triangle, star Basic geometric shapes

Default Sizes:

Shape Default Size
process 120 x 60
decision 100 x 100
terminal 120 x 50
data 120 x 60
document 120 x 70
database 80 x 100
uml-class 150 x 120
cloud 140 x 90
server 60 x 80

Output:

{
  "success": true,
  "itemId": "item_1",
  "shapeType": "process",
  "position": { "x": 400, "y": 300 }
}

pinepaper_connect

Connect two items with a smart connector.

Input Schema:

{
  "type": "object",
  "properties": {
    "sourceItemId": {
      "type": "string",
      "description": "Registry ID of the source item"
    },
    "targetItemId": {
      "type": "string",
      "description": "Registry ID of the target item"
    },
    "routing": {
      "type": "string",
      "enum": ["direct", "orthogonal", "curved"],
      "default": "orthogonal",
      "description": "Path routing style"
    },
    "lineColor": {
      "type": "string",
      "description": "Connector line color"
    },
    "lineWidth": {
      "type": "number",
      "description": "Line width in pixels"
    },
    "lineStyle": {
      "type": "string",
      "enum": ["solid", "dashed", "dotted"],
      "default": "solid"
    },
    "headStyle": {
      "type": "string",
      "enum": ["classic", "stealth", "sharp", "open", "diamond", "circle", "none"],
      "default": "classic",
      "description": "Arrowhead style at target"
    },
    "tailStyle": {
      "type": "string",
      "enum": ["classic", "stealth", "sharp", "open", "diamond", "circle", "none"],
      "default": "none",
      "description": "Arrowhead style at source"
    },
    "label": {
      "type": "string",
      "description": "Label text to display on the connector"
    },
    "curvature": {
      "type": "number",
      "minimum": 0.1,
      "maximum": 1.0,
      "default": 0.5,
      "description": "Curve intensity for curved routing"
    },
    "boltEnabled": {
      "type": "boolean",
      "default": true,
      "description": "Enable animated bolt effect along connector"
    },
    "boltColor": {
      "type": "string",
      "default": "#fbbf24",
      "description": "Bolt animation color"
    }
  },
  "required": ["sourceItemId", "targetItemId"]
}

Output:

{
  "success": true,
  "connectorId": "connector_1",
  "sourceItemId": "item_1",
  "targetItemId": "item_2",
  "routing": "orthogonal"
}

pinepaper_connect_ports

Connect specific ports on items for precise connector placement.

Input Schema:

{
  "type": "object",
  "properties": {
    "sourceItemId": {
      "type": "string"
    },
    "sourcePort": {
      "type": "string",
      "enum": ["top", "bottom", "left", "right", "top-left", "top-right", "bottom-left", "bottom-right", "center", "start", "end"],
      "description": "Port position on source item"
    },
    "targetItemId": {
      "type": "string"
    },
    "targetPort": {
      "type": "string",
      "enum": ["top", "bottom", "left", "right", "top-left", "top-right", "bottom-left", "bottom-right", "center", "start", "end"],
      "description": "Port position on target item"
    },
    "config": {
      "type": "object",
      "description": "Connector configuration (same as pinepaper_connect)"
    }
  },
  "required": ["sourceItemId", "sourcePort", "targetItemId", "targetPort"]
}

pinepaper_add_ports

Add connection ports to an item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Registry ID of the item"
    },
    "portType": {
      "type": "string",
      "enum": ["standard", "line", "path", "custom"],
      "default": "standard",
      "description": "Port configuration type"
    },
    "ports": {
      "type": "array",
      "description": "Custom port definitions (for portType='custom')",
      "items": {
        "type": "object",
        "properties": {
          "position": {
            "type": "string",
            "enum": ["top", "bottom", "left", "right", "top-left", "top-right", "bottom-left", "bottom-right", "center"]
          },
          "type": {
            "type": "string",
            "enum": ["input", "output", "both"],
            "default": "both",
            "description": "Port connection direction"
          }
        }
      }
    },
    "count": {
      "type": "number",
      "description": "Number of ports (for portType='path')"
    }
  },
  "required": ["itemId"]
}

Port Types:

Type Description Ports Created
standard 4-way configuration (default) top, bottom, left, right
line For paths/lines start, end
path Distributed along closed path Evenly spaced points
custom User-defined ports As specified in ports array

pinepaper_auto_layout

Apply automatic layout algorithm to arrange diagram items.

Input Schema:

{
  "type": "object",
  "properties": {
    "layoutType": {
      "type": "string",
      "enum": ["hierarchical", "force-directed", "tree", "radial", "grid"],
      "description": "Layout algorithm to apply"
    },
    "itemIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Items to include (default: all items with ports)"
    },
    "options": {
      "type": "object",
      "properties": {
        "direction": {
          "type": "string",
          "enum": ["TB", "BT", "LR", "RL"],
          "default": "TB",
          "description": "Flow direction (hierarchical/tree)"
        },
        "levelSpacing": {
          "type": "number",
          "default": 100,
          "description": "Vertical spacing between levels"
        },
        "nodeSpacing": {
          "type": "number",
          "default": 80,
          "description": "Horizontal spacing between nodes"
        },
        "iterations": {
          "type": "number",
          "default": 100,
          "description": "Iterations for force-directed layout"
        },
        "attraction": {
          "type": "number",
          "default": 0.01,
          "description": "Attraction force (force-directed)"
        },
        "repulsion": {
          "type": "number",
          "default": 1000,
          "description": "Repulsion force (force-directed)"
        },
        "columns": {
          "type": "number",
          "description": "Number of columns (grid layout)"
        },
        "cellWidth": {
          "type": "number",
          "default": 150,
          "description": "Cell width (grid layout)"
        },
        "cellHeight": {
          "type": "number",
          "default": 100,
          "description": "Cell height (grid layout)"
        },
        "centerX": {
          "type": "number",
          "description": "Center X position (radial layout)"
        },
        "centerY": {
          "type": "number",
          "description": "Center Y position (radial layout)"
        },
        "startRadius": {
          "type": "number",
          "default": 100,
          "description": "Starting radius (radial layout)"
        },
        "radiusStep": {
          "type": "number",
          "default": 80,
          "description": "Radius increment per level (radial layout)"
        }
      }
    }
  },
  "required": ["layoutType"]
}

Layout Types:

Layout Description Best For
hierarchical Layered top-to-bottom or left-to-right Flowcharts, org charts
force-directed Physics-based node positioning Network diagrams
tree Parent-child hierarchical layout Family trees, file structures
radial Concentric circles from center Mind maps, radial hierarchies
grid Regular grid arrangement Inventory, galleries

Output:

{
  "success": true,
  "layoutType": "hierarchical",
  "itemsLayouted": 5,
  "bounds": {
    "x": 100,
    "y": 50,
    "width": 400,
    "height": 500
  }
}

pinepaper_get_diagram_shapes

Get available diagram shapes.

Input Schema:

{
  "type": "object",
  "properties": {
    "category": {
      "type": "string",
      "enum": ["flowchart", "uml", "network", "basic"],
      "description": "Filter by category (optional)"
    }
  }
}

Output:

{
  "shapes": [
    {
      "id": "process",
      "name": "Process",
      "category": "flowchart",
      "description": "Rectangle with rounded corners",
      "defaultSize": { "width": 120, "height": 60 }
    },
    {
      "id": "decision",
      "name": "Decision",
      "category": "flowchart",
      "description": "Diamond shape for conditions",
      "defaultSize": { "width": 100, "height": 100 }
    }
  ]
}

pinepaper_update_connector

Update an existing connector’s style or configuration.

Input Schema:

{
  "type": "object",
  "properties": {
    "connectorId": {
      "type": "string",
      "description": "Connector ID to update"
    },
    "style": {
      "type": "object",
      "properties": {
        "lineColor": { "type": "string" },
        "lineWidth": { "type": "number" },
        "headStyle": { "type": "string" },
        "routing": { "type": "string" }
      }
    },
    "label": {
      "type": "string",
      "description": "Update connector label"
    },
    "labelPosition": {
      "type": "number",
      "minimum": 0,
      "maximum": 1,
      "description": "Label position along path (0-1)"
    }
  },
  "required": ["connectorId"]
}

pinepaper_remove_connector

Remove a connector between items.

Input Schema:

{
  "type": "object",
  "properties": {
    "connectorId": {
      "type": "string",
      "description": "Connector ID to remove"
    }
  },
  "required": ["connectorId"]
}

pinepaper_diagram_mode

Control diagram mode activation and tool selection.

Input Schema:

{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": ["activate", "deactivate", "toggle", "setMode"],
      "description": "Diagram mode action"
    },
    "mode": {
      "type": "string",
      "enum": ["select", "connect", "shape", "pan"],
      "description": "Tool mode (for setMode action)"
    },
    "shapeType": {
      "type": "string",
      "description": "Shape to place (for mode='shape')"
    }
  },
  "required": ["action"]
}

Output:

{
  "success": true,
  "isActive": true,
  "currentMode": "connect"
}

Relation Tools

Relations are the primary mechanism for creating declarative animations.

pinepaper_add_relation

Create a behavior relationship between two items.

Input Schema:

{
  "type": "object",
  "properties": {
    "sourceId": {
      "type": "string",
      "description": "Registry ID of the source item (the item that will be affected)"
    },
    "targetId": {
      "type": "string",
      "description": "Registry ID of the target item (the item being related to, can be null for self-animations)"
    },
    "relationType": {
      "type": "string",
      "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",
        "bone_attached", "ik_target", "blend_reacts_to", "blend_transition"
      ],
      "description": "Type of relationship"
    },
    "params": {
      "type": "object",
      "description": "Relation-specific parameters"
    }
  },
  "required": ["sourceId", "relationType"]
}

Core Relation Parameters:

Relation Parameters
orbits radius (number), speed (number), direction (‘clockwise’/‘counterclockwise’), phase (number)
follows offset ([x, y]), smoothing (0-1), delay (seconds)
attached_to offset ([x, y]), inherit_rotation (boolean)
maintains_distance distance (pixels), strength (0-1)
points_at offset_angle (degrees), smoothing (0-1)
mirrors axis (‘vertical’/‘horizontal’/‘both’), center ([x, y])
parallax depth (0-1), origin ([x, y])
bounds_to padding (pixels), bounce (boolean)
animates keyframes (array), duration (seconds), loop (boolean)
All relations startTime (seconds), endTime (seconds), autoRemove (boolean) — time-scoping parameters

Manim-Inspired Animation Relations:

Relation Description Parameters
grows_from Item scales from zero to full size (like Manim GrowFromPoint) origin (‘center’/‘top’/‘bottom’/‘left’/‘right’/‘topLeft’/‘topRight’/‘bottomLeft’/‘bottomRight’), duration (seconds), delay (seconds), easing
staggered_with Staggered animation timing for groups (like Manim LaggedStart) index (0-based position), stagger (delay between items in seconds), effect (‘fadeIn’/‘fadeOut’/‘growIn’/‘slideIn’/‘popIn’)
indicates Temporary highlight effect (like Manim Indicate) scale (max scale during indication), color (highlight color), duration (seconds), delay (seconds), repeat (number of times)
circumscribes Draw temporary shape around target (like Manim Circumscribe) shape (‘rectangle’/‘circle’/‘ellipse’), color (stroke color), strokeWidth, padding, duration (seconds), fadeOut (boolean)
wave_through Send wave distortion through item (like Manim ApplyWave) amplitude (pixels), frequency (cycles), direction (‘horizontal’/‘vertical’), duration (seconds), delay (seconds)
camera_follows View pans to follow target (like Manim MovingCameraScene) smoothing (0-1), offset ([x, y]), zoom (level), deadzone (pixels), bounds ({minX, maxX, minY, maxY})
camera_animates Keyframe-based camera zoom and pan animation keyframes (array of {time, zoom, center, easing}), duration (seconds), loop (boolean), delay (seconds)
morphs_to Shape morphing animation (like Manim Transform) duration (seconds), delay (seconds), easing, morphColor (boolean), morphSize (boolean), hideTarget (boolean), removeTargetOnComplete (boolean)

Rigging Relations (v0.4):

Relation Description Parameters
bone_attached Item follows a bone’s world transform (priority -10, runs before standard relations) skeletonId (string), boneId (string), offset ([x, y]), inheritRotation (boolean), attachPoint (0=joint, 1=tip)
ik_target Item acts as IK solver target pulling a bone chain (priority -20) skeletonId (string), chainId (string), strength (0-1, FK/IK blend)

Blending Relations (v0.4):

Relation Description Parameters
blend_reacts_to Proximity-based blend mode/opacity changes proximityRadius (pixels), activeMode (blend mode), inactiveMode (blend mode), activeOpacity (0-1), inactiveOpacity (0-1), smoothing (0-1)
blend_transition Automatic time-based blend mode cycling modes (string[]), opacities (number[]), cycleDuration (seconds), easing

Output:

{
  "success": true,
  "sourceId": "item_1",
  "targetId": "item_2",
  "relationType": "orbits"
}

pinepaper_replace_relation

Atomically replace a relation (remove + add with fresh params). Unlike pinepaper_add_relation which merges params, this fully replaces them.

Input Schema: Same as pinepaper_add_relation.

Output:

{
  "success": true,
  "sourceId": "item_1",
  "targetId": "item_2",
  "relationType": "orbits"
}

pinepaper_remove_relation

Remove a relationship between items.

Input Schema:

{
  "type": "object",
  "properties": {
    "sourceId": {
      "type": "string"
    },
    "targetId": {
      "type": "string"
    },
    "relationType": {
      "type": "string",
      "description": "Optional: specific relation type to remove"
    }
  },
  "required": ["sourceId", "targetId"]
}

pinepaper_query_relations

Query relationships for an item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Item to query relations for"
    },
    "relationType": {
      "type": "string",
      "description": "Optional: filter by relation type"
    },
    "direction": {
      "type": "string",
      "enum": ["outgoing", "incoming"],
      "description": "outgoing = from item, incoming = to item"
    }
  },
  "required": ["itemId"]
}

Output:

{
  "relations": [
    {
      "sourceId": "item_1",
      "targetId": "item_2",
      "relationType": "orbits",
      "params": { "radius": 100, "speed": 0.5 }
    }
  ]
}

Animation Tools

pinepaper_animate

Apply a simple animation to an item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string"
    },
    "animationType": {
      "type": "string",
      "enum": ["pulse", "rotate", "bounce", "fade", "wobble", "slide", "typewriter", "shake", "swing", "jelly", "glow"]
    },
    "speed": {
      "type": "number",
      "description": "Animation speed multiplier (default: 1.0)"
    }
  },
  "required": ["itemId", "animationType"]
}

pinepaper_keyframe_animate

Apply keyframe-based animation.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string"
    },
    "keyframes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "time": { "type": "number", "description": "Time in seconds" },
          "properties": { "type": "object", "description": "Property values at this keyframe" },
          "easing": { "type": "string", "enum": ["linear", "easeIn", "easeOut", "easeInOut", "bounce", "elastic"] }
        }
      }
    },
    "duration": {
      "type": "number",
      "description": "Total animation duration in seconds"
    },
    "loop": {
      "type": "boolean"
    },
    "timeOffset": {
      "type": "number",
      "description": "Offset in seconds — delays this item's keyframe start relative to global timeline"
    },
    "relationBehavior": {
      "type": "string",
      "enum": ["override", "keyframeFirst"],
      "description": "How relations interact with keyframes. 'keyframeFirst' pauses relations during playback."
    }
  },
  "required": ["itemId", "keyframes"]
}

Keyframe Properties:

Property Type Description
position [x, y] Item position
x, y number Individual coordinates
width number Width in pixels (absolute sizing)
height number Height in pixels (absolute sizing)
scale number Uniform scale
scaleX, scaleY number Separate axis scaling
rotation number Rotation in degrees
opacity number Transparency (0-1)
fillColor string Fill color
strokeColor string Stroke color
fontSize number Text size

pinepaper_play_timeline

Control keyframe playback.

Input Schema:

{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": ["play", "stop", "seek"]
    },
    "duration": {
      "type": "number",
      "description": "Duration for play action"
    },
    "loop": {
      "type": "boolean"
    },
    "time": {
      "type": "number",
      "description": "Time to seek to"
    }
  },
  "required": ["action"]
}

Camera Tools

Animate camera zoom and pan for cinematic effects.

pinepaper_camera_animate

Animate camera with keyframe-based zoom and pan sequence.

Input Schema:

{
  "type": "object",
  "properties": {
    "keyframes": {
      "type": "array",
      "description": "Array of camera keyframes",
      "items": {
        "type": "object",
        "properties": {
          "time": { "type": "number", "description": "Time in seconds" },
          "zoom": { "type": "number", "description": "Zoom level (1=normal, 2=2x zoom in, 0.5=zoom out)" },
          "center": { "type": "array", "items": { "type": "number" }, "description": "View center [x, y]" },
          "easing": { "type": "string", "enum": ["linear", "easeIn", "easeOut", "easeInOut", "bounce", "elastic"] }
        }
      }
    },
    "duration": {
      "type": "number",
      "description": "Total animation duration in seconds"
    },
    "loop": {
      "type": "boolean",
      "description": "Loop the animation"
    },
    "delay": {
      "type": "number",
      "description": "Delay before animation starts"
    }
  },
  "required": ["keyframes", "duration"]
}

Example - Zoom in, pan right, zoom out:

{
  "duration": 6,
  "loop": true,
  "keyframes": [
    { "time": 0, "zoom": 1, "center": [400, 300] },
    { "time": 2, "zoom": 2, "center": [400, 300], "easing": "easeInOut" },
    { "time": 4, "zoom": 2, "center": [600, 300], "easing": "easeOut" },
    { "time": 6, "zoom": 1, "center": [400, 300], "easing": "easeInOut" }
  ]
}

Output:

{
  "success": true,
  "isAnimating": true
}

pinepaper_camera_zoom

Simple zoom animation.

Input Schema:

{
  "type": "object",
  "properties": {
    "direction": {
      "type": "string",
      "enum": ["in", "out"],
      "description": "Zoom direction"
    },
    "level": {
      "type": "number",
      "description": "Target zoom level (default: 2 for in, 0.5 for out)"
    },
    "duration": {
      "type": "number",
      "description": "Animation duration in seconds (default: 0.5)"
    }
  },
  "required": ["direction"]
}

Output:

{
  "success": true,
  "fromZoom": 1,
  "toZoom": 2
}

pinepaper_camera_pan

Pan camera in a direction or to specific coordinates.

Input Schema:

{
  "type": "object",
  "properties": {
    "direction": {
      "type": "string",
      "enum": ["left", "right", "up", "down"],
      "description": "Pan direction (use with amount)"
    },
    "amount": {
      "type": "number",
      "description": "Pixels to pan (default: 100)"
    },
    "x": {
      "type": "number",
      "description": "Target X coordinate (use with y for panTo)"
    },
    "y": {
      "type": "number",
      "description": "Target Y coordinate (use with x for panTo)"
    },
    "duration": {
      "type": "number",
      "description": "Animation duration in seconds (default: 0.5)"
    }
  }
}

Examples:

// Pan left 200 pixels
{ "direction": "left", "amount": 200 }

// Pan to specific coordinates
{ "x": 200, "y": 200, "duration": 1 }

Output:

{
  "success": true,
  "fromCenter": [400, 300],
  "toCenter": [200, 200]
}

pinepaper_camera_move_to

Combined zoom and pan to a specific location.

Input Schema:

{
  "type": "object",
  "properties": {
    "x": {
      "type": "number",
      "description": "Target X coordinate"
    },
    "y": {
      "type": "number",
      "description": "Target Y coordinate"
    },
    "zoom": {
      "type": "number",
      "description": "Target zoom level"
    },
    "duration": {
      "type": "number",
      "description": "Animation duration in seconds (default: 0.5)"
    }
  },
  "required": ["x", "y", "zoom"]
}

Output:

{
  "success": true,
  "toCenter": [200, 200],
  "toZoom": 2
}

pinepaper_camera_reset

Reset camera to default state (center of canvas, zoom 1).

Input Schema:

{
  "type": "object",
  "properties": {
    "duration": {
      "type": "number",
      "description": "Animation duration in seconds (default: 0.5)"
    }
  }
}

Output:

{
  "success": true,
  "toCenter": [400, 300],
  "toZoom": 1
}

pinepaper_camera_stop

Stop current camera animation.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "wasAnimating": true
}

pinepaper_camera_state

Get current camera state.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "zoom": 1.5,
  "center": [400, 300],
  "isAnimating": false
}

Mask Tools

Apply clipping masks and animated reveal effects to items.

pinepaper_apply_animated_mask

Apply an animated mask reveal to an item. Supports three usage modes for maximum flexibility.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Registry ID of the item to mask"
    },
    "preset": {
      "type": "string",
      "enum": ["wipeLeft", "wipeRight", "wipeUp", "wipeDown", "iris", "irisOut", "star", "heart", "curtainHorizontal", "curtainVertical", "cinematic", "diagonalWipe", "revealUp", "revealDown"],
      "description": "Animation preset name (Mode 1 & 3)"
    },
    "maskType": {
      "type": "string",
      "enum": ["rectangle", "circle", "ellipse", "star", "triangle", "hexagon", "heart", "rounded"],
      "description": "Mask shape type (Mode 2 - full control)"
    },
    "keyframes": {
      "type": "array",
      "description": "Custom keyframes array (Mode 2 & 3)",
      "items": {
        "type": "object",
        "properties": {
          "time": { "type": "number", "description": "Normalized time (0-1)" },
          "properties": {
            "type": "object",
            "description": "Mask properties at this keyframe",
            "properties": {
              "x": { "type": "number" },
              "y": { "type": "number" },
              "width": { "type": "number" },
              "height": { "type": "number" },
              "radius": { "type": "number" },
              "scale": { "type": "number" },
              "rotation": { "type": "number" },
              "opacity": { "type": "number" }
            }
          },
          "easing": {
            "type": "string",
            "enum": ["linear", "easeIn", "easeOut", "easeInOut", "bounce", "elastic"]
          }
        },
        "required": ["time", "properties"]
      }
    },
    "options": {
      "type": "object",
      "description": "Animation options (Mode 1)",
      "properties": {
        "startTime": { "type": "number", "description": "Start time in seconds", "default": 0 },
        "duration": { "type": "number", "description": "Duration in seconds", "default": 0.8 },
        "easing": { "type": "string", "enum": ["linear", "easeIn", "easeOut", "easeInOut", "bounce"], "default": "easeOut" },
        "reversed": { "type": "boolean", "description": "Reverse animation (hide instead of reveal)", "default": false },
        "loop": { "type": "boolean", "description": "Loop the animation", "default": false }
      }
    },
    "maskOptions": {
      "type": "object",
      "description": "Mask shape options (for star, etc.)",
      "properties": {
        "points": { "type": "number", "description": "Number of points (star mask)" },
        "innerRadius": { "type": "number", "description": "Inner radius ratio (star mask)" }
      }
    }
  },
  "required": ["itemId"]
}

Usage Modes:

Mode Description Required Fields
1. Preset Use animation preset with options preset, options
2. Full Control Define exact keyframes maskType, keyframes
3. Hybrid Preset with keyframe override preset, keyframes

Animation Presets:

Preset Effect Mask Type
wipeLeft Reveals from left to right Rectangle
wipeRight Reveals from right to left Rectangle
wipeUp Reveals from bottom to top Rectangle
wipeDown Reveals from top to bottom Rectangle
iris Circle expands from center Circle
irisOut Circle shrinks to center Circle
star Star shape scales up Star
heart Heart shape scales up Heart
curtainHorizontal Opens from center horizontally Rectangle pair
curtainVertical Opens from center vertically Rectangle pair
cinematic Letterbox bars animate Rectangle pair
diagonalWipe Angled reveal from corner Rectangle
revealUp Text slides up within mask Rectangle
revealDown Text slides down within mask Rectangle

Examples:

Mode 1 - Preset with options:

{
  "itemId": "item_1",
  "preset": "wipeLeft",
  "options": {
    "startTime": 0,
    "duration": 0.5,
    "easing": "easeOut"
  }
}

Mode 2 - Full keyframe control:

{
  "itemId": "item_1",
  "maskType": "rectangle",
  "keyframes": [
    { "time": 0, "properties": { "x": 200, "y": 250, "width": 0, "height": 100 }, "easing": "linear" },
    { "time": 0.25, "properties": { "x": 200, "y": 250, "width": 50, "height": 100 }, "easing": "easeIn" },
    { "time": 0.75, "properties": { "x": 200, "y": 250, "width": 150, "height": 100 }, "easing": "easeOut" },
    { "time": 1, "properties": { "x": 200, "y": 250, "width": 200, "height": 100 } }
  ]
}

Mode 3 - Preset with keyframe override:

{
  "itemId": "item_1",
  "preset": "iris",
  "keyframes": [
    { "time": 0, "properties": { "scale": 0.01 }, "easing": "linear" },
    { "time": 0.3, "properties": { "scale": 0.3 }, "easing": "easeIn" },
    { "time": 0.6, "properties": { "scale": 0.7 }, "easing": "easeOut" },
    { "time": 1, "properties": { "scale": 1 }, "easing": "bounce" }
  ]
}

Output:

{
  "success": true,
  "itemId": "item_1",
  "maskType": "rectangle",
  "animated": true,
  "keyframeCount": 4
}

pinepaper_apply_custom_mask

Direct helper for applying custom keyframe-based masks.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Registry ID of the item to mask"
    },
    "maskType": {
      "type": "string",
      "enum": ["rectangle", "circle", "ellipse", "star", "triangle", "hexagon", "heart", "rounded"],
      "description": "Mask shape type"
    },
    "keyframes": {
      "type": "array",
      "description": "Keyframes defining the animation",
      "items": {
        "type": "object",
        "properties": {
          "time": { "type": "number" },
          "properties": { "type": "object" },
          "easing": { "type": "string" }
        }
      }
    },
    "maskOptions": {
      "type": "object",
      "description": "Mask shape options",
      "properties": {
        "points": { "type": "number" },
        "innerRadius": { "type": "number" }
      }
    }
  },
  "required": ["itemId", "maskType", "keyframes"]
}

Example:

{
  "itemId": "item_1",
  "maskType": "star",
  "keyframes": [
    { "time": 0, "properties": { "scale": 0 }, "easing": "linear" },
    { "time": 0.5, "properties": { "scale": 0.5 }, "easing": "easeIn" },
    { "time": 1, "properties": { "scale": 1 }, "easing": "easeOut" }
  ],
  "maskOptions": { "points": 6, "innerRadius": 0.4 }
}

pinepaper_remove_mask

Remove mask from an item, restoring original.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Registry ID of the masked item"
    }
  },
  "required": ["itemId"]
}

pinepaper_get_animatable_properties

Get animatable properties for each mask type. Useful for building custom keyframe animations.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "rectangle": {
    "properties": ["x", "y", "width", "height", "rotation", "opacity"],
    "description": "Rectangular mask with position and size"
  },
  "circle": {
    "properties": ["x", "y", "radius", "scale", "opacity"],
    "description": "Circular mask with center and radius"
  },
  "ellipse": {
    "properties": ["x", "y", "radiusX", "radiusY", "rotation", "scale", "opacity"],
    "description": "Elliptical mask with separate radii"
  },
  "star": {
    "properties": ["x", "y", "radius", "scale", "rotation", "opacity"],
    "description": "Star mask with configurable points"
  },
  "heart": {
    "properties": ["x", "y", "scale", "rotation", "opacity"],
    "description": "Heart-shaped mask"
  }
}

pinepaper_get_available_easings

Get list of available easing functions for mask animations.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "easings": ["linear", "easeIn", "easeOut", "easeInOut", "bounce", "elastic"],
  "descriptions": {
    "linear": "Constant speed",
    "easeIn": "Slow start, fast end",
    "easeOut": "Fast start, slow end",
    "easeInOut": "Slow start and end",
    "bounce": "Bouncing effect at end",
    "elastic": "Spring-like overshoot"
  }
}

pinepaper_get_mask_types

Get available mask types.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "maskTypes": ["rectangle", "circle", "ellipse", "star", "triangle", "hexagon", "heart", "rounded", "custom"]
}

pinepaper_get_mask_animations

Get available mask animation presets.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "animations": [
    "wipeLeft", "wipeRight", "wipeUp", "wipeDown",
    "iris", "irisOut",
    "star", "heart",
    "curtainHorizontal", "curtainVertical", "cinematic",
    "diagonalWipe",
    "revealUp", "revealDown"
  ]
}

Generator Tools

pinepaper_execute_generator

Execute a background generator.

Input Schema:

{
  "type": "object",
  "properties": {
    "generatorName": {
      "type": "string",
      "enum": ["drawSunburst", "drawSunsetScene", "drawGrid", "drawStackedCircles", "drawCircuit", "drawWaves", "drawPattern", "drawSolarSystem", "drawDayNightCycle"]
    },
    "params": {
      "type": "object",
      "description": "Generator-specific parameters"
    }
  },
  "required": ["generatorName"]
}

Generator Parameters:

Generator Key Parameters
drawSunburst rayCount, colors (array), bgColor
drawSunsetScene skyColors (array), cloudCount
drawGrid gridType (‘lines’/‘dots’/‘squares’), spacing, lineColor, bgColor
drawStackedCircles count, colors, distribution (‘poisson’/‘golden’/‘random’)
drawWaves waveCount, colors
drawSolarSystem sunSize, sunColor, showOrbits, orbitColor, speedMultiplier, showLabels, bgColor
drawDayNightCycle cycleEnabled, cycleDuration, startPhase, showSun, sunSize, showMoon, moonSize, showStars, starCount, showClouds, cloudCount

Solar System Generator Details:

The drawSolarSystem generator creates an interactive solar system with:

  • All 8 planets with real orbital eccentricity (elliptical orbits)
  • Kepler’s laws for realistic orbital motion (faster at perihelion, slower at aphelion)
  • Sun and planets are selectable and draggable
  • Moving the Sun moves the entire system (planets and orbits follow)
  • Orbit paths are decorative (non-selectable)

Planet Data Flags:

  • Planets have data.selectable = true and data.isDraggable = true
  • Orbits have data.isDecorative = true (not selectable)
  • Sun has data.isSun = true, planets have data.isPlanet = true

pinepaper_list_generators

Get available generators and their parameter schemas.

Output:

{
  "generators": [
    {
      "name": "drawSunburst",
      "displayName": "Sunburst",
      "category": "patterns",
      "params": {
        "rayCount": { "type": "number", "default": 16 },
        "colors": { "type": "array", "default": ["#FF6B6B", "#4ECDC4"] }
      }
    }
  ]
}

Map Tools

Create data-driven geographic visualizations with interactive maps.

pinepaper_load_map

Load a geographic map onto the canvas with specified projection and styling.

Input Schema:

{
  "type": "object",
  "properties": {
    "mapId": {
      "type": "string",
      "enum": ["world", "worldHighRes", "usa"],
      "description": "Map to load (world=110m, worldHighRes=50m professional quality, usa=US states)"
    },
    "projection": {
      "type": "string",
      "enum": ["mercator", "equalEarth", "naturalEarth", "orthographic", "albers", "stereographic"],
      "default": "naturalEarth",
      "description": "Map projection type"
    },
    "quality": {
      "type": "string",
      "enum": ["fast", "balanced", "professional"],
      "default": "balanced",
      "description": "Rendering quality (professional=no simplification, best for multi-polygon countries)"
    },
    "fillColor": {
      "type": "string",
      "default": "#e5e7eb",
      "description": "Default fill color for regions"
    },
    "strokeColor": {
      "type": "string",
      "default": "#9ca3af",
      "description": "Border/stroke color"
    },
    "strokeWidth": {
      "type": "number",
      "default": 0.5,
      "description": "Border width in pixels"
    },
    "scale": {
      "type": "number",
      "description": "Scale multiplier"
    },
    "center": {
      "type": "array",
      "items": { "type": "number" },
      "description": "Center coordinates [longitude, latitude]"
    },
    "rotate": {
      "type": "array",
      "items": { "type": "number" },
      "description": "Rotation angles [x, y, z]"
    },
    "enableHover": {
      "type": "boolean",
      "default": false,
      "description": "Enable hover effects on regions"
    },
    "enableClick": {
      "type": "boolean",
      "default": false,
      "description": "Enable click events on regions"
    },
    "hoverFill": {
      "type": "string",
      "description": "Fill color on hover"
    },
    "hoverStroke": {
      "type": "string",
      "description": "Stroke color on hover"
    }
  },
  "required": ["mapId"]
}

Output:

{
  "success": true,
  "mapId": "worldHighRes",
  "regionCount": 177,
  "bounds": { "x": 50, "y": 100, "width": 700, "height": 400 }
}

pinepaper_highlight_regions

Highlight specific regions on a loaded map.

Input Schema:

{
  "type": "object",
  "properties": {
    "regionIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Array of region IDs to highlight"
    },
    "fillColor": {
      "type": "string",
      "default": "#22c55e",
      "description": "Highlight fill color"
    },
    "strokeColor": {
      "type": "string",
      "description": "Highlight stroke color"
    },
    "strokeWidth": {
      "type": "number",
      "description": "Highlight stroke width"
    },
    "animate": {
      "type": "boolean",
      "default": false,
      "description": "Animate the highlight transition"
    }
  },
  "required": ["regionIds"]
}

Region ID Formats:

Map ID Format Examples
world, worldHighRes Full country names “United States of America”, “France”, “Japan”, “Russian Federation”
usa State codes “CA”, “TX”, “NY”, “FL”

Output:

{
  "success": true,
  "highlighted": ["United States of America", "Canada", "Mexico"],
  "notFound": []
}

pinepaper_unhighlight_regions

Remove highlights from specific regions.

Input Schema:

{
  "type": "object",
  "properties": {
    "regionIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Array of region IDs to unhighlight (omit for all)"
    }
  }
}

pinepaper_apply_data_colors

Apply data-driven coloring to map regions (choropleth visualization).

Input Schema:

{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "Object mapping region IDs to numeric values",
      "additionalProperties": { "type": "number" }
    },
    "colorScale": {
      "type": "string",
      "enum": ["blues", "greens", "reds", "oranges", "purples", "heat", "viridis"],
      "default": "blues",
      "description": "Color scale to use"
    },
    "minValue": {
      "type": "number",
      "description": "Minimum value for color scale (auto-detected if omitted)"
    },
    "maxValue": {
      "type": "number",
      "description": "Maximum value for color scale (auto-detected if omitted)"
    },
    "showLegend": {
      "type": "boolean",
      "default": true,
      "description": "Show color legend"
    },
    "legendPosition": {
      "type": "string",
      "enum": ["top-left", "top-right", "bottom-left", "bottom-right"],
      "default": "bottom-right",
      "description": "Legend position"
    },
    "legendTitle": {
      "type": "string",
      "description": "Legend title text"
    }
  },
  "required": ["data"]
}

Example:

{
  "data": {
    "California": 39538223,
    "Texas": 29145505,
    "Florida": 21538187,
    "New York": 20201249
  },
  "colorScale": "blues",
  "showLegend": true,
  "legendTitle": "Population"
}

Output:

{
  "success": true,
  "regionsColored": 4,
  "valueRange": { "min": 20201249, "max": 39538223 }
}

pinepaper_add_marker

Add a marker to the map at specified coordinates.

Input Schema:

{
  "type": "object",
  "properties": {
    "lat": {
      "type": "number",
      "description": "Latitude (-90 to 90)"
    },
    "lon": {
      "type": "number",
      "description": "Longitude (-180 to 180)"
    },
    "label": {
      "type": "string",
      "description": "Marker label text"
    },
    "color": {
      "type": "string",
      "default": "#ef4444",
      "description": "Marker color"
    },
    "size": {
      "type": "number",
      "default": 8,
      "description": "Marker size in pixels"
    },
    "pulse": {
      "type": "boolean",
      "default": false,
      "description": "Enable pulse animation"
    },
    "icon": {
      "type": "string",
      "enum": ["circle", "pin", "star", "diamond"],
      "default": "circle",
      "description": "Marker icon shape"
    }
  },
  "required": ["lat", "lon"]
}

Output:

{
  "success": true,
  "markerId": "marker_1",
  "position": { "x": 234, "y": 156 }
}

pinepaper_add_map_labels

Add labels to map regions.

Input Schema:

{
  "type": "object",
  "properties": {
    "regions": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Specific regions to label (omit for all visible)"
    },
    "labelType": {
      "type": "string",
      "enum": ["name", "code", "value"],
      "default": "name",
      "description": "What to display as label"
    },
    "fontSize": {
      "type": "number",
      "default": 10,
      "description": "Font size in pixels"
    },
    "fontColor": {
      "type": "string",
      "default": "#374151",
      "description": "Label text color"
    },
    "fontFamily": {
      "type": "string",
      "default": "Inter, sans-serif",
      "description": "Font family"
    },
    "showBackground": {
      "type": "boolean",
      "default": false,
      "description": "Show background behind labels"
    }
  }
}

pinepaper_pan_map

Pan the map view to specific coordinates.

Input Schema:

{
  "type": "object",
  "properties": {
    "lat": {
      "type": "number",
      "description": "Target latitude"
    },
    "lon": {
      "type": "number",
      "description": "Target longitude"
    },
    "animate": {
      "type": "boolean",
      "default": true,
      "description": "Animate the pan"
    },
    "duration": {
      "type": "number",
      "default": 0.5,
      "description": "Animation duration in seconds"
    }
  },
  "required": ["lat", "lon"]
}

pinepaper_zoom_map

Set the map zoom level.

Input Schema:

{
  "type": "object",
  "properties": {
    "level": {
      "type": "number",
      "minimum": 0.5,
      "maximum": 10,
      "description": "Zoom level (1 = default)"
    },
    "center": {
      "type": "array",
      "items": { "type": "number" },
      "description": "Zoom center [lon, lat] (optional)"
    },
    "animate": {
      "type": "boolean",
      "default": true
    }
  },
  "required": ["level"]
}

pinepaper_export_map

Export the current map configuration for saving/loading.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "mapId": "worldHighRes",
  "projection": "naturalEarth",
  "quality": "professional",
  "highlightedRegions": ["United States of America", "Canada"],
  "dataColors": { "California": "#3b82f6" },
  "markers": [
    { "lat": 37.77, "lon": -122.42, "label": "San Francisco" }
  ],
  "viewState": {
    "center": [0, 0],
    "zoom": 1
  }
}

pinepaper_import_custom_map

Import a custom GeoJSON or TopoJSON map.

Input Schema:

{
  "type": "object",
  "properties": {
    "geoJson": {
      "type": "object",
      "description": "GeoJSON or TopoJSON data"
    },
    "sourceUrl": {
      "type": "string",
      "description": "URL to fetch GeoJSON from (alternative to geoJson)"
    },
    "idProperty": {
      "type": "string",
      "default": "id",
      "description": "Property to use as region ID"
    },
    "nameProperty": {
      "type": "string",
      "default": "name",
      "description": "Property to use as region name"
    },
    "projection": {
      "type": "string",
      "enum": ["mercator", "equalEarth", "naturalEarth", "albers"],
      "default": "naturalEarth"
    },
    "style": {
      "type": "object",
      "properties": {
        "fillColor": { "type": "string" },
        "strokeColor": { "type": "string" },
        "strokeWidth": { "type": "number" }
      }
    }
  }
}

Data Sources:

Source Description URL
GADM Detailed country/admin boundaries gadm.org
Natural Earth Public domain map data naturalearthdata.com
OpenStreetMap Community map data openstreetmap.org
Mapshaper GeoJSON simplification tool mapshaper.org

Recommended Workflow:

  1. Download detailed boundaries from GADM or Natural Earth
  2. Simplify with Mapshaper if needed
  3. Import via pinepaper_import_custom_map

pinepaper_get_region_at_point

Get the region at a specific canvas point (for hit testing).

Input Schema:

{
  "type": "object",
  "properties": {
    "x": { "type": "number" },
    "y": { "type": "number" }
  },
  "required": ["x", "y"]
}

Output:

{
  "found": true,
  "regionId": "California",
  "properties": {
    "name": "California",
    "code": "CA",
    "population": 39538223
  }
}

pinepaper_animate_map_regions

Animate specific map regions with timeline-integrated keyframe color animations.

Input Schema:

{
  "type": "object",
  "properties": {
    "duration": {
      "type": "number",
      "description": "Total animation duration in seconds",
      "default": 5
    },
    "loop": {
      "type": "boolean",
      "description": "Loop the animation",
      "default": true
    },
    "regions": {
      "type": "object",
      "description": "Object mapping region IDs to arrays of keyframes",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "time": { "type": "number", "description": "Time in seconds" },
            "fillColor": { "type": "string", "description": "Fill color at this keyframe" },
            "strokeColor": { "type": "string", "description": "Stroke color at this keyframe" },
            "opacity": { "type": "number", "description": "Opacity at this keyframe (0-1)" }
          },
          "required": ["time", "fillColor"]
        }
      }
    }
  },
  "required": ["regions"]
}

Example:

{
  "duration": 8,
  "loop": true,
  "regions": {
    "USA": [
      { "time": 0, "fillColor": "#ef4444" },
      { "time": 4, "fillColor": "#22c55e" },
      { "time": 8, "fillColor": "#ef4444" }
    ],
    "France": [
      { "time": 0, "fillColor": "#3b82f6" },
      { "time": 8, "fillColor": "#fbbf24" }
    ]
  }
}

Output:

{
  "success": true,
  "animatedRegions": ["USA", "France"],
  "duration": 8,
  "errors": []
}

pinepaper_animate_map_wave

Create a wave animation across all map regions based on geographic position.

Input Schema:

{
  "type": "object",
  "properties": {
    "duration": {
      "type": "number",
      "description": "Total wave duration in seconds",
      "default": 10
    },
    "loop": {
      "type": "boolean",
      "description": "Loop the animation",
      "default": true
    },
    "colors": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Array of colors for the wave",
      "default": ["#ef4444", "#fbbf24", "#22c55e", "#3b82f6"]
    },
    "waveDirection": {
      "type": "string",
      "enum": ["horizontal", "vertical", "radial"],
      "description": "Direction of the wave effect",
      "default": "horizontal"
    }
  }
}

Output:

{
  "success": true,
  "animatedRegions": ["USA", "Canada", "Mexico", "..."],
  "totalRegions": 177
}

pinepaper_stop_map_animations

Stop all or specific map region animations.

Input Schema:

{
  "type": "object",
  "properties": {
    "regions": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Specific region IDs to stop (omit for all)"
    },
    "resetColors": {
      "type": "boolean",
      "description": "Reset regions to default colors",
      "default": true
    }
  }
}

pinepaper_get_animated_map_regions

Get list of currently animated map regions with their animation data.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "animatedRegions": [
    {
      "regionId": "USA",
      "keyframes": [
        { "time": 0, "fillColor": "#ef4444" },
        { "time": 5, "fillColor": "#22c55e" }
      ],
      "duration": 5,
      "loop": true
    }
  ],
  "count": 1
}

pinepaper_export_map_region_csv

Export map region data as CSV including colors, highlight, and selection status.

Input Schema:

{
  "type": "object",
  "properties": {
    "includeHighlighted": {
      "type": "boolean",
      "description": "Include highlight status column",
      "default": true
    },
    "includeSelected": {
      "type": "boolean",
      "description": "Include selection status column",
      "default": true
    },
    "includeColors": {
      "type": "boolean",
      "description": "Include fill/stroke color columns",
      "default": true
    },
    "download": {
      "type": "boolean",
      "description": "Auto-download the CSV file",
      "default": false
    },
    "filename": {
      "type": "string",
      "description": "Filename for download",
      "default": "map-regions.csv"
    }
  }
}

Output:

{
  "success": true,
  "csv": "regionId,name,highlighted,selected,fillColor,strokeColor\nUSA,United States of America,1,0,#22c55e,#16a34a\n...",
  "regionCount": 177
}

pinepaper_import_map_region_csv

Import CSV data to update map region states (colors, highlight, selection).

Input Schema:

{
  "type": "object",
  "properties": {
    "csvText": {
      "type": "string",
      "description": "CSV text content to import"
    },
    "applyColors": {
      "type": "boolean",
      "description": "Apply fill/stroke colors from CSV",
      "default": true
    },
    "applyHighlight": {
      "type": "boolean",
      "description": "Update highlight status from CSV",
      "default": true
    },
    "applySelection": {
      "type": "boolean",
      "description": "Update selection status from CSV",
      "default": true
    }
  },
  "required": ["csvText"]
}

Output:

{
  "success": true,
  "updatedRegions": 50,
  "notFound": ["INVALID_ID"],
  "errors": []
}

pinepaper_select_map_regions

Programmatically select map regions.

Input Schema:

{
  "type": "object",
  "properties": {
    "regionIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Array of region IDs to select"
    }
  },
  "required": ["regionIds"]
}

pinepaper_deselect_map_regions

Programmatically deselect map regions.

Input Schema:

{
  "type": "object",
  "properties": {
    "regionIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Array of region IDs to deselect (omit for all)"
    }
  }
}

pinepaper_get_highlighted_map_regions

Get list of currently highlighted map regions.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "highlighted": ["USA", "Canada", "France"],
  "count": 3
}

pinepaper_export_map_geojson

Export the current map as GeoJSON (with current colors/modifications).

Input Schema:

{
  "type": "object",
  "properties": {
    "includeStyles": {
      "type": "boolean",
      "description": "Include fill/stroke colors as properties",
      "default": true
    },
    "includeMetadata": {
      "type": "boolean",
      "description": "Include region names and IDs",
      "default": true
    },
    "selectedOnly": {
      "type": "boolean",
      "description": "Only export selected regions",
      "default": false
    },
    "download": {
      "type": "boolean",
      "description": "Auto-download the file",
      "default": false
    },
    "filename": {
      "type": "string",
      "description": "Filename for download",
      "default": "map-export.geojson"
    }
  }
}

Output:

{
  "success": true,
  "geoJson": { "type": "FeatureCollection", "features": [...] },
  "regionCount": 177
}

pinepaper_export_original_map_geojson

Export the original source GeoJSON (unmodified boundaries). This returns the exact data that was used to load the map, allowing users to edit boundaries externally and re-import.

Input Schema:

{
  "type": "object",
  "properties": {
    "download": {
      "type": "boolean",
      "description": "Auto-download the file",
      "default": false
    },
    "filename": {
      "type": "string",
      "description": "Filename for download",
      "default": "map-source.geojson"
    }
  }
}

Output:

{
  "success": true,
  "geoJson": { "type": "FeatureCollection", "features": [...] },
  "source": "world",
  "regionCount": 177
}

pinepaper_import_custom_map

Import a custom GeoJSON or TopoJSON map. Supports URLs or inline data.

Input Schema:

{
  "type": "object",
  "properties": {
    "geoJson": {
      "type": "object",
      "description": "GeoJSON or TopoJSON object"
    },
    "sourceUrl": {
      "type": "string",
      "description": "URL to fetch GeoJSON from (alternative to geoJson)"
    },
    "projection": {
      "type": "string",
      "enum": ["mercator", "equalEarth", "naturalEarth", "orthographic", "albers"],
      "default": "naturalEarth",
      "description": "Map projection to use"
    },
    "quality": {
      "type": "string",
      "enum": ["draft", "standard", "professional"],
      "default": "standard"
    },
    "styles": {
      "type": "object",
      "properties": {
        "fill": { "type": "string", "default": "#e5e7eb" },
        "stroke": { "type": "string", "default": "#9ca3af" },
        "strokeWidth": { "type": "number", "default": 0.5 }
      }
    }
  }
}

Output:

{
  "success": true,
  "mapId": "custom_map_1",
  "regionCount": 50,
  "bounds": { "x": 50, "y": 100, "width": 700, "height": 400 }
}

pinepaper_get_map_source_info

Get information about the currently loaded map source.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "source": "world",
  "projection": "naturalEarth",
  "quality": "standard",
  "regionCount": 177,
  "hasOriginalGeoJSON": true,
  "isCustomImport": false
}

Map Events

The map system emits events that can be listened to via triggers:

Event Description Data
map:regionClick Region was clicked { regionId, properties, position }
map:regionHover Mouse entered region { regionId, properties }
map:regionLeave Mouse left region { regionId }
map:markerClick Marker was clicked { markerId, lat, lon, label }

Example Trigger:

{
  "itemId": "map_1",
  "event": "map:regionClick",
  "actions": [
    { "type": "show", "targetItemId": "info_panel" },
    { "type": "update_property", "targetItemId": "region_name", "property": "content", "value": "$event.regionId" }
  ]
}

Font Tools

Create custom hand-drawn fonts by drawing glyphs on a dedicated canvas. Font Studio converts Paper.js paths to OpenType glyphs.

pinepaper_font_show_studio

Open the Font Studio UI for interactive font creation.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "message": "Font Studio opened"
}

pinepaper_font_set_name

Set the font name.

Input Schema:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Font family name (e.g., 'MyHandwriting')"
    }
  },
  "required": ["name"]
}

Output:

{
  "success": true,
  "fontName": "MyHandwriting"
}

pinepaper_font_get_required_chars

Get the list of characters needed for a complete font.

Input Schema:

{
  "type": "object",
  "properties": {
    "set": {
      "type": "string",
      "enum": ["minimum", "standard"],
      "default": "minimum",
      "description": "minimum: A-Z, a-z, 0-9, space (63 chars). standard: adds punctuation (90+ chars)"
    }
  }
}

Output:

{
  "characters": ["A", "B", "C", "..."],
  "count": 63,
  "set": "minimum"
}

pinepaper_font_get_status

Get font completion status.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "fontName": "MyHandwriting",
  "total": 63,
  "completed": 26,
  "pending": 37,
  "percentage": 41,
  "completedChars": ["A", "B", "C", "..."],
  "pendingChars": ["a", "b", "c", "..."],
  "isComplete": false
}

pinepaper_font_create_glyph

Create a glyph from a Paper.js path. Used programmatically when drawing paths for characters.

Input Schema:

{
  "type": "object",
  "properties": {
    "character": {
      "type": "string",
      "description": "Single character (e.g., 'A', 'a', '1', ' ')"
    },
    "pathId": {
      "type": "string",
      "description": "Registry ID of the Paper.js path to use as glyph shape"
    }
  },
  "required": ["character", "pathId"]
}

Output:

{
  "success": true,
  "character": "A",
  "glyphName": "A",
  "advanceWidth": 450
}

pinepaper_font_create_space

Create the space glyph (no visible shape, just advance width).

Input Schema:

{
  "type": "object",
  "properties": {
    "width": {
      "type": "number",
      "default": 250,
      "description": "Space width in font units"
    }
  }
}

Output:

{
  "success": true,
  "character": " ",
  "advanceWidth": 250
}

pinepaper_font_remove_glyph

Remove a glyph from the font.

Input Schema:

{
  "type": "object",
  "properties": {
    "character": {
      "type": "string",
      "description": "Character to remove"
    }
  },
  "required": ["character"]
}

Output:

{
  "success": true,
  "removed": "A"
}

pinepaper_font_set_metrics

Set font metrics (advanced).

Input Schema:

{
  "type": "object",
  "properties": {
    "unitsPerEm": {
      "type": "number",
      "default": 1000,
      "description": "Coordinate grid size"
    },
    "ascender": {
      "type": "number",
      "default": 800,
      "description": "Height above baseline"
    },
    "descender": {
      "type": "number",
      "default": -200,
      "description": "Depth below baseline (negative)"
    },
    "xHeight": {
      "type": "number",
      "default": 500,
      "description": "Lowercase letter height"
    },
    "capHeight": {
      "type": "number",
      "default": 700,
      "description": "Capital letter height"
    }
  }
}

Output:

{
  "success": true,
  "metrics": {
    "unitsPerEm": 1000,
    "ascender": 800,
    "descender": -200,
    "xHeight": 500,
    "capHeight": 700
  }
}

pinepaper_font_export

Export the font as OTF file.

Input Schema:

{
  "type": "object",
  "properties": {
    "download": {
      "type": "boolean",
      "default": true,
      "description": "Trigger browser download"
    }
  }
}

Output:

{
  "success": true,
  "fontName": "MyHandwriting",
  "format": "otf",
  "downloaded": true,
  "glyphCount": 63
}

pinepaper_font_load_into_document

Load the custom font into the document for immediate use in PinePaper.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "fontName": "MyHandwriting",
  "message": "Font 'MyHandwriting' loaded and ready to use"
}

pinepaper_font_export_data

Export font data as JSON for saving progress.

Input Schema:

{
  "type": "object",
  "properties": {
    "download": {
      "type": "boolean",
      "default": true,
      "description": "Trigger browser download"
    }
  }
}

Output:

{
  "success": true,
  "data": {
    "version": "1.0",
    "fontName": "MyHandwriting",
    "metrics": { "..." },
    "glyphs": { "..." }
  },
  "downloaded": true
}

pinepaper_font_import_data

Import font data from previously saved JSON.

Input Schema:

{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "Font data object from pinepaper_font_export_data"
    }
  },
  "required": ["data"]
}

Output:

{
  "success": true,
  "fontName": "MyHandwriting",
  "glyphCount": 26
}

pinepaper_font_clear

Clear all glyphs and reset the font.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "message": "Font cleared"
}

pinepaper_font_remove_overlap

Remove overlapping areas from a path (like FontForge’s RemoveOverlap). Merges multiple overlapping paths into a single clean outline.

Input Schema:

{
  "type": "object",
  "properties": {
    "pathId": {
      "type": "string",
      "description": "Registry ID of the Paper.js path to process"
    }
  },
  "required": ["pathId"]
}

Output:

{
  "success": true,
  "pathId": "item_42",
  "message": "Overlaps removed from path"
}

pinepaper_font_correct_direction

Correct path winding direction for proper fill rendering (like FontForge’s CorrectDirection). Ensures outer contours are clockwise and inner holes are counter-clockwise.

Input Schema:

{
  "type": "object",
  "properties": {
    "pathId": {
      "type": "string",
      "description": "Registry ID of the Paper.js path to process"
    }
  },
  "required": ["pathId"]
}

Output:

{
  "success": true,
  "pathId": "item_42",
  "message": "Path direction corrected"
}

pinepaper_font_cleanup_path

Apply all path cleanup operations in the correct order: removeOverlap → correctDirection → smooth.

Input Schema:

{
  "type": "object",
  "properties": {
    "pathId": {
      "type": "string",
      "description": "Registry ID of the Paper.js path to process"
    },
    "removeOverlap": {
      "type": "boolean",
      "default": true,
      "description": "Merge overlapping strokes"
    },
    "correctDirection": {
      "type": "boolean",
      "default": true,
      "description": "Fix winding direction for fills"
    },
    "smooth": {
      "type": "boolean",
      "default": true,
      "description": "Apply path smoothing"
    },
    "smoothTolerance": {
      "type": "number",
      "default": 2.5,
      "description": "Smoothing tolerance (higher = more simplification)"
    }
  },
  "required": ["pathId"]
}

Output:

{
  "success": true,
  "pathId": "item_42",
  "operations": ["removeOverlap", "correctDirection", "smooth"],
  "message": "Path cleanup complete"
}

Font Studio Typography Guide

When using Font Studio interactively, guide lines help with consistent glyph drawing:

Guide Line Color Description
Cap Height Red (#ff6b6b) Top of capital letters (H, T, A)
x-Height Cyan (#4ecdc4) Top of lowercase letters (a, e, x)
Baseline Green (#95e1d3) Where letters “sit”
Descender Purple (#dda0dd) Below baseline for g, p, y, j

Best Practices:

  • Keep stroke width consistent across all characters
  • Uppercase letters should touch the cap height line
  • Lowercase (except b, d, f, h, k, l, t) stay within x-height
  • Letters g, j, p, q, y extend below baseline to descender

Query Tools

pinepaper_get_items

Get all or filtered items.

Input Schema:

{
  "type": "object",
  "properties": {
    "filter": {
      "type": "object",
      "properties": {
        "type": { "type": "string", "description": "Filter by item type" },
        "source": { "type": "string", "enum": ["user", "generator", "import"] },
        "hasAnimation": { "type": "boolean" },
        "hasRelation": { "type": "boolean" }
      }
    }
  }
}

Output:

{
  "items": [
    {
      "id": "item_1",
      "type": "circle",
      "position": { "x": 400, "y": 300 },
      "hasAnimation": true,
      "relations": ["orbits"]
    }
  ],
  "count": 1
}

pinepaper_get_relation_stats

Get statistics about active relations.

Output:

{
  "activeItems": 5,
  "ruleCount": 8,
  "associationsByType": {
    "orbits": 2,
    "follows": 3,
    "attached_to": 1
  }
}

Export Tools

pinepaper_export_svg

Export the scene as animated SVG.

Output:

{
  "success": true,
  "svgString": "<svg>...</svg>",
  "hasAnimations": true
}

pinepaper_export_training_data

Export relations as training data for LLM fine-tuning.

Output:

{
  "trainingData": [
    {
      "instruction": "moon orbits earth at radius 100",
      "code": "app.addRelation('item_1', 'item_2', 'orbits', {\"radius\":100})",
      "relation": "orbits",
      "params": { "radius": 100 }
    }
  ],
  "count": 5
}

pinepaper_export_scene

Export the complete scene state.

Output:

{
  "items": [...],
  "relations": [...],
  "decorative": [...],
  "backgroundColor": "#1e293b"
}

Effect Tools

pinepaper_apply_effect

Apply a visual effect to an item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string"
    },
    "effectType": {
      "type": "string",
      "enum": ["sparkle", "blast"]
    },
    "params": {
      "type": "object",
      "properties": {
        "color": { "type": "string" },
        "speed": { "type": "number" },
        "size": { "type": "number" }
      }
    }
  },
  "required": ["itemId", "effectType"]
}

Text Design Tools

pinepaper_create_letter_collage

Create stylized text with per-letter customization. Perfect for word games, ransom notes, gradient text, and creative typography.

Input Schema:

{
  "type": "object",
  "properties": {
    "text": {
      "type": "string",
      "description": "The text to stylize"
    },
    "style": {
      "type": "string",
      "enum": ["tile", "magazine", "paperCut", "fold", "gradient", "image"],
      "default": "tile",
      "description": "Style type for the letter collage"
    },
    "palette": {
      "type": "string",
      "description": "Color palette name (e.g., 'wordle', 'candy', 'neon', 'ocean')"
    },
    "position": {
      "type": "object",
      "properties": {
        "x": { "type": "number" },
        "y": { "type": "number" }
      },
      "description": "Position on canvas (defaults to center)"
    },
    "fontSize": {
      "type": "number",
      "default": 48,
      "description": "Base font size in pixels"
    },
    "fontFamily": {
      "type": "string",
      "default": "Inter, sans-serif",
      "description": "Font family to use"
    },
    "spacing": {
      "type": "number",
      "default": 1.1,
      "description": "Letter spacing multiplier"
    },
    "gradientPalette": {
      "type": "string",
      "description": "Gradient palette name (for style='gradient')"
    },
    "gradientDirection": {
      "type": "string",
      "enum": ["vertical", "horizontal", "diagonal", "radial"],
      "default": "vertical",
      "description": "Gradient direction (for style='gradient')"
    },
    "cornerRadius": {
      "type": "number",
      "default": 4,
      "description": "Corner radius for tile backgrounds"
    },
    "shadowEnabled": {
      "type": "boolean",
      "default": true,
      "description": "Enable drop shadows"
    }
  },
  "required": ["text"]
}

Style Types:

Style Description Best For
tile Wordle/Scrabble colored backgrounds Word games, educational
magazine Mixed fonts/colors like cutouts Ransom notes, collage art
paperCut Shadow/depth like cut paper Craft aesthetics
fold Origami-style folded letters Paper crafts
gradient Each letter with gradient fill Modern, vibrant text
image Letters filled with image Photo effects

Available Tile Palettes:

Category Palettes
Game wordle, scrabble
Vibrant candy, neon, rainbow
Soft pastel, cotton
Natural earth, ocean, forest, sunset
Professional corporate, minimal, slate
Seasonal christmas, halloween, spring
Magazine magazine, newspaper, vintage
Paper Craft paperCraft, origami, craftPaper

Available Gradient Palettes: rainbow, sunset, ocean, fire, gold, rose, ice, cyberpunk, neonGlow, purplePink

Output:

{
  "success": true,
  "collageId": "collage_1",
  "itemId": "item_5",
  "text": "HELLO",
  "style": "tile",
  "letterCount": 5
}

pinepaper_animate_letter_collage

Apply animation to all letters in a collage with staggered timing.

Input Schema:

{
  "type": "object",
  "properties": {
    "collageId": {
      "type": "string",
      "description": "Collage ID from create_letter_collage"
    },
    "animationType": {
      "type": "string",
      "enum": ["pulse", "bounce", "fade", "wobble", "rotate"],
      "description": "Animation type to apply"
    },
    "staggerDelay": {
      "type": "number",
      "default": 0.1,
      "description": "Delay between each letter's animation start (seconds)"
    },
    "animationSpeed": {
      "type": "number",
      "default": 1,
      "description": "Animation speed multiplier"
    }
  },
  "required": ["collageId", "animationType"]
}

pinepaper_get_letter_collage_options

Get available styles, palettes, and gradient options for letter collages.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "styles": ["tile", "magazine", "paperCut", "fold", "gradient", "image"],
  "tilePalettes": {
    "game": ["wordle", "scrabble"],
    "vibrant": ["candy", "neon", "rainbow"],
    "soft": ["pastel", "cotton"],
    "natural": ["earth", "ocean", "forest", "sunset"],
    "professional": ["corporate", "minimal", "slate"],
    "seasonal": ["christmas", "halloween", "spring"],
    "magazine": ["magazine", "newspaper", "vintage"],
    "paperCraft": ["paperCraft", "origami", "craftPaper"]
  },
  "gradientPalettes": ["rainbow", "sunset", "ocean", "fire", "gold", "rose", "ice", "cyberpunk", "neonGlow", "purplePink"],
  "gradientDirections": ["vertical", "horizontal", "diagonal", "radial"]
}

Interactive Triggers (v1.5.0+)

Add click, hover, drag, and timeline-based interactions to items.

pinepaper_add_trigger

Add an interactive trigger to an item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Item to attach trigger to"
    },
    "event": {
      "type": "string",
      "enum": ["click", "hover_enter", "hover_exit", "drag_start", "drag_move", "drag_end", "timeline", "scene_enter", "scene_exit", "animation_end", "quiz_answer"],
      "description": "Event that fires the trigger"
    },
    "actions": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["show", "hide", "toggle_visibility", "play_animation", "stop_animation", "navigate", "update_property", "set_variable", "submit_answer", "increment_score", "reset_quiz"]
          },
          "targetItemId": {"type": "string"},
          "animationType": {"type": "string"},
          "property": {"type": "string"},
          "value": {},
          "url": {"type": "string"},
          "points": {"type": "number"}
        },
        "required": ["type"]
      }
    },
    "condition": {
      "type": "string",
      "description": "Optional condition expression (e.g., \"$score > 10\")"
    }
  },
  "required": ["itemId", "event", "actions"]
}

Examples:

// Click to show panel
{"itemId": "button_1", "event": "click", "actions": [{"type": "show", "targetItemId": "panel_1"}]}

// Hover to animate
{"itemId": "star_1", "event": "hover_enter", "actions": [{"type": "play_animation", "targetItemId": "star_1", "animationType": "pulse"}]}

// Click to navigate
{"itemId": "next_btn", "event": "click", "actions": [{"type": "navigate", "url": "#scene2"}]}

pinepaper_remove_trigger

Remove triggers from an item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {"type": "string"},
    "event": {"type": "string", "enum": ["click", "hover_enter", "hover_exit", "drag_start", "drag_move", "drag_end", "timeline", "scene_enter", "scene_exit", "animation_end", "quiz_answer"]},
    "removeAll": {"type": "boolean"}
  },
  "required": ["itemId"]
}

pinepaper_query_triggers

List all triggers on the canvas or for a specific item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {"type": "string", "description": "Filter by item ID"},
    "event": {"type": "string", "description": "Filter by event type"}
  }
}

Quiz/LMS Integration (v1.5.0+)

Create interactive quizzes with SCORM/xAPI support.

pinepaper_create_quiz

Create an interactive quiz with questions, answers, and scoring.

Question Types:

  • multiple-choice: Single correct answer
  • multiple-select: Multiple correct answers
  • drag-drop: Drag items to zones
  • matching: Match pairs
  • sequencing: Order items correctly
  • hotspot: Click correct area
  • true-false: True/false question

Input Schema:

{
  "type": "object",
  "properties": {
    "title": {"type": "string"},
    "questions": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "type": {"type": "string", "enum": ["multiple-choice", "multiple-select", "drag-drop", "matching", "sequencing", "hotspot", "true-false"]},
          "prompt": {"type": "string"},
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {"type": "string"},
                "label": {"type": "string"},
                "isCorrect": {"type": "boolean"}
              }
            }
          },
          "points": {"type": "number"},
          "correctFeedback": {"type": "string"},
          "incorrectFeedback": {"type": "string"}
        },
        "required": ["type", "prompt", "points"]
      }
    },
    "passingScore": {"type": "number", "description": "Minimum percentage to pass (0-100)"},
    "showScore": {"type": "boolean"},
    "allowRetry": {"type": "boolean"},
    "shuffleQuestions": {"type": "boolean"},
    "shuffleOptions": {"type": "boolean"}
  },
  "required": ["questions"]
}

Example:

{
  "title": "Geography Quiz",
  "questions": [
    {
      "type": "multiple-choice",
      "prompt": "What is the capital of France?",
      "options": [
        {"id": "a", "label": "London"},
        {"id": "b", "label": "Paris", "isCorrect": true},
        {"id": "c", "label": "Berlin"}
      ],
      "points": 10,
      "correctFeedback": "Correct! Paris is the capital.",
      "incorrectFeedback": "Sorry, the correct answer is Paris."
    }
  ],
  "passingScore": 70,
  "showScore": true
}

pinepaper_get_quiz_state

Get the current state of an active quiz.

Output:

{
  "quizId": "quiz_1",
  "currentQuestion": 2,
  "totalQuestions": 5,
  "score": 20,
  "maxScore": 50,
  "answers": [{"questionId": "q1", "correct": true}],
  "passed": false,
  "complete": false
}

pinepaper_reset_quiz

Reset a quiz to its initial state.

Input Schema:

{
  "type": "object",
  "properties": {
    "quizId": {"type": "string", "description": "Quiz ID (optional, uses active quiz)"}
  }
}

Agent Flow Mode Tools

Agent mode is enforced by default (v1.5.0+). The browser auto-connects on first tool call with optimized settings for automation.

pinepaper_agent_start_job

Start a new agent job/session for optimized batch workflows.

Input Schema:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Optional job name for tracking"
    },
    "screenshotPolicy": {
      "type": "string",
      "enum": ["on_complete", "on_error", "never", "on_request"],
      "description": "When to take screenshots (default: on_complete)"
    },
    "canvasPreset": {
      "type": "string",
      "enum": ["instagram", "instagram-story", "tiktok", "youtube", "youtube-thumbnail", "twitter", "linkedin", "web", "print-a4", "print-letter"],
      "description": "Set canvas size to platform preset"
    },
    "clearCanvas": {
      "type": "boolean",
      "description": "Clear canvas when starting job (default: true)"
    }
  }
}

pinepaper_agent_end_job

End the current agent job and get summary with export recommendations.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "jobId": "job_12345",
  "duration": 5432,
  "itemsCreated": ["item_1", "item_2", "item_3"],
  "relationsCreated": ["rel_1"],
  "screenshot": "base64...",
  "recommendations": {
    "formats": ["mp4", "gif"],
    "platforms": ["instagram", "tiktok"],
    "hasAnimations": true
  }
}

pinepaper_agent_reset

Fast canvas reset without browser refresh (~200ms vs ~3000ms for page refresh).

Input Schema:

{
  "type": "object",
  "properties": {
    "canvasPreset": {
      "type": "string",
      "enum": ["instagram", "instagram-story", "tiktok", "youtube", "youtube-thumbnail", "twitter", "linkedin", "web", "print-a4", "print-letter"],
      "description": "Set canvas size after reset"
    },
    "backgroundColor": {
      "type": "string",
      "description": "Set background color after reset"
    },
    "preserveBackground": {
      "type": "boolean",
      "description": "Keep existing background"
    }
  }
}

pinepaper_agent_batch_execute

Execute multiple operations in a single browser call. Dramatically faster than individual tool calls.

Performance:

  • 10 individual creates: ~1450ms (10 browser round trips)
  • Batch execute 10 creates: ~300ms (1 browser round trip)

Input Schema:

{
  "type": "object",
  "properties": {
    "operations": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["create", "modify", "animate", "relation", "delete"]
          },
          "itemType": {"type": "string"},
          "itemId": {"type": "string"},
          "position": {"type": "object"},
          "properties": {"type": "object"},
          "animationType": {"type": "string"},
          "animationOptions": {"type": "object"},
          "sourceId": {"type": "string"},
          "targetId": {"type": "string"},
          "relationType": {"type": "string"},
          "relationOptions": {"type": "object"}
        },
        "required": ["type"]
      }
    },
    "atomic": {
      "type": "boolean",
      "description": "All succeed or all fail (default: true)"
    }
  },
  "required": ["operations"]
}

Variable References:

Use $0, $1, etc. to reference items created in earlier operations:

{
  "operations": [
    {"type": "create", "itemType": "circle", "position": {"x": 400, "y": 300}, "properties": {"radius": 50}},
    {"type": "animate", "itemId": "$0", "animationType": "pulse"}
  ]
}

pinepaper_agent_export

Smart export with automatic format detection and platform optimization.

Input Schema:

{
  "type": "object",
  "properties": {
    "platform": {
      "type": "string",
      "enum": ["instagram", "instagram-story", "tiktok", "youtube", "youtube-thumbnail", "twitter", "linkedin", "web", "print-a4", "print-letter"],
      "description": "Target platform (auto-selects optimal format)"
    },
    "format": {
      "type": "string",
      "enum": ["png", "svg", "mp4", "webm", "gif", "pdf"],
      "description": "Override format selection"
    },
    "quality": {
      "type": "string",
      "enum": ["low", "medium", "high", "maximum"],
      "description": "Export quality (default: high)"
    },
    "duration": {
      "type": "number",
      "description": "Animation duration in seconds (default: 5)"
    },
    "fps": {
      "type": "number",
      "description": "Frames per second for video (default: 30)"
    }
  }
}

Platform Optimal Formats:

Platform Dimensions Static Animated
instagram 1080x1080 PNG MP4
instagram-story 1080x1920 PNG MP4
tiktok 1080x1920 PNG MP4@60fps
youtube 1920x1080 PNG MP4
twitter 1200x675 PNG GIF
linkedin 1200x627 PNG GIF
web flexible SVG SVG
print-a4 2480x3508 PDF PDF

pinepaper_agent_analyze

Analyze canvas content for export recommendations.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "hasAnimations": true,
  "animationTypes": ["pulse", "orbits"],
  "colorComplexity": "gradient",
  "itemCount": 5,
  "canvasSize": {"width": 1080, "height": 1080},
  "hasRelations": true,
  "relationTypes": ["orbits"],
  "hasGradients": true,
  "hasShadows": false,
  "hasText": true,
  "hasImages": false,
  "recommendations": {
    "formats": ["mp4", "gif"],
    "platforms": ["instagram", "tiktok"],
    "reason": "Content has animations - video formats recommended"
  }
}

Paper.js Direct Access

pinepaper_register_item

Register a Paper.js item created externally.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemJson": {
      "type": "object",
      "description": "Paper.js item JSON (from item.exportJSON())"
    },
    "itemType": {
      "type": "string",
      "description": "Type name for registry"
    },
    "properties": {
      "type": "object",
      "description": "Custom properties to store"
    }
  },
  "required": ["itemJson", "itemType"]
}

Error Handling

All tools return errors in a consistent format:

{
  "success": false,
  "error": {
    "code": "ITEM_NOT_FOUND",
    "message": "Item with ID 'item_99' not found",
    "details": {}
  }
}

Error Codes:

Code Description
ITEM_NOT_FOUND Item ID doesn’t exist
INVALID_RELATION Unknown relation type
INVALID_PARAMS Missing or invalid parameters
GENERATOR_NOT_FOUND Unknown generator name
EXPORT_FAILED Export operation failed

Rigging Tools (v0.4)

Skeletal animation with bones, FK/IK solvers, poses, and character presets.

pinepaper_create_skeleton

Create a new skeleton for character rigging.

Input Schema:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Skeleton name"
    },
    "rootPosition": {
      "type": "object",
      "properties": {
        "x": { "type": "number" },
        "y": { "type": "number" }
      },
      "description": "World position of skeleton root (default: canvas center)"
    }
  },
  "required": ["name"]
}

Output:

{
  "success": true,
  "skeletonId": "skeleton_1"
}

pinepaper_add_bone

Add a bone to an existing skeleton.

Input Schema:

{
  "type": "object",
  "properties": {
    "skeletonId": {
      "type": "string",
      "description": "Skeleton to add bone to"
    },
    "name": {
      "type": "string",
      "description": "Bone name (e.g., 'upperArm_L')"
    },
    "parentBoneId": {
      "type": "string",
      "description": "Parent bone ID (null for root bone)"
    },
    "length": {
      "type": "number",
      "description": "Bone length in pixels",
      "default": 80
    },
    "angle": {
      "type": "number",
      "description": "Local rotation angle in radians",
      "default": 0
    },
    "constraint": {
      "type": "object",
      "properties": {
        "minAngle": { "type": "number", "description": "Minimum angle in radians" },
        "maxAngle": { "type": "number", "description": "Maximum angle in radians" },
        "fixed": { "type": "boolean", "description": "Lock joint rotation" }
      },
      "description": "Joint angle constraints"
    }
  },
  "required": ["skeletonId", "name"]
}

Output:

{
  "success": true,
  "boneId": "bone_1"
}

pinepaper_attach_item_to_bone

Attach a canvas item to a bone so it follows bone transforms.

Input Schema:

{
  "type": "object",
  "properties": {
    "skeletonId": { "type": "string" },
    "boneId": { "type": "string" },
    "itemId": {
      "type": "string",
      "description": "Item registry ID to attach"
    },
    "attachPoint": {
      "type": "number",
      "description": "Position along bone: 0=joint, 0.5=middle, 1=tip",
      "default": 0.5
    },
    "offset": {
      "type": "array",
      "items": { "type": "number" },
      "description": "Local offset from attach point [x, y]",
      "default": [0, 0]
    },
    "inheritRotation": {
      "type": "boolean",
      "description": "Whether item rotates with bone",
      "default": true
    }
  },
  "required": ["skeletonId", "boneId", "itemId"]
}

Output:

{
  "success": true,
  "skeletonId": "skeleton_1",
  "boneId": "bone_3",
  "itemId": "item_5"
}

pinepaper_set_bone_angle

Set the local rotation angle of a bone (respects joint constraints).

Input Schema:

{
  "type": "object",
  "properties": {
    "skeletonId": { "type": "string" },
    "boneId": { "type": "string" },
    "angle": {
      "type": "number",
      "description": "Angle in radians"
    }
  },
  "required": ["skeletonId", "boneId", "angle"]
}

pinepaper_create_ik_chain

Create an Inverse Kinematics chain for drag-based posing.

Input Schema:

{
  "type": "object",
  "properties": {
    "skeletonId": { "type": "string" },
    "name": { "type": "string" },
    "boneIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Ordered bone IDs from root to effector (minimum 2)",
      "minItems": 2
    },
    "strength": {
      "type": "number",
      "description": "IK influence: 0=FK only, 1=full IK",
      "default": 1,
      "minimum": 0,
      "maximum": 1
    },
    "iterations": {
      "type": "number",
      "description": "FABRIK solver iterations",
      "default": 10
    },
    "tolerance": {
      "type": "number",
      "description": "Convergence tolerance in pixels",
      "default": 0.5
    }
  },
  "required": ["skeletonId", "boneIds"]
}

Output:

{
  "success": true,
  "chainId": "ikchain_1"
}

pinepaper_set_ik_target

Set the IK target item for a chain. The solver will pull the bone chain toward this item’s position.

Input Schema:

{
  "type": "object",
  "properties": {
    "skeletonId": { "type": "string" },
    "chainId": { "type": "string" },
    "targetItemId": {
      "type": "string",
      "description": "Item registry ID to use as IK target (draggable handle)"
    }
  },
  "required": ["skeletonId", "chainId", "targetItemId"]
}

pinepaper_apply_rig_preset

Apply a pre-built character rig preset to a skeleton.

Input Schema:

{
  "type": "object",
  "properties": {
    "skeletonId": { "type": "string" },
    "preset": {
      "type": "string",
      "enum": ["humanoid", "quadruped", "spider", "simple_arm", "snake", "chain"],
      "description": "Character rig preset name"
    }
  },
  "required": ["skeletonId", "preset"]
}

Preset Details:

Preset Bones IK Chains Description
humanoid 16 4 Spine + head + arms(L/R) + legs(L/R)
quadruped 13 4 Horizontal spine + 4 legs + tail
spider 19 8 Body + head + 8 legs
simple_arm 3 1 Upper arm + lower arm + hand
snake 10 1 Spine chain for serpentine motion
chain 5 1 Generic pendulum/rope

Output:

{
  "success": true,
  "skeletonId": "skeleton_1",
  "boneMap": {
    "hip": "bone_1",
    "spine": "bone_2",
    "chest": "bone_3"
  },
  "chainIds": ["ikchain_1", "ikchain_2"]
}

pinepaper_save_pose

Save current bone angles as a named pose for later recall or animation.

Input Schema:

{
  "type": "object",
  "properties": {
    "skeletonId": { "type": "string" },
    "name": {
      "type": "string",
      "description": "Pose name (e.g., 'idle', 'walk_frame1')"
    }
  },
  "required": ["skeletonId", "name"]
}

Output:

{
  "success": true,
  "poseId": "pose_1"
}

pinepaper_load_pose

Load a saved pose onto its skeleton.

Input Schema:

{
  "type": "object",
  "properties": {
    "poseId": { "type": "string" }
  },
  "required": ["poseId"]
}

pinepaper_interpolate_poses

Blend between two poses. Useful for keyframe animation of character rigs.

Input Schema:

{
  "type": "object",
  "properties": {
    "poseIdA": { "type": "string" },
    "poseIdB": { "type": "string" },
    "t": {
      "type": "number",
      "description": "Interpolation factor: 0=pose A, 1=pose B",
      "minimum": 0,
      "maximum": 1
    },
    "apply": {
      "type": "boolean",
      "description": "Apply interpolated angles to skeleton immediately",
      "default": true
    }
  },
  "required": ["poseIdA", "poseIdB", "t"]
}

Output:

{
  "success": true,
  "boneAngles": {
    "bone_1": 0.35,
    "bone_2": -0.15,
    "bone_3": 0.22
  }
}

pinepaper_create_chain_from_items

Auto-create a skeleton by inferring bone hierarchy from a sequence of existing items.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Ordered item IDs — bones created between consecutive items",
      "minItems": 2
    },
    "name": { "type": "string", "description": "Skeleton name" },
    "createIKChain": {
      "type": "boolean",
      "description": "Auto-create IK chain for the full bone sequence",
      "default": false
    }
  },
  "required": ["itemIds"]
}

Output:

{
  "success": true,
  "skeletonId": "skeleton_1",
  "boneIds": ["bone_1", "bone_2"],
  "chainId": "ikchain_1"
}

Blending Tools (v0.4)

Per-item and per-group compositing with presets, transitions, and interactive modes.

pinepaper_apply_blend_preset

Apply a named blend preset (mode + opacity combo) to an item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Item registry ID"
    },
    "preset": {
      "type": "string",
      "enum": [
        "ghost", "neon", "shadow", "silhouette", "glow", "highlight",
        "darkroom", "xray", "dreamy", "vintage",
        "multiply", "screen", "overlay", "dodge", "burn",
        "hardLight", "softLight", "difference", "exclusion"
      ],
      "description": "Blend preset name"
    }
  },
  "required": ["itemId", "preset"]
}

Preset Details:

Preset Blend Mode Opacity Effect
ghost screen 0.5 Ghostly translucent overlay
neon color-dodge 0.85 Bright neon glow
shadow multiply 0.7 Dark shadow overlay
silhouette darken 1.0 Dark silhouette cutout
glow screen 0.8 Bright additive glow
highlight lighten 0.9 Light highlight overlay
darkroom color-burn 0.6 Deep color burn
xray difference 0.8 X-ray inversion
dreamy soft-light 0.9 Soft dreamy haze
vintage overlay 0.7 Warm vintage overlay

Output:

{
  "success": true,
  "itemId": "item_1",
  "preset": "ghost",
  "blendMode": "screen",
  "opacity": 0.5
}

pinepaper_remove_blend_preset

Remove blend preset and reset item to normal blending.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": { "type": "string" }
  },
  "required": ["itemId"]
}

pinepaper_transition_blend_mode

Smoothly transition an item’s blend mode using opacity cross-fade with mode snap at midpoint.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": { "type": "string" },
    "targetMode": {
      "type": "string",
      "description": "Target blend mode (e.g., 'multiply', 'screen', 'overlay')"
    },
    "duration": {
      "type": "number",
      "description": "Transition duration in seconds",
      "default": 0.5
    },
    "easing": {
      "type": "string",
      "enum": ["linear", "easeIn", "easeOut", "easeInOut", "bounce", "elastic"],
      "default": "easeOut"
    },
    "targetOpacity": {
      "type": "number",
      "description": "Final opacity (defaults to current)",
      "minimum": 0,
      "maximum": 1
    }
  },
  "required": ["itemId", "targetMode"]
}

pinepaper_add_interactive_blend

Add interactive blend mode cycling triggered by mouse events.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": { "type": "string" },
    "event": {
      "type": "string",
      "enum": ["hover", "click"],
      "description": "Trigger event type",
      "default": "hover"
    },
    "modes": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Blend modes to cycle through",
      "default": ["normal", "screen"]
    },
    "opacities": {
      "type": "array",
      "items": { "type": "number" },
      "description": "Opacity for each mode",
      "default": [1.0, 0.8]
    }
  },
  "required": ["itemId"]
}

pinepaper_set_group_blend_mode

Set blend mode for all items in a group with optional cascading opacity.

Input Schema:

{
  "type": "object",
  "properties": {
    "groupId": {
      "type": "string",
      "description": "Group ID or item ID of a Paper.js Group"
    },
    "mode": {
      "type": "string",
      "description": "Blend mode to apply to all children"
    },
    "opacity": {
      "type": "number",
      "description": "Group opacity",
      "minimum": 0,
      "maximum": 1
    },
    "cascadeOpacity": {
      "type": "boolean",
      "description": "Multiply child opacity by group opacity",
      "default": false
    }
  },
  "required": ["groupId", "mode"]
}

pinepaper_set_opacity_reaction

Configure automatic blend mode switching based on item opacity thresholds.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": { "type": "string" },
    "thresholds": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "opacity": {
            "type": "number",
            "description": "Opacity threshold (blend mode activates when item opacity <= this value)"
          },
          "blendMode": {
            "type": "string",
            "description": "Blend mode to apply at this threshold"
          }
        },
        "required": ["opacity", "blendMode"]
      },
      "description": "Opacity thresholds sorted from lowest to highest"
    }
  },
  "required": ["itemId", "thresholds"]
}

Example:

{
  "itemId": "item_1",
  "thresholds": [
    { "opacity": 0.2, "blendMode": "screen" },
    { "opacity": 0.5, "blendMode": "multiply" }
  ]
}

When item_1’s opacity drops below 0.2, blend mode switches to “screen”. Between 0.2 and 0.5, it uses “multiply”.


Image Filter Tools

GPU-accelerated image filters for raster items. Filters run on the GPU via WebGL shaders for real-time performance.

pinepaper_apply_image_filter

Apply a single GPU filter to a raster item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Item registry ID of the raster item"
    },
    "filterName": {
      "type": "string",
      "enum": [
        "grayscale", "sepia", "brightness", "contrast", "saturation",
        "invert", "posterize", "hsl", "colorTint", "vignette",
        "edgeDetect", "blur"
      ],
      "description": "Filter to apply"
    },
    "params": {
      "type": "object",
      "description": "Filter-specific parameters (e.g., { \"amount\": 1.5 } for brightness, { \"hue\": 30, \"saturation\": 0.5, \"lightness\": 0.1 } for hsl)"
    }
  },
  "required": ["itemId", "filterName"]
}

Output:

{
  "success": true
}

pinepaper_apply_filter_chain

Apply multiple filters in a single GPU pass for efficient composited effects.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Item registry ID of the raster item"
    },
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "enum": [
              "grayscale", "sepia", "brightness", "contrast", "saturation",
              "invert", "posterize", "hsl", "colorTint", "vignette",
              "edgeDetect", "blur"
            ],
            "description": "Filter name"
          },
          "params": {
            "type": "object",
            "description": "Filter-specific parameters"
          }
        },
        "required": ["name"]
      },
      "description": "Ordered list of filters to apply in sequence"
    }
  },
  "required": ["itemId", "filters"]
}

Output:

{
  "success": true
}

Lasso Tools

Freehand lasso selection for extracting regions from raster images on the canvas.

pinepaper_lasso_activate

Activate lasso mode on an image, enabling freehand selection drawing.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Item registry ID of the raster item to select from"
    }
  },
  "required": ["itemId"]
}

Output:

{
  "success": true,
  "message": "Lasso mode activated"
}

pinepaper_lasso_apply

Apply the current lasso selection to extract the selected region as a new cutout item.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "cutoutId": "item_5"
}

Cutout Style Tools

Apply visual style presets to image cutouts for creative effects.

pinepaper_apply_cutout_style

Apply a visual style preset to a cutout item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Item registry ID of the cutout item"
    },
    "preset": {
      "type": "string",
      "enum": [
        "papercut", "postcard", "sticker", "poster",
        "monochromeCut", "edgeSketch", "warmGlow", "coolTone"
      ],
      "description": "Style preset to apply"
    },
    "options": {
      "type": "object",
      "description": "Optional preset-specific overrides (e.g., { \"borderWidth\": 4, \"shadowColor\": \"#000\" })"
    }
  },
  "required": ["itemId", "preset"]
}

Output:

{
  "success": true
}

pinepaper_get_cutout_styles

List all available cutout style presets with their descriptions.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "presets": [
    { "name": "papercut", "displayName": "Paper Cut", "description": "Rough-edge paper cutout with drop shadow" },
    { "name": "postcard", "displayName": "Postcard", "description": "Rounded corners with white border and stamp texture" },
    { "name": "sticker", "displayName": "Sticker", "description": "Thick white outline with slight tilt and shadow" },
    { "name": "poster", "displayName": "Poster", "description": "High-contrast posterized colors with halftone dots" },
    { "name": "monochromeCut", "displayName": "Monochrome Cut", "description": "Grayscale cutout with sharp edges" },
    { "name": "edgeSketch", "displayName": "Edge Sketch", "description": "Pencil-sketch outline extracted from edges" },
    { "name": "warmGlow", "displayName": "Warm Glow", "description": "Warm color tint with soft vignette" },
    { "name": "coolTone", "displayName": "Cool Tone", "description": "Cool blue-tinted desaturated look" }
  ]
}

View Tools

Control canvas zoom, pan, and viewport fitting.

pinepaper_zoom

Zoom the canvas in or out.

Input Schema:

{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": ["in", "out", "reset", "set"],
      "description": "Zoom action"
    },
    "level": {
      "type": "number",
      "description": "Zoom level (only for action='set'). 1.0 = 100%"
    }
  },
  "required": ["action"]
}

Output:

{
  "success": true,
  "zoomLevel": 1.5
}

pinepaper_pan

Pan the canvas view.

Input Schema:

{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": ["by", "to"],
      "description": "'by' pans by offset, 'to' pans to absolute coordinates"
    },
    "x": { "type": "number", "description": "X offset or coordinate" },
    "y": { "type": "number", "description": "Y offset or coordinate" }
  },
  "required": ["action", "x", "y"]
}

Output:

{
  "success": true
}

pinepaper_fit_view

Fit canvas content into the viewport.

Input Schema:

{
  "type": "object",
  "properties": {
    "mode": {
      "type": "string",
      "enum": ["content", "canvas"],
      "description": "'content' fits all items, 'canvas' fits the canvas bounds"
    },
    "padding": {
      "type": "number",
      "description": "Optional padding in pixels around the content"
    }
  }
}

Output:

{
  "success": true,
  "zoomLevel": 0.85
}

pinepaper_get_view_state

Get current view state (zoom level, scroll position).

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "zoomLevel": 1.2,
  "center": { "x": 400, "y": 300 },
  "bounds": { "x": 0, "y": 0, "width": 800, "height": 600 }
}

Selection Tools

Manage item selection programmatically.

pinepaper_select

Select items by ID, name, or type.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Array of item IDs to select"
    },
    "mode": {
      "type": "string",
      "enum": ["replace", "add", "remove"],
      "default": "replace",
      "description": "'replace' clears existing selection, 'add' adds to it, 'remove' removes from it"
    }
  },
  "required": ["itemIds"]
}

Output:

{
  "success": true,
  "selectedCount": 3
}

pinepaper_select_all

Select all items on the canvas.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "selectedCount": 12
}

pinepaper_deselect_all

Clear all selection.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true
}

pinepaper_get_selection

Get currently selected items.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "items": [
    { "id": "item_1", "type": "text", "name": "Title" },
    { "id": "item_3", "type": "circle", "name": null }
  ]
}

pinepaper_delete_selected

Delete all currently selected items.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "deletedCount": 2
}

Transform Tools

Transform items: nudge, flip, and reorder in stacking order.

pinepaper_nudge

Move selected items by a pixel offset.

Input Schema:

{
  "type": "object",
  "properties": {
    "dx": { "type": "number", "description": "Horizontal offset in pixels" },
    "dy": { "type": "number", "description": "Vertical offset in pixels" }
  },
  "required": ["dx", "dy"]
}

Output:

{
  "success": true
}

pinepaper_flip

Flip selected items horizontally or vertically.

Input Schema:

{
  "type": "object",
  "properties": {
    "direction": {
      "type": "string",
      "enum": ["horizontal", "vertical"],
      "description": "Flip direction"
    }
  },
  "required": ["direction"]
}

Output:

{
  "success": true
}

pinepaper_reorder

Change stacking order of selected items.

Input Schema:

{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": ["bringToFront", "sendToBack", "moveUp", "moveDown"],
      "description": "Stacking order action"
    }
  },
  "required": ["action"]
}

Output:

{
  "success": true
}

Background Tools

Control canvas background color, pattern, or procedural generator.

pinepaper_set_background

Set the canvas background.

Input Schema:

{
  "type": "object",
  "properties": {
    "mode": {
      "type": "string",
      "enum": ["color", "pattern", "generator"],
      "description": "Background mode"
    },
    "color": {
      "type": "string",
      "description": "Background color (hex). Used when mode='color'"
    },
    "pattern": {
      "type": "string",
      "description": "Pattern type name. Used when mode='pattern'"
    },
    "generator": {
      "type": "string",
      "description": "Generator name. Used when mode='generator'"
    },
    "generatorParams": {
      "type": "object",
      "description": "Generator parameters. Used when mode='generator'"
    }
  },
  "required": ["mode"]
}

Output:

{
  "success": true,
  "mode": "color",
  "value": "#1a1a2e"
}

pinepaper_clear_background

Clear the canvas background to transparent.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true
}

pinepaper_get_background

Get current background state.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "mode": "generator",
  "generator": "starfield",
  "params": { "starCount": 200, "twinkle": true }
}

History Tools

Manage undo/redo and edit history.

pinepaper_undo

Undo the last action.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "canUndo": true,
  "canRedo": true
}

pinepaper_redo

Redo the last undone action.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "canUndo": true,
  "canRedo": false
}

pinepaper_get_history_state

Get current history state.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "canUndo": true,
  "canRedo": false,
  "historyLength": 15,
  "currentIndex": 14
}

pinepaper_clear_canvas

Clear the entire canvas (all items, drawings, and background).

Input Schema:

{
  "type": "object",
  "properties": {
    "keepBackground": {
      "type": "boolean",
      "default": false,
      "description": "If true, preserves the background setting"
    }
  }
}

Output:

{
  "success": true
}

Advanced Query Tools

Query items by name, type, position, or custom matchers.

pinepaper_query_items

Query items using flexible matchers.

Input Schema:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Filter by item name (exact or partial match)"
    },
    "type": {
      "type": "string",
      "description": "Filter by item type (e.g., 'text', 'circle', 'Raster')"
    },
    "withinBounds": {
      "type": "object",
      "properties": {
        "x": { "type": "number" },
        "y": { "type": "number" },
        "width": { "type": "number" },
        "height": { "type": "number" }
      },
      "description": "Filter items within a bounding rectangle"
    },
    "hasAnimation": {
      "type": "boolean",
      "description": "Filter by whether item is animated"
    },
    "limit": {
      "type": "number",
      "description": "Maximum number of results"
    }
  }
}

Output:

{
  "success": true,
  "items": [
    {
      "id": "item_1",
      "type": "text",
      "name": "Title",
      "position": { "x": 400, "y": 100 },
      "bounds": { "x": 320, "y": 80, "width": 160, "height": 40 }
    }
  ],
  "count": 1
}

pinepaper_get_item_by_id

Get detailed information about a specific item.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemId": {
      "type": "string",
      "description": "Item registry ID"
    }
  },
  "required": ["itemId"]
}

Output:

{
  "success": true,
  "item": {
    "id": "item_5",
    "type": "text",
    "name": "Heading",
    "position": { "x": 400, "y": 200 },
    "bounds": { "x": 300, "y": 180, "width": 200, "height": 40 },
    "rotation": 0,
    "opacity": 1,
    "visible": true,
    "hasAnimation": true,
    "hasRelations": false,
    "isMasked": false
  }
}

pinepaper_hit_test

Find items at a specific canvas point.

Input Schema:

{
  "type": "object",
  "properties": {
    "x": { "type": "number", "description": "X coordinate" },
    "y": { "type": "number", "description": "Y coordinate" },
    "all": {
      "type": "boolean",
      "default": false,
      "description": "If true, return all items at point (not just topmost)"
    },
    "tolerance": {
      "type": "number",
      "default": 5,
      "description": "Hit test tolerance in pixels"
    }
  },
  "required": ["x", "y"]
}

Output:

{
  "success": true,
  "items": [
    { "id": "item_3", "type": "circle" }
  ]
}

pinepaper_is_empty

Check if the canvas has any content.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "empty": false,
  "itemCount": 8
}

Precomp Tools

Create and manage nested compositions (precomps) with independent local timelines.

pinepaper_create_precomp

Group items into a precomp with an independent timeline.

Input Schema:

{
  "type": "object",
  "properties": {
    "itemIds": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Array of item IDs to include in the precomp"
    },
    "name": {
      "type": "string",
      "description": "Optional name for the precomp"
    },
    "loop": {
      "type": "boolean",
      "default": true,
      "description": "Whether the precomp timeline loops"
    },
    "duration": {
      "type": "number",
      "description": "Precomp timeline duration in seconds"
    }
  },
  "required": ["itemIds"]
}

Output:

{
  "success": true,
  "precompId": "item_20"
}

pinepaper_add_to_precomp

Add an item to an existing precomp.

Input Schema:

{
  "type": "object",
  "properties": {
    "precompId": { "type": "string", "description": "Precomp item ID" },
    "itemId": { "type": "string", "description": "Item to add" }
  },
  "required": ["precompId", "itemId"]
}

Output:

{
  "success": true
}

pinepaper_remove_from_precomp

Remove an item from a precomp.

Input Schema:

{
  "type": "object",
  "properties": {
    "precompId": { "type": "string", "description": "Precomp item ID" },
    "itemId": { "type": "string", "description": "Item to remove" }
  },
  "required": ["precompId", "itemId"]
}

Output:

{
  "success": true
}

Playback Tools

Control keyframe timeline playback.

pinepaper_play_timeline

Start or resume keyframe timeline playback.

Input Schema:

{
  "type": "object",
  "properties": {
    "duration": {
      "type": "number",
      "description": "Timeline duration in seconds. If omitted, uses existing duration."
    },
    "loop": {
      "type": "boolean",
      "default": false,
      "description": "Whether to loop playback"
    }
  }
}

Output:

{
  "success": true,
  "playing": true
}

pinepaper_stop_timeline

Stop timeline playback and reset to start.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "playing": false
}

pinepaper_pause_timeline

Pause timeline playback at current position.

Input Schema:

{
  "type": "object",
  "properties": {}
}

Output:

{
  "success": true,
  "playing": false
}

pinepaper_seek_timeline

Seek to a specific time position.

Input Schema:

{
  "type": "object",
  "properties": {
    "time": {
      "type": "number",
      "description": "Time position in seconds (0 to duration)"
    }
  },
  "required": ["time"]
}

Output:

{
  "success": true,
  "currentTime": 1.5
}

3D Projection Tools

Create and manipulate 3D objects on the 2D canvas using PinePaper’s standalone 3D projection library. Objects are rendered as depth-sorted, lit polygons projected through configurable camera and projection systems.

Architecture: The 3D library (js/3d/) is zero-dependency and outputs renderer-agnostic polygon descriptors. GPU acceleration (WebGPU/WebGL2) is automatic for scenes above 150 faces.

pinepaper_create_3d_object

Create a 3D primitive projected onto the 2D canvas with simulated lighting and depth-sorted face rendering.

Input Schema:

{
  "type": "object",
  "properties": {
    "objectType": {
      "type": "string",
      "enum": ["cube", "sphere", "cylinder", "torus", "cone"],
      "description": "Type of 3D primitive to create"
    },
    "x": {
      "type": "number",
      "description": "World X position (default: 0)"
    },
    "y": {
      "type": "number",
      "description": "World Y position (default: 0)"
    },
    "z": {
      "type": "number",
      "description": "World Z position (default: 0)"
    },
    "color": {
      "type": "string",
      "description": "Face color as hex string (default: '#cccccc')"
    },
    "size": {
      "type": "number",
      "description": "Cube size (cube only, default: 1)"
    },
    "radius": {
      "type": "number",
      "description": "Radius (sphere, cylinder, torus, cone; default: 0.5)"
    },
    "height": {
      "type": "number",
      "description": "Height (cylinder, cone; default: 1)"
    },
    "tube": {
      "type": "number",
      "description": "Tube radius (torus only; default: 0.2)"
    },
    "rotationX": {
      "type": "number",
      "description": "X rotation in degrees (default: 0)"
    },
    "rotationY": {
      "type": "number",
      "description": "Y rotation in degrees (default: 0)"
    },
    "rotationZ": {
      "type": "number",
      "description": "Z rotation in degrees (default: 0)"
    },
    "scale": {
      "type": "number",
      "description": "Uniform scale factor (default: 1)"
    },
    "animationType": {
      "type": "string",
      "enum": ["rotate"],
      "description": "Animation type (optional)"
    },
    "animationSpeed": {
      "type": "number",
      "description": "Rotation speed multiplier (default: 1)"
    }
  },
  "required": ["objectType"]
}

Output:

{
  "success": true,
  "itemId": "item_42",
  "objectType": "cube",
  "faces": 6,
  "message": "Created 3D cube with 6 faces"
}

Face Counts by Primitive:

Primitive Default Faces Key Parameters
cube 6 quads size
sphere ~96 triangles radius, widthSegments (12), heightSegments (8)
cylinder ~34 radius, height, segments (16)
torus ~192 radius, tube, radialSegments (12), tubularSegments (16)
cone ~17 radius, height, segments (16)

pinepaper_create_glossy_sphere

Create a glossy 2D sphere effect using layered radial gradients with shadow. This is a purely 2D effect (no 3D projection) that simulates a shiny sphere appearance.

Input Schema:

{
  "type": "object",
  "properties": {
    "x": {
      "type": "number",
      "description": "X position on canvas (default: center)"
    },
    "y": {
      "type": "number",
      "description": "Y position on canvas (default: center)"
    },
    "radius": {
      "type": "number",
      "description": "Sphere radius in pixels (default: 50)"
    },
    "color": {
      "type": "string",
      "description": "Base sphere color as hex (default: '#4a9eff')"
    },
    "lightDirection": {
      "type": "string",
      "enum": ["top-left", "top-right", "top", "left", "right", "bottom-left", "bottom-right"],
      "description": "Direction of the light source (default: 'top-left')"
    },
    "glossiness": {
      "type": "number",
      "minimum": 0,
      "maximum": 1,
      "description": "Glossiness level from 0 to 1 (default: 0.7)"
    },
    "castShadow": {
      "type": "boolean",
      "description": "Whether to cast a shadow (default: true)"
    },
    "shadowBlur": {
      "type": "number",
      "description": "Shadow blur amount in pixels (default: 15)"
    }
  }
}

Output:

{
  "success": true,
  "itemId": "item_43",
  "message": "Created glossy sphere with radius 60"
}

pinepaper_set_3d_projection

Set the 3D scene projection type. Affects how 3D objects are rendered on the 2D canvas.

Input Schema:

{
  "type": "object",
  "properties": {
    "projectionType": {
      "type": "string",
      "enum": ["perspective", "orthographic", "isometric", "cabinet", "cavalier"],
      "description": "Projection type"
    },
    "fov": {
      "type": "number",
      "description": "Field of view in degrees (perspective only; default: 60)"
    },
    "aspect": {
      "type": "number",
      "description": "Aspect ratio (perspective only; default: 1)"
    },
    "near": {
      "type": "number",
      "description": "Near clipping plane (perspective/orthographic; default: 0.1 or -500)"
    },
    "far": {
      "type": "number",
      "description": "Far clipping plane (perspective/orthographic; default: 1000 or 500)"
    },
    "width": {
      "type": "number",
      "description": "View width (orthographic only; default: 400)"
    },
    "height": {
      "type": "number",
      "description": "View height (orthographic only; default: 400)"
    },
    "scale": {
      "type": "number",
      "description": "Scale factor (isometric only; default: 1)"
    },
    "angle": {
      "type": "number",
      "description": "Shear angle in degrees (cabinet/cavalier; default: 45)"
    },
    "depthScale": {
      "type": "number",
      "description": "Depth scale factor (cabinet only; default: 0.5)"
    }
  },
  "required": ["projectionType"]
}

Output:

{
  "success": true,
  "projectionType": "isometric",
  "message": "Set 3D projection to isometric"
}

Projection Comparison:

Projection Depth Reduction Parallel Lines Use Case
perspective Yes (1/z) No Realistic visualization
orthographic No Yes Technical drawings
isometric No Yes Games, infographics
cabinet Half (0.5) Yes Technical illustration
cavalier No Yes Simple 3D diagrams

pinepaper_set_3d_camera

Set the 3D camera position and look-at target. Defines the viewpoint from which 3D objects are rendered.

Input Schema:

{
  "type": "object",
  "properties": {
    "positionX": {
      "type": "number",
      "description": "Camera X position in world space (default: 0)"
    },
    "positionY": {
      "type": "number",
      "description": "Camera Y position in world space (default: 0)"
    },
    "positionZ": {
      "type": "number",
      "description": "Camera Z position in world space (default: 5)"
    },
    "targetX": {
      "type": "number",
      "description": "Look-at target X (default: 0)"
    },
    "targetY": {
      "type": "number",
      "description": "Look-at target Y (default: 0)"
    },
    "targetZ": {
      "type": "number",
      "description": "Look-at target Z (default: 0)"
    },
    "upX": {
      "type": "number",
      "description": "Up vector X (default: 0)"
    },
    "upY": {
      "type": "number",
      "description": "Up vector Y (default: 1)"
    },
    "upZ": {
      "type": "number",
      "description": "Up vector Z (default: 0)"
    }
  }
}

Output:

{
  "success": true,
  "position": { "x": 3, "y": 2, "z": 5 },
  "target": { "x": 0, "y": 0, "z": 0 },
  "message": "Camera positioned at (3, 2, 5) looking at origin"
}

Implementation Notes

  1. Item IDs: All items are referenced by item.data.registryId (e.g., “item_1”)
  2. Positions: Canvas coordinates, (0,0) is top-left
  3. Colors: Hex (#RRGGBB), RGB, or named colors
  4. Async Operations: Generators may be async, return promises
  5. State Management: Call historyManager.saveState() after batches
  6. Relations: Process automatically each frame, no manual updates needed
  7. Rigging: FK/IK solving runs automatically in the update loop before relations; bone transforms are pre-computed
  8. Blending: Transitions process automatically each frame; blend mode snaps at transition midpoint while opacity cross-fades smoothly
  9. View Tools: Zoom level is relative (1.0 = 100%); pan coordinates are in canvas space
  10. Selection: Selection changes dispatch selectionChanged events; use deselect_all before batch operations to avoid side effects
  11. History: Undo/redo automatically saves/restores all canvas state including relations and animations
  12. 3D Projection: 3D objects are rendered as 2D polygons via a 5-stage pipeline (transform → cull → shade → project → sort). GPU acceleration (WebGPU/WebGL2) is automatic above 150 faces. Scene budget: ~500 faces max.