goatedit-mcp 1.1.21 → 1.1.23

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.
@@ -20219,7 +20219,8 @@ var BASE_TOOLS = [
20219
20219
  inputSchema: {
20220
20220
  type: "object",
20221
20221
  properties: {
20222
- clipIds: { type: "array", items: { type: "string" }, description: "Clip ids from get_timeline, up to 50." }
20222
+ clipIds: { type: "array", items: { type: "string" }, description: "Clip ids from get_timeline, up to 50." },
20223
+ includeHtml: bool("For HTML clips, also return the markup (html), its slot fills and vars \u2014 what update_html_clip starts from. Long markup is cut at 200 KB.")
20223
20224
  },
20224
20225
  required: ["clipIds"]
20225
20226
  },
@@ -20412,7 +20413,7 @@ var BASE_TOOLS = [
20412
20413
  },
20413
20414
  {
20414
20415
  name: "update_shape_clip",
20415
- description: "Change a shape after it was made \u2014 fill, size, corners, outline, and a dashed or rounded outline \u2014 without deleting it and losing its id, keyframes and effects.",
20416
+ description: "Change a shape after it was made \u2014 fill, size, position, length, corners, outline, and a dashed or rounded outline \u2014 without deleting it and losing its id, keyframes and effects.",
20416
20417
  inputSchema: {
20417
20418
  type: "object",
20418
20419
  properties: {
@@ -20432,7 +20433,10 @@ var BASE_TOOLS = [
20432
20433
  closed: bool("Path shapes: join the last anchor back to the first."),
20433
20434
  trimStart: num("Path shapes: where along the path drawing starts, 0..1. Keyframe it as pathTrimStart."),
20434
20435
  trimEnd: num("Path shapes: where drawing stops, 0..1. 0 hides the path; keyframing pathTrimEnd 0 to 1 with set_keyframes draws it on."),
20435
- trimOffset: num("Path shapes: slides the drawn stretch along the path, degrees.")
20436
+ trimOffset: num("Path shapes: slides the drawn stretch along the path, degrees."),
20437
+ x: num("Centre across the frame, 0..1 (sets posX; keyframes on posX still win)."),
20438
+ y: num("Centre down the frame, 0..1 (sets posY)."),
20439
+ duration: num("New length in seconds, from the same start. Refused if it would run into the next clip on the track.")
20436
20440
  },
20437
20441
  required: ["clipId"]
20438
20442
  },
@@ -20505,7 +20509,11 @@ var BASE_TOOLS = [
20505
20509
  x: num("Position as a fraction of the frame width. Defaults to 0.5."),
20506
20510
  y: num("Position as a fraction of the frame height. Defaults to 0.5."),
20507
20511
  name: str("Display name."),
20508
- trackId: str('Video track, or "__new_video__" (default) for a free one.')
20512
+ trackId: str('Video track, or "__new_video__" (default) for a free one.'),
20513
+ threeD: { type: "boolean", description: "A 3D null (AE 3D null object): it gains Z depth and X/Y turns (its layer3d effect: posZ, rotateX, rotateY; rotation is Z). 3D layers parented to it move with it in 3D: turn it about Y with set_clip_effect keyframes and the cards around it swing round as a ring, near ones bigger. Nulls nest (a spin inside a tilt). Give children layer3d faceCamera: 1 to keep them square to the camera." },
20514
+ z: num("3D null only: depth, 1080p px away from the camera. Defaults to 0."),
20515
+ rotateX: num("3D null only: tilt, degrees."),
20516
+ rotateY: num("3D null only: swivel, degrees.")
20509
20517
  },
20510
20518
  required: ["duration"]
20511
20519
  },
@@ -20523,7 +20531,7 @@ var BASE_TOOLS = [
20523
20531
  name: str("Display name for a new camera."),
20524
20532
  params: {
20525
20533
  type: "object",
20526
- description: "Static settings. x / y: truck right and pedestal down, 1080p px. z: dolly toward the scene, 1080p px (a layer at posZ 1000 reaches the lens at about z 2480). pan (look right +), tilt (look up +), roll, degrees. orbit (swing right around the pivot +), orbitTilt (rise over it +), degrees; pivotZ: depth of the point it swings around (put it at the hero layer's posZ). fov: vertical field of view, 40 default; narrower zooms in from where the camera stands. focalLength: the same in full-frame mm (33 mm = 40\xB0). aperture: depth-of-field blur, 0 sharp; focus: depth of the plane in focus, 1080p px."
20534
+ description: "Static settings. x / y: truck right and pedestal down, 1080p px. z: dolly toward the scene, 1080p px, counted from where the camera rests, about 1480 px in front of the frame plane: the lens stands at depth z \u2212 1480, so a layer at posZ 1000 reaches it at about z 2480, and to stand inside a tunnel whose walls span posZ 100..1000 put z near 1580..2400. pan (look right +), tilt (look up +), roll, degrees. orbit (swing right around the pivot +), orbitTilt (rise over it +), degrees; pivotZ: depth of the point it swings around (put it at the hero layer's posZ). fov: vertical field of view, 40 default; narrower zooms in from where the camera stands. focalLength: the same in full-frame mm (33 mm = 40\xB0). aperture: depth-of-field blur, 0 sharp; focus: depth of the plane in focus, 1080p px."
20527
20535
  },
20528
20536
  keyframes: {
20529
20537
  type: "object",
@@ -21052,6 +21060,7 @@ var BASE_TOOLS = [
21052
21060
  scaleY: num("Vertical scale, overriding scale."),
21053
21061
  rotation: num("Rotation in degrees."),
21054
21062
  opacity: num("Opacity from 0 to 1."),
21063
+ enabled: bool("false switches the clip off (the timeline's Disable): it stays in place but draws and plays nothing. true switches a disabled clip back on \u2014 get_timeline lists those with disabled: true."),
21055
21064
  blendMode: {
21056
21065
  type: "string",
21057
21066
  enum: [
@@ -21124,6 +21133,8 @@ var BASE_TOOLS = [
21124
21133
  prop: {
21125
21134
  type: "string",
21126
21135
  enum: [
21136
+ "scale",
21137
+ "position",
21127
21138
  "opacity",
21128
21139
  "volume",
21129
21140
  "posX",
@@ -21158,7 +21169,7 @@ var BASE_TOOLS = [
21158
21169
  "shapeDash",
21159
21170
  "shapeGap"
21160
21171
  ],
21161
- 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). cropLeft/Top/Right/Bottom are 0..1 of the layer cut from that side (set_mask crop sets them once), cropRadius rounds the crop's corners and cropFeather softens its edge, both px @1080p. shapeWidth/shapeHeight/shapeCornerRadius/shapeStrokeWidth/shapeDash/shapeGap animate a shape layer in its own px @1080p (a square or circle needs width and height keyed together)."
21172
+ description: "Property to animate. scale and position key both halves at once, as After Effects does (same times, same eases): value is a number for uniform scale, or [x, y]. Prefer them over keying scaleX/scaleY or posX/posY separately. 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). cropLeft/Top/Right/Bottom are 0..1 of the layer cut from that side (set_mask crop sets them once), cropRadius rounds the crop's corners and cropFeather softens its edge, both px @1080p. shapeWidth/shapeHeight/shapeCornerRadius/shapeStrokeWidth/shapeDash/shapeGap animate a shape layer in its own px @1080p (a square or circle needs width and height keyed together)."
21162
21173
  },
21163
21174
  keyframes: {
21164
21175
  type: "array",
@@ -21166,6 +21177,7 @@ var BASE_TOOLS = [
21166
21177
  items: { type: "object" }
21167
21178
  },
21168
21179
  clear: bool("Remove this property's keyframes instead of setting them, leaving the clip's flat value in charge again."),
21180
+ relative: bool("Values are relative to where the layer rests: multiples of its scale/opacity (1.1 = 10% bigger than it is), offsets for everything else (posX +0.05, rotation +15). A punch-in on a card scaled 0.3 stays a punch-in instead of jumping to full size."),
21169
21181
  expression: {
21170
21182
  type: "string",
21171
21183
  description: `An After-Effects-style expression that drives the property instead (keyframes still feed it as \`value\`); "" removes it. A math-only language: numbers, value, time (seconds from this clip's start), duration, index (this layer's number, top track first), Math.*, wiggle(freq, amp), random(a, b), noise(t), clamp, linear(t, tMin, tMax, v1, v2), ease(...same), valueAtTime(t), loopOut("cycle"|"pingpong"|"offset"|"continue", n?), loopIn(...), thisLayer.<prop>, and layer("Name").<prop> or layer(2).<prop> (optionally .valueAtTime(t)), read at the same moment of the timeline. Rigs: a null named "Controls" whose posX drives others via layer("Controls").posX * 100; scaleY = thisLayer.scaleX; a stagger with valueAtTime(time - (index - 1) * 0.08); a looping bob with keyframes plus loopOut("pingpong"). Props use this tool's units (posX 0..1, rotation degrees).`
@@ -21184,7 +21196,7 @@ var BASE_TOOLS = [
21184
21196
  clipId: CLIP_ID,
21185
21197
  type: {
21186
21198
  type: "string",
21187
- description: "Effect type: blur, invert, hue, saturation, brightness, contrast, exposure, grayscale, sepia, gradientMap, vignette, filmGrain, flicker, posterizeTime, lensDistortion, chromaticAberration, lensFlare, liquidGlass, opacityFx, colorCorrection, depthMap, depthParticles, gradientMap, vegas, glow, pixelDissolve, motionBlur, dropShadow, reflection, colorama, outline, echo, flutedGlass, lightRays, halftone, datamosh, roughenEdges, filmStock, halation, starGlow, filmDamage, lightLeak, thermal, colorBalance, duotone, levels, monochrome, channelMixer, dither, threshold, fourColorGradient, lensBlur, boxBlur, 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, compositeOriginal, grid, repeater, plus transform, layer3d, camera3d (on a camera clip; use set_camera), 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."
21199
+ description: "Effect type: blur, invert, hue, saturation, brightness, contrast, exposure, grayscale, sepia, gradientMap, vignette, filmGrain, flicker, posterizeTime, lensDistortion, chromaticAberration, lensFlare, liquidGlass, opacityFx, colorCorrection, depthMap, depthParticles, gradientMap, vegas, glow, pixelDissolve, motionBlur, dropShadow, reflection, colorama, outline, echo, flutedGlass, lightRays, halftone, datamosh, roughenEdges, filmStock, halation, starGlow, filmDamage, lightLeak, thermal, colorBalance, duotone, levels, monochrome, channelMixer, dither, threshold, fourColorGradient, lensBlur, boxBlur, 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, compositeOriginal, grid, repeater, plus transform, cornerPin (AE Corner Pin: perspective quad from four corners), layer3d, camera3d (on a camera clip; use set_camera), 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."
21188
21200
  },
21189
21201
  params: {
21190
21202
  type: "object",
@@ -21284,7 +21296,7 @@ var BASE_TOOLS = [
21284
21296
  clipId: CLIP_ID,
21285
21297
  preset: {
21286
21298
  type: "string",
21287
- description: "Entrance preset: fadeIn, slideUp, blurIn, typewriter, typewriterCursor, scaleIn, springUp, slideInLeft, slideInRight, riseFade, unfoldDown, unfoldUp, foldFlip, depthPop, wordPop, karaokeHighlight, karaokeScale, springPop, neonGlowPulse, karaokePill, cyberSlant, wipeUp, trackIn, slamIn, elasticPop, squashDrop, glitchIn, tumbleIn, swingIn, flip3D, cinematicRise, stretchIn, bounceDrop, rollIn, maskRise (rises from behind an invisible line), blockReveal (a bar in highlightColor wipes across, then uncovers the text), focusPull (big and blurred, pulling to crisp), whipIn (sideways with a motion smear), scatterSettle (letters scattered up and down drop into line), depthAssemble (letters fly in from scattered depth), decode (letters flicker through random glyphs, then resolve), countUp (the first number in the text counts up to its value, keeping its format, e.g. $787,539.00)."
21299
+ description: "Entrance preset: fadeIn, slideUp, blurIn, typewriter, typewriterCursor, scaleIn, springUp, slideInLeft, slideInRight, riseFade, unfoldDown, unfoldUp, foldFlip, depthPop, wordPop, karaokeHighlight, karaokeScale, springPop, neonGlowPulse, karaokePill, cyberSlant, wipeUp, trackIn, slamIn, elasticPop, squashDrop, glitchIn, tumbleIn, swingIn, flip3D, cinematicRise, stretchIn, bounceDrop, rollIn, maskRise (rises from behind an invisible line), blockReveal (a bar in highlightColor wipes across, then uncovers the text), focusPull (big and blurred, pulling to crisp), whipIn (sideways with a motion smear), scatterSettle (letters scattered up and down drop into line), depthAssemble (letters fly in from scattered depth), decode (letters flicker through random glyphs, then resolve), countUp (the first number in the text counts up to its value, keeping its format, e.g. $787,539.00), custom (After Effects' text animator: each unit eases from `from` to rest on `ease` \u2014 use it for colour sweeps, blur-in with tracking, any look the presets don't have)."
21288
21300
  },
21289
21301
  unit: { type: "string", enum: ["letter", "word", "line"], description: "What the animation steps through." },
21290
21302
  durationIn: num("Seconds for one unit's entrance to complete. 0 cuts each unit on."),
@@ -21302,6 +21314,12 @@ var BASE_TOOLS = [
21302
21314
  },
21303
21315
  placeholder: str('Colour of a solid bar drawn where each unit will appear until it enters, e.g. "#111111" \u2014 words waiting their turn as redaction bars. Empty string removes it.'),
21304
21316
  activeScale: num("Kinetic presets: size of the active word, 1 for no pop (stops it colliding with its neighbours). Defaults per preset, 1.1\u20131.32."),
21317
+ from: {
21318
+ type: "object",
21319
+ description: `custom preset: what each unit starts from, easing to the text's own rest values. opacity (0..1), x, y (px @1080p, y positive is below), scale (1 = rest), rotation (degrees), blur (px @1080p), tracking (extra px between units, closing up \u2014 letters converge), color (start colour fading to the text's own fill, e.g. light blue to navy: color "#9fd0ff" on navy text). Default { opacity: 0, y: 30, blur: 8 }.`,
21320
+ properties: { opacity: { type: "number" }, x: { type: "number" }, y: { type: "number" }, scale: { type: "number" }, rotation: { type: "number" }, blur: { type: "number" }, tracking: { type: "number" }, color: { type: "string" } }
21321
+ },
21322
+ ease: { type: "array", items: { type: "number" }, description: "custom preset: cubic-bezier [x1, y1, x2, y2] for each unit. Default [0.22, 1, 0.36, 1] (ease-out)." },
21305
21323
  remove: bool("Take the animation off, leaving the text to cut on."),
21306
21324
  exit: {
21307
21325
  type: ["object", "null"],
@@ -21312,7 +21330,9 @@ var BASE_TOOLS = [
21312
21330
  stagger: num("Seconds between units leaving. Defaults to the preset's."),
21313
21331
  order: { type: "string", enum: ["forward", "reverse", "center", "edges", "random"], description: "Which unit leaves first. forward: the first word goes first. Defaults to reverse for typewriter exits (backspace), reading order otherwise." },
21314
21332
  distance: num("Travel in px @1080p for the moving presets."),
21315
- seed: num("Seed for random order.")
21333
+ seed: num("Seed for random order."),
21334
+ from: { type: "object", description: "custom exit: what each unit ends on (same keys as from)." },
21335
+ ease: { type: "array", items: { type: "number" }, description: "custom exit: cubic-bezier for each unit." }
21316
21336
  }
21317
21337
  }
21318
21338
  },
@@ -21417,7 +21437,8 @@ var BASE_TOOLS = [
21417
21437
  height: num("Render height in pixels. Defaults to the preset's, or the project height."),
21418
21438
  posX: num("Horizontal centre as a fraction of the frame, 0..1. 0.5 is centre."),
21419
21439
  posY: num("Vertical centre as a fraction of the frame, 0..1. 0.5 is centre."),
21420
- scale: num("Uniform scale, 1 being unchanged."),
21440
+ scale: num('Uniform scale, 1 being unchanged. With size "native", a multiplier on the native size.'),
21441
+ size: str(`"fit" (default): like any picture, the width x height box is fitted inside the frame, so a 600x200 card fills the frame width. "native": one authored px is one frame px, so a 600x200 card is 600x200 on screen. Use native for UI pieces authored at their real size. The result's onScreen gives the box in frame px either way.`),
21421
21442
  opacity: num("Opacity, 0..1. Defaults to 1."),
21422
21443
  name: str("Display name for the clip and its bin entry.")
21423
21444
  },
@@ -21607,10 +21628,11 @@ var BASE_TOOLS = [
21607
21628
  type: "object",
21608
21629
  properties: {
21609
21630
  clipId: CLIP_ID,
21610
- newStartTime: num("New timeline start time in seconds."),
21631
+ startTime: num("New timeline start time in seconds."),
21632
+ newStartTime: num("Same as startTime (older name)."),
21611
21633
  newTrackId: str('Track to move onto. Defaults to the clip\u2019s current track. Accepts "__new_video__" to pick a video track free across the clip\u2019s span, or "__new_track__" for a new video track on top.')
21612
21634
  },
21613
- required: ["clipId", "newStartTime"]
21635
+ required: ["clipId"]
21614
21636
  },
21615
21637
  method: "moveClip"
21616
21638
  },
@@ -22431,6 +22453,9 @@ function withRunProject(stepArgs, projectId) {
22431
22453
  }
22432
22454
  function withRunSequence(stepArgs, sequenceId, tool) {
22433
22455
  if (typeof sequenceId !== "string" || !sequenceId || typeof stepArgs.expectedSequenceId === "string") return stepArgs;
22456
+ if (tool?.name === "update_sequence") {
22457
+ return typeof stepArgs.sequenceId === "string" ? stepArgs : { ...stepArgs, sequenceId };
22458
+ }
22434
22459
  if (!tool || !("expectedSequenceId" in (tool.inputSchema.properties ?? {}))) return stepArgs;
22435
22460
  return { ...stepArgs, expectedSequenceId: sequenceId };
22436
22461
  }
@@ -25699,6 +25724,42 @@ async function importLocalFile(args, target) {
25699
25724
  );
25700
25725
  }
25701
25726
  }
25727
+ var RUN_STEP_COMMON_ARGS = /* @__PURE__ */ new Set(["projectId", "expectedSequenceId", "opId"]);
25728
+ function preflightSteps(calls) {
25729
+ const errors = [], warnings = [];
25730
+ calls.forEach((raw, i) => {
25731
+ const step = raw;
25732
+ const n = i + 1;
25733
+ const tool = typeof step?.tool === "string" ? step.tool : "";
25734
+ if (!tool) {
25735
+ errors.push(`step ${n}: no tool name.`);
25736
+ return;
25737
+ }
25738
+ if (tool === "run_tools") {
25739
+ errors.push(`step ${n}: run_tools cannot be nested.`);
25740
+ return;
25741
+ }
25742
+ const def = BROWSER_TOOLS_BY_NAME.get(tool);
25743
+ if (!def) return;
25744
+ const args = step.args && typeof step.args === "object" ? step.args : {};
25745
+ const props = def.inputSchema?.properties ?? {};
25746
+ for (const key of def.inputSchema?.required ?? []) {
25747
+ if (args[key] === void 0) errors.push(`step ${n} (${tool}): missing required "${key}".`);
25748
+ }
25749
+ for (const [key, value] of Object.entries(args)) {
25750
+ const spec = props[key];
25751
+ if (!spec) {
25752
+ if (!RUN_STEP_COMMON_ARGS.has(key)) warnings.push(`step ${n} (${tool}): "${key}" is not an argument of ${tool} and is ignored. It takes: ${Object.keys(props).join(", ")}.`);
25753
+ continue;
25754
+ }
25755
+ if (typeof value === "string" && value.startsWith("$")) continue;
25756
+ const want = spec.type;
25757
+ const ok = !want || value === null || (want === "number" || want === "integer" ? typeof value === "number" : want === "string" ? typeof value === "string" : want === "boolean" ? typeof value === "boolean" : want === "array" ? Array.isArray(value) : want === "object" ? typeof value === "object" && !Array.isArray(value) : true);
25758
+ if (!ok) errors.push(`step ${n} (${tool}): "${key}" should be ${want}, got ${Array.isArray(value) ? "array" : typeof value}.`);
25759
+ }
25760
+ });
25761
+ return { errors, warnings };
25762
+ }
25702
25763
  async function runTools(args) {
25703
25764
  const calls = args.calls;
25704
25765
  if (!Array.isArray(calls) || !calls.length) {
@@ -25707,6 +25768,16 @@ async function runTools(args) {
25707
25768
  if (args.rollback && args.continueOnError) {
25708
25769
  throw new McpError(ErrorCode.InvalidParams, "rollback and continueOnError cannot be combined: a run that keeps going after a failure has nothing to roll back to.");
25709
25770
  }
25771
+ const check = preflightSteps(calls);
25772
+ if (check.errors.length) {
25773
+ return {
25774
+ ok: false,
25775
+ ran: 0,
25776
+ errors: check.errors,
25777
+ note: "Nothing ran: fix these and send the run again.",
25778
+ ...check.warnings.length ? { warnings: check.warnings } : {}
25779
+ };
25780
+ }
25710
25781
  const results = [];
25711
25782
  const images = [];
25712
25783
  const refs = /* @__PURE__ */ new Map();
@@ -25761,6 +25832,8 @@ async function runTools(args) {
25761
25832
  return {
25762
25833
  ok: failed === 0,
25763
25834
  results,
25835
+ ...check.warnings.length ? { warnings: check.warnings } : {},
25836
+ ...failed && !args.continueOnError && !args.rollback ? { hint: "One failing step skips the rest. Pass continueOnError: true to run the other steps anyway." } : {},
25764
25837
  ...failed && runOpId ? { opId: runOpId, retry: `Repeat this run_tools call with opId "${runOpId}": finished steps answer from the tab without running again.` } : {},
25765
25838
  ...rolledBack !== void 0 ? { rolledBack } : {},
25766
25839
  ...images.length ? { _images: images } : {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goatedit-mcp",
3
- "version": "1.1.21",
3
+ "version": "1.1.23",
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",