@productmaker/mcp 12.2.7 → 12.2.8

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/README.md CHANGED
@@ -371,6 +371,20 @@ out on purpose: the integration key is a secret pasted in Integrations. All
371
371
  nine are MCP-only (`whatsapp: "unavailable"`) and behind the `financial-control`
372
372
  admin feature.
373
373
 
374
+ ### 12.2.8 — Result-viewer origin and correction delivery (unreleased)
375
+
376
+ - Declare the shared OpenAI component origin on listed and readable result-viewer
377
+ resources, matching the uploader. Keep the standard host-selected origin and
378
+ fail-closed media CSP unchanged for other MCP Apps hosts.
379
+ - SDK transport tests verify both metadata placements. Native acceptance and the
380
+ cause of a browser sandbox cancellation remain separate checks.
381
+ - Deliver published image corrections from `get_image_edit_status` through the
382
+ same read-only task viewer and protected asset proxy. Preserve operation status,
383
+ degradation and error; queued/processing stay pending and failed stays error.
384
+ Missing or invalid proxy/media configuration stays empty, with no raw storage
385
+ URL or storage key in model-facing content. The original task being done never
386
+ makes an unfinished correction ready. No generation or paid action is added.
387
+
374
388
  ### 12.2.7 — Upload reliability and media transport hardening (unreleased)
375
389
 
376
390
  - Correct public landing/Shopify publication and Meta creative URL/temporary-asset
package/dist/http.js CHANGED
@@ -3021,7 +3021,7 @@ var LlmPricingSnapshotSchema = z3.discriminatedUnion("source", [
3021
3021
  });
3022
3022
  function nativeOutputTokenCeiling(target) {
3023
3023
  if (target.nativeOwnedOutputPolicy) return target.nativeOwnedOutputPolicy.verifiedMaxOutputTokens;
3024
- return target.transport === "google" || target.id === "gemini-3.1-pro-openrouter" ? 65536 : 1e5;
3024
+ return target.transport === "google" || target.id === "gemini-flash-runware" || target.id === "gemini-3.1-pro-openrouter" ? 65536 : 1e5;
3025
3025
  }
3026
3026
  __name(nativeOutputTokenCeiling, "nativeOutputTokenCeiling");
3027
3027
  var LlmRouteTargetSchema = z3.object({
@@ -8288,6 +8288,12 @@ var CodeLandingAuthorEnvelopeSchema = z23.object({
8288
8288
  */
8289
8289
  variantFacts: z23.array(LandingVariantFactSchema).max(16).optional()
8290
8290
  });
8291
+ var CODE_LANDING_DEFERRED_AUTHOR_PROVIDER_RESULT_KIND = "code_landing_deferred_author_provider_v1";
8292
+ var CodeLandingDeferredAuthorProviderResultSchema = z23.object({
8293
+ kind: z23.literal(CODE_LANDING_DEFERRED_AUTHOR_PROVIDER_RESULT_KIND),
8294
+ stepKey: z23.string().min(1),
8295
+ providerResult: z23.record(z23.string(), z23.unknown())
8296
+ });
8291
8297
  var CodeLandingCommerceChangeSchema = z23.object({
8292
8298
  price: z23.string().trim().min(1).max(40).optional(),
8293
8299
  compareAtPrice: z23.string().trim().min(1).max(40).nullable().optional(),
@@ -10818,6 +10824,8 @@ var role = z38.object({
10818
10824
  provider: id2,
10819
10825
  model: id2,
10820
10826
  bindingId: id2,
10827
+ /** Immutable shared-router chain for fresh recipes; absent preserves legacy custody. */
10828
+ routeSnapshot: LlmRouteSnapshotSchema.optional(),
10821
10829
  /** null explicitly omits effort on OpenRouter; undefined is a historical recipe. */
10822
10830
  reasoning: CreativeEngineRoleReasoningSchema.nullable().optional(),
10823
10831
  /** Server-owned output ceiling; omitted historical recipes keep their old stage cap. */
@@ -10837,7 +10845,13 @@ var CreativeEngineRecipeSchema = z38.object({
10837
10845
  roles: z38.object({
10838
10846
  director: role,
10839
10847
  reviewer: role,
10840
- executor: role.nullable()
10848
+ executor: role.nullable(),
10849
+ /**
10850
+ * Independent reviewer of the assembled final video only (owner
10851
+ * decision 2026-10-26). Absent on historical recipes: their final
10852
+ * review keeps the frozen `reviewer`, unchanged hash and identity.
10853
+ */
10854
+ finalReviewer: role.optional()
10841
10855
  }).strict(),
10842
10856
  capabilities: z38.object({
10843
10857
  videoModels: z38.array(id2).min(1),
@@ -10856,9 +10870,14 @@ var CreativeEngineRecipeSchema = z38.object({
10856
10870
  /** New recipes reserve an explicit native failover; historical calls stay single-route. */
10857
10871
  modelFallbackPolicy: z38.literal("anthropic_conclusive_v1").optional(),
10858
10872
  /** New reviewer/executor calls use the shared same-model native provider router. */
10859
- centralModelRouting: z38.literal("native_owned_same_model_v1").optional(),
10873
+ centralModelRouting: z38.enum([
10874
+ "native_owned_same_model_v1",
10875
+ "shared_role_chain_v1"
10876
+ ]).optional(),
10860
10877
  /** Skip only a redundant global review of a deterministically frozen scene repair. */
10861
10878
  repairPlanReviewPolicy: z38.literal("frozen_contract_v1").optional(),
10879
+ /** Root-only visual patch wire contract; absent preserves historic full-plan recovery. */
10880
+ repairAuthoring: z38.literal("scene_patch_v1").optional(),
10862
10881
  /** New requests maximize output inside model and measured input headroom. */
10863
10882
  outputTokenPolicy: z38.literal("model_max_v1").optional(),
10864
10883
  /**
@@ -11319,6 +11338,7 @@ var CreativeEngineCandidateSchema = z38.object({
11319
11338
  qualityScore: z38.number().min(0).max(100)
11320
11339
  }).strict();
11321
11340
  var CreativeEngineCostBasisSchema = z38.enum([
11341
+ "reused",
11322
11342
  "provider_reported",
11323
11343
  "provider_credits_conversion",
11324
11344
  "catalogue_estimate"
@@ -11619,6 +11639,15 @@ var CreativeEngineEventSchema = z38.discriminatedUnion("type", [
11619
11639
  }).strict(),
11620
11640
  plan: CreativeEnginePlanSchema
11621
11641
  }).strict(),
11642
+ z38.object({
11643
+ type: z38.literal("accepted_author_output_revalidated"),
11644
+ operationId: id2,
11645
+ acceptedId: id2,
11646
+ context: CreativeEngineContextBindingSchema,
11647
+ outputSha256: hash,
11648
+ validationRevision: z38.string().regex(/^[a-z][a-z0-9_]{0,63}$/),
11649
+ plan: CreativeEnginePlanSchema
11650
+ }).strict(),
11622
11651
  z38.object({
11623
11652
  type: z38.literal("plan_recorded"),
11624
11653
  plan: CreativeEnginePlanSchema
@@ -13110,7 +13139,9 @@ var SERVICE_MODES = [
13110
13139
  ];
13111
13140
  var ServiceModeSchema = z46.enum(SERVICE_MODES);
13112
13141
  var AppFeaturesSchema = z46.object({
13113
- serviceMotionGraphics: z46.boolean()
13142
+ serviceMotionGraphics: z46.boolean(),
13143
+ /** GIF authoring controls; absent on older APIs means hidden. */
13144
+ landingGif: z46.boolean().default(false)
13114
13145
  });
13115
13146
  var MOTION_GRAPHICS_FORMATS = [
13116
13147
  "vertical",
@@ -30873,11 +30904,12 @@ var ApiClient = class {
30873
30904
  };
30874
30905
 
30875
30906
  // src/index.ts
30876
- var MCP_VERSION = "12.2.7";
30907
+ var MCP_VERSION = "12.2.8";
30877
30908
 
30878
30909
  // src/meta-upload-app.ts
30879
30910
  import { readFileSync } from "fs";
30880
30911
  import { z as z132 } from "zod";
30912
+ import { registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
30881
30913
 
30882
30914
  // src/public-https.ts
30883
30915
  import { lookup } from "dns/promises";
@@ -31337,11 +31369,12 @@ function assertSafePublicBaseUrl(envName, url2) {
31337
31369
  }
31338
31370
  __name(assertSafePublicBaseUrl, "assertSafePublicBaseUrl");
31339
31371
 
31372
+ // src/app-origin.ts
31373
+ var PRODUCTMAKER_APP_ORIGIN = "https://productmaker.app";
31374
+
31340
31375
  // src/meta-upload-app.ts
31341
- import { registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
31342
31376
  var MEDIA_UPLOAD_APP_RESOURCE_URI = "ui://media-upload/v1.html";
31343
31377
  var MEDIA_UPLOAD_APP_NAME = "ProductMaker media upload";
31344
- var PRODUCTMAKER_APP_ORIGIN = "https://productmaker.app";
31345
31378
  var MEDIA_UPLOAD_APP_HTML_URL = new URL("./ui/meta-upload-app.html", import.meta.url);
31346
31379
  var PRODUCTMAKER_UPLOAD_STORAGE_ORIGIN = "https://825805a8113ddb98b68b9b0ddbb5d72a.r2.cloudflarestorage.com";
31347
31380
  var MEDIA_UPLOAD_CONNECT_DOMAINS = [
@@ -31541,6 +31574,7 @@ function registerTaskResultsAppResource(server, proxyBaseUrl) {
31541
31574
  connectDomains: []
31542
31575
  }
31543
31576
  },
31577
+ "openai/widgetDomain": PRODUCTMAKER_APP_ORIGIN,
31544
31578
  "openai/widgetCSP": {
31545
31579
  resource_domains: resourceDomains,
31546
31580
  connect_domains: []
@@ -37271,7 +37305,7 @@ function resolveLandingSetup(setup) {
37271
37305
  };
37272
37306
  }
37273
37307
  __name(resolveLandingSetup, "resolveLandingSetup");
37274
- function registerCreativeTools(server, api, { transport = "http" } = {}) {
37308
+ function registerCreativeTools(server, api, { transport = "http", proxyBaseUrl = null } = {}) {
37275
37309
  server.registerTool("generate_free_video", {
37276
37310
  title: "Custom-script video",
37277
37311
  description: generateFreeVideoGuidance.summary + ' Si el usuario adjunta o menciona una imagen local, llama primero request_media_upload con mediaKind=image y usa el assetId devuelto; no pidas path ni URL. Devuelve un taskId y procesa el job de forma as\xEDncrona.\n\nREQUERIDOS: rawPrompt, quality, durationSeconds y videoResolution.\n\nCALIDAD: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan). Economy admite 6/8/10/15s; Medium admite cualquier duraci\xF3n entera de 4 a 15s; Pro admite enteros de 2 a 30s y audio natural. `freeProModel` se elimin\xF3 \u2014 usa `modelId` (ver su descripci\xF3n); Seedance 2.5 est\xE1 inactivo y se rechaza con un error claro.\n\nSUBT\xCDTULOS: si addSubtitles=true, el rawPrompt completo se usa como texto exacto de subt\xEDtulos y debe tener m\xE1ximo 500 caracteres; no existe una pregunta adicional de transcripci\xF3n.\n\nPara videos normales con narrativa/\xE1ngulo usa generate_video_creative. Para tareas combinadas de producto usa create_product_task.',
@@ -37489,10 +37523,43 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
37489
37523
  taskId: z142.string().uuid(),
37490
37524
  operationId: z142.string().uuid()
37491
37525
  },
37492
- annotations: READS_INTERNAL
37526
+ annotations: READS_INTERNAL,
37527
+ _meta: taskResultsToolMeta()
37493
37528
  }, async (input) => {
37494
37529
  try {
37495
- return asText(await api.getJson(`/v1/creatives/images/${encodeURIComponent(input.taskId)}/operations/${encodeURIComponent(input.operationId)}`));
37530
+ const { assetUrl, assetKey: _assetKey, ...operation } = ImageCreativeEditStatusResponse.parse(await api.getJson(`/v1/creatives/images/${encodeURIComponent(input.taskId)}/operations/${encodeURIComponent(input.operationId)}`));
37531
+ const imageExtension = assetUrl ? new URL(assetUrl).pathname.match(/\.(png|jpe?g|webp)$/i)?.[0]?.toLowerCase() : void 0;
37532
+ const proxyUrl = operation.status === "published" && assetUrl ? buildProxyUrl({
37533
+ r2Url: assetUrl,
37534
+ filename: `image-edit-${operation.variantIndex + 1}${imageExtension ?? ".bin"}`,
37535
+ proxyBaseUrl
37536
+ }) : null;
37537
+ const view = buildTaskResultsView({
37538
+ images: proxyUrl ? [
37539
+ {
37540
+ url: proxyUrl,
37541
+ alt: `Corrected image ${operation.variantIndex + 1}`
37542
+ }
37543
+ ] : [],
37544
+ videos: [],
37545
+ links: []
37546
+ }, proxyBaseUrl);
37547
+ if (operation.status === "failed") view.state = "error";
37548
+ else if (operation.status !== "published") view.state = "pending";
37549
+ const deliveredUrl = view.images[0]?.url;
37550
+ const response = {
37551
+ ...operation,
37552
+ ...deliveredUrl ? {
37553
+ assetUrl: deliveredUrl
37554
+ } : {}
37555
+ };
37556
+ return {
37557
+ ...asText(response),
37558
+ structuredContent: response,
37559
+ _meta: {
37560
+ taskResults: view
37561
+ }
37562
+ };
37496
37563
  } catch (error) {
37497
37564
  throw translateError(error);
37498
37565
  }
@@ -41413,6 +41480,7 @@ function createServer(opts) {
41413
41480
  registerServiceImageTools(server, api);
41414
41481
  registerAnimatedVideoTools(server, api);
41415
41482
  registerCreativeTools(server, api, {
41483
+ proxyBaseUrl,
41416
41484
  transport
41417
41485
  });
41418
41486
  registerCreativeVariantTools(server, api);
package/dist/stdio.js CHANGED
@@ -2796,7 +2796,7 @@ var LlmPricingSnapshotSchema = z3.discriminatedUnion("source", [
2796
2796
  });
2797
2797
  function nativeOutputTokenCeiling(target) {
2798
2798
  if (target.nativeOwnedOutputPolicy) return target.nativeOwnedOutputPolicy.verifiedMaxOutputTokens;
2799
- return target.transport === "google" || target.id === "gemini-3.1-pro-openrouter" ? 65536 : 1e5;
2799
+ return target.transport === "google" || target.id === "gemini-flash-runware" || target.id === "gemini-3.1-pro-openrouter" ? 65536 : 1e5;
2800
2800
  }
2801
2801
  __name(nativeOutputTokenCeiling, "nativeOutputTokenCeiling");
2802
2802
  var LlmRouteTargetSchema = z3.object({
@@ -8063,6 +8063,12 @@ var CodeLandingAuthorEnvelopeSchema = z23.object({
8063
8063
  */
8064
8064
  variantFacts: z23.array(LandingVariantFactSchema).max(16).optional()
8065
8065
  });
8066
+ var CODE_LANDING_DEFERRED_AUTHOR_PROVIDER_RESULT_KIND = "code_landing_deferred_author_provider_v1";
8067
+ var CodeLandingDeferredAuthorProviderResultSchema = z23.object({
8068
+ kind: z23.literal(CODE_LANDING_DEFERRED_AUTHOR_PROVIDER_RESULT_KIND),
8069
+ stepKey: z23.string().min(1),
8070
+ providerResult: z23.record(z23.string(), z23.unknown())
8071
+ });
8066
8072
  var CodeLandingCommerceChangeSchema = z23.object({
8067
8073
  price: z23.string().trim().min(1).max(40).optional(),
8068
8074
  compareAtPrice: z23.string().trim().min(1).max(40).nullable().optional(),
@@ -10593,6 +10599,8 @@ var role = z38.object({
10593
10599
  provider: id2,
10594
10600
  model: id2,
10595
10601
  bindingId: id2,
10602
+ /** Immutable shared-router chain for fresh recipes; absent preserves legacy custody. */
10603
+ routeSnapshot: LlmRouteSnapshotSchema.optional(),
10596
10604
  /** null explicitly omits effort on OpenRouter; undefined is a historical recipe. */
10597
10605
  reasoning: CreativeEngineRoleReasoningSchema.nullable().optional(),
10598
10606
  /** Server-owned output ceiling; omitted historical recipes keep their old stage cap. */
@@ -10612,7 +10620,13 @@ var CreativeEngineRecipeSchema = z38.object({
10612
10620
  roles: z38.object({
10613
10621
  director: role,
10614
10622
  reviewer: role,
10615
- executor: role.nullable()
10623
+ executor: role.nullable(),
10624
+ /**
10625
+ * Independent reviewer of the assembled final video only (owner
10626
+ * decision 2026-10-26). Absent on historical recipes: their final
10627
+ * review keeps the frozen `reviewer`, unchanged hash and identity.
10628
+ */
10629
+ finalReviewer: role.optional()
10616
10630
  }).strict(),
10617
10631
  capabilities: z38.object({
10618
10632
  videoModels: z38.array(id2).min(1),
@@ -10631,9 +10645,14 @@ var CreativeEngineRecipeSchema = z38.object({
10631
10645
  /** New recipes reserve an explicit native failover; historical calls stay single-route. */
10632
10646
  modelFallbackPolicy: z38.literal("anthropic_conclusive_v1").optional(),
10633
10647
  /** New reviewer/executor calls use the shared same-model native provider router. */
10634
- centralModelRouting: z38.literal("native_owned_same_model_v1").optional(),
10648
+ centralModelRouting: z38.enum([
10649
+ "native_owned_same_model_v1",
10650
+ "shared_role_chain_v1"
10651
+ ]).optional(),
10635
10652
  /** Skip only a redundant global review of a deterministically frozen scene repair. */
10636
10653
  repairPlanReviewPolicy: z38.literal("frozen_contract_v1").optional(),
10654
+ /** Root-only visual patch wire contract; absent preserves historic full-plan recovery. */
10655
+ repairAuthoring: z38.literal("scene_patch_v1").optional(),
10637
10656
  /** New requests maximize output inside model and measured input headroom. */
10638
10657
  outputTokenPolicy: z38.literal("model_max_v1").optional(),
10639
10658
  /**
@@ -11094,6 +11113,7 @@ var CreativeEngineCandidateSchema = z38.object({
11094
11113
  qualityScore: z38.number().min(0).max(100)
11095
11114
  }).strict();
11096
11115
  var CreativeEngineCostBasisSchema = z38.enum([
11116
+ "reused",
11097
11117
  "provider_reported",
11098
11118
  "provider_credits_conversion",
11099
11119
  "catalogue_estimate"
@@ -11394,6 +11414,15 @@ var CreativeEngineEventSchema = z38.discriminatedUnion("type", [
11394
11414
  }).strict(),
11395
11415
  plan: CreativeEnginePlanSchema
11396
11416
  }).strict(),
11417
+ z38.object({
11418
+ type: z38.literal("accepted_author_output_revalidated"),
11419
+ operationId: id2,
11420
+ acceptedId: id2,
11421
+ context: CreativeEngineContextBindingSchema,
11422
+ outputSha256: hash,
11423
+ validationRevision: z38.string().regex(/^[a-z][a-z0-9_]{0,63}$/),
11424
+ plan: CreativeEnginePlanSchema
11425
+ }).strict(),
11397
11426
  z38.object({
11398
11427
  type: z38.literal("plan_recorded"),
11399
11428
  plan: CreativeEnginePlanSchema
@@ -12885,7 +12914,9 @@ var SERVICE_MODES = [
12885
12914
  ];
12886
12915
  var ServiceModeSchema = z46.enum(SERVICE_MODES);
12887
12916
  var AppFeaturesSchema = z46.object({
12888
- serviceMotionGraphics: z46.boolean()
12917
+ serviceMotionGraphics: z46.boolean(),
12918
+ /** GIF authoring controls; absent on older APIs means hidden. */
12919
+ landingGif: z46.boolean().default(false)
12889
12920
  });
12890
12921
  var MOTION_GRAPHICS_FORMATS = [
12891
12922
  "vertical",
@@ -29200,11 +29231,12 @@ var ApiClient = class {
29200
29231
  };
29201
29232
 
29202
29233
  // src/index.ts
29203
- var MCP_VERSION = "12.2.7";
29234
+ var MCP_VERSION = "12.2.8";
29204
29235
 
29205
29236
  // src/meta-upload-app.ts
29206
29237
  import { readFileSync } from "fs";
29207
29238
  import { z as z131 } from "zod";
29239
+ import { registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
29208
29240
 
29209
29241
  // src/public-https.ts
29210
29242
  import { lookup } from "dns/promises";
@@ -29668,11 +29700,12 @@ function assertSafeApiBaseUrl(url2) {
29668
29700
  }
29669
29701
  __name(assertSafeApiBaseUrl, "assertSafeApiBaseUrl");
29670
29702
 
29703
+ // src/app-origin.ts
29704
+ var PRODUCTMAKER_APP_ORIGIN = "https://productmaker.app";
29705
+
29671
29706
  // src/meta-upload-app.ts
29672
- import { registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
29673
29707
  var MEDIA_UPLOAD_APP_RESOURCE_URI = "ui://media-upload/v1.html";
29674
29708
  var MEDIA_UPLOAD_APP_NAME = "ProductMaker media upload";
29675
- var PRODUCTMAKER_APP_ORIGIN = "https://productmaker.app";
29676
29709
  var MEDIA_UPLOAD_APP_HTML_URL = new URL("./ui/meta-upload-app.html", import.meta.url);
29677
29710
  var PRODUCTMAKER_UPLOAD_STORAGE_ORIGIN = "https://825805a8113ddb98b68b9b0ddbb5d72a.r2.cloudflarestorage.com";
29678
29711
  var MEDIA_UPLOAD_CONNECT_DOMAINS = [
@@ -29872,6 +29905,7 @@ function registerTaskResultsAppResource(server, proxyBaseUrl) {
29872
29905
  connectDomains: []
29873
29906
  }
29874
29907
  },
29908
+ "openai/widgetDomain": PRODUCTMAKER_APP_ORIGIN,
29875
29909
  "openai/widgetCSP": {
29876
29910
  resource_domains: resourceDomains,
29877
29911
  connect_domains: []
@@ -35756,7 +35790,7 @@ function resolveLandingSetup(setup) {
35756
35790
  };
35757
35791
  }
35758
35792
  __name(resolveLandingSetup, "resolveLandingSetup");
35759
- function registerCreativeTools(server, api, { transport = "http" } = {}) {
35793
+ function registerCreativeTools(server, api, { transport = "http", proxyBaseUrl = null } = {}) {
35760
35794
  server.registerTool("generate_free_video", {
35761
35795
  title: "Custom-script video",
35762
35796
  description: generateFreeVideoGuidance.summary + ' Si el usuario adjunta o menciona una imagen local, llama primero request_media_upload con mediaKind=image y usa el assetId devuelto; no pidas path ni URL. Devuelve un taskId y procesa el job de forma as\xEDncrona.\n\nREQUERIDOS: rawPrompt, quality, durationSeconds y videoResolution.\n\nCALIDAD: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan). Economy admite 6/8/10/15s; Medium admite cualquier duraci\xF3n entera de 4 a 15s; Pro admite enteros de 2 a 30s y audio natural. `freeProModel` se elimin\xF3 \u2014 usa `modelId` (ver su descripci\xF3n); Seedance 2.5 est\xE1 inactivo y se rechaza con un error claro.\n\nSUBT\xCDTULOS: si addSubtitles=true, el rawPrompt completo se usa como texto exacto de subt\xEDtulos y debe tener m\xE1ximo 500 caracteres; no existe una pregunta adicional de transcripci\xF3n.\n\nPara videos normales con narrativa/\xE1ngulo usa generate_video_creative. Para tareas combinadas de producto usa create_product_task.',
@@ -35974,10 +36008,43 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
35974
36008
  taskId: z141.string().uuid(),
35975
36009
  operationId: z141.string().uuid()
35976
36010
  },
35977
- annotations: READS_INTERNAL
36011
+ annotations: READS_INTERNAL,
36012
+ _meta: taskResultsToolMeta()
35978
36013
  }, async (input) => {
35979
36014
  try {
35980
- return asText(await api.getJson(`/v1/creatives/images/${encodeURIComponent(input.taskId)}/operations/${encodeURIComponent(input.operationId)}`));
36015
+ const { assetUrl, assetKey: _assetKey, ...operation } = ImageCreativeEditStatusResponse.parse(await api.getJson(`/v1/creatives/images/${encodeURIComponent(input.taskId)}/operations/${encodeURIComponent(input.operationId)}`));
36016
+ const imageExtension = assetUrl ? new URL(assetUrl).pathname.match(/\.(png|jpe?g|webp)$/i)?.[0]?.toLowerCase() : void 0;
36017
+ const proxyUrl = operation.status === "published" && assetUrl ? buildProxyUrl({
36018
+ r2Url: assetUrl,
36019
+ filename: `image-edit-${operation.variantIndex + 1}${imageExtension ?? ".bin"}`,
36020
+ proxyBaseUrl
36021
+ }) : null;
36022
+ const view = buildTaskResultsView({
36023
+ images: proxyUrl ? [
36024
+ {
36025
+ url: proxyUrl,
36026
+ alt: `Corrected image ${operation.variantIndex + 1}`
36027
+ }
36028
+ ] : [],
36029
+ videos: [],
36030
+ links: []
36031
+ }, proxyBaseUrl);
36032
+ if (operation.status === "failed") view.state = "error";
36033
+ else if (operation.status !== "published") view.state = "pending";
36034
+ const deliveredUrl = view.images[0]?.url;
36035
+ const response = {
36036
+ ...operation,
36037
+ ...deliveredUrl ? {
36038
+ assetUrl: deliveredUrl
36039
+ } : {}
36040
+ };
36041
+ return {
36042
+ ...asText(response),
36043
+ structuredContent: response,
36044
+ _meta: {
36045
+ taskResults: view
36046
+ }
36047
+ };
35981
36048
  } catch (error) {
35982
36049
  throw translateError(error);
35983
36050
  }
@@ -39958,6 +40025,7 @@ function createServer(opts) {
39958
40025
  registerServiceImageTools(server, api);
39959
40026
  registerAnimatedVideoTools(server, api);
39960
40027
  registerCreativeTools(server, api, {
40028
+ proxyBaseUrl,
39961
40029
  transport
39962
40030
  });
39963
40031
  registerCreativeVariantTools(server, api);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@productmaker/mcp",
3
- "version": "12.2.7",
3
+ "version": "12.2.8",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "description": "ProductMaker MCP server — cost products, generate landing pages, UGC videos, and ad creatives, and publish to Shopify, Meta Ads, and TikTok Ads.",