@writepanda/mcp 1.265.0 → 1.267.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 +85 -6
  2. package/package.json +1 -1
package/bin/server.mjs CHANGED
@@ -3576,6 +3576,35 @@ const TOOLS = [
3576
3576
  },
3577
3577
  command: "project.add-spotlight",
3578
3578
  },
3579
+ {
3580
+ name: "project_set_speaker_background",
3581
+ description:
3582
+ "The speaker's background for the WHOLE video as one look: blur, remove (wallpaper shows; outline on by default), image (studio plate) or none. Replaces the previous whole-video background instead of stacking; partial background-effect regions stay. Camera footage. For one stretch use project_add_background_effect.",
3583
+ inputSchema: {
3584
+ type: "object",
3585
+ properties: {
3586
+ id: { type: "string" },
3587
+ path: { type: "string" },
3588
+ mode: { type: "string", enum: ["none", "blur", "remove", "image"] },
3589
+ strength: { type: "number", description: "blur: 1-120, default 18." },
3590
+ backgroundImage: {
3591
+ type: "string",
3592
+ description:
3593
+ "image: warm-creator, tech-rgb, neutral-grey, podcast-warm, daylight-airy, gradient-gel, cinematic-dark, or an image path.",
3594
+ },
3595
+ outline: {
3596
+ type: "boolean",
3597
+ description: "Keyline around the cutout (on by default for remove).",
3598
+ },
3599
+ outlineWidth: { type: "number" },
3600
+ outlineColor: { type: "string" },
3601
+ outlineShadow: { type: "boolean" },
3602
+ expectedRevision: { type: "number" },
3603
+ },
3604
+ required: ["mode"],
3605
+ },
3606
+ command: "project.set-speaker-background",
3607
+ },
3579
3608
  {
3580
3609
  name: "project_add_background_effect",
3581
3610
  description:
@@ -5964,6 +5993,30 @@ const TOOLS = [
5964
5993
  },
5965
5994
  command: "caption.set-style",
5966
5995
  },
5996
+ {
5997
+ name: "caption_set_look",
5998
+ description:
5999
+ "Set a COMPLETE caption look in one call, replacing the current one: on/off, template, words per line, position and every override (in style). What the look leaves out goes back to the template's own, never what an earlier style left. How a recipe's captions are applied; use it to copy a look exactly. For one tweak use caption_set_style.",
6000
+ inputSchema: {
6001
+ type: "object",
6002
+ properties: {
6003
+ id: { type: "string" },
6004
+ path: { type: "string" },
6005
+ enabled: { type: "boolean" },
6006
+ templateId: { type: "string", description: "A caption_set_template id." },
6007
+ wordsPerLine: { type: "number", description: "1-10. Default the template's own." },
6008
+ positionY: { type: "number", description: "% from the top. Default the project's." },
6009
+ style: {
6010
+ type: "object",
6011
+ description:
6012
+ "caption_set_style's look fields: fontFamily, fontSize, color, backgroundColor, highlightColor, highlightBackgroundColor, strokeColor, strokeWidth, uppercase, highlightMode, emphasisColor, emphasisBackgroundColor, emphasisScale, emphasisItalic, emphasisFontFamily, boxRotation.",
6013
+ },
6014
+ expectedRevision: { type: "number" },
6015
+ },
6016
+ required: ["enabled"],
6017
+ },
6018
+ command: "caption.set-look",
6019
+ },
5967
6020
  {
5968
6021
  name: "caption_mark_emphasis",
5969
6022
  description:
@@ -6157,17 +6210,20 @@ const TOOLS = [
6157
6210
  properties: {
6158
6211
  script: {
6159
6212
  type: "string",
6160
- description: "What the user will read, plain text (no markdown or stage directions), up to 20,000 characters.",
6213
+ description:
6214
+ "What the user will read, plain text (no markdown or stage directions), up to 20,000 characters.",
6161
6215
  },
6162
6216
  mode: {
6163
6217
  type: "string",
6164
6218
  enum: ["camera", "screen", "both"],
6165
- description: "camera (solo; default with a script), screen (screen only), or both (screen + camera bubble; default without a script).",
6219
+ description:
6220
+ "camera (solo; default with a script), screen (screen only), or both (screen + camera bubble; default without a script).",
6166
6221
  },
6167
6222
  orientation: {
6168
6223
  type: "string",
6169
6224
  enum: ["landscape", "portrait"],
6170
- description: "landscape 16:9 (YouTube) or portrait 9:16 (Shorts, Reels, TikTok): the camera shape for a camera take; a screen take's final shape is set while editing.",
6225
+ description:
6226
+ "landscape 16:9 (YouTube) or portrait 9:16 (Shorts, Reels, TikTok): the camera shape for a camera take; a screen take's final shape is set while editing.",
6171
6227
  },
6172
6228
  speed: { type: "number", description: "Teleprompter scroll speed 0.25-3." },
6173
6229
  fontSize: { type: "number", description: "Teleprompter text size in px, 16-72." },
@@ -7439,7 +7495,7 @@ const TOOLS = [
7439
7495
  {
7440
7496
  name: "recipe_apply_style",
7441
7497
  description:
7442
- "Apply a recipe's fixed style to a project, before recipe_render's content work. Returns { applied, failed, pending, notes }: applied / failed are read back from the project, notes = parts left to you. Fails, changing nothing, when the recipe needs footage the project lacks (a camera recipe on an audio-only project).",
7498
+ "Apply a recipe's fixed style to a project, before recipe_render's content work: aspect, the full caption look, speaker background, vertical framing, grade, camera layout. It REPLACES an earlier recipe's look. Returns { applied, failed, pending, notes }: applied / failed are read back from the project, notes = parts left to you. Fails, changing nothing, when the recipe needs footage the project lacks (a camera recipe on an audio-only project).",
7443
7499
  inputSchema: {
7444
7500
  type: "object",
7445
7501
  properties: {
@@ -7452,6 +7508,17 @@ const TOOLS = [
7452
7508
  },
7453
7509
  command: "recipe.apply-style",
7454
7510
  },
7511
+ {
7512
+ name: "recipe_look_frames",
7513
+ description:
7514
+ "The recipe's target look as images (attached): stills of its finished edit at key moments, each with what it shows. Look before editing with a recipe; compare project_render_frame at the matching beats before saying done. Match the look, never the content.",
7515
+ inputSchema: {
7516
+ type: "object",
7517
+ properties: { id: { type: "string", description: "Recipe id." } },
7518
+ required: ["id"],
7519
+ },
7520
+ command: "recipe.look-frames",
7521
+ },
7455
7522
  {
7456
7523
  name: "recipe_save",
7457
7524
  description:
@@ -7462,7 +7529,7 @@ const TOOLS = [
7462
7529
  recipe: {
7463
7530
  type: "object",
7464
7531
  description:
7465
- "{ id?, title, description, category, footage?, aspectRatio?, fields: [{ key, label, type: text|longtext|select|color|images, default?, options?, required?, help?, minCount?, maxCount?, optional? }], prompt, style?: { aspectRatio?, colorCorrection?, lut?: { preset, intensity? }, background?: { mode, image? }, cameraLayout?, captions?: { enabled, templateId? }, wallpaper? }, checklist: string[] }",
7532
+ "{ 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.",
7466
7533
  },
7467
7534
  },
7468
7535
  required: ["recipe"],
@@ -9049,10 +9116,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
9049
9116
  for (const previewPath of previews) {
9050
9117
  const fs = await import("node:fs/promises");
9051
9118
  const buf = await fs.readFile(previewPath);
9119
+ const ext = previewPath.toLowerCase().split(".").pop();
9052
9120
  content.push({
9053
9121
  type: "image",
9054
9122
  data: buf.toString("base64"),
9055
- mimeType: "image/png",
9123
+ mimeType:
9124
+ ext === "jpg" || ext === "jpeg"
9125
+ ? "image/jpeg"
9126
+ : ext === "webp"
9127
+ ? "image/webp"
9128
+ : "image/png",
9056
9129
  });
9057
9130
  }
9058
9131
  } catch (imgErr) {
@@ -9113,6 +9186,12 @@ function collectInlinePreviewPaths(command, data) {
9113
9186
  if (command === "motion.screenshot") {
9114
9187
  return typeof data.previewPath === "string" ? [data.previewPath] : [];
9115
9188
  }
9189
+ if (command === "recipe.look-frames") {
9190
+ const frames = Array.isArray(data.frames) ? data.frames : [];
9191
+ return frames
9192
+ .map((f) => (f && typeof f.path === "string" ? f.path : null))
9193
+ .filter((p) => p !== null);
9194
+ }
9116
9195
  if (command === "motion.verify-frames") {
9117
9196
  const frames = Array.isArray(data.frames) ? data.frames : [];
9118
9197
  return frames
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@writepanda/mcp",
3
- "version": "1.265.0",
3
+ "version": "1.267.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",