@writepanda/mcp 1.9.5 → 1.11.1
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.
- package/README.md +9 -6
- package/bin/server.mjs +392 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,17 +48,20 @@ After adding, restart your client. The MCP server auto-launches PandaStudio if i
|
|
|
48
48
|
|
|
49
49
|
## What the agent gets
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
55 tools covering the full PandaStudio editorial surface — complete UI parity:
|
|
52
52
|
|
|
53
53
|
| Category | Tools |
|
|
54
54
|
|---|---|
|
|
55
55
|
| Discovery | `system_status`, `system_list_commands` |
|
|
56
|
-
| Project lifecycle | `project_list`, `project_show`, `project_read`, `project_new`, `project_open` |
|
|
57
|
-
|
|
|
58
|
-
|
|
|
56
|
+
| Project lifecycle | `project_list`, `project_show`, `project_read`, `project_new`, `project_open`, `project_save`, `project_delete` |
|
|
57
|
+
| Clips | `project_add_clip`, `project_remove_clip`, `project_split_clip` |
|
|
58
|
+
| Composition | `project_add_motion_graphic`, `project_add_fx`, `project_add_lower_third`, `project_add_zoom`, `project_add_trim`, `project_add_speed`, `project_add_annotation` |
|
|
59
|
+
| Region editing | `project_remove_region`, `project_update_region` |
|
|
60
|
+
| Canvas & style | `project_set_aspect_ratio`, `project_set_wallpaper`, `project_set_style`, `project_set_crop`, `project_set_webcam_layout`, `project_set_export_settings` |
|
|
61
|
+
| Transcript editing | `transcript_transcribe`, `transcript_get`, `transcript_delete_words`, `transcript_remove_fillers`, `transcript_search`, `transcript_find_replace`, `transcript_remove_silences` |
|
|
59
62
|
| Audio | `audio_clean` (DeepFilter denoising) |
|
|
60
|
-
| Captions | `caption_toggle`, `caption_set_template` |
|
|
61
|
-
| Motion graphics | `motion_list`, `motion_themes`, `motion_generate` |
|
|
63
|
+
| Captions | `caption_toggle`, `caption_set_template`, `caption_set_style` |
|
|
64
|
+
| Motion graphics | `motion_list`, `motion_themes`, `motion_generate`, `motion_render_html` |
|
|
62
65
|
| Assets | `asset_list_sounds`, `asset_list_fx` |
|
|
63
66
|
| AI metadata | `llm_generate_title`, `llm_generate_description`, `llm_generate_timestamps` |
|
|
64
67
|
| Export | `export_start`, `export_list` |
|
package/bin/server.mjs
CHANGED
|
@@ -187,7 +187,7 @@ const TOOLS = [
|
|
|
187
187
|
{
|
|
188
188
|
name: "project_read",
|
|
189
189
|
description:
|
|
190
|
-
"Read a project's full JSON. Returns { path, project }. Pass `project.revision` back as `expectedRevision` on subsequent writes for conflict-safe edits.",
|
|
190
|
+
"Read a project's full JSON. Returns { path, project, clipStates }. `clipStates` is a per-clip summary: { clipId, mediaPath, durationMs, transcribed, wordCount, audioCleaned, cleanedAudioPath? } — use it to decide whether to call transcript_transcribe or audio_clean before editing. Pass `project.revision` back as `expectedRevision` on subsequent writes for conflict-safe edits.",
|
|
191
191
|
inputSchema: {
|
|
192
192
|
type: "object",
|
|
193
193
|
properties: {
|
|
@@ -232,13 +232,19 @@ const TOOLS = [
|
|
|
232
232
|
// ── compose: clips, motion graphics, FX, lower-thirds ──────────
|
|
233
233
|
{
|
|
234
234
|
name: "project_add_clip",
|
|
235
|
-
description:
|
|
235
|
+
description:
|
|
236
|
+
"Append (or insert) a video clip into the project's main track. Probes duration via FFmpeg.",
|
|
236
237
|
inputSchema: {
|
|
237
238
|
type: "object",
|
|
238
239
|
properties: {
|
|
239
240
|
id: { type: "string" },
|
|
240
241
|
path: { type: "string" },
|
|
241
242
|
media: { type: "string", description: "Absolute path to video file" },
|
|
243
|
+
atIndex: {
|
|
244
|
+
type: "number",
|
|
245
|
+
description:
|
|
246
|
+
"Insert before this zero-based clip index. Omit to append at the end.",
|
|
247
|
+
},
|
|
242
248
|
expectedRevision: { type: "number" },
|
|
243
249
|
},
|
|
244
250
|
required: ["media"],
|
|
@@ -301,7 +307,18 @@ const TOOLS = [
|
|
|
301
307
|
description:
|
|
302
308
|
"name-bar | slash-reveal | center-stack | minimal-underline | box-reveal | corner-brackets | border-frame | split-horizontal",
|
|
303
309
|
},
|
|
304
|
-
accentColor: { type: "string" },
|
|
310
|
+
accentColor: { type: "string", description: "Hex accent/background color" },
|
|
311
|
+
textColor: { type: "string", description: "Hex text color. Default #ffffff" },
|
|
312
|
+
backgroundColor: {
|
|
313
|
+
type: "string",
|
|
314
|
+
description: "Hex background fill. Default matches accentColor",
|
|
315
|
+
},
|
|
316
|
+
backgroundRadius: {
|
|
317
|
+
type: "number",
|
|
318
|
+
description: "Corner radius in pixels. Default 8",
|
|
319
|
+
},
|
|
320
|
+
fontSize: { type: "number", description: "Primary text font size in px. Default 28" },
|
|
321
|
+
fontFamily: { type: "string", description: "CSS font family name. Default Inter" },
|
|
305
322
|
expectedRevision: { type: "number" },
|
|
306
323
|
},
|
|
307
324
|
required: ["content", "atMs"],
|
|
@@ -364,6 +381,309 @@ const TOOLS = [
|
|
|
364
381
|
command: "project.add-speed",
|
|
365
382
|
},
|
|
366
383
|
|
|
384
|
+
{
|
|
385
|
+
name: "project_add_annotation",
|
|
386
|
+
description:
|
|
387
|
+
"Drop a text or figure annotation overlay on the canvas for a given time range. Position and size are in percent (0-100) of the canvas dimensions.",
|
|
388
|
+
inputSchema: {
|
|
389
|
+
type: "object",
|
|
390
|
+
properties: {
|
|
391
|
+
id: { type: "string" },
|
|
392
|
+
path: { type: "string" },
|
|
393
|
+
startMs: { type: "number" },
|
|
394
|
+
endMs: { type: "number" },
|
|
395
|
+
type: {
|
|
396
|
+
type: "string",
|
|
397
|
+
description: "text | figure",
|
|
398
|
+
},
|
|
399
|
+
text: { type: "string", description: "Required when type is 'text'" },
|
|
400
|
+
x: { type: "number", description: "Horizontal center, percent 0-100. Default 50." },
|
|
401
|
+
y: { type: "number", description: "Vertical center, percent 0-100. Default 50." },
|
|
402
|
+
width: { type: "number", description: "Width, percent 0-100. Default 30." },
|
|
403
|
+
height: { type: "number", description: "Height, percent 0-100. Default 20." },
|
|
404
|
+
expectedRevision: { type: "number" },
|
|
405
|
+
},
|
|
406
|
+
required: ["startMs", "endMs", "type"],
|
|
407
|
+
},
|
|
408
|
+
command: "project.add-annotation",
|
|
409
|
+
},
|
|
410
|
+
|
|
411
|
+
// ── project lifecycle (extended) ───────────────────────────────
|
|
412
|
+
{
|
|
413
|
+
name: "project_save",
|
|
414
|
+
description:
|
|
415
|
+
"Overwrite a project with the full JSON you supply. Use this when you've built or mutated a project object client-side and want to persist it. Always pass `expectedRevision` (the revision you read) — the server will reject the write if a concurrent edit happened between your read and save, returning { ok: false, details: { code: 'revision_conflict' } }.",
|
|
416
|
+
inputSchema: {
|
|
417
|
+
type: "object",
|
|
418
|
+
properties: {
|
|
419
|
+
id: { type: "string" },
|
|
420
|
+
path: { type: "string" },
|
|
421
|
+
project: { type: "object", description: "Full project JSON to persist" },
|
|
422
|
+
expectedRevision: {
|
|
423
|
+
type: "number",
|
|
424
|
+
description: "Revision from your last project_read. Strongly recommended.",
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
required: ["project"],
|
|
428
|
+
},
|
|
429
|
+
command: "project.save",
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
name: "project_delete",
|
|
433
|
+
description:
|
|
434
|
+
"Permanently delete a project file from disk. There is no trash — this is irreversible. Use project_list to confirm the id before deleting.",
|
|
435
|
+
inputSchema: {
|
|
436
|
+
type: "object",
|
|
437
|
+
properties: {
|
|
438
|
+
id: { type: "string" },
|
|
439
|
+
path: { type: "string" },
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
command: "project.delete",
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
name: "project_remove_clip",
|
|
446
|
+
description:
|
|
447
|
+
"Remove a clip from the main track by its clip id. Use project_read → clipStates to find clip ids. All regions whose time falls within the removed clip are also removed.",
|
|
448
|
+
inputSchema: {
|
|
449
|
+
type: "object",
|
|
450
|
+
properties: {
|
|
451
|
+
id: { type: "string" },
|
|
452
|
+
path: { type: "string" },
|
|
453
|
+
clipId: {
|
|
454
|
+
type: "string",
|
|
455
|
+
description: "Clip id to remove (e.g. clip-1). From clipStates in project_read.",
|
|
456
|
+
},
|
|
457
|
+
expectedRevision: { type: "number" },
|
|
458
|
+
},
|
|
459
|
+
required: ["clipId"],
|
|
460
|
+
},
|
|
461
|
+
command: "project.remove-clip",
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
name: "project_split_clip",
|
|
465
|
+
description:
|
|
466
|
+
"Split a clip in two at a position in source time (milliseconds from the start of that clip). Produces two clips: the portion before the split point and the portion after. Useful for inserting a motion graphic between two halves of a recording.",
|
|
467
|
+
inputSchema: {
|
|
468
|
+
type: "object",
|
|
469
|
+
properties: {
|
|
470
|
+
id: { type: "string" },
|
|
471
|
+
path: { type: "string" },
|
|
472
|
+
clipId: { type: "string", description: "Clip to split" },
|
|
473
|
+
atSourceMs: {
|
|
474
|
+
type: "number",
|
|
475
|
+
description: "Split position in milliseconds from the clip's own start (source time)",
|
|
476
|
+
},
|
|
477
|
+
expectedRevision: { type: "number" },
|
|
478
|
+
},
|
|
479
|
+
required: ["clipId", "atSourceMs"],
|
|
480
|
+
},
|
|
481
|
+
command: "project.split-clip",
|
|
482
|
+
},
|
|
483
|
+
|
|
484
|
+
// ── compose: edit existing regions ─────────────────────────────
|
|
485
|
+
{
|
|
486
|
+
name: "project_remove_region",
|
|
487
|
+
description:
|
|
488
|
+
"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.",
|
|
489
|
+
inputSchema: {
|
|
490
|
+
type: "object",
|
|
491
|
+
properties: {
|
|
492
|
+
id: { type: "string" },
|
|
493
|
+
path: { type: "string" },
|
|
494
|
+
regionType: {
|
|
495
|
+
type: "string",
|
|
496
|
+
description: "zoom | trim | speed | annotation | fx | lower-third | overlay",
|
|
497
|
+
},
|
|
498
|
+
regionId: { type: "string", description: "UUID of the region to delete" },
|
|
499
|
+
expectedRevision: { type: "number" },
|
|
500
|
+
},
|
|
501
|
+
required: ["regionType", "regionId"],
|
|
502
|
+
},
|
|
503
|
+
command: "project.remove-region",
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
name: "project_update_region",
|
|
507
|
+
description:
|
|
508
|
+
"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.",
|
|
509
|
+
inputSchema: {
|
|
510
|
+
type: "object",
|
|
511
|
+
properties: {
|
|
512
|
+
id: { type: "string" },
|
|
513
|
+
path: { type: "string" },
|
|
514
|
+
regionType: {
|
|
515
|
+
type: "string",
|
|
516
|
+
description: "zoom | trim | speed | annotation | fx | lower-third | overlay",
|
|
517
|
+
},
|
|
518
|
+
regionId: { type: "string", description: "UUID of the region to update" },
|
|
519
|
+
patch: {
|
|
520
|
+
type: "object",
|
|
521
|
+
description:
|
|
522
|
+
"Fields to update (partial). E.g. { depth: 4 } to change zoom depth, or { content: 'New Name' } on a lower-third.",
|
|
523
|
+
},
|
|
524
|
+
expectedRevision: { type: "number" },
|
|
525
|
+
},
|
|
526
|
+
required: ["regionType", "regionId", "patch"],
|
|
527
|
+
},
|
|
528
|
+
command: "project.update-region",
|
|
529
|
+
},
|
|
530
|
+
|
|
531
|
+
// ── compose: webcam + crop + export settings ────────────────────
|
|
532
|
+
{
|
|
533
|
+
name: "project_set_webcam_layout",
|
|
534
|
+
description:
|
|
535
|
+
"Set the webcam layout preset and optional position/scale for the current project. Use 'none' to hide the webcam overlay entirely.",
|
|
536
|
+
inputSchema: {
|
|
537
|
+
type: "object",
|
|
538
|
+
properties: {
|
|
539
|
+
id: { type: "string" },
|
|
540
|
+
path: { type: "string" },
|
|
541
|
+
preset: {
|
|
542
|
+
type: "string",
|
|
543
|
+
description:
|
|
544
|
+
"picture-in-picture | vertical-stack | side-by-side | none. 'none' hides the webcam.",
|
|
545
|
+
},
|
|
546
|
+
cx: {
|
|
547
|
+
type: "number",
|
|
548
|
+
description:
|
|
549
|
+
"Horizontal center of the webcam overlay, normalised 0-1. Only for picture-in-picture.",
|
|
550
|
+
},
|
|
551
|
+
cy: {
|
|
552
|
+
type: "number",
|
|
553
|
+
description:
|
|
554
|
+
"Vertical center of the webcam overlay, normalised 0-1. Only for picture-in-picture.",
|
|
555
|
+
},
|
|
556
|
+
scale: {
|
|
557
|
+
type: "number",
|
|
558
|
+
description: "Size multiplier for the webcam overlay. Default 1.0.",
|
|
559
|
+
},
|
|
560
|
+
cropX: { type: "number", description: "Webcam crop left edge, normalised 0-1." },
|
|
561
|
+
cropY: { type: "number", description: "Webcam crop top edge, normalised 0-1." },
|
|
562
|
+
cropWidth: { type: "number", description: "Webcam crop width, normalised 0-1." },
|
|
563
|
+
cropHeight: { type: "number", description: "Webcam crop height, normalised 0-1." },
|
|
564
|
+
expectedRevision: { type: "number" },
|
|
565
|
+
},
|
|
566
|
+
required: ["preset"],
|
|
567
|
+
},
|
|
568
|
+
command: "project.set-webcam-layout",
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
name: "project_set_crop",
|
|
572
|
+
description:
|
|
573
|
+
"Set the main video crop region for the project. All values are normalised 0-1 relative to the source frame dimensions. Default is { x:0, y:0, width:1, height:1 } (no crop).",
|
|
574
|
+
inputSchema: {
|
|
575
|
+
type: "object",
|
|
576
|
+
properties: {
|
|
577
|
+
id: { type: "string" },
|
|
578
|
+
path: { type: "string" },
|
|
579
|
+
x: { type: "number", description: "Left edge, normalised 0-1" },
|
|
580
|
+
y: { type: "number", description: "Top edge, normalised 0-1" },
|
|
581
|
+
width: { type: "number", description: "Crop width, normalised 0-1" },
|
|
582
|
+
height: { type: "number", description: "Crop height, normalised 0-1" },
|
|
583
|
+
expectedRevision: { type: "number" },
|
|
584
|
+
},
|
|
585
|
+
required: ["x", "y", "width", "height"],
|
|
586
|
+
},
|
|
587
|
+
command: "project.set-crop",
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
name: "project_set_export_settings",
|
|
591
|
+
description:
|
|
592
|
+
"Pre-configure the project's export defaults (quality, format, resolution). These are the settings the Export dialog opens with — they don't affect the CLI export_start quality flag.",
|
|
593
|
+
inputSchema: {
|
|
594
|
+
type: "object",
|
|
595
|
+
properties: {
|
|
596
|
+
id: { type: "string" },
|
|
597
|
+
path: { type: "string" },
|
|
598
|
+
quality: {
|
|
599
|
+
type: "string",
|
|
600
|
+
description: "medium | good | source. Controls CRF/bitrate preset.",
|
|
601
|
+
},
|
|
602
|
+
format: {
|
|
603
|
+
type: "string",
|
|
604
|
+
description: "mp4 | webm | gif. Default mp4.",
|
|
605
|
+
},
|
|
606
|
+
resolution: {
|
|
607
|
+
type: "string",
|
|
608
|
+
description:
|
|
609
|
+
"Output resolution: 4k | 1080p | 720p | 480p | source. Default source.",
|
|
610
|
+
},
|
|
611
|
+
gifFrameRate: {
|
|
612
|
+
type: "number",
|
|
613
|
+
description: "GIF frame rate (fps). Only used when format is gif. Default 15.",
|
|
614
|
+
},
|
|
615
|
+
gifSize: {
|
|
616
|
+
type: "string",
|
|
617
|
+
description:
|
|
618
|
+
"GIF size preset: small | medium | large. Only used when format is gif.",
|
|
619
|
+
},
|
|
620
|
+
expectedRevision: { type: "number" },
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
command: "project.set-export-settings",
|
|
624
|
+
},
|
|
625
|
+
|
|
626
|
+
{
|
|
627
|
+
name: "project_set_aspect_ratio",
|
|
628
|
+
description:
|
|
629
|
+
"Change the project's output aspect ratio. Affects the canvas size and how the video is cropped/letterboxed on export. Pick based on the target platform: 16:9 for YouTube/desktop, 9:16 for Shorts/Reels/TikTok, 1:1 for Instagram feed.",
|
|
630
|
+
inputSchema: {
|
|
631
|
+
type: "object",
|
|
632
|
+
properties: {
|
|
633
|
+
id: { type: "string" },
|
|
634
|
+
path: { type: "string" },
|
|
635
|
+
ratio: {
|
|
636
|
+
type: "string",
|
|
637
|
+
description: "16:9 | 9:16 | 1:1 | 4:3 | 3:4",
|
|
638
|
+
},
|
|
639
|
+
expectedRevision: { type: "number" },
|
|
640
|
+
},
|
|
641
|
+
required: ["ratio"],
|
|
642
|
+
},
|
|
643
|
+
command: "project.set-aspect-ratio",
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
name: "project_set_wallpaper",
|
|
647
|
+
description:
|
|
648
|
+
"Set the project's background wallpaper. Pass a bundled wallpaper id (e.g. 'gradient-blue', 'dark-mesh') or 'none' to remove the background. The available wallpaper ids match the filenames in the app's /public/wallpapers/ directory.",
|
|
649
|
+
inputSchema: {
|
|
650
|
+
type: "object",
|
|
651
|
+
properties: {
|
|
652
|
+
id: { type: "string" },
|
|
653
|
+
path: { type: "string" },
|
|
654
|
+
wallpaper: {
|
|
655
|
+
type: "string",
|
|
656
|
+
description: "Bundled wallpaper id or 'none' to remove background",
|
|
657
|
+
},
|
|
658
|
+
expectedRevision: { type: "number" },
|
|
659
|
+
},
|
|
660
|
+
required: ["wallpaper"],
|
|
661
|
+
},
|
|
662
|
+
command: "project.set-wallpaper",
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
name: "project_set_style",
|
|
666
|
+
description:
|
|
667
|
+
"Adjust the project's cinematic framing style: padding around the recording (0-200), drop shadow intensity (0-100), border radius (0-100), motion blur amount (0-100), and whether to show blur behind the recording. Pass only the fields you want to change — others are left as-is.",
|
|
668
|
+
inputSchema: {
|
|
669
|
+
type: "object",
|
|
670
|
+
properties: {
|
|
671
|
+
id: { type: "string" },
|
|
672
|
+
path: { type: "string" },
|
|
673
|
+
padding: { type: "number", description: "Padding around the recording in px. 0-200." },
|
|
674
|
+
shadowIntensity: { type: "number", description: "Drop shadow strength. 0-100." },
|
|
675
|
+
borderRadius: { type: "number", description: "Corner rounding. 0-100." },
|
|
676
|
+
motionBlurAmount: { type: "number", description: "Motion blur strength. 0-100." },
|
|
677
|
+
showBlur: {
|
|
678
|
+
type: "boolean",
|
|
679
|
+
description: "Whether to show a blurred background behind the recording.",
|
|
680
|
+
},
|
|
681
|
+
expectedRevision: { type: "number" },
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
command: "project.set-style",
|
|
685
|
+
},
|
|
686
|
+
|
|
367
687
|
// ── transcript-based editing ────────────────────────────────────
|
|
368
688
|
{
|
|
369
689
|
name: "transcript_transcribe",
|
|
@@ -442,6 +762,41 @@ const TOOLS = [
|
|
|
442
762
|
},
|
|
443
763
|
command: "transcript.search",
|
|
444
764
|
},
|
|
765
|
+
{
|
|
766
|
+
name: "transcript_find_replace",
|
|
767
|
+
description:
|
|
768
|
+
"Find the first occurrence of a phrase in the transcript and replace it with new text. Useful for correcting mis-transcribed names, technical terms, or brand names without re-transcribing. Returns { matched, replacements } — matched is false if the phrase wasn't found.",
|
|
769
|
+
inputSchema: {
|
|
770
|
+
type: "object",
|
|
771
|
+
properties: {
|
|
772
|
+
id: { type: "string" },
|
|
773
|
+
path: { type: "string" },
|
|
774
|
+
find: { type: "string", description: "Phrase to search for (case-insensitive)" },
|
|
775
|
+
replace: { type: "string", description: "Replacement text (replaces the whole phrase)" },
|
|
776
|
+
expectedRevision: { type: "number" },
|
|
777
|
+
},
|
|
778
|
+
required: ["find", "replace"],
|
|
779
|
+
},
|
|
780
|
+
command: "transcript.find-replace",
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
name: "transcript_remove_silences",
|
|
784
|
+
description:
|
|
785
|
+
"Detect and trim silent gaps in the recording — leading silence before the first word, trailing silence after the last word, and inter-word gaps longer than `thresholdMs`. Bulk-creates trim regions. Returns { removed, totalTrimmedMs }.",
|
|
786
|
+
inputSchema: {
|
|
787
|
+
type: "object",
|
|
788
|
+
properties: {
|
|
789
|
+
id: { type: "string" },
|
|
790
|
+
path: { type: "string" },
|
|
791
|
+
thresholdMs: {
|
|
792
|
+
type: "number",
|
|
793
|
+
description: "Gaps longer than this are trimmed. Default 700ms.",
|
|
794
|
+
},
|
|
795
|
+
expectedRevision: { type: "number" },
|
|
796
|
+
},
|
|
797
|
+
},
|
|
798
|
+
command: "transcript.remove-silences",
|
|
799
|
+
},
|
|
445
800
|
|
|
446
801
|
// ── audio ───────────────────────────────────────────────────────
|
|
447
802
|
{
|
|
@@ -492,6 +847,39 @@ const TOOLS = [
|
|
|
492
847
|
command: "caption.set-template",
|
|
493
848
|
},
|
|
494
849
|
|
|
850
|
+
{
|
|
851
|
+
name: "caption_set_style",
|
|
852
|
+
description:
|
|
853
|
+
"Override specific style properties of the caption overlay without changing the template. All fields are optional — pass only what you want to change. positionY controls vertical placement (0=top, 100=bottom, default 85). fontSize accepts CSS values like '28px' or '1.5em'.",
|
|
854
|
+
inputSchema: {
|
|
855
|
+
type: "object",
|
|
856
|
+
properties: {
|
|
857
|
+
id: { type: "string" },
|
|
858
|
+
path: { type: "string" },
|
|
859
|
+
wordsPerLine: {
|
|
860
|
+
type: "number",
|
|
861
|
+
description: "Max words shown at once. Default varies by template.",
|
|
862
|
+
},
|
|
863
|
+
positionY: { type: "number", description: "Vertical position 0-100. Default 85." },
|
|
864
|
+
color: { type: "string", description: "Caption text color (hex/CSS)" },
|
|
865
|
+
backgroundColor: { type: "string", description: "Caption background color" },
|
|
866
|
+
highlightColor: {
|
|
867
|
+
type: "string",
|
|
868
|
+
description: "Color of the currently-spoken word highlight",
|
|
869
|
+
},
|
|
870
|
+
highlightBackgroundColor: {
|
|
871
|
+
type: "string",
|
|
872
|
+
description: "Background of the currently-spoken word",
|
|
873
|
+
},
|
|
874
|
+
strokeColor: { type: "string", description: "Text stroke/outline color" },
|
|
875
|
+
strokeWidth: { type: "number", description: "Text stroke width in px" },
|
|
876
|
+
fontSize: { type: "string", description: "CSS font-size value, e.g. '28px'" },
|
|
877
|
+
expectedRevision: { type: "number" },
|
|
878
|
+
},
|
|
879
|
+
},
|
|
880
|
+
command: "caption.set-style",
|
|
881
|
+
},
|
|
882
|
+
|
|
495
883
|
// ── motion graphics ─────────────────────────────────────────────
|
|
496
884
|
{
|
|
497
885
|
name: "motion_list",
|
|
@@ -719,7 +1107,7 @@ const TOOLS = [
|
|
|
719
1107
|
const server = new Server(
|
|
720
1108
|
{
|
|
721
1109
|
name: "pandastudio",
|
|
722
|
-
version: "1.
|
|
1110
|
+
version: "1.11.0",
|
|
723
1111
|
},
|
|
724
1112
|
{
|
|
725
1113
|
capabilities: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@writepanda/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.1",
|
|
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",
|