@pixeldojo/mcp 0.30.0 → 0.31.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/dist/index.cjs CHANGED
@@ -551,7 +551,7 @@ var init_generate = __esm({
551
551
  InputSchema = zod.z.object({
552
552
  prompt: zod.z.string().min(1).max(8e3).describe('Prompt describing what to generate. Write @Name to use a character or element the user saved in Character Studio ("@Mara on a beach"): its photos are attached automatically on models that take reference images. pixeldojo_library source=characters lists them.'),
553
553
  model: zod.z.string().optional().describe(
554
- `Model apiId. Recommended (the models the PixelDojo studios use): "seedream-5" for images (the default), "seedance-2-5" for video (prompt only or a starting image), "wan-3-0-video" for video the others refuse. Use another model only when the user names one. Full catalog: https://pixeldojo.ai/api/v1/models; one model's fields: https://pixeldojo.ai/llm/{apiId}.txt. Omit for seedream-5, which makes still images only; name a video model to get a video.`
554
+ `Model apiId. Recommended (the models the PixelDojo studios use): "seedream-5" for images (the default), "seedance-2-5" for video (prompt only or a starting image), "kling-4-0" for a whole scene up to 30 s written as a shot list (dialogue in quotes, exact on-screen text), "minimax-h3-turbo" for the cheapest video from a photo or up to 9 reference images (it needs at least one picture), "wan-3-0-video" for video the others refuse. Use another model only when the user names one. Full catalog: https://pixeldojo.ai/api/v1/models; one model's fields: https://pixeldojo.ai/llm/{apiId}.txt. Omit for seedream-5, which makes still images only; name a video model to get a video.`
555
555
  ),
556
556
  preset: zod.z.string().optional().describe(
557
557
  "Preset slug that seeds the running model's settings; explicit fields and params override it. Each preset belongs to one model (browse them by model at https://pixeldojo.ai/presets), so set `model` to that preset's model: a slug the running model has no preset for is rejected with a 400 before any charge."
@@ -590,7 +590,7 @@ var init_generate = __esm({
590
590
  prompt: { type: "string", description: 'Prompt describing what to generate. Write @Name to use a character or element the user saved in Character Studio ("@Mara on a beach"): its photos are attached automatically on models that take reference images. pixeldojo_library source=characters lists them.' },
591
591
  model: {
592
592
  type: "string",
593
- description: `Model apiId. Recommended (the models the PixelDojo studios use): "seedream-5" for images (the default), "seedance-2-5" for video (prompt only or a starting image), "wan-3-0-video" for video the others refuse. Use another model only when the user names one. Full catalog: https://pixeldojo.ai/api/v1/models; one model's fields: https://pixeldojo.ai/llm/{apiId}.txt. Omit for seedream-5, which makes still images only; name a video model to get a video.`
593
+ description: `Model apiId. Recommended (the models the PixelDojo studios use): "seedream-5" for images (the default), "seedance-2-5" for video (prompt only or a starting image), "kling-4-0" for a whole scene up to 30 s written as a shot list (dialogue in quotes, exact on-screen text), "minimax-h3-turbo" for the cheapest video from a photo or up to 9 reference images (it needs at least one picture), "wan-3-0-video" for video the others refuse. Use another model only when the user names one. Full catalog: https://pixeldojo.ai/api/v1/models; one model's fields: https://pixeldojo.ai/llm/{apiId}.txt. Omit for seedream-5, which makes still images only; name a video model to get a video.`
594
594
  },
595
595
  preset: {
596
596
  type: "string",
@@ -638,8 +638,8 @@ var init_generate = __esm({
638
638
  };
639
639
  generateSkill = {
640
640
  name: "pixeldojo_generate",
641
- description: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a prompt runs on seedream-5, which makes still images only. For a video, name seedance-2-5, which works from a prompt alone or a starting image. If a provider refuses the content, retry once on wan-3-0-video (video) or seedream-5 (images), the least-restricted models. For a multi-shot film or a music video synced to a song use pixeldojo_film; to change, move or extend an existing clip use pixeldojo_video. These are the models the PixelDojo studios use; name another only when the user asks for it. References: `image_url`/`image_urls` for stills, `video_url` for a source clip, `image_path`/`image_paths` for absolute local files (uploaded to 24h temp storage first). A clip or an audio track URL with no `model` runs on seedance-2-reference; a named model that cannot read a clip is swapped for it and the result says so, while a named model with no audio input drops the track. Model-specific settings go in `params` alongside an explicit `model`. Returns asset URLs, or a jobId for pixeldojo_status when the job outlasts the 30s wait.",
642
- hostedDescription: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a prompt runs on seedream-5, which makes still images only. For a video, name seedance-2-5, which works from a prompt alone or a starting image. If a provider refuses the content, retry once on wan-3-0-video (video) or seedream-5 (images), the least-restricted models. For a multi-shot film or a music video synced to a song use pixeldojo_film; to change, move or extend an existing clip use pixeldojo_video. These are the models the PixelDojo studios use; name another only when the user asks for it. References: `image_url`/`image_urls` for stills and `video_url` for a source clip, all public http(s) URLs. A clip or an audio track URL with no `model` runs on seedance-2-reference; a named model that cannot read a clip is swapped for it and the result says so, while a named model with no audio input drops the track. Model-specific settings go in `params` alongside an explicit `model`. Returns asset URLs, or a jobId for pixeldojo_status when the job outlasts the 30s wait.",
641
+ description: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a prompt runs on seedream-5, which makes still images only. For a video, name seedance-2-5, which works from a prompt alone or a starting image; kling-4-0 for a multi-shot scene up to 30 s with dialogue; minimax-h3-turbo for the lowest price when you have a photo or reference images (it refuses a prompt alone). If a provider refuses the content, retry once on wan-3-0-video (video) or seedream-5 (images), the least-restricted models. For a multi-shot film or a music video synced to a song use pixeldojo_film; to change, move or extend an existing clip use pixeldojo_video. These are the models the PixelDojo studios use; name another only when the user asks for it. References: `image_url`/`image_urls` for stills, `video_url` for a source clip, `image_path`/`image_paths` for absolute local files (uploaded to 24h temp storage first). A clip or an audio track URL with no `model` runs on seedance-2-reference; a named model that cannot read a clip is swapped for it and the result says so, while a named model with no audio input drops the track. Model-specific settings go in `params` alongside an explicit `model`. Returns asset URLs, or a jobId for pixeldojo_status when the job outlasts the 30s wait.",
642
+ hostedDescription: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a prompt runs on seedream-5, which makes still images only. For a video, name seedance-2-5, which works from a prompt alone or a starting image; kling-4-0 for a multi-shot scene up to 30 s with dialogue; minimax-h3-turbo for the lowest price when you have a photo or reference images (it refuses a prompt alone). If a provider refuses the content, retry once on wan-3-0-video (video) or seedream-5 (images), the least-restricted models. For a multi-shot film or a music video synced to a song use pixeldojo_film; to change, move or extend an existing clip use pixeldojo_video. These are the models the PixelDojo studios use; name another only when the user asks for it. References: `image_url`/`image_urls` for stills and `video_url` for a source clip, all public http(s) URLs. A clip or an audio track URL with no `model` runs on seedance-2-reference; a named model that cannot read a clip is swapped for it and the result says so, while a named model with no audio input drops the track. Model-specific settings go in `params` alongside an explicit `model`. Returns asset URLs, or a jobId for pixeldojo_status when the job outlasts the 30s wait.",
643
643
  inputZod: InputSchema,
644
644
  inputJsonSchema: InputJsonSchema,
645
645
  allowedModels: null,
@@ -1053,6 +1053,8 @@ var init_storyboard = __esm({
1053
1053
  ALLOWED2 = [
1054
1054
  "veo-3.1-fast",
1055
1055
  "veo-3.1-standard",
1056
+ // Kling 4.0 (2026-10-24): a brief written as a shot list renders as one clip, up to 30 s.
1057
+ "kling-4-0",
1056
1058
  "kling-video-v3-standard-text",
1057
1059
  "seedance-2-high",
1058
1060
  VIDEO_REFERENCE_MODEL
@@ -2444,6 +2446,27 @@ function buildVideoPayload(verb, apiId, i) {
2444
2446
  return { body: { prompt, video_url: i.videoUrl, video_duration: vd }, note: droppedImages };
2445
2447
  case "happyhorse-1.0-video-edit":
2446
2448
  return { body: { prompt, video_url: i.videoUrl, video_duration: vd, reference_urls: i.images } };
2449
+ case "kling-4-0":
2450
+ return {
2451
+ body: {
2452
+ prompt: /@video\s*1/i.test(prompt) ? prompt : `Edit @Video1: ${prompt}`,
2453
+ video: i.videoUrl,
2454
+ reference_images: i.images,
2455
+ duration: clamp(Math.ceil(vd), 3, 30),
2456
+ resolution: "1080p"
2457
+ }
2458
+ };
2459
+ case "minimax-h3-turbo":
2460
+ return {
2461
+ body: {
2462
+ prompt: `Recreate <Video 1> exactly: the same people, the same motion and timing, the same camera move and framing, with one change: ${prompt}`,
2463
+ reference_videos: [i.videoUrl],
2464
+ reference_video_audio: true,
2465
+ resolution: "720p",
2466
+ duration: clamp(Math.ceil(vd ?? 5), 5, 15)
2467
+ },
2468
+ note: droppedImages
2469
+ };
2447
2470
  default:
2448
2471
  return { body: { prompt, video_url: i.videoUrl, video_duration: vd, image_urls: i.images } };
2449
2472
  }
@@ -2572,6 +2595,8 @@ var init_video = __esm({
2572
2595
  "seedance-2-5-video-edit",
2573
2596
  "flux-video-edit",
2574
2597
  "kling-video-edit",
2598
+ "kling-4-0",
2599
+ "minimax-h3-turbo",
2575
2600
  "wan-video-edit",
2576
2601
  "seedance-video-edit",
2577
2602
  "happyhorse-1.0-video-edit",
@@ -2591,9 +2616,10 @@ var init_video = __esm({
2591
2616
  "happyhorse-1.0-video-edit",
2592
2617
  "xai-video-edit",
2593
2618
  "kling-motion-control",
2594
- "wan-video-character-swap"
2619
+ "wan-video-character-swap",
2620
+ "kling-4-0"
2595
2621
  ]);
2596
- NO_IMAGE_ENGINES = /* @__PURE__ */ new Set(["flux-video-edit", "xai-video-edit"]);
2622
+ NO_IMAGE_ENGINES = /* @__PURE__ */ new Set(["flux-video-edit", "xai-video-edit", "minimax-h3-turbo"]);
2597
2623
  InputSchema11 = zod.z.object({
2598
2624
  verb: zod.z.enum(VERBS),
2599
2625
  prompt: zod.z.string().max(8e3).optional(),
@@ -2948,6 +2974,14 @@ function describeDrama(v, o = DRAMA_OPTS) {
2948
2974
  text: [`Planned (${o.idField}: ${id}), ${v.format === "9:16" ? "vertical 9:16" : "widescreen 16:9"} (to switch, create it again in the other format before producing):`, v.plan ?? "", "", `Nothing has been charged yet. ${cost} Show this to the user and, once they agree, call ${next2("produce")}. (In Sensei: put it in pixeldojo_plan as ONE step with skill "${music ? "music_video" : "drama"}" and params {"${o.idField}": "${id}"}, which prices it from this quote.)`].join("\n")
2949
2975
  };
2950
2976
  }
2977
+ const gist = (note) => {
2978
+ const first = note.split(/(?<=\.) /)[0];
2979
+ return first.length > 160 ? `${first.slice(0, 157).trimEnd()}...` : first;
2980
+ };
2981
+ const rewrites = (b) => {
2982
+ const shots2 = Array.from(new Set(Array.from((b.redo_films ?? "").matchAll(/Shot (\d+) \(/g), (m) => m[1])));
2983
+ return shots2.length ? ` (the redo rewrites shot${shots2.length > 1 ? "s" : ""} ${shots2.join(", ")})` : "";
2984
+ };
2951
2985
  if (v.status === "notes") {
2952
2986
  const flagged = v.beats.filter((b) => b.note && (b.needs_redo ?? true));
2953
2987
  const other = v.beats.filter((b) => b.note && b.needs_redo === false);
@@ -2955,17 +2989,17 @@ function describeDrama(v, o = DRAMA_OPTS) {
2955
2989
  kind: "text",
2956
2990
  text: [
2957
2991
  `Every ${o.unit} is filmed. Before the cut, the review flagged ${o.unit}s ${flagged.map((b) => b.beat).join(", ")}:`,
2958
- ...flagged.map((b) => `- ${o.unit} ${b.beat}: ${b.note}${b.redo_films ? ` The redo films: ${b.redo_films}` : ""}`),
2959
- other.length ? `Also noted, no redo needed: ${other.map((b) => `${o.unit} ${b.beat}: ${b.note}`).join(" ")}` : "",
2992
+ ...flagged.map((b) => `- ${o.unit} ${b.beat}: ${gist(b.note)}${rewrites(b)}`),
2993
+ other.length ? `Also noted, no redo needed: ${other.map((b) => `${o.unit} ${b.beat}: ${gist(b.note)}`).join(" ")}` : "",
2960
2994
  simplify,
2961
- `Show these to the user and ask which they want: redo those ${o.unit}s with these notes (${o.tool} with {"${o.idField}": "${id}", "action": "redo", "beats": [${flagged.map((b) => b.beat).join(", ")}], "notes": [the notes, same order]}, each at its own price), or cut it as it is (action "cut", free). Nothing more is filmed until they choose.`
2995
+ `Show these to the user and ask which they want: redo those ${o.unit}s with the review's fixes (${o.tool} with {"${o.idField}": "${id}", "action": "redo", "beats": [${flagged.map((b) => b.beat).join(", ")}]}, no notes needed, each at its own price; add notes only for the user's own changes), or cut it as it is (action "cut", free). Nothing more is filmed until they choose.`
2962
2996
  ].filter(Boolean).join("\n")
2963
2997
  };
2964
2998
  }
2965
2999
  if (v.status === "done" && v.final_url) {
2966
3000
  const redo = v.beats.filter((b) => (b.note || b.missing_lines.length) && (b.needs_redo ?? true));
2967
- const notes = redo.map((b) => `${o.unit} ${b.beat}: ${b.note ?? `did not say ${b.missing_lines.map((l) => `"${l}"`).join(", ")}`}${b.redo_films ? ` The redo films: ${b.redo_films}` : ""}`);
2968
- const other = v.beats.filter((b) => b.note && b.needs_redo === false).map((b) => `${o.unit} ${b.beat}: ${b.note}`);
3001
+ const notes = redo.map((b) => `${o.unit} ${b.beat}: ${b.note ? gist(b.note) : `did not say ${b.missing_lines.map((l) => `"${l}"`).join(", ")}`}`);
3002
+ const other = v.beats.filter((b) => b.note && b.needs_redo === false).map((b) => `${o.unit} ${b.beat}: ${gist(b.note)}`);
2969
3003
  return {
2970
3004
  kind: "assets",
2971
3005
  text: [
@@ -2981,7 +3015,7 @@ function describeDrama(v, o = DRAMA_OPTS) {
2981
3015
  const doing = music ? { scripting: "listening to the song and writing the plan", shots: "filming the sections", cutting: "cutting it to the song" }[v.status] ?? STEP[v.status] ?? v.status : STEP[v.status] ?? v.status;
2982
3016
  const ready = v.beats.filter((b) => b.url).length;
2983
3017
  const total = v.beats.length || (music ? v.sections?.length ?? 0 : 5);
2984
- const again = v.rendering.map((n) => v.beats.find((b) => b.beat === n)).filter((b) => Boolean(b?.url)).map((b) => `${o.unit} ${b.beat} is being filmed again${b.missing_lines.length ? ` (it dropped the line "${b.missing_lines[0]}")` : b.note ? ` (the review asked: ${b.note.split(/(?<=\.) /)[0]})` : ""}`);
3018
+ const again = v.rendering.map((n) => v.beats.find((b) => b.beat === n)).filter((b) => Boolean(b?.url)).map((b) => `${o.unit} ${b.beat} is being filmed again${b.filming_note ? ` (your note: ${gist(b.filming_note)})` : b.missing_lines.length ? ` (it dropped the line "${b.missing_lines[0]}")` : b.note ? ` (the review asked: ${gist(b.note)})` : ""}`);
2985
3019
  return {
2986
3020
  kind: "text",
2987
3021
  text: `Still ${doing}${v.status === "shots" ? ` (${ready} of ${total} ${o.unit}s ready${v.rendering.length ? `, filming ${o.unit} ${v.rendering.join(", ")}` : ""})` : ""}.${again.length ? ` ${again.join("; ")}.` : ""} It takes about 10 to 15 minutes in all. Call ${next2("status")} in about a minute.`,
@@ -3333,7 +3367,7 @@ var init_kata = __esm({
3333
3367
  },
3334
3368
  photos: {
3335
3369
  type: "array",
3336
- items: { type: "object", properties: { url: { type: "string" }, note: { type: "string", description: 'What it is (e.g. "the product").' } }, required: ["url"] },
3370
+ items: { type: "object", properties: { url: { type: "string", description: "Public URL of the photo." }, note: { type: "string", description: 'What it is (e.g. "the product").' } }, required: ["url"] },
3337
3371
  description: "Create: up to 4 products or photos to put in the edit, on the PixelDojo CDN."
3338
3372
  },
3339
3373
  instructions: { type: "string", description: "Create (optional): what to change, e.g. the setting, the words on screen, where the product goes." },
@@ -4424,11 +4458,11 @@ var init_marketing = __esm({
4424
4458
  action: { type: "string", enum: ["get", "import", "update"], description: "Default get." },
4425
4459
  url: { type: "string", description: "import: the brand website, e.g. yourbrand.com." },
4426
4460
  save: { type: "boolean", description: "import: false returns the kit without saving it. Default true." },
4427
- name: { type: "string" },
4428
- tagline: { type: "string" },
4461
+ name: { type: "string", description: "Brand name." },
4462
+ tagline: { type: "string", description: "Short brand tagline." },
4429
4463
  voice: { type: "string", description: "How the brand talks, one or two sentences." },
4430
4464
  colors: { type: "array", items: { type: "string" }, maxItems: 5, description: "#RRGGBB, lead color first." },
4431
- fonts: { type: "array", items: { type: "string" }, maxItems: 2 },
4465
+ fonts: { type: "array", items: { type: "string" }, maxItems: 2, description: "Up to two brand font names." },
4432
4466
  selling_points: { type: "array", items: { type: "string" }, maxItems: 5, description: "Short product claims, 2-7 words each." },
4433
4467
  logo_url: { type: "string", format: "uri", description: "A logo on PixelDojo (upload it first); PNG with transparency is best." }
4434
4468
  }
@@ -4481,8 +4515,8 @@ var init_marketing = __esm({
4481
4515
  description: `image: an image template id from templates (e.g. stacked-shout, pure-white, ice-float). motion: ${MOTION.join(", ")}.`
4482
4516
  },
4483
4517
  product_url: { type: "string", format: "uri", description: "image: product page; name, description and photos are read from it." },
4484
- product_name: { type: "string" },
4485
- product_description: { type: "string" },
4518
+ product_name: { type: "string", description: "Product name when there is no product_url (with product_image_urls)." },
4519
+ product_description: { type: "string", description: "Short product description when there is no product_url." },
4486
4520
  product_image_urls: { type: "array", items: { type: "string", format: "uri" }, maxItems: 5, description: "Product photos. motion uses the first, cut out automatically." },
4487
4521
  product_image_paths: { type: "array", items: { type: "string" }, maxItems: 5, description: "Local product photos instead of URLs; uploaded first." },
4488
4522
  character_image_urls: { type: "array", items: { type: "string", format: "uri" }, maxItems: 2, description: "image: your own character (e.g. from pixeldojo_library source characters) for templates with a person." },
@@ -5119,7 +5153,7 @@ function makeRedactedLogger(target = console) {
5119
5153
  }
5120
5154
 
5121
5155
  // src/server.ts
5122
- var PACKAGE_VERSION = "0.30.0" ;
5156
+ var PACKAGE_VERSION = "0.31.0" ;
5123
5157
  var SERVER_INSTRUCTIONS = "Pixel Dojo generates images, video, audio and short films from one catalog of AI models, billed in credits from the connected Pixel Dojo account. A job that runs past the 30-second wait returns a jobId to check later; check it rather than submitting again, since every new submission is charged. Generated asset URLs are deleted one hour after they are created: pixeldojo_save keeps one in the user's My Media permanently (after a safety check), and finished films stay in the account library. In any prompt, @Name uses a character, product, outfit, location, prop or style the user saved in Character Studio: its photos are attached automatically. pixeldojo_library source=characters lists them, and pixeldojo_save_character saves a new one from 3 to 5 photos.";
5124
5158
  function buildServer(options) {
5125
5159
  if (!options.apiKey) {