@writepanda/mcp 1.18.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/server.mjs +40 -13
  2. package/package.json +1 -1
package/bin/server.mjs CHANGED
@@ -354,7 +354,7 @@ const TOOLS = [
354
354
  {
355
355
  name: "project_add_zoom",
356
356
  description:
357
- "Add a zoom region — highlight a UI moment. Typical pattern: find 'click X' in transcript, drop zoom there. Ships with a short swoosh SFX by default; pass soundUrl=\"none\" for silent.",
357
+ "Add a zoom region — highlight a UI moment. Typical pattern: find 'click X' in transcript, drop zoom there. ALWAYS pass anchorSourceMs (= the same source-time value you use for atMs) when picking from a transcript word — without it, the zoom drifts off the moment as soon as any trim is added (which the YouTube editing playbook always does via remove-fillers / remove-silences). Ships with a short swoosh SFX by default; pass soundUrl=\"none\" for silent.",
358
358
  inputSchema: {
359
359
  type: "object",
360
360
  properties: {
@@ -374,6 +374,16 @@ const TOOLS = [
374
374
  type: "number",
375
375
  description: "Sound volume 0–1. Default 1.",
376
376
  },
377
+ anchorSourceMs: {
378
+ type: "number",
379
+ description:
380
+ "Anchor the zoom to a moment in the original recording (a transcript word's startMs, a click in cursor telemetry). When set, the zoom's edited-time position is recomputed automatically every time a trim or speed region is added/removed. STRONGLY RECOMMENDED when atMs comes from the transcript — otherwise the zoom will drift off the moment as soon as any trim is added.",
381
+ },
382
+ anchorSourceEndMs: {
383
+ type: "number",
384
+ description:
385
+ "Optional anchor end (source ms). When set, the zoom's duration tracks the source-time span instead of preserving the original visible duration. Useful for zooms covering a multi-word phrase.",
386
+ },
377
387
  expectedRevision: { type: "number" },
378
388
  },
379
389
  required: ["atMs", "durationMs"],
@@ -548,7 +558,7 @@ const TOOLS = [
548
558
  {
549
559
  name: "project_remove_region",
550
560
  description:
551
- "Delete an existing region (zoom, trim, speed, annotation, fx, lower-third, overlay) by its UUID. Use project_read to find region IDs. Returns the updated project.",
561
+ "Delete an existing region (zoom, trim, speed, annotation, fx, lower-third, overlay, audio-overlay) by its id. Use project_read to find region ids — visual regions live under editor.*Regions; audio overlays live under audioOverlays[]. Returns the updated project.",
552
562
  inputSchema: {
553
563
  type: "object",
554
564
  properties: {
@@ -556,9 +566,10 @@ const TOOLS = [
556
566
  path: { type: "string" },
557
567
  regionType: {
558
568
  type: "string",
559
- description: "zoom | trim | speed | annotation | fx | lower-third | overlay",
569
+ description:
570
+ "zoom | trim | speed | annotation | fx | lower-third | overlay | audio-overlay",
560
571
  },
561
- regionId: { type: "string", description: "UUID of the region to delete" },
572
+ regionId: { type: "string", description: "id of the region to delete" },
562
573
  expectedRevision: { type: "number" },
563
574
  },
564
575
  required: ["regionType", "regionId"],
@@ -568,7 +579,7 @@ const TOOLS = [
568
579
  {
569
580
  name: "project_update_region",
570
581
  description:
571
- "Patch fields on an existing region without replacing it. Accepts any subset of the region's own properties — only the supplied fields are changed, everything else is preserved. Works on zoom (depth, focusX, focusY), trim (startMs, endMs), speed (startMs, endMs, speed), lower-third (content, subtitle, atMs, durationMs, designType, accentColor, textColor, backgroundColor, backgroundRadius, fontSize, fontFamily), fx (atMs, durationMs), annotation, and overlay regions.",
582
+ "Patch fields on an existing region without replacing it. Accepts any subset of the region's own properties — only the supplied fields are changed, everything else is preserved. Works on zoom (depth, focusX, focusY), trim (startMs, endMs), speed (startMs, endMs, speed), lower-third (content, subtitle, atMs, durationMs, designType, accentColor, textColor, backgroundColor, backgroundRadius, fontSize, fontFamily), fx (atMs, durationMs), annotation, overlay, and audio-overlay (startMs, endMs, sourceStartMs, volume — lets you drag-trim an audio overlay without removing it).",
572
583
  inputSchema: {
573
584
  type: "object",
574
585
  properties: {
@@ -576,13 +587,14 @@ const TOOLS = [
576
587
  path: { type: "string" },
577
588
  regionType: {
578
589
  type: "string",
579
- description: "zoom | trim | speed | annotation | fx | lower-third | overlay",
590
+ description:
591
+ "zoom | trim | speed | annotation | fx | lower-third | overlay | audio-overlay",
580
592
  },
581
- regionId: { type: "string", description: "UUID of the region to update" },
593
+ regionId: { type: "string", description: "id of the region to update" },
582
594
  patch: {
583
595
  type: "object",
584
596
  description:
585
- "Fields to update (partial). E.g. { depth: 4 } to change zoom depth, or { content: 'New Name' } on a lower-third.",
597
+ "Fields to update (partial). E.g. { depth: 4 } to change zoom depth, { content: 'New Name' } on a lower-third, or { startMs: 2000, endMs: 15000, sourceStartMs: 4000 } to shift + trim an audio overlay (play seconds 4–17 of the source from the 2s mark on the timeline).",
586
598
  },
587
599
  expectedRevision: { type: "number" },
588
600
  },
@@ -748,7 +760,7 @@ const TOOLS = [
748
760
  {
749
761
  name: "project_add_audio",
750
762
  description:
751
- "Add a background audio track (music, VO, ambient sound) to the project. The audio plays over the full mix from startMs and is exported automatically. Use project_remove_audio to remove it. Returns { overlayId } — save this to remove it later.",
763
+ "Add a background audio overlay (music, VO, ambient) as a first-class timeline region. Plays from startMs to endMs on the edited timeline; sourceStartMs is the in-point into the source file. Waveform peaks are extracted automatically and stored on the overlay for the timeline UI. Use project_update_region (regionType=audio-overlay) to drag/trim it afterward. Returns { overlayId } — save this to trim/remove later.",
752
764
  inputSchema: {
753
765
  type: "object",
754
766
  properties: {
@@ -760,12 +772,27 @@ const TOOLS = [
760
772
  },
761
773
  startMs: {
762
774
  type: "number",
763
- description: "Where in the edited timeline playback starts. Default 0.",
775
+ description: "Where on the edited timeline playback starts. Default 0.",
776
+ },
777
+ endMs: {
778
+ type: "number",
779
+ description:
780
+ "Where on the edited timeline playback ends. Precedence: endMs > maxDurationMs > durationMs. If all are omitted, defaults to the source file's real duration.",
781
+ },
782
+ sourceStartMs: {
783
+ type: "number",
784
+ description:
785
+ "In-point into the source file in ms. Default 0. Combine with endMs-startMs to play a window of the source (e.g. startMs=2000, endMs=15000, sourceStartMs=4000 plays seconds 4–17 of the source at timeline position 2–15s).",
786
+ },
787
+ durationMs: {
788
+ type: "number",
789
+ description: "Fallback duration when neither endMs nor maxDurationMs is given.",
764
790
  },
765
791
  volume: { type: "number", description: "Volume multiplier 0–2. Default 0.8." },
766
792
  maxDurationMs: {
767
793
  type: "number",
768
- description: "Clip the audio at this duration. Omit to play the full file.",
794
+ description:
795
+ "[Legacy] Sets endMs = startMs + maxDurationMs when endMs is absent. Prefer endMs.",
769
796
  },
770
797
  expectedRevision: { type: "number" },
771
798
  },
@@ -1048,7 +1075,7 @@ const TOOLS = [
1048
1075
  {
1049
1076
  name: "motion_render_html",
1050
1077
  description:
1051
- "Render arbitrary HTML/CSS/JS to video. Use this when the bundled motion-graphic templates don't fit the brief — you write the HTML, the Chromium capturePage FFmpeg pipeline does the rest. Pass either inline `html` or a `htmlPath`. Animations should auto-start on DOMContentLoaded. Set `transparent: true` to get a WebM with alpha channel for overlays (lower thirds, watermarks, name plates) that composite over existing video. IMPORTANT: renders are sequential — call job_wait to completion before starting another render, or you'll get a RENDER_BUSY error. Async — returns { jobId, outputPath }; poll job_wait for the final file.",
1078
+ "Render arbitrary HTML/CSS/JS to video via the HyperFrames engine — frame-perfect, seekable capture through chrome-headless-shell's BeginFrame API. Use this when the bundled motion-graphic templates don't fit the brief. The HTML MUST expose a paused GSAP timeline registered as `window.__timelines[<data-composition-id>] = tl` NOT CSS keyframes, NOT setTimeout, NOT `window.__hf.seek` (that lower-level protocol skips the compositor invalidation wrapper and renders with 1-second stalls). See the SKILL.md `Custom motion graphics — HTML authoring` section for the required `data-composition-id`/`data-width`/`data-height`/`data-duration` root element, the canonical template, and pacing rules. Pass either inline `html` or `htmlPath`. Set `transparent: true` for a WebM+alpha overlay (lower thirds, watermarks). IMPORTANT: renders are sequential — call job_wait to completion before starting another render, or you'll get a RENDER_BUSY error. Async — returns { jobId, outputPath }; poll job_wait for the final file.",
1052
1079
  inputSchema: {
1053
1080
  type: "object",
1054
1081
  properties: {
@@ -1167,7 +1194,7 @@ const TOOLS = [
1167
1194
  {
1168
1195
  name: "asset_list_music",
1169
1196
  description:
1170
- "List every bundled background music track (id, title, category, mood, durationMs, absolutePath). Use absolutePath with project_add_audio to attach a track to a project.",
1197
+ "List every bundled background music track. Each track has: id, title, category, mood, durationMs, absolutePath, and agent-routing hints `intents` (e.g. product_video, kinetic_text, promo, intro, outro, tech_review, vlog, generic) and `recommendedFor` (youtube-long | shorts | linkedin | loom). Match on intents first when picking a track — use mood/category as tiebreakers. Use absolutePath with project_add_audio to attach a track to a project.",
1171
1198
  inputSchema: { type: "object", properties: {} },
1172
1199
  command: "asset.list-music",
1173
1200
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@writepanda/mcp",
3
- "version": "1.18.0",
3
+ "version": "1.21.0",
4
4
  "description": "Model Context Protocol server for PandaStudio. Exposes the desktop video editor's automation surface to Cursor, Continue, Cline, Claude Desktop, and any MCP-compliant client.",
5
5
  "keywords": [
6
6
  "pandastudio",