@pixeldojo/mcp 0.5.0 → 0.6.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
@@ -260,7 +260,7 @@ var init_generate = __esm({
260
260
  InputSchema = zod.z.object({
261
261
  prompt: zod.z.string().min(1).max(8e3).describe("Prompt describing what to generate."),
262
262
  model: zod.z.string().optional().describe(
263
- 'Override the model. Any apiId from /api/v1/models (e.g. "flux", "google-nano-banana", "veo-3.1", "kling-video"). Omit to use the default.'
263
+ 'Override the model. Any apiId from /api/v1/models (e.g. "flux", "google-nano-banana", "veo-3.1-fast", "kling-video-v3-standard-text"). Omit to use the default.'
264
264
  ),
265
265
  preset: zod.z.string().optional().describe(
266
266
  'Preset slug to seed the params (e.g. "cinematic-portrait", "product-floating-clean", "magazine-cover-text"). Browse the catalog at https://pixeldojo.ai/presets. Explicit fields override preset values.'
@@ -279,7 +279,7 @@ var init_generate = __esm({
279
279
  prompt: { type: "string", description: "Prompt describing what to generate." },
280
280
  model: {
281
281
  type: "string",
282
- description: 'Override the model. Any apiId from /api/v1/models (e.g. "flux", "google-nano-banana", "veo-3.1", "kling-video"). Omit to use the default.'
282
+ description: 'Override the model. Any apiId from /api/v1/models (e.g. "flux", "google-nano-banana", "veo-3.1-fast", "kling-video-v3-standard-text"). Omit to use the default.'
283
283
  },
284
284
  preset: {
285
285
  type: "string",
@@ -473,17 +473,22 @@ async function run3(input, ctx) {
473
473
  };
474
474
  }
475
475
  const apiId = requested;
476
- if ((apiId === "flux-edit" || apiId === "gpt-image-2-edit") && !input.reference_image_url) {
476
+ if (REQUIRES_REFERENCE.has(apiId) && !input.reference_image_url) {
477
477
  return {
478
478
  kind: "text",
479
- text: `pixeldojo:character with model="${apiId}" requires reference_image_url (the source image of the character to edit). For generation from a prompt alone, use model="ideogram-character".`
479
+ text: `pixeldojo:character with model="${apiId}" requires reference_image_url (the source image of the character to edit). For generation from a prompt alone, use model="${DEFAULT_MODEL3}".`
480
480
  };
481
481
  }
482
482
  const body = { prompt: input.prompt };
483
- if (input.aspect_ratio) body.aspect_ratio = input.aspect_ratio;
484
483
  if (input.reference_image_url) {
485
- body.image_url = input.reference_image_url;
486
- body.reference_image_url = input.reference_image_url;
484
+ if (apiId === "flux-edit") {
485
+ body.input_image = input.reference_image_url;
486
+ } else {
487
+ body.image_urls = [input.reference_image_url];
488
+ }
489
+ }
490
+ if (input.aspect_ratio && apiId === "flux-edit" && FLUX_EDIT_ASPECT_RATIOS.has(input.aspect_ratio)) {
491
+ body.aspect_ratio = input.aspect_ratio;
487
492
  }
488
493
  const submitted = await ctx.client.run(apiId, body);
489
494
  const result = await pollJobUntilDoneOrHandoff(
@@ -500,20 +505,35 @@ async function run3(input, ctx) {
500
505
  (urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Character shot ready. Asset: ${urls[0]}`
501
506
  );
502
507
  }
503
- var ALLOWED, DEFAULT_MODEL3, InputSchema3, InputJsonSchema3, characterSkill;
508
+ var ALLOWED, DEFAULT_MODEL3, REQUIRES_REFERENCE, FLUX_EDIT_ASPECT_RATIOS, InputSchema3, InputJsonSchema3, characterSkill;
504
509
  var init_character = __esm({
505
510
  "src/skills/character.ts"() {
506
511
  init_poll();
507
512
  init_types();
508
- ALLOWED = ["ideogram-character", "flux-edit", "gpt-image-2-edit"];
509
- DEFAULT_MODEL3 = "ideogram-character";
513
+ ALLOWED = ["seedream-5", "seedream-4", "flux-edit", "gpt-image-2-edit"];
514
+ DEFAULT_MODEL3 = "seedream-5";
515
+ REQUIRES_REFERENCE = /* @__PURE__ */ new Set(["flux-edit", "gpt-image-2-edit"]);
516
+ FLUX_EDIT_ASPECT_RATIOS = /* @__PURE__ */ new Set([
517
+ "1:1",
518
+ "16:9",
519
+ "9:16",
520
+ "21:9",
521
+ "9:21",
522
+ "3:2",
523
+ "2:3",
524
+ "4:5",
525
+ "5:4",
526
+ "3:4",
527
+ "4:3",
528
+ "match_input_image"
529
+ ]);
510
530
  InputSchema3 = zod.z.object({
511
531
  prompt: zod.z.string().min(1).max(8e3),
512
532
  model: zod.z.string().optional().describe(`One of: ${ALLOWED.join(", ")}. Defaults to ${DEFAULT_MODEL3}.`),
513
533
  reference_image_url: zod.z.string().url().optional().describe(
514
- "Reference image of the character. Required by flux-edit and gpt-image-2-edit; optional for ideogram-character."
534
+ "Reference image of the character. Required by flux-edit and gpt-image-2-edit; optional for seedream-5/seedream-4."
515
535
  ),
516
- aspect_ratio: zod.z.string().optional()
536
+ aspect_ratio: zod.z.string().optional().describe('Only honored for model="flux-edit".')
517
537
  });
518
538
  InputJsonSchema3 = {
519
539
  type: "object",
@@ -531,7 +551,7 @@ var init_character = __esm({
531
551
  };
532
552
  characterSkill = {
533
553
  name: "pixeldojo:character",
534
- description: "Generate or edit consistent characters across shots. Pass a reference_image_url for edit-style models.",
554
+ description: "Generate or edit consistent characters across shots. Pass a reference_image_url for identity locking (seedream-5 by default).",
535
555
  inputZod: InputSchema3,
536
556
  inputJsonSchema: InputJsonSchema3,
537
557
  allowedModels: [...ALLOWED],
@@ -572,8 +592,13 @@ var init_storyboard = __esm({
572
592
  "src/skills/storyboard.ts"() {
573
593
  init_poll();
574
594
  init_types();
575
- ALLOWED2 = ["veo-3.1", "kling-video", "seedance-2"];
576
- DEFAULT_MODEL4 = "veo-3.1";
595
+ ALLOWED2 = [
596
+ "veo-3.1-fast",
597
+ "veo-3.1-standard",
598
+ "kling-video-v3-standard-text",
599
+ "seedance-2-high"
600
+ ];
601
+ DEFAULT_MODEL4 = "veo-3.1-fast";
577
602
  InputSchema4 = zod.z.object({
578
603
  brief: zod.z.string().min(1).max(8e3).describe("Storyboard brief: scene, shots, mood, action."),
579
604
  model: zod.z.string().optional().describe(`One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}.`),
@@ -619,11 +644,20 @@ async function run5(input, ctx) {
619
644
  const apiId = requested;
620
645
  const body = {
621
646
  prompt: "",
622
- image_url: input.image_url
647
+ image: input.image_url
623
648
  };
624
649
  if (apiId === "magnific-upscaler") {
625
- body.scale_factor = input.scale_factor ?? 2;
650
+ const allowed = [2, 4, 8, 16];
651
+ const requestedScale = input.scale_factor ?? 2;
652
+ const nearest = allowed.reduce(
653
+ (a, b) => Math.abs(b - requestedScale) < Math.abs(a - requestedScale) ? b : a
654
+ );
655
+ body.scale_factor = `${nearest}x`;
626
656
  if (input.creativity !== void 0) body.creativity = input.creativity;
657
+ } else if (apiId === "creative-upscale") {
658
+ body.scale_factor = Math.min(10, Math.max(1, input.scale_factor ?? 2));
659
+ } else if (apiId === "face-enhance") {
660
+ body.scale_factor = Math.min(8, Math.max(1, input.scale_factor ?? 4));
627
661
  }
628
662
  const submitted = await ctx.client.run(apiId, body);
629
663
  const result = await pollJobUntilDoneOrHandoff(
@@ -650,7 +684,9 @@ var init_upscale = __esm({
650
684
  InputSchema5 = zod.z.object({
651
685
  image_url: zod.z.string().url().describe("URL of the source image to upscale."),
652
686
  model: zod.z.string().optional().describe(`One of: ${ALLOWED3.join(", ")}. Defaults to ${DEFAULT_MODEL5}.`),
653
- scale_factor: zod.z.number().int().min(1).max(4).optional().describe("Magnific only: 1, 2, or 4. Defaults to 2."),
687
+ scale_factor: zod.z.number().min(1).max(16).optional().describe(
688
+ "Upscale multiplier. Magnific snaps to the nearest of 2/4/8/16 (default 2); creative-upscale accepts 1-10 (default 2); face-enhance accepts 1-8 (default 4)."
689
+ ),
654
690
  creativity: zod.z.number().min(0).max(1).optional().describe("Magnific only: 0 (preserve) \u2192 1 (creative). Defaults to 0.")
655
691
  });
656
692
  InputJsonSchema5 = {
@@ -658,7 +694,7 @@ var init_upscale = __esm({
658
694
  properties: {
659
695
  image_url: { type: "string", format: "uri" },
660
696
  model: { type: "string", enum: ALLOWED3 },
661
- scale_factor: { type: "integer", minimum: 1, maximum: 4 },
697
+ scale_factor: { type: "number", minimum: 1, maximum: 16 },
662
698
  creativity: { type: "number", minimum: 0, maximum: 1 }
663
699
  },
664
700
  required: ["image_url"]
@@ -1287,7 +1323,24 @@ async function runWorkflow(input, ctx) {
1287
1323
  text: `Step ${i + 1} (${step.skill}) has invalid args: ${issue?.path.join(".") || "input"} ${issue?.message || "invalid"}.`
1288
1324
  };
1289
1325
  }
1290
- const result = await skill.run(parsed.data, ctx);
1326
+ let result = await skill.run(parsed.data, ctx);
1327
+ if (result.kind === "handoff") {
1328
+ const handoffJobId = result.jobId;
1329
+ const polled = await pollJobUntilDoneOrHandoff(
1330
+ handoffJobId,
1331
+ (id) => ctx.client.getJob(id),
1332
+ ctx.buildStatusUrl,
1333
+ {
1334
+ syncBudgetMs: WORKFLOW_STEP_EXTRA_BUDGET_MS,
1335
+ now: ctx.pollOverrides?.now,
1336
+ sleep: ctx.pollOverrides?.sleep
1337
+ }
1338
+ );
1339
+ result = pollResultToSkillResult(
1340
+ polled,
1341
+ (urls) => urls.length === 0 ? `Job ${handoffJobId} completed but returned no assets.` : `Done. Asset: ${urls[0]}`
1342
+ );
1343
+ }
1291
1344
  const url = firstUrl(result);
1292
1345
  if (url) {
1293
1346
  prevUrl = url;
@@ -1297,6 +1350,11 @@ async function runWorkflow(input, ctx) {
1297
1350
  kind: "text",
1298
1351
  text: `Workflow "${workflow.name}" stopped at step ${i + 1} (${step.skill}): ${result.text}`
1299
1352
  };
1353
+ } else if (result.kind === "handoff") {
1354
+ return {
1355
+ kind: "text",
1356
+ text: `Workflow "${workflow.name}" is still on step ${i + 1} (${step.skill}) after an extended wait. Poll with pixeldojo:status { jobId: "${result.jobId}" }, then re-run the workflow once it completes.`
1357
+ };
1300
1358
  } else {
1301
1359
  outputs.push(`step ${i + 1} (${step.skill}): done (no asset URL)`);
1302
1360
  }
@@ -1307,9 +1365,12 @@ async function runWorkflow(input, ctx) {
1307
1365
  ${outputs.join("\n")}`
1308
1366
  };
1309
1367
  }
1310
- var StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
1368
+ var WORKFLOW_STEP_EXTRA_BUDGET_MS, StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
1311
1369
  var init_workflows = __esm({
1312
1370
  "src/skills/workflows.ts"() {
1371
+ init_poll();
1372
+ init_types();
1373
+ WORKFLOW_STEP_EXTRA_BUDGET_MS = 6e4;
1313
1374
  StepSchema = zod.z.object({
1314
1375
  skill: zod.z.string().regex(/^pixeldojo:(generate|edit|character|storyboard|upscale|audio|upload|from_url)$/, {
1315
1376
  message: "Runnable skills only: generate, edit, character, storyboard, upscale, audio, upload, from_url."
@@ -1494,7 +1555,7 @@ function makeRedactedLogger(target = console) {
1494
1555
  }
1495
1556
 
1496
1557
  // src/server.ts
1497
- var PACKAGE_VERSION = "0.1.0";
1558
+ var PACKAGE_VERSION = "0.6.0" ;
1498
1559
  function buildServer(options) {
1499
1560
  if (!options.apiKey) {
1500
1561
  throw new Error(