@writepanda/mcp 1.234.0 → 1.241.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 +145 -20
- package/package.json +1 -1
package/bin/server.mjs
CHANGED
|
@@ -3065,6 +3065,58 @@ const TOOLS = [
|
|
|
3065
3065
|
},
|
|
3066
3066
|
command: "audio.probe",
|
|
3067
3067
|
},
|
|
3068
|
+
{
|
|
3069
|
+
name: "audio_detect_beats",
|
|
3070
|
+
description:
|
|
3071
|
+
"Beats of a music track on the EDITED timeline: beatsMs, downbeatsMs (bar starts, 4/4 estimated), tempoBpm, confidence. Local analysis, cached per file; follows the track's trim, in-point and loop. regionId = audio overlay id (default: the longest music track). Use to time cuts, graphics or B-roll to music; project_place_on_beats does a whole montage. No beats / confidence < 0.2 = no steady beat.",
|
|
3072
|
+
inputSchema: {
|
|
3073
|
+
type: "object",
|
|
3074
|
+
properties: {
|
|
3075
|
+
id: { type: "string" },
|
|
3076
|
+
path: { type: "string" },
|
|
3077
|
+
regionId: {
|
|
3078
|
+
type: "string",
|
|
3079
|
+
description: "Audio overlay id. Default: the longest music track.",
|
|
3080
|
+
},
|
|
3081
|
+
fromMs: { type: "number", minimum: 0, description: "Only beats from here (edited ms)." },
|
|
3082
|
+
toMs: { type: "number", minimum: 0, description: "Only beats up to here (edited ms)." },
|
|
3083
|
+
force: { type: "boolean", description: "Re-analyse instead of using the cache." },
|
|
3084
|
+
},
|
|
3085
|
+
},
|
|
3086
|
+
command: "audio.detect-beats",
|
|
3087
|
+
},
|
|
3088
|
+
{
|
|
3089
|
+
name: "project_place_on_beats",
|
|
3090
|
+
description:
|
|
3091
|
+
"Music-driven montage: lay pictures / B-roll / video overlays out so each changes on the beat. regionIds = existing overlay ids in play order (retimed; B-roll transitions follow) OR paths = new image/video files to add full-frame. every: 1 (every beat), 2 (default), 4 (every bar, from a downbeat). fromMs/toMs bound the run (default: the music's span). Item i plays from cut i to cut i+1; extras come back in unplaced.",
|
|
3092
|
+
inputSchema: {
|
|
3093
|
+
type: "object",
|
|
3094
|
+
properties: {
|
|
3095
|
+
id: { type: "string" },
|
|
3096
|
+
path: { type: "string" },
|
|
3097
|
+
regionIds: {
|
|
3098
|
+
type: "array",
|
|
3099
|
+
items: { type: "string" },
|
|
3100
|
+
description: "Overlay ids, in play order.",
|
|
3101
|
+
},
|
|
3102
|
+
paths: {
|
|
3103
|
+
type: "array",
|
|
3104
|
+
items: { type: "string" },
|
|
3105
|
+
description: "Or image/video files to add, in play order.",
|
|
3106
|
+
},
|
|
3107
|
+
every: { type: "number", enum: [1, 2, 4], description: "Beats per item. Default 2." },
|
|
3108
|
+
fromMs: { type: "number", minimum: 0 },
|
|
3109
|
+
toMs: { type: "number", minimum: 0 },
|
|
3110
|
+
musicRegionId: {
|
|
3111
|
+
type: "string",
|
|
3112
|
+
description: "Audio overlay to follow. Default: the longest music track.",
|
|
3113
|
+
},
|
|
3114
|
+
expectedRevision: { type: "number" },
|
|
3115
|
+
},
|
|
3116
|
+
required: ["id"],
|
|
3117
|
+
},
|
|
3118
|
+
command: "project.place-on-beats",
|
|
3119
|
+
},
|
|
3068
3120
|
{
|
|
3069
3121
|
name: "project_set_region_sound",
|
|
3070
3122
|
description: "Set or clear the SFX on an existing zoom, motionGraphic or fx region.",
|
|
@@ -3952,9 +4004,14 @@ const TOOLS = [
|
|
|
3952
4004
|
fadeOut: { type: "number", description: "ms; needs endMs." },
|
|
3953
4005
|
anchorSourceMs: { type: "number", description: "SFX only (not music): SOURCE ms anchor." },
|
|
3954
4006
|
anchorSourceEndMs: ANCHOR_END_PROP,
|
|
4007
|
+
loop: {
|
|
4008
|
+
type: "boolean",
|
|
4009
|
+
description: "Repeat the file to endMs (a ~30 s Lyria clip under a longer video).",
|
|
4010
|
+
},
|
|
3955
4011
|
transcribe: {
|
|
3956
4012
|
type: "boolean",
|
|
3957
|
-
description:
|
|
4013
|
+
description:
|
|
4014
|
+
"Words into the transcript (job_wait transcribeJobId). A generated narration is in by DEFAULT (script timed to the audio); false keeps it out. true transcribes any other voiceover.",
|
|
3958
4015
|
},
|
|
3959
4016
|
ducking: {
|
|
3960
4017
|
description: "Duck under the voice: true or a ducking object.",
|
|
@@ -4069,6 +4126,46 @@ const TOOLS = [
|
|
|
4069
4126
|
},
|
|
4070
4127
|
command: "project.set-clip-color",
|
|
4071
4128
|
},
|
|
4129
|
+
{
|
|
4130
|
+
name: "project_align_cursor",
|
|
4131
|
+
description:
|
|
4132
|
+
"Fix a screen recording whose drawn cursor / cursor auto-zooms land in the wrong place (old recordings saved the pointer with the wrong mapping) without re-recording. Pins: at atMs the REAL pointer (or what was clicked) is at x,y, fractions 0-1 of the recorded frame. 1 pin = offset; 2+ pins far apart also fix scale per axis. Stored on the clip (non-destructive), used by preview, export and auto-zoom; cursor auto-zooms follow unless moveZooms false. reset removes it. Check with project_render_frame.",
|
|
4133
|
+
inputSchema: {
|
|
4134
|
+
type: "object",
|
|
4135
|
+
properties: {
|
|
4136
|
+
id: { type: "string" },
|
|
4137
|
+
path: { type: "string" },
|
|
4138
|
+
clipId: {
|
|
4139
|
+
type: "string",
|
|
4140
|
+
description: "Default: the clip under the first pin (or the only clip).",
|
|
4141
|
+
},
|
|
4142
|
+
points: {
|
|
4143
|
+
type: "array",
|
|
4144
|
+
description:
|
|
4145
|
+
"[{atMs (edited timeline ms) or sourceMs (clip's own ms), x 0-1, y 0-1}] where the real pointer is.",
|
|
4146
|
+
items: {
|
|
4147
|
+
type: "object",
|
|
4148
|
+
properties: {
|
|
4149
|
+
atMs: { type: "number" },
|
|
4150
|
+
sourceMs: { type: "number" },
|
|
4151
|
+
x: { type: "number" },
|
|
4152
|
+
y: { type: "number" },
|
|
4153
|
+
},
|
|
4154
|
+
required: ["x", "y"],
|
|
4155
|
+
},
|
|
4156
|
+
},
|
|
4157
|
+
add: { type: "boolean", description: "Add to the clip's existing pins (refine)." },
|
|
4158
|
+
reset: { type: "boolean", description: "Remove the correction." },
|
|
4159
|
+
moveZooms: {
|
|
4160
|
+
type: "boolean",
|
|
4161
|
+
description: "Re-point cursor-placed auto-zooms with it (default true).",
|
|
4162
|
+
},
|
|
4163
|
+
dryRun: { type: "boolean" },
|
|
4164
|
+
expectedRevision: { type: "number" },
|
|
4165
|
+
},
|
|
4166
|
+
},
|
|
4167
|
+
command: "project.align-cursor",
|
|
4168
|
+
},
|
|
4072
4169
|
{
|
|
4073
4170
|
name: "project_set_clip_chroma_key",
|
|
4074
4171
|
description:
|
|
@@ -4402,7 +4499,7 @@ const TOOLS = [
|
|
|
4402
4499
|
{
|
|
4403
4500
|
name: "transcript_transcribe",
|
|
4404
4501
|
description:
|
|
4405
|
-
"Transcribe clips with word timestamps (default: only clips without words). Engine: language auto/english = Parakeet; any other named language = local Whisper LOCKED to it (engine override). Returns { jobId, plan } (plan = engine + reason, ranges, totalAudioMs: the audio that will be processed; tell the user for long jobs). To REDO a transcript (wrong language, bad run) confirm language, pass per-run language and provider overrides, 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 tail trim, e.g. one half of a split; only the kept parts when cuts hide most of a long recording; result transcribedRanges[]). ASYNC: { jobId }, job_wait. Concurrent saves are merged and retried (three attempts). Exhausted conflicts report code revision_conflict / status 409 (job.errorDetails for async jobs).",
|
|
4502
|
+
"Transcribe clips with word timestamps (default: only clips without words). Engine: language auto/english = Parakeet; any other named language = local Whisper LOCKED to it (engine override). Returns { jobId, plan } (plan = engine + reason, ranges, totalAudioMs: the audio that will be processed, estimate/estimatedMs: how long on this computer, advice: faster options for a long Whisper run; tell the user for long jobs). Long Whisper runs are saved chunk by chunk: stalls restart from the last chunk automatically; after job_cancel, a crash or an app restart, transcribing again resumes there. Progress is real (audio decoded); time left in progress.message and progress.data.etaMs. To REDO a transcript (wrong language, bad run) confirm language, pass per-run language and provider overrides, 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 tail trim, e.g. one half of a split; only the kept parts when cuts hide most of a long recording; result transcribedRanges[]). ASYNC: { jobId }, job_wait. Concurrent saves are merged and retried (three attempts). Exhausted conflicts report code revision_conflict / status 409 (job.errorDetails for async jobs).",
|
|
4406
4503
|
inputSchema: {
|
|
4407
4504
|
type: "object",
|
|
4408
4505
|
properties: {
|
|
@@ -4443,6 +4540,26 @@ const TOOLS = [
|
|
|
4443
4540
|
inputSchema: { type: "object", properties: {} },
|
|
4444
4541
|
command: "system.download-whisper-model",
|
|
4445
4542
|
},
|
|
4543
|
+
{
|
|
4544
|
+
name: "transcript_align_narration",
|
|
4545
|
+
description:
|
|
4546
|
+
"Generated narrations into the transcript and captions (script timed to the audio with local speech recognition: the words are exactly the script). New narrations are aligned automatically; use for older projects (default: every narration with a script but no words), force re-timing, or include false to keep one out (sung / non-speech) / true to put it back. ASYNC { jobIds }: job_wait each.",
|
|
4547
|
+
inputSchema: {
|
|
4548
|
+
type: "object",
|
|
4549
|
+
properties: {
|
|
4550
|
+
id: { type: "string" },
|
|
4551
|
+
path: { type: "string" },
|
|
4552
|
+
regionId: {
|
|
4553
|
+
type: "string",
|
|
4554
|
+
description: "One narration (audio-N); omit for all that need it.",
|
|
4555
|
+
},
|
|
4556
|
+
include: { type: "boolean", description: "false = out of transcript + captions." },
|
|
4557
|
+
force: { type: "boolean", description: "Re-align even with words." },
|
|
4558
|
+
expectedRevision: { type: "number" },
|
|
4559
|
+
},
|
|
4560
|
+
},
|
|
4561
|
+
command: "transcript.align-narration",
|
|
4562
|
+
},
|
|
4446
4563
|
{
|
|
4447
4564
|
name: "transcript_import",
|
|
4448
4565
|
description:
|
|
@@ -4665,7 +4782,7 @@ const TOOLS = [
|
|
|
4665
4782
|
{
|
|
4666
4783
|
name: "transcript_remove_silences",
|
|
4667
4784
|
description:
|
|
4668
|
-
"Remove measured quiet runs inside transcript pauses (never into a word) with a 50ms decay hold. Counts only visible time (nothing under a head trim or existing cut). Returns snapped/skipped/warnings; snapToAudio=false uses legacy timing.",
|
|
4785
|
+
"Remove measured quiet runs inside transcript pauses (never into a word) with a 50ms decay hold. Counts only visible time (nothing under a head trim or existing cut). Returns snapped/skipped/warnings; snapToAudio=false uses legacy timing. Applies its cuts to the project as it is when it writes (editor saves meanwhile are kept, no revision_conflict). Fails with code media_offline / media_read_stalled / media_read_too_slow when the source (e.g. an online-only Dropbox / iCloud file) can't be read: tell the user to make it available offline, then run again; project_changed_during_analysis when the clips or word timings kept changing.",
|
|
4669
4786
|
inputSchema: {
|
|
4670
4787
|
type: "object",
|
|
4671
4788
|
properties: {
|
|
@@ -5056,7 +5173,7 @@ const TOOLS = [
|
|
|
5056
5173
|
{
|
|
5057
5174
|
name: "media_regenerate_narration",
|
|
5058
5175
|
description:
|
|
5059
|
-
"Regenerate a narration already on the timeline IN PLACE from its stored source (script, model, voice, tone on audioOverlays[].generatedFrom). Pass only what changes (text with the edited script, voice, model, ...). Same start, volume, fades, ducking; length = new audio.
|
|
5176
|
+
"Regenerate a narration already on the timeline IN PLACE from its stored source (script, model, voice, tone on audioOverlays[].generatedFrom). Pass only what changes (text with the edited script, voice, model, ...). Same start, volume, fades, ducking; length = new audio. Its words in the transcript are re-timed to the new take from the script (transcribeJobId: job_wait it) unless it opted out. One undo step. No stored source (older narration) = pass text.",
|
|
5060
5177
|
inputSchema: {
|
|
5061
5178
|
type: "object",
|
|
5062
5179
|
properties: {
|
|
@@ -5585,30 +5702,38 @@ const TOOLS = [
|
|
|
5585
5702
|
{
|
|
5586
5703
|
name: "media_generate_music",
|
|
5587
5704
|
description:
|
|
5588
|
-
"Generate instrumental music via Replicate
|
|
5705
|
+
"Generate a ~30 s instrumental music clip with Google Lyria 2 via Replicate (paid, user's account). Under a longer video add it with project_add_audio loop=true endMs=<video>. Returns { audioPath, durationMs, generatedFrom }. MusicGen was removed (non-commercial licence): no model choice, reference, continuation or length.",
|
|
5589
5706
|
inputSchema: {
|
|
5590
5707
|
type: "object",
|
|
5591
5708
|
properties: {
|
|
5592
5709
|
prompt: { type: "string", description: "Genre, mood, instruments, tempo." },
|
|
5593
|
-
negativePrompt: { type: "string", description: "
|
|
5710
|
+
negativePrompt: { type: "string", description: "Qualities to avoid." },
|
|
5594
5711
|
seed: { type: "number" },
|
|
5595
|
-
model: { type: "string", enum: ["lyria", "musicgen"] },
|
|
5596
|
-
reference: {
|
|
5597
|
-
type: "string",
|
|
5598
|
-
description: "musicgen: absolute path (audio or video) to match.",
|
|
5599
|
-
},
|
|
5600
|
-
referenceStartMs: { type: "number" },
|
|
5601
|
-
referenceDurationMs: { type: "number", description: "Default 15000, max 30000." },
|
|
5602
|
-
continuation: { type: "boolean" },
|
|
5603
|
-
durationSec: {
|
|
5604
|
-
type: "number",
|
|
5605
|
-
description: "musicgen: default 30, max 300.",
|
|
5606
|
-
},
|
|
5607
5712
|
},
|
|
5608
5713
|
required: ["prompt"],
|
|
5609
5714
|
},
|
|
5610
5715
|
command: "media.generate-music",
|
|
5611
5716
|
},
|
|
5717
|
+
{
|
|
5718
|
+
name: "media_regenerate_music",
|
|
5719
|
+
description:
|
|
5720
|
+
"Regenerate a generated music track on the timeline IN PLACE with Lyria from its stored source (prompt, avoid, seed on audioOverlays[].generatedFrom). Pass only what changes; newSeed for a fresh variation. Keeps start, level, fades, ducking; a looping bed keeps its window. A track made with MusicGen (removed) regenerates with Lyria. Paid Replicate run, only when asked.",
|
|
5721
|
+
inputSchema: {
|
|
5722
|
+
type: "object",
|
|
5723
|
+
properties: {
|
|
5724
|
+
id: { type: "string" },
|
|
5725
|
+
path: { type: "string" },
|
|
5726
|
+
regionId: { type: "string", description: "The track's audio overlay id (audio-N)." },
|
|
5727
|
+
prompt: { type: "string" },
|
|
5728
|
+
negativePrompt: { type: "string", description: "Avoid; '' clears." },
|
|
5729
|
+
seed: { type: "number" },
|
|
5730
|
+
newSeed: { type: "boolean", description: "A fresh variation." },
|
|
5731
|
+
expectedRevision: { type: "number" },
|
|
5732
|
+
},
|
|
5733
|
+
required: ["regionId"],
|
|
5734
|
+
},
|
|
5735
|
+
command: "media.regenerate-music",
|
|
5736
|
+
},
|
|
5612
5737
|
{
|
|
5613
5738
|
name: "media_remove_background",
|
|
5614
5739
|
description:
|
|
@@ -6438,7 +6563,7 @@ const TOOLS = [
|
|
|
6438
6563
|
{
|
|
6439
6564
|
name: "clips_make",
|
|
6440
6565
|
description:
|
|
6441
|
-
"Long video (podcast, webinar, talk) in, scored vertical clips out, no agent needed: imports, transcribes, finds the best sentence-aligned moments across the whole video (local AI + transcript score), and forks each into its own 9:16 project with captions and face-following framing. Async: returns { clipSetId, jobId }; poll clips_get. Then clips_export, or edit a clip's projectPath with any project tool.",
|
|
6566
|
+
"Long video (podcast, webinar, talk) in, scored vertical clips out, no agent needed: imports, transcribes, finds the best sentence-aligned moments across the whole video (local AI + transcript score), and forks each into its own 9:16 project with captions and face-following framing. Async: returns { clipSetId, jobId, transcription: { engine, estimate, estimatedMs, advice? } } (tell the user the estimate; advice = faster options for a long Whisper run); poll clips_get. Then clips_export, or edit a clip's projectPath with any project tool.",
|
|
6442
6567
|
inputSchema: {
|
|
6443
6568
|
type: "object",
|
|
6444
6569
|
properties: {
|
|
@@ -6476,7 +6601,7 @@ const TOOLS = [
|
|
|
6476
6601
|
{
|
|
6477
6602
|
name: "clips_get",
|
|
6478
6603
|
description:
|
|
6479
|
-
"One clip set: status (importing, transcribing, finding, building, ready, error), usedModel, sourceProjectPath and clips[] best-first ({ id, title, hook, score 0-100, startMs, endMs, status, projectPath, thumbPath, exportedPath }).",
|
|
6604
|
+
"One clip set: status (importing, transcribing, finding, building, ready, error), stage { message, percent }, transcription { engine, estimate, advice?, etaMs (time left while transcribing) }, usedModel, sourceProjectPath and clips[] best-first ({ id, title, hook, score 0-100, startMs, endMs, status, projectPath, thumbPath, exportedPath }).",
|
|
6480
6605
|
inputSchema: {
|
|
6481
6606
|
type: "object",
|
|
6482
6607
|
properties: { id: { type: "string", description: "Clip set id." } },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@writepanda/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.241.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",
|