@productmaker/mcp 3.4.3 → 3.4.4

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/http.js CHANGED
@@ -3509,7 +3509,15 @@ var TaskCreativeVariantResult = TaskCreativeVariantBaseResult.extend({
3509
3509
  var MVPResult = z24.object({
3510
3510
  taskId: z24.string().uuid(),
3511
3511
  product: Product,
3512
- angles: z24.array(Angle).max(3),
3512
+ // READ contract, NOT a generation cap. The generator writes exactly 3 angles
3513
+ // (`replaceAngles` renumbers positions 0..2), but a duplicated angles run
3514
+ // leaves TWO full sets on the task — alert on task a1954a35 (2026-08-21):
3515
+ // 6 rows, positions 0,0,1,1,2,2. Because the controller guards the whole
3516
+ // response with `MVPResult.parse()`, a cap here turns extra-but-valid rows
3517
+ // into a 500 on GET /v1/results/:taskId and hides EVERY deliverable of a
3518
+ // task that already finished. Same failure shape as the variant landing cap
3519
+ // below (alert 88badc8). The write path is what must stay at 3.
3520
+ angles: z24.array(Angle),
3513
3521
  topVideos: z24.array(AdVideo).max(20),
3514
3522
  landing: z24.object({
3515
3523
  // Allow legacy data (10 sections × 2 variants) and new data (7 sections × 2)
@@ -3613,7 +3621,7 @@ var PendingUserActionSchema = z24.discriminatedUnion("kind", [
3613
3621
  actor: z24.string(),
3614
3622
  /** Saved custom actor (Actor.id) backing this angle, when one was chosen. */
3615
3623
  actorId: z24.string().optional()
3616
- })).min(1).max(3)
3624
+ })).min(1)
3617
3625
  }),
3618
3626
  z24.object({
3619
3627
  kind: z24.literal("service_script_approval"),
@@ -11327,8 +11335,9 @@ var OAuthOboCredential = class {
11327
11335
  // src/guidance/productmaker-guidance.ts
11328
11336
  var START_DROPSHIPPING_PROMPT_NAME = "start_dropshipping";
11329
11337
  var PRODUCTMAKER_SERVER_INSTRUCTIONS = [
11330
- "When a ProductMaker request needs an image or video the user attached, pasted, or has locally and no reusable ProductMaker assetId is already available, call request_media_upload immediately before asking for any missing business inputs. Do this even when the user says not to generate or publish yet: uploading only stages the file and does not generate, publish, or consume credits, unless the user explicitly says not to upload, share, or store the file. Treat natural requests such as 'create a landing with this product', 'make creatives with this photo', or 'upload this video to Meta' as upload intent; never require the user to name the uploader.",
11338
+ "Whenever a ProductMaker request needs a new image or video and no reusable ProductMaker assetId is available, call request_media_upload immediately in the same response\u2014whether media is the next missing input or the user attached, pasted, mentioned, or has the file locally. The inline uploader is how ProductMaker asks for the file. Never merely ask the user to attach or upload it in chat and wait for a later turn. Call it before asking for any missing business inputs, even when the user says not to generate or publish yet: uploading only stages the file and does not generate, publish, or consume credits, unless the user explicitly says not to upload, share, or store the file. Treat natural requests such as 'create a landing with this product', 'make creatives with this photo', or 'upload this video to Meta' as upload intent; never require the user to name the uploader.",
11331
11339
  "For requests that do not need a new media upload, understand the user's intent before choosing a ProductMaker tool.",
11340
+ "For every concrete ProductMaker request to calculate how much to charge, profitability, or margin for a dropshipping product, you must call cost_product after collecting its missing country and real supplier cost. Never calculate or reproduce ProductMaker's costing formula yourself; answer from the tool result.",
11332
11341
  "For remote MCP hosts, never ask for a local path, CDN URL, bytes, or base64. Pass supported host file references to request_media_upload; otherwise let its inline App open the file picker. The external upload page is fallback only.",
11333
11342
  "After the upload App sends its OK continuation, resume the original request with the verified assetId values, do not ask for another upload, and ask only for remaining business inputs in chat. The host-inserted continuation may contain opaque asset IDs; do not repeat them in narrative prose or expose session IDs, tokens, private URLs, file names, or JSON handoff payloads.",
11334
11343
  "Keep focused requests direct: creatives, landing pages, Shopify publication, Meta publication, and status checks do not require a DropshippingProject.",
@@ -11687,7 +11696,7 @@ var ApiClient = class {
11687
11696
  };
11688
11697
 
11689
11698
  // src/index.ts
11690
- var MCP_VERSION = "3.4.3";
11699
+ var MCP_VERSION = "3.4.4";
11691
11700
 
11692
11701
  // src/meta-upload-app.ts
11693
11702
  import { readFileSync } from "fs";
@@ -15528,7 +15537,7 @@ __name(resolveEndpointForSession, "resolveEndpointForSession");
15528
15537
  function registerMediaUploadTools(server, api) {
15529
15538
  registerAppTool(server, "request_media_upload", {
15530
15539
  title: "Subir archivos",
15531
- description: "Abre el selector universal de ProductMaker para im\xE1genes o videos del usuario. Ll\xE1malo autom\xE1ticamente y antes de preguntar por campos faltantes cuando una petici\xF3n natural adjunte o mencione un archivo local, por ejemplo \u2018crea una landing con este producto\u2019, \u2018haz creativos con esta foto\u2019 o \u2018sube este video a Meta\u2019; hazlo aunque el usuario diga que todav\xEDa no generes ni publiques, porque esta herramienta solo prepara el archivo y no consume cr\xE9ditos, salvo que proh\xEDba expl\xEDcitamente subir, compartir o almacenar el archivo; no pidas una ruta local ni URL. Es la \xFAnica ruta de carga para create_product_task, generate_image_creatives, generate_video_creative, generate_free_video, generate_landing y publish_creatives_to_meta. Pasa las referencias opcionales de ChatGPT en files; si el host no puede transferirlas, el mismo App muestra el selector inline. Usa uploadPurpose=product_reference para fotos de producto y landings, creative para creativos o anuncios, y generic solo cuando ninguno aplique. Usa mediaKind=image para referencias de producto y landings; mixed solo cuando el consumidor acepte ambos tipos. El App NO te avisa cuando termina: en cuanto el usuario diga que ya subi\xF3 el archivo o que sigas, llama `check_media_upload` con este sessionId para obtener los assetId, y reanuda la intenci\xF3n original usando \xFAnicamente assetId y mediaKind, sin pedir que vuelva a subir ni mostrar datos t\xE9cnicos. El enlace externo es fallback solo si el App inline falla. Esta herramienta no genera, publica ni consume cr\xE9ditos.",
15540
+ description: "Abre el selector universal de ProductMaker para im\xE1genes o videos del usuario. Cuando la foto o el video sea el siguiente dato faltante, ll\xE1malo en esa misma respuesta: no te limites a pedir que lo adjunte en el chat y esperar otro turno. Ll\xE1malo tambi\xE9n autom\xE1ticamente y antes de preguntar por campos faltantes adicionales cuando una petici\xF3n natural adjunte o mencione un archivo local, por ejemplo \u2018crea una landing con este producto\u2019, \u2018haz creativos con esta foto\u2019 o \u2018sube este video a Meta\u2019; hazlo aunque el usuario diga que todav\xEDa no generes ni publiques, porque esta herramienta solo prepara el archivo y no consume cr\xE9ditos, salvo que proh\xEDba expl\xEDcitamente subir, compartir o almacenar el archivo; no pidas una ruta local ni URL. Es la \xFAnica ruta de carga para create_product_task, generate_image_creatives, generate_video_creative, generate_free_video, generate_landing y publish_creatives_to_meta. Pasa las referencias opcionales de ChatGPT en files; si el host no puede transferirlas, el mismo App muestra el selector inline. Usa uploadPurpose=product_reference para fotos de producto y landings, creative para creativos o anuncios, y generic solo cuando ninguno aplique. Usa mediaKind=image para referencias de producto y landings; mixed solo cuando el consumidor acepte ambos tipos. El App NO te avisa cuando termina: en cuanto el usuario diga que ya subi\xF3 el archivo o que sigas, llama `check_media_upload` con este sessionId para obtener los assetId, y reanuda la intenci\xF3n original usando \xFAnicamente assetId y mediaKind, sin pedir que vuelva a subir ni mostrar datos t\xE9cnicos. El enlace externo es fallback solo si el App inline falla. Esta herramienta no genera, publica ni consume cr\xE9ditos.",
15532
15541
  inputSchema: UploadSessionToolInputShape,
15533
15542
  annotations: CREATES_INTERNAL,
15534
15543
  outputSchema: UniversalUploadStructuredResponse.shape,
@@ -16057,7 +16066,7 @@ var ProductCostingToolInput = z61.object({
16057
16066
  desiredMarginPercent: optionalPercent("Margen de ganancia deseado. Ejemplo: 10 significa 10%. Omite para usar el valor gu\xEDa editable del pa\xEDs.")
16058
16067
  });
16059
16068
  function registerProductCostingTools(server) {
16060
- server.tool("cost_product", "Calcula GRATIS y sin cr\xE9ditos cu\xE1nto cobrar por un producto de dropshipping en cualquiera de los pa\xEDses disponibles en ProductMaker. Es READ-ONLY: no crea tareas ni publica nada. Pide country y el costo real del proveedor; los dem\xE1s campos pueden usar valores gu\xEDa editables del pa\xEDs. Devuelve `price` y `compareAtPrice` listos para `create_product_task`. No inventes un costo de proveedor.", ProductCostingToolInput.shape, READS_INTERNAL, async (input) => {
16069
+ server.tool("cost_product", "Calcula GRATIS y sin cr\xE9ditos cu\xE1nto cobrar por un producto de dropshipping en cualquiera de los pa\xEDses disponibles en ProductMaker. Ll\xE1mala siempre que el usuario pida calcular cu\xE1nto cobrar, la rentabilidad o el margen de un producto concreto; no hagas el c\xE1lculo ni reconstruyas la f\xF3rmula por tu cuenta. Es READ-ONLY: no crea tareas ni publica nada. Pide country y el costo real del proveedor; los dem\xE1s campos pueden usar valores gu\xEDa editables del pa\xEDs. Devuelve `price` y `compareAtPrice` listos para `create_product_task`. No inventes un costo de proveedor.", ProductCostingToolInput.shape, READS_INTERNAL, async (input) => {
16061
16070
  if (input.country !== void 0 && input.country !== "CO" && [
16062
16071
  input.supplierCostCop,
16063
16072
  input.shippingCostCop,
package/dist/stdio.js CHANGED
@@ -264,7 +264,7 @@ var ApiClient = class {
264
264
  };
265
265
 
266
266
  // src/index.ts
267
- var MCP_VERSION = "3.4.3";
267
+ var MCP_VERSION = "3.4.4";
268
268
 
269
269
  // src/meta-upload-app.ts
270
270
  import { readFileSync } from "fs";
@@ -4131,7 +4131,15 @@ var TaskCreativeVariantResult = TaskCreativeVariantBaseResult.extend({
4131
4131
  var MVPResult = z24.object({
4132
4132
  taskId: z24.string().uuid(),
4133
4133
  product: Product,
4134
- angles: z24.array(Angle).max(3),
4134
+ // READ contract, NOT a generation cap. The generator writes exactly 3 angles
4135
+ // (`replaceAngles` renumbers positions 0..2), but a duplicated angles run
4136
+ // leaves TWO full sets on the task — alert on task a1954a35 (2026-08-21):
4137
+ // 6 rows, positions 0,0,1,1,2,2. Because the controller guards the whole
4138
+ // response with `MVPResult.parse()`, a cap here turns extra-but-valid rows
4139
+ // into a 500 on GET /v1/results/:taskId and hides EVERY deliverable of a
4140
+ // task that already finished. Same failure shape as the variant landing cap
4141
+ // below (alert 88badc8). The write path is what must stay at 3.
4142
+ angles: z24.array(Angle),
4135
4143
  topVideos: z24.array(AdVideo).max(20),
4136
4144
  landing: z24.object({
4137
4145
  // Allow legacy data (10 sections × 2 variants) and new data (7 sections × 2)
@@ -4235,7 +4243,7 @@ var PendingUserActionSchema = z24.discriminatedUnion("kind", [
4235
4243
  actor: z24.string(),
4236
4244
  /** Saved custom actor (Actor.id) backing this angle, when one was chosen. */
4237
4245
  actorId: z24.string().optional()
4238
- })).min(1).max(3)
4246
+ })).min(1)
4239
4247
  }),
4240
4248
  z24.object({
4241
4249
  kind: z24.literal("service_script_approval"),
@@ -14330,7 +14338,7 @@ __name(resolveEndpointForSession, "resolveEndpointForSession");
14330
14338
  function registerMediaUploadTools(server, api) {
14331
14339
  registerAppTool(server, "request_media_upload", {
14332
14340
  title: "Subir archivos",
14333
- description: "Abre el selector universal de ProductMaker para im\xE1genes o videos del usuario. Ll\xE1malo autom\xE1ticamente y antes de preguntar por campos faltantes cuando una petici\xF3n natural adjunte o mencione un archivo local, por ejemplo \u2018crea una landing con este producto\u2019, \u2018haz creativos con esta foto\u2019 o \u2018sube este video a Meta\u2019; hazlo aunque el usuario diga que todav\xEDa no generes ni publiques, porque esta herramienta solo prepara el archivo y no consume cr\xE9ditos, salvo que proh\xEDba expl\xEDcitamente subir, compartir o almacenar el archivo; no pidas una ruta local ni URL. Es la \xFAnica ruta de carga para create_product_task, generate_image_creatives, generate_video_creative, generate_free_video, generate_landing y publish_creatives_to_meta. Pasa las referencias opcionales de ChatGPT en files; si el host no puede transferirlas, el mismo App muestra el selector inline. Usa uploadPurpose=product_reference para fotos de producto y landings, creative para creativos o anuncios, y generic solo cuando ninguno aplique. Usa mediaKind=image para referencias de producto y landings; mixed solo cuando el consumidor acepte ambos tipos. El App NO te avisa cuando termina: en cuanto el usuario diga que ya subi\xF3 el archivo o que sigas, llama `check_media_upload` con este sessionId para obtener los assetId, y reanuda la intenci\xF3n original usando \xFAnicamente assetId y mediaKind, sin pedir que vuelva a subir ni mostrar datos t\xE9cnicos. El enlace externo es fallback solo si el App inline falla. Esta herramienta no genera, publica ni consume cr\xE9ditos.",
14341
+ description: "Abre el selector universal de ProductMaker para im\xE1genes o videos del usuario. Cuando la foto o el video sea el siguiente dato faltante, ll\xE1malo en esa misma respuesta: no te limites a pedir que lo adjunte en el chat y esperar otro turno. Ll\xE1malo tambi\xE9n autom\xE1ticamente y antes de preguntar por campos faltantes adicionales cuando una petici\xF3n natural adjunte o mencione un archivo local, por ejemplo \u2018crea una landing con este producto\u2019, \u2018haz creativos con esta foto\u2019 o \u2018sube este video a Meta\u2019; hazlo aunque el usuario diga que todav\xEDa no generes ni publiques, porque esta herramienta solo prepara el archivo y no consume cr\xE9ditos, salvo que proh\xEDba expl\xEDcitamente subir, compartir o almacenar el archivo; no pidas una ruta local ni URL. Es la \xFAnica ruta de carga para create_product_task, generate_image_creatives, generate_video_creative, generate_free_video, generate_landing y publish_creatives_to_meta. Pasa las referencias opcionales de ChatGPT en files; si el host no puede transferirlas, el mismo App muestra el selector inline. Usa uploadPurpose=product_reference para fotos de producto y landings, creative para creativos o anuncios, y generic solo cuando ninguno aplique. Usa mediaKind=image para referencias de producto y landings; mixed solo cuando el consumidor acepte ambos tipos. El App NO te avisa cuando termina: en cuanto el usuario diga que ya subi\xF3 el archivo o que sigas, llama `check_media_upload` con este sessionId para obtener los assetId, y reanuda la intenci\xF3n original usando \xFAnicamente assetId y mediaKind, sin pedir que vuelva a subir ni mostrar datos t\xE9cnicos. El enlace externo es fallback solo si el App inline falla. Esta herramienta no genera, publica ni consume cr\xE9ditos.",
14334
14342
  inputSchema: UploadSessionToolInputShape,
14335
14343
  annotations: CREATES_INTERNAL,
14336
14344
  outputSchema: UniversalUploadStructuredResponse.shape,
@@ -14859,7 +14867,7 @@ var ProductCostingToolInput = z60.object({
14859
14867
  desiredMarginPercent: optionalPercent("Margen de ganancia deseado. Ejemplo: 10 significa 10%. Omite para usar el valor gu\xEDa editable del pa\xEDs.")
14860
14868
  });
14861
14869
  function registerProductCostingTools(server) {
14862
- server.tool("cost_product", "Calcula GRATIS y sin cr\xE9ditos cu\xE1nto cobrar por un producto de dropshipping en cualquiera de los pa\xEDses disponibles en ProductMaker. Es READ-ONLY: no crea tareas ni publica nada. Pide country y el costo real del proveedor; los dem\xE1s campos pueden usar valores gu\xEDa editables del pa\xEDs. Devuelve `price` y `compareAtPrice` listos para `create_product_task`. No inventes un costo de proveedor.", ProductCostingToolInput.shape, READS_INTERNAL, async (input) => {
14870
+ server.tool("cost_product", "Calcula GRATIS y sin cr\xE9ditos cu\xE1nto cobrar por un producto de dropshipping en cualquiera de los pa\xEDses disponibles en ProductMaker. Ll\xE1mala siempre que el usuario pida calcular cu\xE1nto cobrar, la rentabilidad o el margen de un producto concreto; no hagas el c\xE1lculo ni reconstruyas la f\xF3rmula por tu cuenta. Es READ-ONLY: no crea tareas ni publica nada. Pide country y el costo real del proveedor; los dem\xE1s campos pueden usar valores gu\xEDa editables del pa\xEDs. Devuelve `price` y `compareAtPrice` listos para `create_product_task`. No inventes un costo de proveedor.", ProductCostingToolInput.shape, READS_INTERNAL, async (input) => {
14863
14871
  if (input.country !== void 0 && input.country !== "CO" && [
14864
14872
  input.supplierCostCop,
14865
14873
  input.shippingCostCop,
@@ -15464,8 +15472,9 @@ __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
15464
15472
  // src/guidance/productmaker-guidance.ts
15465
15473
  var START_DROPSHIPPING_PROMPT_NAME = "start_dropshipping";
15466
15474
  var PRODUCTMAKER_SERVER_INSTRUCTIONS = [
15467
- "When a ProductMaker request needs an image or video the user attached, pasted, or has locally and no reusable ProductMaker assetId is already available, call request_media_upload immediately before asking for any missing business inputs. Do this even when the user says not to generate or publish yet: uploading only stages the file and does not generate, publish, or consume credits, unless the user explicitly says not to upload, share, or store the file. Treat natural requests such as 'create a landing with this product', 'make creatives with this photo', or 'upload this video to Meta' as upload intent; never require the user to name the uploader.",
15475
+ "Whenever a ProductMaker request needs a new image or video and no reusable ProductMaker assetId is available, call request_media_upload immediately in the same response\u2014whether media is the next missing input or the user attached, pasted, mentioned, or has the file locally. The inline uploader is how ProductMaker asks for the file. Never merely ask the user to attach or upload it in chat and wait for a later turn. Call it before asking for any missing business inputs, even when the user says not to generate or publish yet: uploading only stages the file and does not generate, publish, or consume credits, unless the user explicitly says not to upload, share, or store the file. Treat natural requests such as 'create a landing with this product', 'make creatives with this photo', or 'upload this video to Meta' as upload intent; never require the user to name the uploader.",
15468
15476
  "For requests that do not need a new media upload, understand the user's intent before choosing a ProductMaker tool.",
15477
+ "For every concrete ProductMaker request to calculate how much to charge, profitability, or margin for a dropshipping product, you must call cost_product after collecting its missing country and real supplier cost. Never calculate or reproduce ProductMaker's costing formula yourself; answer from the tool result.",
15469
15478
  "For remote MCP hosts, never ask for a local path, CDN URL, bytes, or base64. Pass supported host file references to request_media_upload; otherwise let its inline App open the file picker. The external upload page is fallback only.",
15470
15479
  "After the upload App sends its OK continuation, resume the original request with the verified assetId values, do not ask for another upload, and ask only for remaining business inputs in chat. The host-inserted continuation may contain opaque asset IDs; do not repeat them in narrative prose or expose session IDs, tokens, private URLs, file names, or JSON handoff payloads.",
15471
15480
  "Keep focused requests direct: creatives, landing pages, Shopify publication, Meta publication, and status checks do not require a DropshippingProject.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@productmaker/mcp",
3
- "version": "3.4.3",
3
+ "version": "3.4.4",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "description": "Product Maker MCP server — cost products, generate dropshipping landing pages, UGC videos, and ad creatives, and publish to Shopify and Meta Ads from Claude, ChatGPT, or Gemini.",