@writepanda/mcp 1.269.0 → 1.272.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 +300 -8
  2. package/package.json +1 -1
package/bin/server.mjs CHANGED
@@ -623,6 +623,11 @@ const MOTION_ELEMENT_PROPS = {
623
623
  accent: { type: "string" },
624
624
  highlight: { type: "string" },
625
625
  text: { type: "string" },
626
+ surface: {
627
+ type: "string",
628
+ description:
629
+ "The element's own plate / pill / band colour (lowerThird plate, chip, endCard, ticker band). Default: the family's (clean = light card). Text left unset picks a readable ink.",
630
+ },
626
631
  font: { type: "string" },
627
632
  size: { type: "string", enum: ["xs", "s", "m", "l", "xl"] },
628
633
  outline: { type: "boolean" },
@@ -783,6 +788,10 @@ const TOOLS = [
783
788
  type: "string",
784
789
  description: "What happened and your diagnosis (no user content).",
785
790
  },
791
+ description: {
792
+ type: "string",
793
+ description: "Same as details; pass either.",
794
+ },
786
795
  kind: {
787
796
  type: "string",
788
797
  enum: ["capability-gap", "command-failed", "wrong-output", "crash", "confusing", "other"],
@@ -800,7 +809,7 @@ const TOOLS = [
800
809
  userContent: { type: "string" },
801
810
  userConsented: { type: "boolean" },
802
811
  },
803
- required: ["title", "details"],
812
+ required: ["title"],
804
813
  },
805
814
  command: "system.report-issue",
806
815
  },
@@ -2020,11 +2029,11 @@ const TOOLS = [
2020
2029
  ...[
2021
2030
  [
2022
2031
  "status",
2023
- "Read the live podcast session code, guest link, recording and sharing state, the host's micMuted / cameraOff / devices, and each guest's name, role, state, micMuted, cameraOff and sharing.",
2032
+ "Read the live podcast session code, mode (hosting / producing), links (guest, call-in, host, producer), recording and sharing state, the desktop's micMuted / cameraOff / devices, each guest's name, role, state, micMuted, cameraOff and sharing, and people: everyone's role, stage (on / back), upNext, talkingPrivately and (while recording) whether they're recorded. While recording, takeStage is who was on stage when.",
2024
2033
  ],
2025
2034
  [
2026
2035
  "start-recording",
2027
- "Start recording the host and signal connected guests to record. Returns once recording has really started; fails with the reason otherwise.",
2036
+ "Start the take: everyone on stage records now, everyone else from their first time on stage (a producer backstage is never recorded). Returns once recording has really started; fails with the reason otherwise.",
2028
2037
  ],
2029
2038
  [
2030
2039
  "stop-recording",
@@ -2149,19 +2158,67 @@ const TOOLS = [
2149
2158
  {
2150
2159
  name: "podcast_set_stage",
2151
2160
  description:
2152
- "Put a participant (host | guest | guest-2 | guest-3) on air or backstage (onAir), or mute them in the stream only (muted). The recording is never affected.",
2161
+ "Put someone on stage or backstage (stage on|back, live or recording or before the show), queue them up next (upNext: they hear the show and get a cue), or mute them in the stream only (muted). Only on-stage people are in the stream, the recording and the edit; backstage they're recorded as silence. Ids: host (the show's host), producer (the desktop when a producer runs the show), cohost, guest, guest-2, guest-3, caller-N, producer-web-N (browser producers can't go on stage). See podcast_status.",
2153
2162
  inputSchema: {
2154
2163
  type: "object",
2155
2164
  properties: {
2156
2165
  waitSec: PODCAST_WAIT,
2157
2166
  participant: { type: "string" },
2158
- onAir: { type: "boolean" },
2167
+ stage: { type: "string", enum: ["on", "back"] },
2168
+ onAir: { type: "boolean", description: "Same as stage on (true) / back (false)." },
2169
+ upNext: { type: "boolean" },
2159
2170
  muted: { type: "boolean" },
2160
2171
  },
2161
2172
  required: ["participant"],
2162
2173
  },
2163
2174
  command: "podcast.set-stage",
2164
2175
  },
2176
+ {
2177
+ name: "podcast_talkback",
2178
+ description:
2179
+ 'Talk privately from the studio desktop (a producer running the show): its mic reaches only `to` (participant ids, or "stage" for everyone on stage), never the stream or the recording, until you call it with active false.',
2180
+ inputSchema: {
2181
+ type: "object",
2182
+ properties: {
2183
+ to: { type: "array", items: { type: "string" } },
2184
+ active: { type: "boolean", description: "false stops (default true)." },
2185
+ },
2186
+ },
2187
+ command: "podcast.talkback",
2188
+ },
2189
+ {
2190
+ name: "podcast_set_mode",
2191
+ description:
2192
+ "Who runs the show from this desktop: hosting (its operator hosts, on camera; default) or producing (a producer runs the studio backstage, never recorded unless they step on stage; the host joins by the host link from podcast_invite as host). Not while recording.",
2193
+ inputSchema: {
2194
+ type: "object",
2195
+ properties: { mode: { type: "string", enum: ["hosting", "producing"] } },
2196
+ required: ["mode"],
2197
+ },
2198
+ command: "podcast.set-mode",
2199
+ },
2200
+ {
2201
+ name: "podcast_host_control",
2202
+ description:
2203
+ "Give the host (host link) control on their page, or take it back: Record, bring people on or backstage, next segment. Graphics and going live stay with the producer. Off by default.",
2204
+ inputSchema: {
2205
+ type: "object",
2206
+ properties: { on: { type: "boolean" } },
2207
+ required: ["on"],
2208
+ },
2209
+ command: "podcast.host-control",
2210
+ },
2211
+ {
2212
+ name: "podcast_cue_host",
2213
+ description:
2214
+ 'Show the host a cue card on their page ("Wrap up in 2", "Ask about pricing"). Never on air. Needs the host connected by the host link.',
2215
+ inputSchema: {
2216
+ type: "object",
2217
+ properties: { text: { type: "string", description: "Up to 280 characters." } },
2218
+ required: ["text"],
2219
+ },
2220
+ command: "podcast.cue-host",
2221
+ },
2165
2222
  {
2166
2223
  name: "podcast_show_overlay",
2167
2224
  description:
@@ -2290,10 +2347,214 @@ const TOOLS = [
2290
2347
  "YouTube title when it should differ from the episode title; empty = follow it.",
2291
2348
  },
2292
2349
  draftRundown: { type: "boolean" },
2350
+ mode: {
2351
+ type: "string",
2352
+ enum: ["hosting", "producing"],
2353
+ description:
2354
+ "producing: a producer runs the studio, the host joins by the host link (podcast_invite as host).",
2355
+ },
2356
+ host: {
2357
+ type: "object",
2358
+ description: "Producing: the show's host (their lower third).",
2359
+ properties: {
2360
+ name: { type: "string" },
2361
+ email: { type: "string" },
2362
+ role: { type: "string" },
2363
+ },
2364
+ required: ["name"],
2365
+ },
2366
+ crew: {
2367
+ type: "array",
2368
+ description: "The production side: producers, editor, client.",
2369
+ items: {
2370
+ type: "object",
2371
+ properties: {
2372
+ name: { type: "string" },
2373
+ email: { type: "string" },
2374
+ role: { type: "string" },
2375
+ },
2376
+ required: ["name"],
2377
+ },
2378
+ },
2379
+ hostControl: {
2380
+ type: "boolean",
2381
+ description: "Producing: the host gets Record, stage and next segment on their page.",
2382
+ },
2383
+ showId: { type: "string", description: "The show (series) it belongs to." },
2293
2384
  },
2294
2385
  },
2295
2386
  command: "podcast.schedule",
2296
2387
  },
2388
+ {
2389
+ name: "show_list",
2390
+ description:
2391
+ "Podcast shows (series) in the current workspace. A workspace is the client; a show is one of its series, with defaults for new episodes and a delivery after each recording.",
2392
+ inputSchema: { type: "object", properties: {} },
2393
+ command: "show.list",
2394
+ },
2395
+ {
2396
+ name: "show_create",
2397
+ description:
2398
+ "Create a podcast show in the current workspace. Episodes scheduled with its showId (podcast_schedule) start from its mode (hosting / producing), host, crew, host control, run-of-show template, recipe and destinations. A delivery with edit / MP3 / Shorts / upload proposes a delivery routine the user turns on.",
2399
+ inputSchema: {
2400
+ type: "object",
2401
+ properties: {
2402
+ name: { type: "string" },
2403
+ description: { type: "string" },
2404
+ mode: { type: "string", enum: ["hosting", "producing"] },
2405
+ host: {
2406
+ type: "object",
2407
+ properties: {
2408
+ name: { type: "string" },
2409
+ email: { type: "string" },
2410
+ role: { type: "string" },
2411
+ },
2412
+ required: ["name"],
2413
+ },
2414
+ crew: {
2415
+ type: "array",
2416
+ items: {
2417
+ type: "object",
2418
+ properties: {
2419
+ name: { type: "string" },
2420
+ email: { type: "string" },
2421
+ role: { type: "string" },
2422
+ },
2423
+ required: ["name"],
2424
+ },
2425
+ },
2426
+ hostControl: { type: "boolean" },
2427
+ recipeId: { type: "string", description: "The edit's recipe (recipe_list); empty clears." },
2428
+ rundownTemplate: { type: "object", description: "Run of show new episodes start from." },
2429
+ destinationIds: { type: "array", items: { type: "string" } },
2430
+ delivery: {
2431
+ type: "object",
2432
+ description:
2433
+ "After each recorded episode: folder (absolute) gets rawFiles (each person's own recording + the live program); edit, audioMaster (MP3), shorts (0-10) and youtube {accountId, privacy} run as a delivery routine the user turns on. null clears.",
2434
+ properties: {
2435
+ folder: { type: "string" },
2436
+ rawFiles: { type: "boolean" },
2437
+ edit: { type: "boolean" },
2438
+ audioMaster: { type: "boolean" },
2439
+ shorts: { type: "number" },
2440
+ youtube: {
2441
+ type: "object",
2442
+ properties: {
2443
+ accountId: { type: "string" },
2444
+ privacy: { type: "string", enum: ["private", "unlisted", "public"] },
2445
+ },
2446
+ required: ["accountId"],
2447
+ },
2448
+ notes: { type: "string" },
2449
+ },
2450
+ },
2451
+ },
2452
+ required: ["name"],
2453
+ },
2454
+ command: "show.create",
2455
+ },
2456
+ {
2457
+ name: "show_update",
2458
+ description: "Change a show's name, defaults or delivery (only the fields given).",
2459
+ inputSchema: {
2460
+ type: "object",
2461
+ properties: {
2462
+ id: { type: "string" },
2463
+ name: { type: "string" },
2464
+ description: { type: "string" },
2465
+ mode: { type: "string", enum: ["hosting", "producing"] },
2466
+ host: {
2467
+ type: "object",
2468
+ properties: {
2469
+ name: { type: "string" },
2470
+ email: { type: "string" },
2471
+ role: { type: "string" },
2472
+ },
2473
+ required: ["name"],
2474
+ },
2475
+ crew: {
2476
+ type: "array",
2477
+ items: {
2478
+ type: "object",
2479
+ properties: {
2480
+ name: { type: "string" },
2481
+ email: { type: "string" },
2482
+ role: { type: "string" },
2483
+ },
2484
+ required: ["name"],
2485
+ },
2486
+ },
2487
+ hostControl: { type: "boolean" },
2488
+ recipeId: { type: "string", description: "The edit's recipe (recipe_list); empty clears." },
2489
+ rundownTemplate: { type: "object", description: "Run of show new episodes start from." },
2490
+ destinationIds: { type: "array", items: { type: "string" } },
2491
+ delivery: {
2492
+ type: "object",
2493
+ description:
2494
+ "After each recorded episode: folder (absolute) gets rawFiles (each person's own recording + the live program); edit, audioMaster (MP3), shorts (0-10) and youtube {accountId, privacy} run as a delivery routine the user turns on. null clears.",
2495
+ properties: {
2496
+ folder: { type: "string" },
2497
+ rawFiles: { type: "boolean" },
2498
+ edit: { type: "boolean" },
2499
+ audioMaster: { type: "boolean" },
2500
+ shorts: { type: "number" },
2501
+ youtube: {
2502
+ type: "object",
2503
+ properties: {
2504
+ accountId: { type: "string" },
2505
+ privacy: { type: "string", enum: ["private", "unlisted", "public"] },
2506
+ },
2507
+ required: ["accountId"],
2508
+ },
2509
+ notes: { type: "string" },
2510
+ },
2511
+ },
2512
+ },
2513
+ required: ["id"],
2514
+ },
2515
+ command: "show.update",
2516
+ },
2517
+ {
2518
+ name: "show_set_delivery",
2519
+ description:
2520
+ "What to hand over after each recorded episode of a show: raw files to a folder (copied right after recording), plus the edit, MP3, Shorts and YouTube upload as a delivery routine the user turns on.",
2521
+ inputSchema: {
2522
+ type: "object",
2523
+ properties: {
2524
+ id: { type: "string" },
2525
+ delivery: {
2526
+ type: "object",
2527
+ description:
2528
+ "After each recorded episode: folder (absolute) gets rawFiles (each person's own recording + the live program); edit, audioMaster (MP3), shorts (0-10) and youtube {accountId, privacy} run as a delivery routine the user turns on. null clears.",
2529
+ properties: {
2530
+ folder: { type: "string" },
2531
+ rawFiles: { type: "boolean" },
2532
+ edit: { type: "boolean" },
2533
+ audioMaster: { type: "boolean" },
2534
+ shorts: { type: "number" },
2535
+ youtube: {
2536
+ type: "object",
2537
+ properties: {
2538
+ accountId: { type: "string" },
2539
+ privacy: { type: "string", enum: ["private", "unlisted", "public"] },
2540
+ },
2541
+ required: ["accountId"],
2542
+ },
2543
+ notes: { type: "string" },
2544
+ },
2545
+ },
2546
+ },
2547
+ required: ["id", "delivery"],
2548
+ },
2549
+ command: "show.set-delivery",
2550
+ },
2551
+ {
2552
+ name: "show_delete",
2553
+ description:
2554
+ "Delete a show (ask the user first). Its episodes and files stay; its delivery routine is removed.",
2555
+ inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
2556
+ command: "show.delete",
2557
+ },
2297
2558
  {
2298
2559
  name: "podcast_list_upcoming",
2299
2560
  description:
@@ -2324,13 +2585,14 @@ const TOOLS = [
2324
2585
  {
2325
2586
  name: "podcast_invite",
2326
2587
  description:
2327
- "An episode's guest invite: join link, invite text and a calendar invite (.ics, needs a date). out writes the .ics there. Don't send it yourself unless the user asks.",
2588
+ "An episode's invite: the link, invite text and a calendar invite (.ics, needs a date). as: guest (default), host (the host link, when a producer runs the studio) or producer (a browser producer link: watch, talk privately, approve the AI producer). out writes the .ics there. Don't send it yourself unless the user asks.",
2328
2589
  inputSchema: {
2329
2590
  type: "object",
2330
2591
  properties: {
2331
2592
  path: { type: "string" },
2332
2593
  id: { type: "string" },
2333
2594
  sessionCode: { type: "string" },
2595
+ as: { type: "string", enum: ["guest", "host", "producer"] },
2334
2596
  out: { type: "string", description: "Absolute path ending in .ics." },
2335
2597
  hostName: { type: "string" },
2336
2598
  },
@@ -3472,7 +3734,7 @@ const TOOLS = [
3472
3734
  {
3473
3735
  name: "project_check_broll",
3474
3736
  description:
3475
- "B-roll, the LAST step of an edit. YOU pick the moments from what's said (transcript_get; any language, any topic; in a Short ~1 per 6-8 s with the first right after the opening line, in long-form ~1 per 10-15 s) and what each picture shows; this checks them: span, clashes with the steps list / end card / other pictures, spacing, a nearby suggestion when blocked, insetSide (card away from the face). No moments: free stretches. Returns imageConnector. Never makes images: show the user your moments and ASK: their own images, generate on their connector (uses credits), or none. No one to ask: skip it and say so.",
3737
+ "B-roll, the LAST step of an edit. YOU pick the moments from what's said (transcript_get; any language, any topic; in a Short ~1 per 6-8 s with the first right after the opening line, in long-form ~1 per 10-15 s) and what each picture shows; this checks them: span, clashes with the steps list / end card / pictures it would hide / graphics covering most of it (by position and stacking: a thin header or logo strip over it is fine), spacing, a nearby suggestion when blocked, insetSide (card away from the face). No moments: free stretches. Returns imageConnector. Never makes images: show the user your moments and ASK: their own images, generate on their connector (uses credits), or none. No one to ask: skip it and say so.",
3476
3738
  inputSchema: {
3477
3739
  type: "object",
3478
3740
  properties: {
@@ -3488,6 +3750,11 @@ const TOOLS = [
3488
3750
  endWordId: { type: "string" },
3489
3751
  durationMs: { type: "number" },
3490
3752
  picture: { type: "string", description: "What the picture shows." },
3753
+ layout: {
3754
+ type: "string",
3755
+ enum: ["full", "inset"],
3756
+ description: "The add-broll layout you plan (default full).",
3757
+ },
3491
3758
  },
3492
3759
  },
3493
3760
  },
@@ -5140,6 +5407,24 @@ const TOOLS = [
5140
5407
  },
5141
5408
  command: "project.set-clip-chroma-key",
5142
5409
  },
5410
+ {
5411
+ name: "project_set_clip_flip",
5412
+ description:
5413
+ "Flip a main-track clip's picture: fixes a recording that came out upside down (horizontal + vertical = turned 180 degrees, e.g. a monitor mounted upside down) or mirrored (horizontal). Corrects the source: crops, cursor and zoom focus read the flipped picture. Omitted axes keep their value; both false removes it. Check with project_render_frame.",
5414
+ inputSchema: {
5415
+ type: "object",
5416
+ properties: {
5417
+ id: { type: "string" },
5418
+ path: { type: "string" },
5419
+ clipId: { type: "string" },
5420
+ horizontal: { type: "boolean", description: "Mirror left to right." },
5421
+ vertical: { type: "boolean", description: "Mirror top to bottom." },
5422
+ expectedRevision: { type: "number" },
5423
+ },
5424
+ required: ["clipId"],
5425
+ },
5426
+ command: "project.set-clip-flip",
5427
+ },
5143
5428
  {
5144
5429
  name: "project_set_clip_kind",
5145
5430
  description:
@@ -5459,7 +5744,7 @@ const TOOLS = [
5459
5744
  {
5460
5745
  name: "transcript_transcribe",
5461
5746
  description:
5462
- "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).",
5747
+ "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[]). 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).",
5463
5748
  inputSchema: {
5464
5749
  type: "object",
5465
5750
  properties: {
@@ -7531,6 +7816,13 @@ const TOOLS = [
7531
7816
  description:
7532
7817
  "{ id?, title, description, category, footage?, aspectRatio?, fields: [{ key, label, type: text|longtext|select|color|images, default?, options?, required?, help?, minCount?, maxCount?, optional? }], prompt, lookFrames?: [{ src: absolute image path, shows: what it shows (position, size, colours), atMs? }] (up to 8 stills of the target look; copied into the recipe), style?: { aspectRatio?, colorCorrection?, lut?: { preset, intensity? }, speakerBackground?: { mode: none|blur|remove|image, image?, strength?, outline?: { enabled, width?, color?, shadow? } }, framing?: { shortsLayout: full|camera-corner }, cameraLayout?, captions?: { enabled, templateId?, wordsPerLine?, positionY?, style?: caption_set_look's style }, broll?: { use: none|ask|generate|user-images, layout?: full|split|card, notes? }, graphics?: { family?, titleFont?, bodyFont?, accentColor?, textColor?, surfaceColor?, notes? }, wallpaper? }, checklist: string[] }. Put the WHOLE look in style (every caption value, the background, framing, B-roll rule, title fonts and colours): it is applied exactly, the prompt only covers what depends on the footage.",
7533
7818
  },
7819
+ id: {
7820
+ type: "string",
7821
+ description:
7822
+ "Project the edit was made in (default: the one open in the editor). Without lookFrames, three stills of it become the recipe's cover on Home and the look the next run matches.",
7823
+ },
7824
+ path: { type: "string", description: "Same as id, by project file path." },
7825
+ stills: { type: "boolean", description: "false = save without stills of the edit." },
7534
7826
  },
7535
7827
  required: ["recipe"],
7536
7828
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@writepanda/mcp",
3
- "version": "1.269.0",
3
+ "version": "1.272.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",