goatedit-mcp 1.1.4 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19194,7 +19194,13 @@ var TEXT_STYLE_PROPS = {
19194
19194
  textSticker: { type: "string", enum: ["ghost", "arrow", "pen", "star", "flame"], description: "Small sticker drawn beside the accent word." },
19195
19195
  textLayoutMode: { type: "string", enum: ["side-grid", "luxury-stack", "editorial-hero", "slanted-red", "double-hero"], description: "Editorial layout engine for multi-word titles." },
19196
19196
  posX: num("Horizontal position as a fraction of the frame, 0..1. 0.5 is centre."),
19197
- posY: num("Vertical position as a fraction of the frame, 0..1. 0.5 is centre.")
19197
+ posY: num("Vertical position as a fraction of the frame, 0..1. 0.5 is centre."),
19198
+ path: {
19199
+ type: ["object", "null"],
19200
+ description: "Set the text along a curve instead of in a block: { points: [[x, y], ...] (fractions of the frame, at least two; anchors without handles are smoothed into a curve through them, and points may lie outside 0..1 so a ribbon runs off the frame), ribbonColor? (paints a band along the path behind the letters), ribbonWidth? (px @1080p, default 380), waveLength? (px between wave crests, default 900), waveSpeed? (crests per second, default 0.5) }. The clip's position moves the whole path. null returns the text to a block. Text animations do not apply along a path; animate pathOffset and pathWave with set_keyframes (as textPathOffset / textPathWave) instead."
19201
+ },
19202
+ pathOffset: num("Where the middle of the text sits along its path, 0 at the start, 1 at the end (default 0.5). Below 0 or above 1 runs the words off the ends, so keyframing it from -0.3 to 0.5 slides a word in along its ribbon."),
19203
+ pathWave: num("Height of the wave travelling down the path, px @1080p (default 0, flat). It bends the ribbon and the letters together.")
19198
19204
  };
19199
19205
  var BASE_TOOLS = [
19200
19206
  {
@@ -19338,16 +19344,38 @@ var BASE_TOOLS = [
19338
19344
  },
19339
19345
  {
19340
19346
  name: "create_sequence",
19341
- description: "Make a new, empty sequence with the project's frame size and rate. By default it opens, so the edits that follow build it; pass open: false to stay where you are and place it later with add_sequence_clip. Returns its id.",
19347
+ description: "Make a new, empty sequence. It takes the project's frame size and rate unless width, height or fps say otherwise, and can be given a fixed length. By default it opens, so the edits that follow build it; pass open: false to stay where you are and place it later with add_sequence_clip. Returns its id.",
19342
19348
  inputSchema: {
19343
19349
  type: "object",
19344
19350
  properties: {
19345
19351
  name: str("Name for the sequence."),
19346
- open: { type: "boolean", description: "Open it for editing. Default true." }
19352
+ open: { type: "boolean", description: "Open it for editing. Default true." },
19353
+ width: num("Frame width in pixels."),
19354
+ height: num("Frame height in pixels."),
19355
+ fps: num("Frame rate."),
19356
+ backgroundColor: str('Background colour, e.g. "#000000".'),
19357
+ length: num("A fixed length in seconds: playback and export stop there whatever the clips do. 0 goes back to following the last clip.")
19347
19358
  }
19348
19359
  },
19349
19360
  method: "createSequence"
19350
19361
  },
19362
+ {
19363
+ name: "update_sequence",
19364
+ description: "Rename a sequence or change its own frame size, frame rate, background or fixed length \u2014 the Sequence Settings dialog. Only the fields given change; clips are not rescaled, so check framing with render_preview_frame after a size change. Defaults to the open sequence.",
19365
+ inputSchema: {
19366
+ type: "object",
19367
+ properties: {
19368
+ sequenceId: str("Sequence id from list_sequences. Defaults to the open one."),
19369
+ name: str("New name."),
19370
+ width: num("Frame width in pixels."),
19371
+ height: num("Frame height in pixels."),
19372
+ fps: num("Frame rate."),
19373
+ backgroundColor: str('Background colour, e.g. "#000000".'),
19374
+ length: num("A fixed length in seconds: playback and export stop there whatever the clips do. 0 goes back to following the last clip.")
19375
+ }
19376
+ },
19377
+ method: "updateSequence"
19378
+ },
19351
19379
  {
19352
19380
  name: "open_sequence",
19353
19381
  description: "Open a sequence for editing \u2014 the same as clicking its tab. Every tool then reads and edits that sequence; clip and track ids from the one you left no longer apply, so call get_timeline next. Open the previous one again to go back out of a nest.",
@@ -19466,7 +19494,7 @@ var BASE_TOOLS = [
19466
19494
  inputSchema: {
19467
19495
  type: "object",
19468
19496
  properties: {
19469
- url: str("Publicly reachable https URL of the video, audio or image."),
19497
+ url: str("Publicly reachable https URL of the video, audio or image, or a `magnific:<id>` url from search_stock."),
19470
19498
  name: str("Display name for the bin."),
19471
19499
  type: { type: "string", enum: ["video", "audio", "image"], description: "Kind of media." },
19472
19500
  duration: num("Duration in seconds. Required for video and audio, but treated as a hint \u2014 the probe on import overrides it when they disagree."),
@@ -19524,6 +19552,7 @@ var BASE_TOOLS = [
19524
19552
  type: "object",
19525
19553
  properties: {
19526
19554
  text: str("The text to display."),
19555
+ name: str("The layer's name in the timeline. Defaults to the text itself."),
19527
19556
  duration: num("How long the card stays on screen, in seconds."),
19528
19557
  startTime: num("Where it starts on the timeline, in seconds. Defaults to 0."),
19529
19558
  trackId: str("Target video track. Defaults to the topmost one that is free across the card\u2019s span, creating a new track above everything if none is free."),
@@ -19613,6 +19642,62 @@ var BASE_TOOLS = [
19613
19642
  },
19614
19643
  method: "updateShapeClip"
19615
19644
  },
19645
+ {
19646
+ name: "create_3d_shape",
19647
+ description: 'Make a 3D shape on the timeline \u2014 a ball, ring, pill, block, can, cone or blob \u2014 with no file to import. It is a 3D model clip: set_clip_effect on its "model3d" effect turns, spins, frames and lights it, and `material` gives it a look (Glass, Chrome, Iridescent, Candy Paint, Pearl\u2026), which keeps the shape\'s own colour or gradient. Position, scale, keyframes and parenting work as on any clip. Drawn at the sequence size on a transparent background, so it stacks over anything.',
19648
+ inputSchema: {
19649
+ type: "object",
19650
+ properties: {
19651
+ shape: { type: "string", enum: ["sphere", "torus", "capsule", "box", "cylinder", "cone", "blob", "pile"], description: `sphere (ball), torus (ring), capsule (pill), box (block), cylinder (can), cone, blob, or pile: many balls that burst from the middle and settle in a heap over 3 seconds (its "Burst" animation, which then holds still; delay it with the model3d effect's animOffset, slow it with animSpeed).` },
19652
+ color: str('A solid colour, "#rrggbb". Given on its own it turns any gradient off. Defaults to near-white.'),
19653
+ gradient: { type: "string", enum: ["none", "around", "vertical", "diagonal"], description: 'Paint `colors` across the shape: "around" runs round its axis (the rainbow ring), "vertical" top to bottom, "diagonal" corner to corner. The gradient is in the mesh, so it turns with the shape and shows through glass.' },
19654
+ colors: { type: "array", items: { type: "string" }, description: '2\u20136 "#rrggbb" colours, spread evenly, for the gradient. "around" closes back on the first colour by itself. For a pile, 1\u20136 colours the balls take turns from.' },
19655
+ roughness: num("0 mirror-smooth \u2026 1 chalky. Defaults to 0.22 (glossy plastic)."),
19656
+ metalness: num("0 plastic \u2026 1 metal. Defaults to 0."),
19657
+ proportion: num("Ring: tube thickness as a share of its radius, 0.05\u20130.9. Pill, can, cone: length against width, 0\u20134. Blob: lumpiness, 0\u20131."),
19658
+ size: { type: "array", items: { type: "number" }, description: "Block only: [width, height, depth], relative, 0.1\u20134 each." },
19659
+ round: num("Block only: edge rounding, 0 sharp \u2026 1 fully round."),
19660
+ seed: num("Blob: which blob. Pile: how the balls fall. The same seed gives the same result."),
19661
+ count: num("Pile only: how many balls, 3\u2013150. Defaults to 40."),
19662
+ arrange: { type: "string", enum: ["heap", "burst"], description: 'Pile only: "heap" (default) \u2014 the balls fall and settle in a heap; "burst" \u2014 they fly out every way and hang in the air in a wide cloud, for an explosion of balls around something.' },
19663
+ material: str("A look by name: Original (default, the colour above), Chrome, Gold, Glass, Clay, Toon, Plastic, Matte, Iridescent, Wireframe, X-Ray Glow, Hologram, Crystal, Holographic, Candy Paint, Pearl."),
19664
+ rotateX: num("Starting tilt, degrees."),
19665
+ rotateY: num("Starting turn, degrees."),
19666
+ rotateZ: num("Starting roll, degrees."),
19667
+ spin: num("Turn while it plays, degrees per second."),
19668
+ duration: num("Seconds on screen. Defaults to 5."),
19669
+ startTime: num("Where it starts, seconds. Defaults to 0."),
19670
+ trackId: str('Video track, or "__new_video__" (default) for one free across the span.'),
19671
+ name: str("Display name.")
19672
+ },
19673
+ required: ["shape"]
19674
+ },
19675
+ method: "addShape3D"
19676
+ },
19677
+ {
19678
+ name: "update_3d_shape",
19679
+ description: "Change a 3D shape made with create_3d_shape \u2014 its kind, colour, gradient, gloss or proportions \u2014 keeping the clip, its keyframes and effects. Only the fields given change. Every clip using the same shape changes with it.",
19680
+ inputSchema: {
19681
+ type: "object",
19682
+ properties: {
19683
+ clipId: CLIP_ID,
19684
+ shape: { type: "string", enum: ["sphere", "torus", "capsule", "box", "cylinder", "cone", "blob", "pile"], description: `sphere (ball), torus (ring), capsule (pill), box (block), cylinder (can), cone, blob, or pile: many balls that burst from the middle and settle in a heap over 3 seconds (its "Burst" animation, which then holds still; delay it with the model3d effect's animOffset, slow it with animSpeed).` },
19685
+ color: str('A solid colour, "#rrggbb". Given on its own it turns any gradient off. Defaults to near-white.'),
19686
+ gradient: { type: "string", enum: ["none", "around", "vertical", "diagonal"], description: 'Paint `colors` across the shape: "around" runs round its axis (the rainbow ring), "vertical" top to bottom, "diagonal" corner to corner. The gradient is in the mesh, so it turns with the shape and shows through glass.' },
19687
+ colors: { type: "array", items: { type: "string" }, description: '2\u20136 "#rrggbb" colours, spread evenly, for the gradient. "around" closes back on the first colour by itself. For a pile, 1\u20136 colours the balls take turns from.' },
19688
+ roughness: num("0 mirror-smooth \u2026 1 chalky. Defaults to 0.22 (glossy plastic)."),
19689
+ metalness: num("0 plastic \u2026 1 metal. Defaults to 0."),
19690
+ proportion: num("Ring: tube thickness as a share of its radius, 0.05\u20130.9. Pill, can, cone: length against width, 0\u20134. Blob: lumpiness, 0\u20131."),
19691
+ size: { type: "array", items: { type: "number" }, description: "Block only: [width, height, depth], relative, 0.1\u20134 each." },
19692
+ round: num("Block only: edge rounding, 0 sharp \u2026 1 fully round."),
19693
+ seed: num("Blob: which blob. Pile: how the balls fall. The same seed gives the same result."),
19694
+ count: num("Pile only: how many balls, 3\u2013150. Defaults to 40."),
19695
+ arrange: { type: "string", enum: ["heap", "burst"], description: 'Pile only: "heap" (default) \u2014 the balls fall and settle in a heap; "burst" \u2014 they fly out every way and hang in the air in a wide cloud, for an explosion of balls around something.' }
19696
+ },
19697
+ required: ["clipId"]
19698
+ },
19699
+ method: "updateShape3D"
19700
+ },
19616
19701
  {
19617
19702
  name: "add_null",
19618
19703
  description: "Add a Null Object: an invisible handle that other clips are parented to (set_parent). Move, scale or rotate the null and everything under it follows, orbiting its position \u2014 the After Effects way to group a polaroid with its caption, or make a whole layout drift as one.",
@@ -19701,24 +19786,101 @@ var BASE_TOOLS = [
19701
19786
  },
19702
19787
  {
19703
19788
  name: "join_scenes",
19704
- description: "Join two scenes at a cut so the edit flows instead of cutting: push (one camera move across a shared canvas \u2014 the outgoing scene speeds out and the incoming arrives at the same speed, so the cut falls mid-motion), zoomThrough (push into one element of the outgoing scene until it fills the frame; the incoming scene opens out of it), or matchCut (a layer of the incoming scene starts exactly where a layer of the outgoing one was \u2014 position, size, turn, through parents, 3D models included \u2014 then settles into its own place). push and zoomThrough add a camera null per side and parent that side's top-level clips to it, so every layer stays editable and the camera's keyframes can be tuned afterwards. at is the cut: outgoing clips end there and incoming clips start there.",
19789
+ description: "Join two scenes at a cut so the edit flows instead of cutting: push (one camera move across a shared canvas \u2014 the outgoing scene speeds out and the incoming arrives at the same speed, so the cut falls mid-motion), zoomThrough (push into one element of the outgoing scene until it fills the frame; the incoming scene opens out of it), or morph (every pair of layers at once, Smart Animate style: each incoming layer starts on the drawn pixels of its outgoing partner \u2014 a tag inside a full-frame snippet counts as the tag \u2014 and stretches and slides into place, pairs staggered left to right), or matchCut (a layer of the incoming scene starts exactly where a layer of the outgoing one was \u2014 position, size, turn, through parents, 3D models included \u2014 then settles into its own place). push and zoomThrough add a camera null per side and parent that side's top-level clips to it, so every layer stays editable and the camera's keyframes can be tuned afterwards. at is the cut: outgoing clips end there and incoming clips start there.",
19705
19790
  inputSchema: {
19706
19791
  type: "object",
19707
19792
  properties: {
19708
19793
  at: num("The cut time in seconds."),
19709
- type: { type: "string", enum: ["push", "zoomThrough", "matchCut"], description: "Which join." },
19794
+ type: { type: "string", enum: ["auto", "push", "zoomThrough", "matchCut", "morph"], description: "Which join. auto picks one from what is on each side: morph when incoming layers are named after outgoing ones and not animated yet, a push in the outgoing scene's own direction when it is already moving into the cut, a zoom through one small element near the middle, else a push \u2014 and says why in `picked`." },
19710
19795
  duration: num("Seconds the move takes on each side of the cut. Default 0.4."),
19711
19796
  direction: { type: "string", enum: ["left", "right", "up", "down"], description: "push: which way the picture travels. Default left." },
19712
19797
  clipId: str("zoomThrough: the element of the outgoing scene to fly into."),
19713
19798
  zoom: num("zoomThrough: how far in the outgoing camera goes. Default: until the element overfills the frame."),
19714
19799
  inZoom: num("zoomThrough: scale the incoming scene opens from. Default 1.8."),
19715
19800
  fromClipId: str("matchCut: the outgoing layer to match."),
19716
- toClipId: str("matchCut: the incoming layer that takes its place.")
19801
+ toClipId: str("matchCut: the incoming layer that takes its place."),
19802
+ pairs: {
19803
+ type: "array",
19804
+ items: { type: "object" },
19805
+ description: 'morph: [{ from, to }] clip ids \u2014 each incoming layer starts on its outgoing partner. Omit to pair automatically: layers whose names end in the same word ("S2 tag New" \u2192 "S2 block New"), then the rest left to right. Full-frame grounds are left out.'
19806
+ },
19807
+ stagger: num("morph: seconds between one pair starting and the next, left to right. Default 0.04.")
19717
19808
  },
19718
19809
  required: ["at", "type"]
19719
19810
  },
19720
19811
  method: "joinScenes"
19721
19812
  },
19813
+ {
19814
+ name: "animate_clip",
19815
+ description: "Give one layer a named move from the motion recipe library, already eased, timed and overshot by the motion principles, relative to where the layer rests (it lands on its own position and scale). Entrances: fadeIn, fadeUp, popIn, slideIn, maskReveal (wiped on behind a soft edge), riseFromLine (rises from behind its own baseline \u2014 the title reveal), blurIn (2D only), zoomIn, dropIn (falls, squashes, springs back), growIn (lines and bars), spinIn. Exits (end on the clip's last frame, or `delay` before it): fadeOut, slideOut (pulls back first, then away), popOut, maskHide, blurOut. Between them: hold (a slow drift after landing, so nothing freezes). Through the whole clip: drift (slow push-in for grounds), float (gentle bob). Overshoots are real damped springs. Don't use on text clips: text animates with set_text_animation. An entrance replaces the keys in its own window only, so an entrance and an exit stack. Prefer animate_scene for a whole scene.",
19816
+ inputSchema: {
19817
+ type: "object",
19818
+ properties: {
19819
+ clipId: str("The layer to animate."),
19820
+ recipe: {
19821
+ type: "string",
19822
+ enum: ["fadeIn", "fadeUp", "popIn", "slideIn", "maskReveal", "riseFromLine", "blurIn", "zoomIn", "dropIn", "growIn", "spinIn", "fadeOut", "slideOut", "popOut", "maskHide", "blurOut", "hold", "drift", "float"],
19823
+ description: "The move."
19824
+ },
19825
+ style: { type: "string", enum: ["smooth", "snappy", "bouncy"], description: "The feel: smooth (no overshoot, 0.6s), snappy (hard ease-out, small overshoot, 0.4s), bouncy (10% overshoot, 0.55s). Default smooth. Use one feel for a whole video." },
19826
+ delay: num("Entrances: seconds into the clip before the move starts. Exits: seconds before the clip ends that the layer is gone, so a group leaves in turn. Default 0."),
19827
+ from: num("hold: clip-relative second the drift starts (where the entrance lands)."),
19828
+ to: num("hold: clip-relative second it ends (where the exit starts). Default the clip end."),
19829
+ depth: num("hold: how much it drifts \u2014 1 for the hero, 0.4\u20130.6 for what sits behind it."),
19830
+ motionBlur: bool("Smear fast travel with a camera-shutter motion blur (2D layers). Draws once where nothing moves."),
19831
+ arc: num("slideIn, slideOut, dropIn: travel on a curve \u2014 how far the path bows toward the middle of the frame, as a fraction of the travel. 0.3 is gentle. For pictures; keep type and bars straight."),
19832
+ anticipate: bool("fadeOut: a small lift the other way before it fades, for big layers."),
19833
+ length: num("Seconds the move takes. Default by style."),
19834
+ direction: { type: "string", enum: ["left", "right", "up", "down"], description: "Which way the layer travels (slideIn, slideOut, maskReveal, maskHide), or the axis growIn grows on." },
19835
+ distance: num("Travel as a fraction of the frame height. Default by style (0.04\u20130.08).")
19836
+ },
19837
+ required: ["clipId", "recipe"]
19838
+ },
19839
+ method: "animateClip"
19840
+ },
19841
+ {
19842
+ name: "animate_scene",
19843
+ description: "Animate a whole scene the way a motion designer would, in one call. Each layer gets a role from what it draws \u2014 ground (covers the frame: a slow drift), hero (the one thing the scene is about: enters first and biggest), support (staggered outward from the hero), text, detail (small marks, popping in last), follower (parented to a picture: arrives a beat after it) \u2014 and a move and start time from its role, its size, the scene's length and the feel, so the scene speaks one motion language. Text always gets a text animation (letters or words), never a block move; pictures get keyframed recipes. Moves travel the way the scene's joins push (flow). With music on the timeline the lead lands on a beat (onBeat). Pictures travel on arcs, type and bars straight. Between the entrance and the exit every picture keeps a slow drift, deeper for the hero (hold). Layers leave last in, first out, the way the next scene comes in; big layers gather before a fade-out. Moves that would cross another layer are swapped for ones that stay in place (note). Layers that already move are left alone unless replace is true. A scene runs between two cuts; at picks it (default the playhead), all does every scene. Returns what each layer got. Follow with lint_motion to join the cuts.",
19844
+ inputSchema: {
19845
+ type: "object",
19846
+ properties: {
19847
+ at: num("A time inside the scene to animate. Default: the playhead."),
19848
+ all: bool("Animate every scene in the sequence."),
19849
+ style: { type: "string", enum: ["smooth", "snappy", "bouncy"], description: "The feel, for every layer. Default smooth." },
19850
+ replace: bool("Re-animate layers that already move, replacing their entrance (and exit if they leave early)."),
19851
+ flow: { type: "string", enum: ["left", "right", "up", "down"], description: "The way moves travel. Default: the way the scene's join camera moves, else up." },
19852
+ pace: num("Spacing of the cascade: 0.6 tight, 1 normal (default), 1.6 loose."),
19853
+ hold: bool("Keep a slow drift on every picture between its entrance and its exit. Default true."),
19854
+ beats: bool("With music on the timeline (beat markers, or audio clips), move the cascade so the lead lands on the nearest beat. Default true."),
19855
+ dryRun: bool("Return the plan without changing anything.")
19856
+ }
19857
+ },
19858
+ method: "animateScene"
19859
+ },
19860
+ {
19861
+ name: "describe_motion",
19862
+ description: "The motion design rules to animate by \u2014 easing curves, durations, stagger, overshoot, hierarchy, holds and reading time, which join to use between scenes \u2014 the same numbers lint_motion checks. Read it before animating a sequence.",
19863
+ inputSchema: { type: "object", properties: {} },
19864
+ method: "describeMotion"
19865
+ },
19866
+ {
19867
+ name: "lint_motion",
19868
+ description: "Check the open sequence's animation the way a motion designer would: still cuts (the picture jumps instead of moving through the change), linear moves (no easing), several layers making the same entrance on one frame (no stagger), moves too fast to follow, and text cut away before it can be read. Each finding has a message and, when the fix is mechanical, `fix`: [method, params] calls to run in order, one call each (run_tools), then lint again. Applying every fix is the one-click polish.",
19869
+ inputSchema: {
19870
+ type: "object",
19871
+ properties: {
19872
+ from: num("Only findings from this time, seconds."),
19873
+ to: num("Only findings up to this time, seconds.")
19874
+ }
19875
+ },
19876
+ method: "lintMotion"
19877
+ },
19878
+ {
19879
+ name: "list_cuts",
19880
+ description: "Every cut in the open sequence \u2014 a time where layers end and others start together \u2014 with what leaves, what arrives, and whether the picture moves through it (a camera move, or layers moving on both sides) or it jumps (a hard cut, a still frame before an entrance, an exit before a still cut). `stillCuts` lists the ones that jump. Read it before joining scenes, and again after.",
19881
+ inputSchema: { type: "object", properties: {} },
19882
+ method: "listCuts"
19883
+ },
19722
19884
  {
19723
19885
  name: "create_3d_object",
19724
19886
  description: "Make a word, a logo or an SVG solid: extruded to a depth with rounded edges and lit like a 3D model, as its own clip with nothing around it (no backdrop), so it floats over whatever is beneath. Give text (drawn in font/weight/color) or mediaFileId of a transparent PNG or an SVG in the bin (a photo needs remove_background first). spins turns it whole times over the clip; rotateX/Y/Z pose it. It is a showcase clip: describe_effect showcase lists its looks (chrome, glass\u2026), lighting and side colour, set with set_clip_effect.",
@@ -20100,9 +20262,11 @@ var BASE_TOOLS = [
20100
20262
  "orbitStartAngle",
20101
20263
  "pathTrimStart",
20102
20264
  "pathTrimEnd",
20103
- "pathTrimOffset"
20265
+ "pathTrimOffset",
20266
+ "textPathOffset",
20267
+ "textPathWave"
20104
20268
  ],
20105
- description: "Property to animate. posX/posY and opacity are 0..1 fractions, rotation is degrees, scaleX/scaleY are multipliers (1 = unchanged), pathTrimEnd 0\u21921 draws a pen stroke on."
20269
+ description: "Property to animate. posX/posY and opacity are 0..1 fractions, rotation is degrees, scaleX/scaleY are multipliers (1 = unchanged), pathTrimEnd 0\u21921 draws a pen stroke on, textPathOffset slides text along its path (0..1) and textPathWave is the height of the wave bending it (px @1080p)."
20106
20270
  },
20107
20271
  keyframes: {
20108
20272
  type: "array",
@@ -20124,7 +20288,7 @@ var BASE_TOOLS = [
20124
20288
  clipId: CLIP_ID,
20125
20289
  type: {
20126
20290
  type: "string",
20127
- description: "Effect type: blur, invert, hue, saturation, brightness, contrast, exposure, grayscale, sepia, gradientMap, vignette, filmGrain, flicker, posterizeTime, lensDistortion, chromaticAberration, lensFlare, liquidGlass, opacityFx, colorCorrection, depthMap, gradientMap, glow, pixelDissolve, motionBlur, dropShadow, reflection, colorama, outline, echo, flutedGlass, lightRays, halftone, datamosh, roughenEdges, filmStock, halation, starGlow, thermal, colorBalance, duotone, levels, monochrome, channelMixer, dither, threshold, lensBlur, directionalBlur, spinBlur, zoomBlur, sharpen, cameraShake, bulge, twirl, ripple, waveWarp, polarCoords, turbulentDisplace, elasticGrid, gridSplit, cubify, glitch, vhs, ntsc, crtScreen, ledScreen, rgbSplit, jpegGlitch, ascii, macpaint, modulation, stripe, risograph, emboss, bevel, inkBleed, paperTexture, paperCutout, crossHatch, scatter, blobTracker, edgeGlow, plus transform, layer3d, model3d and showcase. Call describe_effect with a type for its parameters, their ranges and what they do before setting anything but the obvious. An unknown name comes back with the full list."
20291
+ description: "Effect type: blur, invert, hue, saturation, brightness, contrast, exposure, grayscale, sepia, gradientMap, vignette, filmGrain, flicker, posterizeTime, lensDistortion, chromaticAberration, lensFlare, liquidGlass, opacityFx, colorCorrection, depthMap, gradientMap, glow, pixelDissolve, motionBlur, dropShadow, reflection, colorama, outline, echo, flutedGlass, lightRays, halftone, datamosh, roughenEdges, filmStock, halation, starGlow, thermal, colorBalance, duotone, levels, monochrome, channelMixer, dither, threshold, lensBlur, directionalBlur, spinBlur, zoomBlur, sharpen, cameraShake, bulge, twirl, ripple, waveWarp, polarCoords, turbulentDisplace, elasticGrid, gridSplit, cubify, glitch, vhs, ntsc, crtScreen, ledScreen, rgbSplit, jpegGlitch, ascii, macpaint, modulation, stripe, risograph, emboss, bevel, inkBleed, paperTexture, paperCutout, crossHatch, scatter, blobTracker, edgeGlow, pageTurn, lightSweep, deepGlow, twister, fill, grid, repeater, plus transform, layer3d, model3d and showcase. Call describe_effect with a type for its parameters, their ranges and what they do before setting anything but the obvious. An unknown name comes back with the full list."
20128
20292
  },
20129
20293
  params: {
20130
20294
  type: "object",
@@ -20229,6 +20393,7 @@ var BASE_TOOLS = [
20229
20393
  unit: { type: "string", enum: ["letter", "word", "line"], description: "What the animation steps through." },
20230
20394
  durationIn: num("Seconds for one unit's entrance to complete."),
20231
20395
  stagger: num("Seconds between consecutive units starting. 0 moves them together."),
20396
+ delay: num("Seconds into the clip before the first unit starts. Default 0."),
20232
20397
  distance: num("Slide or offset distance in pixels @1080p, for the slide/spring/unfold presets."),
20233
20398
  highlightColor: str('Highlight colour for the karaoke-style presets and the bar of blockReveal, e.g. "#ff2d55".'),
20234
20399
  order: { type: "string", enum: ["forward", "reverse", "center", "edges", "random"], description: "Which unit goes first. Defaults to reading order." },
@@ -20272,7 +20437,7 @@ var BASE_TOOLS = [
20272
20437
  },
20273
20438
  {
20274
20439
  name: "search_stock",
20275
- description: "Search Pexels for stock footage and stills, through the editor's own proxy \u2014 the API key is held server-side, so no key is needed here and the public api.pexels.com endpoint must not be called directly. Results come back with one chosen encode each: the smallest that still covers the project width, because anything larger spends download and decode on pixels the frame discards. Pass a result's `url` straight to add_media_file to bring it into the bin; the browser downloads it itself, so the bytes never cross this bridge. Orientation defaults to the shape of the project, which is what keeps portrait projects from filling up with landscape shots that have to be scaled and cropped.",
20440
+ description: "Search stock footage and stills. source \"pexels\" (default) goes through the editor's own proxy \u2014 the API key is held server-side, so no key is needed here and the public api.pexels.com endpoint must not be called directly. source \"magnific\" searches Magnific footage with the key the USER connected in the editor's Stock \u2192 Magnific panel; never ask for or pass that key here \u2014 if it is not connected the call says so. Magnific results carry a `magnific:<id>` url, `premium` and `aiGenerated`; adding one downloads the full-quality file in the tab and counts against the user's Magnific download quota, so add only what the edit will use. For Pexels: Results come back with one chosen encode each: the smallest that still covers the project width, because anything larger spends download and decode on pixels the frame discards. Pass a result's `url` straight to add_media_file to bring it into the bin; the browser downloads it itself, so the bytes never cross this bridge. Orientation defaults to the shape of the project, which is what keeps portrait projects from filling up with landscape shots that have to be scaled and cropped.",
20276
20441
  inputSchema: {
20277
20442
  type: "object",
20278
20443
  properties: {
@@ -20283,7 +20448,11 @@ var BASE_TOOLS = [
20283
20448
  enum: ["landscape", "portrait", "square"],
20284
20449
  description: "Defaults to the project's own shape \u2014 portrait for a vertical sequence."
20285
20450
  },
20286
- perPage: num("How many results, 1..80. Defaults to 12.")
20451
+ perPage: num("How many results, 1..80. Defaults to 12."),
20452
+ source: { type: "string", enum: ["pexels", "magnific"], description: "Where to search. Defaults to pexels." },
20453
+ page: num("Magnific only: result page, from 1."),
20454
+ freeOnly: { type: "boolean", description: "Magnific only: clips downloadable without a premium plan." },
20455
+ excludeAi: { type: "boolean", description: "Magnific only: leave out AI-generated clips." }
20287
20456
  },
20288
20457
  required: ["query"]
20289
20458
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goatedit-mcp",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Local MCP server for the GoatEdit video editor: drive your open editor tab from Claude Code or any MCP client",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",