@writepanda/mcp 1.207.0 → 1.210.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.
- package/bin/server.mjs +140 -19
- package/package.json +1 -1
package/bin/server.mjs
CHANGED
|
@@ -627,7 +627,11 @@ const MOTION_ELEMENT_PROPS = {
|
|
|
627
627
|
enum: ["auto", "none", "pop", "whoosh", "hit", "tick", "bell"],
|
|
628
628
|
description: "Role for project_compose_soundtrack.",
|
|
629
629
|
},
|
|
630
|
-
zIndex: {
|
|
630
|
+
zIndex: {
|
|
631
|
+
type: "number",
|
|
632
|
+
description:
|
|
633
|
+
"Stack order, higher on top (default 0). Front elements share one stack with media overlays and annotations at group base + zIndex (B-roll 0, overlays 1000, annotations 2000, front elements 3000), so by default they draw over both; -2500 drops one under the default overlays.",
|
|
634
|
+
},
|
|
631
635
|
anchor: { type: "string", enum: ["auto", "free"] },
|
|
632
636
|
};
|
|
633
637
|
const TOOLS = [
|
|
@@ -635,7 +639,7 @@ const TOOLS = [
|
|
|
635
639
|
{
|
|
636
640
|
name: "system_status",
|
|
637
641
|
description:
|
|
638
|
-
"App version and license; automationGated true = trial expired, or the Solo plan (license.agentEditing.allowed false: no agent editing, relay license.agentEditing.message to the user), and every other tool fails; license.socialPublishing.allowed false = the plan has no Instagram/TikTok/social publishing (Creator, Team, Pro only). Call first.",
|
|
642
|
+
"App version and license; automationGated true = trial expired, or the Solo plan (license.agentEditing.allowed false: no agent editing, relay license.agentEditing.message to the user), and every other tool fails; license.socialPublishing.allowed false = the plan has no Instagram/TikTok/social publishing (Creator, Team, Pro only); license.exportQuality.allowed = the export_start qualities that work (free trial: draft 720p only; standard/high/ultra need a license). Call first.",
|
|
639
643
|
inputSchema: { type: "object", properties: {} },
|
|
640
644
|
command: "system.status",
|
|
641
645
|
},
|
|
@@ -725,7 +729,7 @@ const TOOLS = [
|
|
|
725
729
|
{
|
|
726
730
|
name: "system_get_transcription_language",
|
|
727
731
|
description:
|
|
728
|
-
"Workspace transcription language
|
|
732
|
+
"Workspace transcription language. auto = Parakeet TDT v3, which detects the language itself across 25 languages, English included: Bulgarian, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, German, Greek, Hungarian, Italian, Latvian, Lithuanian, Maltese, Polish, Portuguese, Romanian, Russian, Slovak, Slovenian, Spanish, Swedish, Ukrainian. Anything else names a Whisper language.",
|
|
729
733
|
inputSchema: { type: "object", properties: {} },
|
|
730
734
|
command: "system.get-transcription-language",
|
|
731
735
|
},
|
|
@@ -752,7 +756,7 @@ const TOOLS = [
|
|
|
752
756
|
{
|
|
753
757
|
name: "system_set_transcription_language",
|
|
754
758
|
description:
|
|
755
|
-
"Set the workspace transcription language.
|
|
759
|
+
"Set the workspace transcription language. auto = Parakeet TDT v3, which detects the language itself across 25 languages, English included: Bulgarian, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, German, Greek, Hungarian, Italian, Latvian, Lithuanian, Maltese, Polish, Portuguese, Romanian, Russian, Slovak, Slovenian, Spanish, Swedish, Ukrainian. For any of those (e.g. Romanian) use auto; their names are accepted and saved as auto. The other values use Whisper, a ~1.1 GB download: tell the user first (system.is-whisper-model-downloaded via pandastudio_call).",
|
|
756
760
|
inputSchema: {
|
|
757
761
|
type: "object",
|
|
758
762
|
properties: {
|
|
@@ -762,6 +766,30 @@ const TOOLS = [
|
|
|
762
766
|
"auto",
|
|
763
767
|
"english",
|
|
764
768
|
"en",
|
|
769
|
+
"bulgarian",
|
|
770
|
+
"croatian",
|
|
771
|
+
"czech",
|
|
772
|
+
"danish",
|
|
773
|
+
"dutch",
|
|
774
|
+
"estonian",
|
|
775
|
+
"finnish",
|
|
776
|
+
"french",
|
|
777
|
+
"german",
|
|
778
|
+
"greek",
|
|
779
|
+
"hungarian",
|
|
780
|
+
"italian",
|
|
781
|
+
"latvian",
|
|
782
|
+
"lithuanian",
|
|
783
|
+
"maltese",
|
|
784
|
+
"polish",
|
|
785
|
+
"portuguese",
|
|
786
|
+
"romanian",
|
|
787
|
+
"russian",
|
|
788
|
+
"slovak",
|
|
789
|
+
"slovenian",
|
|
790
|
+
"spanish",
|
|
791
|
+
"swedish",
|
|
792
|
+
"ukrainian",
|
|
765
793
|
"chinese",
|
|
766
794
|
"japanese",
|
|
767
795
|
"korean",
|
|
@@ -1048,8 +1076,14 @@ const TOOLS = [
|
|
|
1048
1076
|
},
|
|
1049
1077
|
{
|
|
1050
1078
|
name: "youtube_connect",
|
|
1051
|
-
description:
|
|
1052
|
-
|
|
1079
|
+
description:
|
|
1080
|
+
"Connect a YouTube account via browser sign-in (only when the user asks). Pass email to reconnect an existing account. permissionIssue set = the user unticked a Google permission: relay its message.",
|
|
1081
|
+
inputSchema: {
|
|
1082
|
+
type: "object",
|
|
1083
|
+
properties: {
|
|
1084
|
+
email: { type: "string", description: "Reconnect: that account's email." },
|
|
1085
|
+
},
|
|
1086
|
+
},
|
|
1053
1087
|
command: "youtube.connect",
|
|
1054
1088
|
},
|
|
1055
1089
|
{
|
|
@@ -1065,13 +1099,15 @@ const TOOLS = [
|
|
|
1065
1099
|
},
|
|
1066
1100
|
{
|
|
1067
1101
|
name: "youtube_list_accounts",
|
|
1068
|
-
description:
|
|
1102
|
+
description:
|
|
1103
|
+
"Connected YouTube accounts and channels (pick before export_publish_youtube). issues[] = accounts missing a Google permission (code youtube_permission_missing): relay message, follow howToFix (the user reconnects in Settings > YouTube, leaving every box ticked; you can't do the sign-in).",
|
|
1069
1104
|
inputSchema: { type: "object", properties: {} },
|
|
1070
1105
|
command: "youtube.list-accounts",
|
|
1071
1106
|
},
|
|
1072
1107
|
{
|
|
1073
1108
|
name: "youtube_list_channels",
|
|
1074
|
-
description:
|
|
1109
|
+
description:
|
|
1110
|
+
"Refresh an account's channel list from YouTube (bypasses cache). Error code youtube_permission_missing = channel permission unticked on Google's screen: relay message, follow howToFix; canStillPublish true = publish without channelId.",
|
|
1075
1111
|
inputSchema: {
|
|
1076
1112
|
type: "object",
|
|
1077
1113
|
properties: { accountId: { type: "string" } },
|
|
@@ -1082,7 +1118,7 @@ const TOOLS = [
|
|
|
1082
1118
|
{
|
|
1083
1119
|
name: "export_publish_youtube",
|
|
1084
1120
|
description:
|
|
1085
|
-
"Publish an export entry to YouTube. Slow. Check the entry's youtubeVideoId before republishing. Returns { videoUrl }.",
|
|
1121
|
+
"Publish an export entry to YouTube. Slow. Check the entry's youtubeVideoId before republishing. channelId optional (uploads go to the account's own channel; omit when channels can't be listed). Error code youtube_permission_missing: relay message, follow howToFix. Returns { videoUrl, channelId }.",
|
|
1086
1122
|
inputSchema: {
|
|
1087
1123
|
type: "object",
|
|
1088
1124
|
properties: {
|
|
@@ -1096,7 +1132,7 @@ const TOOLS = [
|
|
|
1096
1132
|
privacyStatus: { type: "string", enum: ["public", "unlisted", "private"] },
|
|
1097
1133
|
setThumbnail: { type: "boolean" },
|
|
1098
1134
|
},
|
|
1099
|
-
required: ["id", "accountId", "
|
|
1135
|
+
required: ["id", "accountId", "title"],
|
|
1100
1136
|
},
|
|
1101
1137
|
command: "export.publish-youtube",
|
|
1102
1138
|
},
|
|
@@ -1380,7 +1416,7 @@ const TOOLS = [
|
|
|
1380
1416
|
{
|
|
1381
1417
|
name: "project_add_clip",
|
|
1382
1418
|
description:
|
|
1383
|
-
"Append or insert a video clip, or a still image shown for durationMs, on the main track (later content moves with it).
|
|
1419
|
+
"Append or insert a video clip, or a still image shown for durationMs, on the main track (later content moves with it). atMs (edited time) inserts at that moment, splitting the clip under it; add replaceToMs to replace [atMs, replaceToMs) with the clip (e.g. a re-recorded take).",
|
|
1384
1420
|
inputSchema: {
|
|
1385
1421
|
type: "object",
|
|
1386
1422
|
properties: {
|
|
@@ -1391,6 +1427,14 @@ const TOOLS = [
|
|
|
1391
1427
|
fill: { type: "boolean", description: "Images: cover the frame (default true)." },
|
|
1392
1428
|
webcam: { type: "string", description: "Guest source: a two-speaker podcast clip." },
|
|
1393
1429
|
atIndex: { type: "number", description: "0-based; omit = append." },
|
|
1430
|
+
atMs: {
|
|
1431
|
+
type: "number",
|
|
1432
|
+
description: "Insert at this edited ms (splits the clip there; not with atIndex).",
|
|
1433
|
+
},
|
|
1434
|
+
replaceToMs: {
|
|
1435
|
+
type: "number",
|
|
1436
|
+
description: "With atMs: cut [atMs, replaceToMs) (a trim) and put the clip there.",
|
|
1437
|
+
},
|
|
1394
1438
|
expectedRevision: { type: "number" },
|
|
1395
1439
|
},
|
|
1396
1440
|
required: ["media"],
|
|
@@ -1433,6 +1477,66 @@ const TOOLS = [
|
|
|
1433
1477
|
},
|
|
1434
1478
|
command: "project.add-podcast-clip",
|
|
1435
1479
|
},
|
|
1480
|
+
{
|
|
1481
|
+
name: "podcast_open_host",
|
|
1482
|
+
description: "Open or focus the live podcast host window. Call podcast_status for the session code and guest link once it loads.",
|
|
1483
|
+
inputSchema: {
|
|
1484
|
+
type: "object",
|
|
1485
|
+
properties: {
|
|
1486
|
+
sessionCode: { type: "string", description: "Resume an existing session." },
|
|
1487
|
+
projectPath: { type: "string", description: "Matching podcast project when resuming." },
|
|
1488
|
+
},
|
|
1489
|
+
},
|
|
1490
|
+
command: "podcast.open-host",
|
|
1491
|
+
},
|
|
1492
|
+
...[
|
|
1493
|
+
["status", "Read the live podcast session code, guest link, participants, recording, and sharing state."],
|
|
1494
|
+
["start-recording", "Start recording the host and signal connected guests to record. Returns once recording has really started; fails with the reason otherwise."],
|
|
1495
|
+
["stop-recording", "Stop recording and finalize podcast media. Check podcast_status for finalization and guest uploads."],
|
|
1496
|
+
["start-screen-share", "Open the desktop picker to share and record the host screen during a podcast. Waits for the host to choose; fails if the picker is cancelled or capture fails."],
|
|
1497
|
+
["stop-screen-share", "Stop and finalize the host's podcast screen share."],
|
|
1498
|
+
["open-in-editor", "Open the finished podcast in the editor when guest media has arrived."],
|
|
1499
|
+
].map(([noun, description]) => ({
|
|
1500
|
+
name: `podcast_${noun.replaceAll("-", "_")}`,
|
|
1501
|
+
description,
|
|
1502
|
+
inputSchema: { type: "object", properties: {} },
|
|
1503
|
+
command: `podcast.${noun}`,
|
|
1504
|
+
})),
|
|
1505
|
+
{
|
|
1506
|
+
name: "project_set_podcast_source_crop",
|
|
1507
|
+
description:
|
|
1508
|
+
"Frame one podcast camera or screen-share source independently. Use source=host|guest|guest-2|guest-3|share:0; normalized x,y,width,height. 0,0,1,1 resets the crop. Preview and export use the same framing.",
|
|
1509
|
+
inputSchema: {
|
|
1510
|
+
type: "object",
|
|
1511
|
+
properties: {
|
|
1512
|
+
id: { type: "string" },
|
|
1513
|
+
path: { type: "string" },
|
|
1514
|
+
clipId: { type: "string" },
|
|
1515
|
+
source: { type: "string", description: "host, guest, guest-2, guest-3, or share:<index>." },
|
|
1516
|
+
x: { type: "number", description: "Left edge, 0-1." },
|
|
1517
|
+
y: { type: "number", description: "Top edge, 0-1." },
|
|
1518
|
+
width: { type: "number", description: "Crop width, >0 to 1." },
|
|
1519
|
+
height: { type: "number", description: "Crop height, >0 to 1." },
|
|
1520
|
+
expectedRevision: { type: "number" },
|
|
1521
|
+
},
|
|
1522
|
+
required: ["clipId", "source", "x", "y", "width", "height"],
|
|
1523
|
+
},
|
|
1524
|
+
command: "project.set-podcast-source-crop",
|
|
1525
|
+
},
|
|
1526
|
+
{
|
|
1527
|
+
name: "project_list_podcast_screen_shares",
|
|
1528
|
+
description:
|
|
1529
|
+
"List the screen-share intervals shown on the podcast editor timeline. Returns speaker, clip-local and merged-source timing, edited timing after trims/speed, and whether each interval is visible. Read-only.",
|
|
1530
|
+
inputSchema: {
|
|
1531
|
+
type: "object",
|
|
1532
|
+
properties: {
|
|
1533
|
+
id: { type: "string" },
|
|
1534
|
+
path: { type: "string" },
|
|
1535
|
+
clipId: { type: "string", description: "Optional podcast clip filter." },
|
|
1536
|
+
},
|
|
1537
|
+
},
|
|
1538
|
+
command: "project.list-podcast-screen-shares",
|
|
1539
|
+
},
|
|
1436
1540
|
{
|
|
1437
1541
|
name: "project_set_participant_offset",
|
|
1438
1542
|
description: "Nudge one guest's A/V sync on a podcast composite (host is the reference).",
|
|
@@ -2923,7 +3027,7 @@ const TOOLS = [
|
|
|
2923
3027
|
{
|
|
2924
3028
|
name: "project_update_region",
|
|
2925
3029
|
description:
|
|
2926
|
-
"Patch a region; unspecified fields are kept. Patchable: zoom (depth, focusX, focusY, focusMode static|auto), trim / speed (startMs, endMs, speed, rampIn, rampOut, preservePitch, freezeMs, reverse, reverseAudio), fx (atMs, durationMs, opacity, blendMode, speed), annotation, overlay (x, y, width, height in canvas %, layer, opacity, blendMode, muted, volume, loop, motionBlur), adjustment (startMs, endMs, blendMode), motion (motionBlur), clip-transform (startMs, endMs, preset, transitionMs, easing, bezier), background-effect (as project_add_background_effect), audio-overlay (startMs, endMs, sourceStartMs, volume 0-2, fadeIn, fadeOut).",
|
|
3030
|
+
"Patch a region; unspecified fields are kept. Patchable: zoom (depth, focusX, focusY, focusMode static|auto), trim / speed (startMs, endMs, speed, rampIn, rampOut, preservePitch, freezeMs, reverse, reverseAudio), fx (atMs, durationMs, opacity, blendMode, speed, zIndex), annotation (zIndex), overlay (x, y, width, height in canvas %, layer, opacity, blendMode, muted, volume, loop, motionBlur, zIndex), adjustment (startMs, endMs, blendMode), motion (motionBlur), clip-transform (startMs, endMs, preset, transitionMs, easing, bezier), background-effect (as project_add_background_effect), audio-overlay (startMs, endMs, sourceStartMs, volume 0-2, fadeIn, fadeOut).",
|
|
2927
3031
|
inputSchema: {
|
|
2928
3032
|
type: "object",
|
|
2929
3033
|
properties: {
|
|
@@ -2932,7 +3036,11 @@ const TOOLS = [
|
|
|
2932
3036
|
path: { type: "string" },
|
|
2933
3037
|
regionType: { type: "string", enum: REGION_TYPES },
|
|
2934
3038
|
regionId: { type: "string" },
|
|
2935
|
-
patch: {
|
|
3039
|
+
patch: {
|
|
3040
|
+
type: "object",
|
|
3041
|
+
description:
|
|
3042
|
+
"e.g. { depth: 4 }; null clears a value. zIndex (overlay / annotation / fx): stack order, higher on top; overlays, annotations and front motion elements share one stack at group base + zIndex (B-roll 0, overlays 1000, annotations 2000, motion elements 3000).",
|
|
3043
|
+
},
|
|
2936
3044
|
expectedRevision: { type: "number" },
|
|
2937
3045
|
},
|
|
2938
3046
|
required: ["regionType", "regionId", "patch"],
|
|
@@ -3141,13 +3249,19 @@ const TOOLS = [
|
|
|
3141
3249
|
},
|
|
3142
3250
|
{
|
|
3143
3251
|
name: "project_set_export_settings",
|
|
3144
|
-
description:
|
|
3252
|
+
description:
|
|
3253
|
+
"Project export defaults (Export dialog and export_start). quality good and source need a license: a free trial gets quality_requires_license, use medium.",
|
|
3145
3254
|
inputSchema: {
|
|
3146
3255
|
type: "object",
|
|
3147
3256
|
properties: {
|
|
3148
3257
|
id: { type: "string" },
|
|
3149
3258
|
path: { type: "string" },
|
|
3150
|
-
quality: {
|
|
3259
|
+
quality: {
|
|
3260
|
+
type: "string",
|
|
3261
|
+
enum: ["medium", "good", "source"],
|
|
3262
|
+
description:
|
|
3263
|
+
"medium 720p, good 1080p, source = source resolution (good/source license only).",
|
|
3264
|
+
},
|
|
3151
3265
|
format: { type: "string", enum: ["mp4"] },
|
|
3152
3266
|
normalizeLoudness: {
|
|
3153
3267
|
type: ["boolean", "string"],
|
|
@@ -3575,7 +3689,7 @@ const TOOLS = [
|
|
|
3575
3689
|
{
|
|
3576
3690
|
name: "transcript_transcribe",
|
|
3577
3691
|
description:
|
|
3578
|
-
"Transcribe clips with word timestamps (default: only clips without words). To REDO a transcript (wrong language, bad run) fix the language first, then force: true (all clips) or clipId. Word fixes are re-applied; tell the user about result droppedWordEdits[] (fixes that may need redoing). ASYNC: { jobId }, job_wait.",
|
|
3692
|
+
"Transcribe clips with word timestamps (default: only clips without words). To REDO a transcript (wrong language, bad run) fix the language first, then force: true (all clips) or clipId. Word fixes are re-applied; tell the user about result droppedWordEdits[] (fixes that may need redoing). Each clip is transcribed only over the part it plays (head trim to out-point, e.g. one half of a split; result transcribedRanges[]). ASYNC: { jobId }, job_wait.",
|
|
3579
3693
|
inputSchema: {
|
|
3580
3694
|
type: "object",
|
|
3581
3695
|
properties: {
|
|
@@ -5043,14 +5157,19 @@ const TOOLS = [
|
|
|
5043
5157
|
{
|
|
5044
5158
|
name: "export_start",
|
|
5045
5159
|
description:
|
|
5046
|
-
"Render the project to MP4. ASYNC: { jobId, outputPath }; job_wait. Tell the user any warning and the result's loudness before / after.",
|
|
5160
|
+
"Render the project to MP4. ASYNC: { jobId, outputPath, quality }; job_wait. Tell the user any warning and the result's loudness before / after. Free trial: draft (720p) only (system_status license.exportQuality); standard/high/ultra fail with quality_requires_license.",
|
|
5047
5161
|
inputSchema: {
|
|
5048
5162
|
type: "object",
|
|
5049
5163
|
properties: {
|
|
5050
5164
|
id: { type: "string" },
|
|
5051
5165
|
path: { type: "string" },
|
|
5052
5166
|
outputPath: { type: "string" },
|
|
5053
|
-
quality: {
|
|
5167
|
+
quality: {
|
|
5168
|
+
type: "string",
|
|
5169
|
+
enum: ["draft", "standard", "high", "ultra"],
|
|
5170
|
+
description:
|
|
5171
|
+
"draft 720p, standard 1080p, high/ultra source resolution (standard and up: license only). Omit = high, or draft on a trial.",
|
|
5172
|
+
},
|
|
5054
5173
|
normalizeLoudness: {
|
|
5055
5174
|
type: ["boolean", "string"],
|
|
5056
5175
|
description: "streaming / podcast / off; omit = project setting.",
|
|
@@ -5165,7 +5284,7 @@ const TOOLS = [
|
|
|
5165
5284
|
{
|
|
5166
5285
|
name: "clips_export",
|
|
5167
5286
|
description:
|
|
5168
|
-
"Export a clip set's finished clips to MP4 (all, or clipIds) into Movies/PandaStudio Clips/<video
|
|
5287
|
+
"Export a clip set's finished clips to MP4 (all, or clipIds) into Movies/PandaStudio Clips/<video>/, at standard quality (1080p; 720p on a free trial). Async: returns { jobId, outputDir }; job_wait for { exported[] }.",
|
|
5169
5288
|
inputSchema: {
|
|
5170
5289
|
type: "object",
|
|
5171
5290
|
properties: {
|
|
@@ -5483,6 +5602,8 @@ const INSTRUCTIONS = `PandaStudio is a desktop video editor; these tools drive t
|
|
|
5483
5602
|
|
|
5484
5603
|
Start with system_status. Unknown arguments are rejected. Verbs without a tool of their own (system_list_commands) go through pandastudio_call.
|
|
5485
5604
|
|
|
5605
|
+
Read-only tools (project_read, transcript_get / _search / _find_issues, audio_probe, project_render_frame / _render_sheet, timeline_*, ...) use the project open in the editor when you pass no id or path; edits always need the id.
|
|
5606
|
+
|
|
5486
5607
|
Before an editing pass, read the skill's "Which tool for which moment" section (skill_read section="Which tool for which moment").
|
|
5487
5608
|
|
|
5488
5609
|
"Edit my video" / "make this a Short" with no specifics = this pipeline, in order. Confirm scope once ("full polish, or just part of it?"), then run it all:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@writepanda/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.210.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",
|