@writepanda/mcp 1.285.0 → 1.286.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 +128 -17
- package/package.json +1 -1
package/bin/server.mjs
CHANGED
|
@@ -1416,7 +1416,7 @@ const TOOLS = [
|
|
|
1416
1416
|
{
|
|
1417
1417
|
name: "youtube_list_accounts",
|
|
1418
1418
|
description:
|
|
1419
|
-
"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).",
|
|
1419
|
+
"Connected YouTube accounts and channels (pick before export_publish_youtube). Each channel's userLastPrivacy = what the user last picked in the app's Publish window (use only when they ask for their usual setting). 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).",
|
|
1420
1420
|
inputSchema: { type: "object", properties: {} },
|
|
1421
1421
|
command: "youtube.list-accounts",
|
|
1422
1422
|
},
|
|
@@ -1434,7 +1434,7 @@ const TOOLS = [
|
|
|
1434
1434
|
{
|
|
1435
1435
|
name: "export_publish_youtube",
|
|
1436
1436
|
description:
|
|
1437
|
-
"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. Error code daily_limit or youtube_quota_exceeded (with resetsAt): tell the user when it resets; never retry before resetsAt. Returns { videoUrl, channelId }.",
|
|
1437
|
+
"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. Error code daily_limit or youtube_quota_exceeded (with resetsAt): tell the user when it resets; never retry before resetsAt. privacyStatus defaults to unlisted: public only when the user asked. A vertical or square export of 3 min or less becomes a YouTube Short (result short: true); pass addShortsTag to add #Shorts. Returns { videoUrl, channelId, short }.",
|
|
1438
1438
|
inputSchema: {
|
|
1439
1439
|
type: "object",
|
|
1440
1440
|
properties: {
|
|
@@ -1447,6 +1447,10 @@ const TOOLS = [
|
|
|
1447
1447
|
categoryId: { type: "string" },
|
|
1448
1448
|
privacyStatus: { type: "string", enum: ["public", "unlisted", "private"] },
|
|
1449
1449
|
setThumbnail: { type: "boolean" },
|
|
1450
|
+
addShortsTag: {
|
|
1451
|
+
type: "boolean",
|
|
1452
|
+
description: "Add #Shorts to the description when the export is a Short. Default false.",
|
|
1453
|
+
},
|
|
1450
1454
|
subtitles: {
|
|
1451
1455
|
type: "boolean",
|
|
1452
1456
|
description:
|
|
@@ -1463,7 +1467,7 @@ const TOOLS = [
|
|
|
1463
1467
|
{
|
|
1464
1468
|
name: "social_channels",
|
|
1465
1469
|
description:
|
|
1466
|
-
"Social accounts connected in the active workspace (Instagram, TikTok, Facebook, LinkedIn, X) with ids, limits and per-post settings, plus each network's count.",
|
|
1470
|
+
"Social accounts connected in the active workspace (Instagram, TikTok, Facebook, LinkedIn, X) with ids, limits and per-post settings, plus each network's count. X accounts carry xPremium (25,000-char limit when true, else 280). YouTube and YouTube Shorts aren't here: use youtube_list_accounts + export_publish_youtube.",
|
|
1467
1471
|
inputSchema: { type: "object", properties: {} },
|
|
1468
1472
|
command: "social.channels",
|
|
1469
1473
|
},
|
|
@@ -1490,6 +1494,20 @@ const TOOLS = [
|
|
|
1490
1494
|
},
|
|
1491
1495
|
command: "social.connect-status",
|
|
1492
1496
|
},
|
|
1497
|
+
{
|
|
1498
|
+
name: "social_set_x_premium",
|
|
1499
|
+
description:
|
|
1500
|
+
"Mark a connected X account as X Premium (posts up to 25,000 chars) or standard (280). Only when the user says the account has Premium: X rejects long posts from other accounts. Returns the updated channel.",
|
|
1501
|
+
inputSchema: {
|
|
1502
|
+
type: "object",
|
|
1503
|
+
properties: {
|
|
1504
|
+
channelId: { type: "string", description: "The X account's id from social_channels." },
|
|
1505
|
+
premium: { type: "boolean" },
|
|
1506
|
+
},
|
|
1507
|
+
required: ["channelId", "premium"],
|
|
1508
|
+
},
|
|
1509
|
+
command: "social.set-x-premium",
|
|
1510
|
+
},
|
|
1493
1511
|
{
|
|
1494
1512
|
name: "social_disconnect",
|
|
1495
1513
|
description:
|
|
@@ -1803,7 +1821,7 @@ const TOOLS = [
|
|
|
1803
1821
|
{
|
|
1804
1822
|
name: "project_edit_summary",
|
|
1805
1823
|
description:
|
|
1806
|
-
"What the edit contains now: lengths (editedDurationMs, sourceDurationMs, removedMs cut or sped up), counts (cuts, zooms, motionElements, graphics, transitions, brollBeats, mediaOverlays, captions { on, template }, audio { narration, music, soundEffects }, voiceEnhancedClips vs loudnessNormalizedClips, ...) and highlights[] (plain lines). Each recording counts once, so splits change neither source length nor cuts. Cheap; use it to report an editing pass instead of project_read.",
|
|
1824
|
+
"What the edit contains now: lengths (editedDurationMs, sourceDurationMs, removedMs cut or sped up), counts (cuts, zooms, motionElements, graphics, transitions, brollBeats, mediaOverlays, captions { on, template }, audio { narration, music, soundEffects }, audioTracks[{id, kind voice|music|sfx, basis}] (the same kind the export mix and audio_preview_mix use), voiceEnhancedClips vs loudnessNormalizedClips, ...) and highlights[] (plain lines). Each recording counts once, so splits change neither source length nor cuts. Cheap; use it to report an editing pass instead of project_read.",
|
|
1807
1825
|
inputSchema: {
|
|
1808
1826
|
type: "object",
|
|
1809
1827
|
properties: {
|
|
@@ -2092,14 +2110,17 @@ const TOOLS = [
|
|
|
2092
2110
|
],
|
|
2093
2111
|
[
|
|
2094
2112
|
"stop-recording",
|
|
2095
|
-
"Stop recording
|
|
2113
|
+
"Stop recording. The take goes into the episode project by itself (desktop track once finalized, each guest's as their upload lands, even after the studio is left); returns savedTo and takeId. podcast_status shows finalization and guest uploads.",
|
|
2096
2114
|
],
|
|
2097
2115
|
[
|
|
2098
2116
|
"start-screen-share",
|
|
2099
2117
|
"Open the desktop picker to share the host screen with everyone in the call (any time, backstage included; it's recorded while recording). One sharer at a time. Waits for the host to choose; fails if the picker is cancelled or capture fails.",
|
|
2100
2118
|
],
|
|
2101
2119
|
["stop-screen-share", "Stop and finalize the host's podcast screen share."],
|
|
2102
|
-
[
|
|
2120
|
+
[
|
|
2121
|
+
"open-in-editor",
|
|
2122
|
+
"Open the finished podcast's episode in the editor when guest media has arrived (the take is already in the episode project).",
|
|
2123
|
+
],
|
|
2103
2124
|
].map(([noun, description]) => ({
|
|
2104
2125
|
name: `podcast_${noun.replaceAll("-", "_")}`,
|
|
2105
2126
|
description,
|
|
@@ -2623,6 +2644,34 @@ const TOOLS = [
|
|
|
2623
2644
|
},
|
|
2624
2645
|
command: "podcast.list-upcoming",
|
|
2625
2646
|
},
|
|
2647
|
+
{
|
|
2648
|
+
name: "podcast_found_recordings",
|
|
2649
|
+
description:
|
|
2650
|
+
"Recordings that belong to a podcast episode but never reached it (older takes left by Back before Open in editor): guest tracks matched by session code plus the nearest desktop camera recording, each with a key. No path / id / sessionCode = every episode.",
|
|
2651
|
+
inputSchema: {
|
|
2652
|
+
type: "object",
|
|
2653
|
+
properties: {
|
|
2654
|
+
path: { type: "string" },
|
|
2655
|
+
id: { type: "string" },
|
|
2656
|
+
sessionCode: { type: "string" },
|
|
2657
|
+
},
|
|
2658
|
+
},
|
|
2659
|
+
command: "podcast.found-recordings",
|
|
2660
|
+
},
|
|
2661
|
+
{
|
|
2662
|
+
name: "podcast_add_found_recordings",
|
|
2663
|
+
description:
|
|
2664
|
+
"Add a podcast_found_recordings take (path + key) to its episode: it becomes the episode's podcast clip, files move into the project folder. Matched by time, so ask the user first; check the sync afterwards (project_auto_sync_podcast).",
|
|
2665
|
+
inputSchema: {
|
|
2666
|
+
type: "object",
|
|
2667
|
+
properties: {
|
|
2668
|
+
path: { type: "string", description: "The episode's project file." },
|
|
2669
|
+
key: { type: "string", description: "The found take's key." },
|
|
2670
|
+
},
|
|
2671
|
+
required: ["path", "key"],
|
|
2672
|
+
},
|
|
2673
|
+
command: "podcast.add-found-recordings",
|
|
2674
|
+
},
|
|
2626
2675
|
{
|
|
2627
2676
|
name: "podcast_get_episode",
|
|
2628
2677
|
description:
|
|
@@ -3698,6 +3747,39 @@ const TOOLS = [
|
|
|
3698
3747
|
},
|
|
3699
3748
|
command: "project.remove-mute-region",
|
|
3700
3749
|
},
|
|
3750
|
+
{
|
|
3751
|
+
name: "project_add_original_voice",
|
|
3752
|
+
description:
|
|
3753
|
+
'Turn Enhance voice off for an edited-time span ("Original voice"): the main track plays its original audio there, enhanced elsewhere. Only enhanced clips change. Returns regionId (editor.enhanceOffRegions).',
|
|
3754
|
+
inputSchema: {
|
|
3755
|
+
type: "object",
|
|
3756
|
+
properties: {
|
|
3757
|
+
id: { type: "string" },
|
|
3758
|
+
path: { type: "string" },
|
|
3759
|
+
atMs: { type: "number" },
|
|
3760
|
+
durationMs: { type: "number" },
|
|
3761
|
+
expectedRevision: { type: "number" },
|
|
3762
|
+
},
|
|
3763
|
+
required: ["atMs", "durationMs"],
|
|
3764
|
+
},
|
|
3765
|
+
command: "project.add-original-voice",
|
|
3766
|
+
},
|
|
3767
|
+
{
|
|
3768
|
+
name: "project_remove_original_voice",
|
|
3769
|
+
description:
|
|
3770
|
+
"Remove an Original voice region so Enhance voice applies there again (ids: editor.enhanceOffRegions[].id).",
|
|
3771
|
+
inputSchema: {
|
|
3772
|
+
type: "object",
|
|
3773
|
+
properties: {
|
|
3774
|
+
id: { type: "string" },
|
|
3775
|
+
path: { type: "string" },
|
|
3776
|
+
regionId: { type: "string" },
|
|
3777
|
+
expectedRevision: { type: "number" },
|
|
3778
|
+
},
|
|
3779
|
+
required: ["regionId"],
|
|
3780
|
+
},
|
|
3781
|
+
command: "project.remove-original-voice",
|
|
3782
|
+
},
|
|
3701
3783
|
{
|
|
3702
3784
|
name: "project_add_bleep",
|
|
3703
3785
|
description:
|
|
@@ -4143,7 +4225,7 @@ const TOOLS = [
|
|
|
4143
4225
|
{
|
|
4144
4226
|
name: "project_review_moment",
|
|
4145
4227
|
description:
|
|
4146
|
-
"LOOK AND LISTEN to a moment of the edit as the viewer gets it: a contact sheet of the frames around atMs (edited ms) or wordId, the EXPORTED mix of that stretch transcribed and compared with what the edit should play (extra = leftover of a cut word or line, missing = clipped word), whether each cut lands in quiet or speech, nearby edits and stutters, plus a plain verdict. Use after every cut / pause / insert fix BEFORE telling the user it's fixed, and when the user names a moment ('at 16 seconds'). ASYNC: { jobId }; job_wait.",
|
|
4228
|
+
"LOOK AND LISTEN to a moment of the edit as the viewer gets it: a contact sheet of the frames around atMs (edited ms) or wordId, the EXPORTED mix of that stretch transcribed and compared with what the edit should play (the clips' words AND narration / voiceover track words; extra = leftover of a cut word or line, missing = clipped word), whether each cut that interrupts the main track's sound lands in quiet or speech (judged on the main track alone, so narration or music playing across it doesn't count; a join of silent clips such as images is never a cut in the speech), nearby edits and stutters, plus a plain verdict. Use after every cut / pause / insert fix BEFORE telling the user it's fixed, and when the user names a moment ('at 16 seconds'). ASYNC: { jobId }; job_wait.",
|
|
4147
4229
|
inputSchema: {
|
|
4148
4230
|
type: "object",
|
|
4149
4231
|
properties: {
|
|
@@ -4198,7 +4280,7 @@ const TOOLS = [
|
|
|
4198
4280
|
{
|
|
4199
4281
|
name: "audio_preview_mix",
|
|
4200
4282
|
description:
|
|
4201
|
-
"Render final export audio only to temporary .m4a plus description and voice/music/SFX stem RMS/masking flags. Edited-time range fromMs..toMs inside 0..editedDurationMs (project_read), default whole project, max 10 minutes. Async: job.wait.",
|
|
4283
|
+
"Render final export audio only to temporary .m4a plus description and voice/music/SFX stem RMS/masking flags; tracks[{id, kind, basis}] = which stem each audio track went to (same as project_edit_summary audioTracks). Edited-time range fromMs..toMs inside 0..editedDurationMs (project_read), default whole project, max 10 minutes. Async: job.wait.",
|
|
4202
4284
|
inputSchema: {
|
|
4203
4285
|
type: "object",
|
|
4204
4286
|
properties: {
|
|
@@ -5126,7 +5208,7 @@ const TOOLS = [
|
|
|
5126
5208
|
{
|
|
5127
5209
|
name: "project_auto_reframe",
|
|
5128
5210
|
description:
|
|
5129
|
-
"Active-speaker auto-reframe: frames whoever talks, shot by shot (face tracking, no speaker IDs needed). Landscape footage on a vertical / square canvas gets a crop that follows the speaker; footage that already has the canvas shape (a 16:9 wide of two hosts in a 16:9 video) gets a punch-in on the speaker inside the frame, which is also how to get face-tracked zooms on the main video. zoom = fixed punch-in. split=true stacks two people (podcast / interview wide) one above the other on a 9:16 canvas. Slow (minutes). clear reverts. Concurrent saves are merged and retried (three attempts). Exhausted conflicts report code revision_conflict / status 409 (job.errorDetails for async jobs).",
|
|
5211
|
+
"Active-speaker auto-reframe: frames whoever talks, shot by shot (face tracking, no speaker IDs needed). Landscape footage on a vertical / square canvas gets a crop that follows the speaker; footage that already has the canvas shape (a 16:9 wide of two hosts in a 16:9 video) gets a punch-in on the speaker inside the frame, which is also how to get face-tracked zooms on the main video. zoom = fixed punch-in. split=true stacks two people (podcast / interview wide) one above the other on a 9:16 canvas (not on a clip with its own camera video). In the vertical-stack camera layout the crop is computed for the main video's top half. Slow (minutes). clear reverts. Concurrent saves are merged and retried (three attempts). Exhausted conflicts report code revision_conflict / status 409 (job.errorDetails for async jobs).",
|
|
5130
5212
|
inputSchema: {
|
|
5131
5213
|
type: "object",
|
|
5132
5214
|
properties: {
|
|
@@ -5396,6 +5478,12 @@ const TOOLS = [
|
|
|
5396
5478
|
type: "boolean",
|
|
5397
5479
|
description: "Repeat the file to endMs (a ~30 s Lyria clip under a longer video).",
|
|
5398
5480
|
},
|
|
5481
|
+
audioKind: {
|
|
5482
|
+
type: "string",
|
|
5483
|
+
enum: ["voice", "music", "sfx"],
|
|
5484
|
+
description:
|
|
5485
|
+
"What the track is (its mix bus, preview-mix stem and edit-summary count). Omit for bundled library files and generated narration / music / SFX (known); pass it for other files, e.g. music for an uploaded song. Change later: project_update_region regionType=audio-overlay patch {audioKind}.",
|
|
5486
|
+
},
|
|
5399
5487
|
transcribe: {
|
|
5400
5488
|
type: "boolean",
|
|
5401
5489
|
description:
|
|
@@ -5807,7 +5895,7 @@ const TOOLS = [
|
|
|
5807
5895
|
{
|
|
5808
5896
|
name: "project_set_clip_webcam",
|
|
5809
5897
|
description:
|
|
5810
|
-
"Attach, replace or remove a clip's camera video
|
|
5898
|
+
"Attach, replace or remove a clip's camera video, in sync from its first frame: a presenter camera over a screen recording, or a REACTION video (main clip = the video reacted to, camera = the reactor; audio=mix plays both). The main video keeps its kind. In 9:16 use set-webcam-layout vertical-stack (main on top, camera below), then auto-reframe frames the main video inside its half. Not for podcast composites.",
|
|
5811
5899
|
inputSchema: {
|
|
5812
5900
|
type: "object",
|
|
5813
5901
|
properties: {
|
|
@@ -5818,8 +5906,9 @@ const TOOLS = [
|
|
|
5818
5906
|
webcam: { type: "string", description: "Absolute path, or '' to remove." },
|
|
5819
5907
|
audio: {
|
|
5820
5908
|
type: "string",
|
|
5821
|
-
enum: ["auto", "camera", "keep"],
|
|
5822
|
-
description:
|
|
5909
|
+
enum: ["auto", "mix", "camera", "keep"],
|
|
5910
|
+
description:
|
|
5911
|
+
"auto: camera audio if the main video is silent; mix: both sounds (reaction video); camera: camera's sound only; keep: unchanged. Re-transcribe after a change.",
|
|
5823
5912
|
},
|
|
5824
5913
|
expectedRevision: { type: "number" },
|
|
5825
5914
|
},
|
|
@@ -5895,13 +5984,14 @@ const TOOLS = [
|
|
|
5895
5984
|
{
|
|
5896
5985
|
name: "system_set_transcription_preferences",
|
|
5897
5986
|
description:
|
|
5898
|
-
"Save workspace transcription language, provider and/or on-device engine atomically (pass any). engine: auto (Parakeet for English/auto-detect, Whisper LOCKED to any other named language), parakeet (keeps fillers, detects the language, can't be locked), whisper (locks to the language). Confirm consent to upload audio for cloud. Cloud and apple cannot use auto.",
|
|
5987
|
+
"Save workspace transcription language, provider and/or on-device engine atomically (pass any). engine: auto (Parakeet for English/auto-detect, Whisper LOCKED to any other named language), parakeet (keeps fillers, detects the language, can't be locked), whisper (locks to the language). Confirm consent to upload audio for cloud. Cloud and apple cannot use auto. fallback: when the cloud provider / Apple speech still fails after retries, local (default: this computer transcribes only the failed parts, reported) or none (fail, never transcribe on this computer: use when the user wants the cloud provider only).",
|
|
5899
5988
|
inputSchema: {
|
|
5900
5989
|
type: "object",
|
|
5901
5990
|
properties: {
|
|
5902
5991
|
language: { type: "string" },
|
|
5903
5992
|
provider: { type: "string", enum: ["local", "apple", "deepgram", "elevenlabs"] },
|
|
5904
5993
|
engine: { type: "string", enum: ["auto", "parakeet", "whisper"] },
|
|
5994
|
+
fallback: { type: "string", enum: ["local", "none"] },
|
|
5905
5995
|
},
|
|
5906
5996
|
},
|
|
5907
5997
|
command: "system.set-transcription-preferences",
|
|
@@ -5910,13 +6000,19 @@ const TOOLS = [
|
|
|
5910
6000
|
{
|
|
5911
6001
|
name: "transcript_transcribe",
|
|
5912
6002
|
description:
|
|
5913
|
-
"Transcribe clips with word timestamps (default: only clips without words). Asking again while the same transcription is still running returns that job (alreadyRunning: true), never a second run: keep waiting on it. 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[]). Clips with no audio track are skipped (result noAudioClips), not failed. Result warnings[] flags words that can't cover the audio (sound with no words, too few words: music, noise, another language) and a re-run with the same words as before: surface it, and get a second reading with engine whisper or a cloud provider (Parakeet isn't locked by language english, so retrying the same way repeats it). 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).",
|
|
6003
|
+
"Transcribe clips with word timestamps (default: only clips without words). Asking again while the same transcription is still running returns that job (alreadyRunning: true), never a second run: keep waiting on it. 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[]). Clips with no audio track are skipped (result noAudioClips), not failed. Result warnings[] flags words that can't cover the audio (sound with no words, too few words: music, noise, another language) and a re-run with the same words as before: surface it, and get a second reading with engine whisper or a cloud provider (Parakeet isn't locked by language english, so retrying the same way repeats it). 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). CLOUD (deepgram / elevenlabs): long audio goes up in ~5 min parts, each retried on network drops, timeouts, 5xx and 429. fallback: none = parts that still fail FAIL the job (job.errorDetails.code cloud_failed, failedRanges; nothing runs on this computer; parts that worked are kept for a re-run), local = this computer transcribes only the failed parts. Default none when you pass a cloud/apple provider, else the workspace setting. The job says which engine really ran: progress.data.engine / fallbackFrom while running, result clips[].engine / engines / fallback. job_cancel stops every upload, retry and on-device helper of the job.",
|
|
5914
6004
|
inputSchema: {
|
|
5915
6005
|
type: "object",
|
|
5916
6006
|
properties: {
|
|
5917
6007
|
id: { type: "string" },
|
|
5918
6008
|
path: { type: "string" },
|
|
5919
6009
|
clipId: { type: "string", description: "Only this clip, even if already transcribed." },
|
|
6010
|
+
fallback: {
|
|
6011
|
+
type: "string",
|
|
6012
|
+
enum: ["local", "none"],
|
|
6013
|
+
description:
|
|
6014
|
+
"When the cloud provider / Apple speech still fails after retries: none = fail the job (never transcribe on this computer), local = this computer transcribes only the failed parts. Default: none when provider is passed, else the workspace setting.",
|
|
6015
|
+
},
|
|
5920
6016
|
language: {
|
|
5921
6017
|
type: "string",
|
|
5922
6018
|
description:
|
|
@@ -8676,13 +8772,18 @@ const TOOLS = [
|
|
|
8676
8772
|
{
|
|
8677
8773
|
name: "llm_generate_title",
|
|
8678
8774
|
description:
|
|
8679
|
-
"Generate a YouTube title from what the EDITED video says (cut words left out) with the local LLM. Returns { title }: one complete phrase within maxChars, never cut mid-word.",
|
|
8775
|
+
"Generate a YouTube title from what the EDITED video says (cut words left out) with the local LLM. Names the people speaking when the project knows them (podcast participants); instruction steers it. Returns { title }: one complete phrase within maxChars, never cut mid-word.",
|
|
8680
8776
|
inputSchema: {
|
|
8681
8777
|
type: "object",
|
|
8682
8778
|
properties: {
|
|
8683
8779
|
id: { type: "string" },
|
|
8684
8780
|
path: { type: "string" },
|
|
8685
8781
|
maxChars: { type: "number" },
|
|
8782
|
+
instruction: {
|
|
8783
|
+
type: "string",
|
|
8784
|
+
description:
|
|
8785
|
+
"Optional steer from the user (what to focus on), max 500 chars. Speaker names the project knows are used automatically.",
|
|
8786
|
+
},
|
|
8686
8787
|
},
|
|
8687
8788
|
},
|
|
8688
8789
|
command: "llm.generate-title",
|
|
@@ -8690,13 +8791,18 @@ const TOOLS = [
|
|
|
8690
8791
|
{
|
|
8691
8792
|
name: "llm_generate_description",
|
|
8692
8793
|
description:
|
|
8693
|
-
"Generate a 3-5 sentence YouTube description from what the EDITED video says, with the local LLM. Returns { description, warnings? }: a warning means it repeated the transcript, so write the description yourself.",
|
|
8794
|
+
"Generate a 3-5 sentence YouTube description from what the EDITED video says, with the local LLM. Names the people speaking when the project knows them (podcast participants); instruction steers what it focuses on. Returns { description, warnings? }: a warning means it repeated the transcript, so write the description yourself.",
|
|
8694
8795
|
inputSchema: {
|
|
8695
8796
|
type: "object",
|
|
8696
8797
|
properties: {
|
|
8697
8798
|
id: { type: "string" },
|
|
8698
8799
|
path: { type: "string" },
|
|
8699
8800
|
maxChars: { type: "number" },
|
|
8801
|
+
instruction: {
|
|
8802
|
+
type: "string",
|
|
8803
|
+
description:
|
|
8804
|
+
"Optional steer from the user (what to focus on), max 500 chars. Speaker names the project knows are used automatically.",
|
|
8805
|
+
},
|
|
8700
8806
|
},
|
|
8701
8807
|
},
|
|
8702
8808
|
command: "llm.generate-description",
|
|
@@ -8725,6 +8831,11 @@ const TOOLS = [
|
|
|
8725
8831
|
id: { type: "string" },
|
|
8726
8832
|
path: { type: "string" },
|
|
8727
8833
|
maxChapters: { type: "number" },
|
|
8834
|
+
instruction: {
|
|
8835
|
+
type: "string",
|
|
8836
|
+
description:
|
|
8837
|
+
"Optional steer from the user (what to focus on), max 500 chars. Speaker names the project knows are used automatically.",
|
|
8838
|
+
},
|
|
8728
8839
|
},
|
|
8729
8840
|
},
|
|
8730
8841
|
command: "llm.generate-timestamps",
|
|
@@ -8939,7 +9050,7 @@ const TOOLS = [
|
|
|
8939
9050
|
{
|
|
8940
9051
|
name: "clips_export",
|
|
8941
9052
|
description:
|
|
8942
|
-
"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[] }.",
|
|
9053
|
+
"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[{ clipId, outputPath, exportId }] }. To publish a clip, export it here, then pass exportId to export_publish_youtube (9:16 = Short) or export_publish_social.",
|
|
8943
9054
|
inputSchema: {
|
|
8944
9055
|
type: "object",
|
|
8945
9056
|
properties: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@writepanda/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.286.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",
|