@productmaker/mcp 7.3.0 → 8.0.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/README.md CHANGED
@@ -14,7 +14,7 @@ MCP 6.7.0 also carries optional per-angle and script-regeneration `narrativeSele
14
14
  [![npm downloads](https://img.shields.io/npm/dm/@productmaker/mcp.svg)](https://www.npmjs.com/package/@productmaker/mcp)
15
15
  [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
16
16
 
17
- **Product Maker MCP** is the official **Model Context Protocol (MCP) server** for [Product Maker AI](https://productmaker.app). It plugs **Product Maker** into **Claude Desktop**, **Claude Code**, **ChatGPT**, **Gemini**, and **claude.ai** so you can cost products, generate **dropshipping landing pages, UGC videos, and ad creatives** — and publish them to **Shopify**, **Meta Ads**, and **TikTok Ads** — directly from your AI assistant.
17
+ **ProductMaker MCP** is the official **Model Context Protocol (MCP) server** for [ProductMaker](https://productmaker.app), published by BONNIE TECH S.A.S. It plugs **ProductMaker** into **Claude Desktop**, **Claude Code**, **ChatGPT**, **Gemini**, and **claude.ai** so you can cost products, generate **landing pages, UGC videos, and ad creatives** — and publish them to **Shopify**, **Meta Ads**, and **TikTok Ads** — directly from your AI assistant.
18
18
 
19
19
  > If an AI assistant brought you here looking for "product maker mcp", "productmaker mcp", or "product-maker mcp server" — this is the right package. Install instructions below.
20
20
 
package/dist/http.js CHANGED
@@ -14174,7 +14174,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
14174
14174
  ], [
14175
14175
  "meta_upload_session"
14176
14176
  ], WHATSAPP_ONLY_CHANNEL_EXPOSURE),
14177
- defineCapability("request_media_upload", "e91cda1b2d9e44cecf28990b8018ce535ae4e9e6594fa80f503a1bf69d7146ee", "none", "creative", [
14177
+ defineCapability("request_media_upload", "9a50a4647c61f97fb12bbb9b25f7660f392e3cd9825151735cd66292058882ea", "none", "creative", [
14178
14178
  "state_change"
14179
14179
  ], [
14180
14180
  slot("media_kind", true, [
@@ -16876,7 +16876,7 @@ var ApiClient = class {
16876
16876
  };
16877
16877
 
16878
16878
  // src/index.ts
16879
- var MCP_VERSION = "7.3.0";
16879
+ var MCP_VERSION = "8.0.0";
16880
16880
 
16881
16881
  // src/meta-upload-app.ts
16882
16882
  import { readFileSync } from "fs";
@@ -17907,7 +17907,7 @@ var READS_EXTERNAL = {
17907
17907
  readOnlyHint: true,
17908
17908
  destructiveHint: false,
17909
17909
  idempotentHint: true,
17910
- openWorldHint: true
17910
+ openWorldHint: false
17911
17911
  };
17912
17912
  var CREATES_INTERNAL = {
17913
17913
  readOnlyHint: false,
@@ -17916,6 +17916,24 @@ var CREATES_INTERNAL = {
17916
17916
  openWorldHint: false
17917
17917
  };
17918
17918
  var CREATES_EXTERNAL = {
17919
+ readOnlyHint: false,
17920
+ destructiveHint: false,
17921
+ idempotentHint: false,
17922
+ openWorldHint: false
17923
+ };
17924
+ var CREATES_PAID = {
17925
+ readOnlyHint: false,
17926
+ destructiveHint: true,
17927
+ idempotentHint: false,
17928
+ openWorldHint: false
17929
+ };
17930
+ var CREATES_PAID_OPEN_WORLD = {
17931
+ readOnlyHint: false,
17932
+ destructiveHint: true,
17933
+ idempotentHint: false,
17934
+ openWorldHint: true
17935
+ };
17936
+ var CREATES_OPEN_WORLD = {
17919
17937
  readOnlyHint: false,
17920
17938
  destructiveHint: false,
17921
17939
  idempotentHint: false,
@@ -17931,7 +17949,7 @@ var OVERWRITES_EXTERNAL = {
17931
17949
  readOnlyHint: false,
17932
17950
  destructiveHint: true,
17933
17951
  idempotentHint: false,
17934
- openWorldHint: true
17952
+ openWorldHint: false
17935
17953
  };
17936
17954
  var DailyControlStatusEnum = z70.enum([
17937
17955
  "ok",
@@ -19681,7 +19699,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
19681
19699
 
19682
19700
  REQUERIDOS: images o projectId expl\xEDcito, language y country. Cuando los outputs incluyen video (tambi\xE9n por default), pregunta SIEMPRE videoAngleCount: 1, 2 o 3; es una decisi\xF3n de costo incluso con aiDecidesAll. Si falta una foto local, llama primero \`request_media_upload\`. Pregunta price, offer, paymentMethods y compareAtPrice cuando aplique; nunca asumas country/language.
19683
19701
 
19684
- ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explica que inicia trabajo pagado y espera confirmaci\xF3n expl\xEDcita. aiDecidesAll omitido/false pausa para reviews conversacionales; muestra todos los \xE1ngulos candidatos y permite escoger/editar hasta el m\xE1ximo autorizado. Usa aiDecidesAll=true s\xF3lo si el usuario pidi\xF3 \u201Cdecide todo\u201D o \u201Cno me preguntes\u201D.`, CreateProductTaskInput.shape, CREATES_EXTERNAL, async (input) => {
19702
+ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explica que inicia trabajo pagado y espera confirmaci\xF3n expl\xEDcita. aiDecidesAll omitido/false pausa para reviews conversacionales; muestra todos los \xE1ngulos candidatos y permite escoger/editar hasta el m\xE1ximo autorizado. Usa aiDecidesAll=true s\xF3lo si el usuario pidi\xF3 \u201Cdecide todo\u201D o \u201Cno me preguntes\u201D.`, CreateProductTaskInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
19685
19703
  try {
19686
19704
  const selectedOutputs = input.outputs ?? DEFAULT_PRODUCT_TASK_OUTPUTS;
19687
19705
  const videoPreset = selectedOutputs.includes("video") && input.competitorScanEnabled === true ? "auto" : input.videoPreset;
@@ -19772,7 +19790,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
19772
19790
  throw translateError(e);
19773
19791
  }
19774
19792
  });
19775
- server.tool("create_service_video", createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.", CreateServiceVideoInput.shape, CREATES_EXTERNAL, async (input) => {
19793
+ server.tool("create_service_video", createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.", CreateServiceVideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
19776
19794
  try {
19777
19795
  await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
19778
19796
  const created = await api.postJson("/v2/ingest", {
@@ -20697,7 +20715,7 @@ function resolveLandingSetup(setup) {
20697
20715
  }
20698
20716
  __name(resolveLandingSetup, "resolveLandingSetup");
20699
20717
  function registerCreativeTools(server, api, { transport = "http" } = {}) {
20700
- server.tool("generate_free_video", 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.', FreeVideoInput.shape, CREATES_EXTERNAL, async (input) => {
20718
+ server.tool("generate_free_video", 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.', FreeVideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
20701
20719
  try {
20702
20720
  if (input.freeProModel) {
20703
20721
  throw new Error("freeProModel se elimin\xF3 en MCP 7.0.0. Usa `modelId` para elegir el modelo expl\xEDcitamente (ver la descripci\xF3n del par\xE1metro).");
@@ -20745,7 +20763,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
20745
20763
  throw translateError(e);
20746
20764
  }
20747
20765
  });
20748
- server.tool("generate_video_creative", generateVideoCreativeGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), title, primaryAngle, language, country, aspectRatio, videoAngleCount y creativeSetup. Pregunta SIEMPRE cu\xE1ntos videos quiere (1, 2 o 3): la cantidad cambia el costo y no forma parte de \u2018la IA decide todo\u2019. Si falta una foto local, llama primero `request_media_upload` y usa los assetId; no pidas path ni URL. PREGUNTA price y offer si faltan; no asumas country/language.\n\nFORMATO Y CALIDAD: pregunta videoStructure (Un solo clip o Multiescena) y videoQuality (Econ\xF3mico, Medio o Pro). Un solo clip se genera completo y puede incluir cambios de plano. El sistema elige el proveedor internamente.\n\nCONFIGURACI\xD3N: salvo que el usuario diga expl\xEDcitamente que la IA decida todo, usa creativeSetup.mode=guided y pregunta narrativa solo si no hay estudio de mercado; recoge p\xFAblico comprador, presentador (actor guardado, descripci\xF3n o ninguno) y direcci\xF3n creativa. Si el usuario dice qui\xE9n debe aparecer (mujer, hombre o ambos), env\xEDa creativeGender; no lo preguntes si no lo menciona. creativeDirection=null s\xF3lo despu\xE9s de que el usuario delegue esa decisi\xF3n concreta. No inventes valores de setup.\n\nANTES de invocar, muestra un resumen compacto que incluya cantidad, planificaci\xF3n (estudio de mercado o narrativa), p\xFAblico, presentador y direcci\xF3n y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. Multiescena se factura por escena, as\xED que avisa ese mayor costo. Advierte tambi\xE9n que, si luego el usuario confirma que las fotos son de varios productos (combo), el pipeline r\xE1pido actualmente omite la pausa de guion aunque mantiene las dem\xE1s revisiones.\n\nREVIEWS: guided muestra los \xE1ngulos candidatos y permite escoger hasta videoAngleCount, editar cada \xE1ngulo y revisar sus guiones. automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite ambas reviews. scriptNotes agrega restricciones al guion; get_video_script y approve_video_script manejan la review palabra por palabra.", VideoInput.shape, CREATES_EXTERNAL, async (input) => {
20766
+ server.tool("generate_video_creative", generateVideoCreativeGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), title, primaryAngle, language, country, aspectRatio, videoAngleCount y creativeSetup. Pregunta SIEMPRE cu\xE1ntos videos quiere (1, 2 o 3): la cantidad cambia el costo y no forma parte de \u2018la IA decide todo\u2019. Si falta una foto local, llama primero `request_media_upload` y usa los assetId; no pidas path ni URL. PREGUNTA price y offer si faltan; no asumas country/language.\n\nFORMATO Y CALIDAD: pregunta videoStructure (Un solo clip o Multiescena) y videoQuality (Econ\xF3mico, Medio o Pro). Un solo clip se genera completo y puede incluir cambios de plano. El sistema elige el proveedor internamente.\n\nCONFIGURACI\xD3N: salvo que el usuario diga expl\xEDcitamente que la IA decida todo, usa creativeSetup.mode=guided y pregunta narrativa solo si no hay estudio de mercado; recoge p\xFAblico comprador, presentador (actor guardado, descripci\xF3n o ninguno) y direcci\xF3n creativa. Si el usuario dice qui\xE9n debe aparecer (mujer, hombre o ambos), env\xEDa creativeGender; no lo preguntes si no lo menciona. creativeDirection=null s\xF3lo despu\xE9s de que el usuario delegue esa decisi\xF3n concreta. No inventes valores de setup.\n\nANTES de invocar, muestra un resumen compacto que incluya cantidad, planificaci\xF3n (estudio de mercado o narrativa), p\xFAblico, presentador y direcci\xF3n y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. Multiescena se factura por escena, as\xED que avisa ese mayor costo. Advierte tambi\xE9n que, si luego el usuario confirma que las fotos son de varios productos (combo), el pipeline r\xE1pido actualmente omite la pausa de guion aunque mantiene las dem\xE1s revisiones.\n\nREVIEWS: guided muestra los \xE1ngulos candidatos y permite escoger hasta videoAngleCount, editar cada \xE1ngulo y revisar sus guiones. automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite ambas reviews. scriptNotes agrega restricciones al guion; get_video_script y approve_video_script manejan la review palabra por palabra.", VideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
20749
20767
  try {
20750
20768
  if (!input.images && !input.winnerReference) {
20751
20769
  throw new Error("images o winnerReference es requerido.");
@@ -20809,7 +20827,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
20809
20827
  throw translateError(e);
20810
20828
  }
20811
20829
  });
20812
- server.tool("generate_image_creatives", generateImageCreativesGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), productTitle, language, country y creativeSetup. Si falta una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language. primaryAngle es opcional: si falta, ProductMaker lo genera y guided lo muestra para revisi\xF3n.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. No hagas un interrogatorio campo por campo: presenta UN checklist compacto con arquetipo, tratamiento visual, formato, cantidad, calidad, mezcla condicional, copy, competencia, contexto, direcci\xF3n, colores y copy exacto; propone los defaults recomendados y permite que el usuario delegue los campos con ai_decides o null donde el schema lo admite. La UI ofrece 1, 2, 3, 4 o 6 variantes: para 2\u20134 pregunta styleMix; para 1 o 6 usa null, y 6 activa autom\xE1ticamente una imagen de cada estilo. Premium 2K no admite 4:5.\n\nANTES de invocar, muestra el resumen de esas decisiones y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", ImageInput.shape, CREATES_EXTERNAL, async (input) => {
20830
+ server.tool("generate_image_creatives", generateImageCreativesGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), productTitle, language, country y creativeSetup. Si falta una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language. primaryAngle es opcional: si falta, ProductMaker lo genera y guided lo muestra para revisi\xF3n.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. No hagas un interrogatorio campo por campo: presenta UN checklist compacto con arquetipo, tratamiento visual, formato, cantidad, calidad, mezcla condicional, copy, competencia, contexto, direcci\xF3n, colores y copy exacto; propone los defaults recomendados y permite que el usuario delegue los campos con ai_decides o null donde el schema lo admite. La UI ofrece 1, 2, 3, 4 o 6 variantes: para 2\u20134 pregunta styleMix; para 1 o 6 usa null, y 6 activa autom\xE1ticamente una imagen de cada estilo. Premium 2K no admite 4:5.\n\nANTES de invocar, muestra el resumen de esas decisiones y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", ImageInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
20813
20831
  try {
20814
20832
  if (!input.images && !input.winnerReference) {
20815
20833
  throw new Error("images o winnerReference es requerido.");
@@ -20855,7 +20873,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
20855
20873
  throw translateError(e);
20856
20874
  }
20857
20875
  });
20858
- server.tool("generate_landing", generateLandingGuidance.summary + " No expone landing editable/code mientras siga siendo admin-only. Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), language, country y creativeSetup. Ante \u201Ccrea una landing con este producto\u201D y una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. Presenta UN checklist compacto \u2014no preguntas seriales\u2014 con estrategia, formato, competencia, m\xE9todos de pago, contexto, direcci\xF3n creativa y headline/subheadline exactos opcionales. Prop\xF3n defaults recomendados; null significa que el usuario deleg\xF3 esa decisi\xF3n concreta, nunca que el agente la olvid\xF3.\n\nANTES de invocar, muestra el resumen y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", LandingInput.shape, CREATES_EXTERNAL, async (input) => {
20876
+ server.tool("generate_landing", generateLandingGuidance.summary + " No expone landing editable/code mientras siga siendo admin-only. Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), language, country y creativeSetup. Ante \u201Ccrea una landing con este producto\u201D y una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. Presenta UN checklist compacto \u2014no preguntas seriales\u2014 con estrategia, formato, competencia, m\xE9todos de pago, contexto, direcci\xF3n creativa y headline/subheadline exactos opcionales. Prop\xF3n defaults recomendados; null significa que el usuario deleg\xF3 esa decisi\xF3n concreta, nunca que el agente la olvid\xF3.\n\nANTES de invocar, muestra el resumen y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", LandingInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
20859
20877
  try {
20860
20878
  if (!input.images && !input.winnerReference) {
20861
20879
  throw new Error("images o winnerReference es requerido.");
@@ -21133,7 +21151,7 @@ function registerCreativeVariantTools(server, api) {
21133
21151
  throw translateError(error);
21134
21152
  }
21135
21153
  });
21136
- server.tool("create_creative_variant", createCreativeVariantGuidance.summary + " ES UNA ACCI\xD3N DE PAGO: primero llama estimate_creative_variant, muestra el rango de cr\xE9ditos al usuario y solo despu\xE9s invoca este tool con confirm=true. Las recomendaciones IA tambi\xE9n son acciones pagas a 2x del costo real. clientRequestId es obligatorio: genera un UUID por intenci\xF3n y reutiliza el mismo ante timeouts o transporte ambiguo. Si recibes status=error, pide confirmaci\xF3n para un intento nuevo y usa otro UUID. Reutiliza el producto y referencias del task origen; crea un child task independiente y devuelve variantTaskId. Para landing puedes enviar instructions en texto libre y omitir sectionKey: el backend lo clasifica con IA. No expone ni permite cambiar videoModel, videoTier, videoStyle o narrativeStyle; esos valores se heredan del task origen.", CreateCreativeVariantInputBase.shape, CREATES_EXTERNAL, async (input) => {
21154
+ server.tool("create_creative_variant", createCreativeVariantGuidance.summary + " ES UNA ACCI\xD3N DE PAGO: primero llama estimate_creative_variant, muestra el rango de cr\xE9ditos al usuario y solo despu\xE9s invoca este tool con confirm=true. Las recomendaciones IA tambi\xE9n son acciones pagas a 2x del costo real. clientRequestId es obligatorio: genera un UUID por intenci\xF3n y reutiliza el mismo ante timeouts o transporte ambiguo. Si recibes status=error, pide confirmaci\xF3n para un intento nuevo y usa otro UUID. Reutiliza el producto y referencias del task origen; crea un child task independiente y devuelve variantTaskId. Para landing puedes enviar instructions en texto libre y omitir sectionKey: el backend lo clasifica con IA. No expone ni permite cambiar videoModel, videoTier, videoStyle o narrativeStyle; esos valores se heredan del task origen.", CreateCreativeVariantInputBase.shape, CREATES_PAID, async (input) => {
21137
21155
  try {
21138
21156
  const validatedInput = parseVariantInput(CreateCreativeVariantInput, input);
21139
21157
  const estimateInput = EstimateCreativeVariantInput.parse({
@@ -21288,9 +21306,9 @@ function registerScriptReviewTools(server, api) {
21288
21306
  // Not CREATES_INTERNAL: approving the script is what STARTS the render, so
21289
21307
  // this call dispatches jobs to the video providers and burns credits. Its own
21290
21308
  // description says so ("Tras llamarlo, el render arranca y consume créditos").
21291
- // A host that decides when to interrupt the user by `destructiveHint ||
21292
- // openWorldHint` would otherwise auto-invoke the one call that spends money.
21293
- CREATES_EXTERNAL,
21309
+ // `destructiveHint` keeps a host from treating the credit charge as a
21310
+ // reversible bookkeeping update.
21311
+ CREATES_PAID,
21294
21312
  async (input) => {
21295
21313
  try {
21296
21314
  await requirePaidCreativeConfirmation(server, `Aprobar ${input.scenes.length} escena(s) y comenzar el render pagado del video.`);
@@ -22119,7 +22137,7 @@ var UploadSessionInputBase = z80.object({
22119
22137
  maxFiles: z80.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
22120
22138
  });
22121
22139
  var OpenAiFileReference = z80.object({
22122
- download_url: z80.string().url().optional().describe("Optional host-provided download URL. The App prefers getFileDownloadUrl(file_id) and the server never fetches this URL."),
22140
+ download_url: z80.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
22123
22141
  file_id: z80.string().min(1),
22124
22142
  mime_type: z80.string().min(1).optional(),
22125
22143
  file_name: z80.string().min(1).optional()
@@ -22234,7 +22252,7 @@ __name(resolveEndpointForSession, "resolveEndpointForSession");
22234
22252
  function registerMediaUploadTools(server, api) {
22235
22253
  registerAppTool(server, "request_media_upload", {
22236
22254
  title: "Subir archivos",
22237
- description: requestMediaUploadGuidance.summary + " 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.",
22255
+ description: requestMediaUploadGuidance.summary + " 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 de ChatGPT en files con download_url y file_id. Si otro host no puede proporcionar ambos, omite files para que el App abra el selector inline o el enlace de carga. 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.",
22238
22256
  inputSchema: UploadSessionToolInputShape,
22239
22257
  annotations: CREATES_INTERNAL,
22240
22258
  outputSchema: UniversalUploadStructuredResponse.shape,
@@ -23362,7 +23380,7 @@ async function pollUntilTerminal(api, runId, waitSeconds) {
23362
23380
  }
23363
23381
  __name(pollUntilTerminal, "pollUntilTerminal");
23364
23382
  function registerProductResearchTools(server, api) {
23365
- server.tool("find_winning_products", `${findWinningProductsGuidance.summary} CUESTA ${PRICE_CREDITS} CR\xC9DITOS por ejecuci\xF3n. ANTES de invocar, dile al usuario el costo y espera su aceptaci\xF3n expl\xEDcita; s\xF3lo entonces pasa confirmed: true. Consulta primero list_product_research_runs (GRATIS) \u2014 puede que el usuario ya tenga un reporte pagado para ese pa\xEDs/categor\xEDa y no necesites cobrar de nuevo. Pa\xEDses disponibles: CO, MX, PE, EC, CL. Tarda varios minutos: usa waitSeconds para esperar, y si expira consulta el resultado con get_product_research_run \u2014 el reporte NO se pierde.`, FindInput.shape, CREATES_EXTERNAL, async (input) => {
23383
+ server.tool("find_winning_products", `${findWinningProductsGuidance.summary} CUESTA ${PRICE_CREDITS} CR\xC9DITOS por ejecuci\xF3n. ANTES de invocar, dile al usuario el costo y espera su aceptaci\xF3n expl\xEDcita; s\xF3lo entonces pasa confirmed: true. Consulta primero list_product_research_runs (GRATIS) \u2014 puede que el usuario ya tenga un reporte pagado para ese pa\xEDs/categor\xEDa y no necesites cobrar de nuevo. Pa\xEDses disponibles: CO, MX, PE, EC, CL. Tarda varios minutos: usa waitSeconds para esperar, y si expira consulta el resultado con get_product_research_run \u2014 el reporte NO se pierde.`, FindInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
23366
23384
  const parsed = FindInput.parse(input);
23367
23385
  if (!parsed.confirmed) {
23368
23386
  throw mcp(McpErrorCode.INVALID_INPUT, `This research run costs ${PRICE_CREDITS} credits. Tell the user the cost, get an explicit yes, then call again with confirmed: true.`);
@@ -23417,7 +23435,7 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
23417
23435
  throw translateError(error);
23418
23436
  }
23419
23437
  });
23420
- server.tool("prepare_winning_product_image", prepareWinningProductImageGuidance.summary + " GRATIS. \xDAsalo s\xF3lo despu\xE9s de que el usuario elija un candidato del reporte. Importa de forma segura la foto exacta a ProductMaker, la muestra y luego pide elegir: usarla, usarla y agregar m\xE1s, o subir s\xF3lo fotos propias.", WinnerReferenceInput.shape, CREATES_EXTERNAL, async (input) => {
23438
+ server.tool("prepare_winning_product_image", prepareWinningProductImageGuidance.summary + " GRATIS. \xDAsalo s\xF3lo despu\xE9s de que el usuario elija un candidato del reporte. Importa de forma segura la foto exacta a ProductMaker, la muestra y luego pide elegir: usarla, usarla y agregar m\xE1s, o subir s\xF3lo fotos propias.", WinnerReferenceInput.shape, CREATES_OPEN_WORLD, async (input) => {
23421
23439
  const parsed = WinnerReferenceInput.parse(input);
23422
23440
  try {
23423
23441
  const prepared = WinningProductPreparedImageSchema.parse(await api.postJson(`/v1/product-research/runs/${encodeURIComponent(parsed.runId)}/candidates/${encodeURIComponent(parsed.candidateSourceId)}/image-asset`, {}));
package/dist/stdio.js CHANGED
@@ -14196,7 +14196,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
14196
14196
  ], [
14197
14197
  "meta_upload_session"
14198
14198
  ], WHATSAPP_ONLY_CHANNEL_EXPOSURE),
14199
- defineCapability("request_media_upload", "e91cda1b2d9e44cecf28990b8018ce535ae4e9e6594fa80f503a1bf69d7146ee", "none", "creative", [
14199
+ defineCapability("request_media_upload", "9a50a4647c61f97fb12bbb9b25f7660f392e3cd9825151735cd66292058882ea", "none", "creative", [
14200
14200
  "state_change"
14201
14201
  ], [
14202
14202
  slot("media_kind", true, [
@@ -15255,7 +15255,7 @@ var ApiClient = class {
15255
15255
  };
15256
15256
 
15257
15257
  // src/index.ts
15258
- var MCP_VERSION = "7.3.0";
15258
+ var MCP_VERSION = "8.0.0";
15259
15259
 
15260
15260
  // src/meta-upload-app.ts
15261
15261
  import { readFileSync } from "fs";
@@ -16286,7 +16286,7 @@ var READS_EXTERNAL = {
16286
16286
  readOnlyHint: true,
16287
16287
  destructiveHint: false,
16288
16288
  idempotentHint: true,
16289
- openWorldHint: true
16289
+ openWorldHint: false
16290
16290
  };
16291
16291
  var CREATES_INTERNAL = {
16292
16292
  readOnlyHint: false,
@@ -16295,6 +16295,24 @@ var CREATES_INTERNAL = {
16295
16295
  openWorldHint: false
16296
16296
  };
16297
16297
  var CREATES_EXTERNAL = {
16298
+ readOnlyHint: false,
16299
+ destructiveHint: false,
16300
+ idempotentHint: false,
16301
+ openWorldHint: false
16302
+ };
16303
+ var CREATES_PAID = {
16304
+ readOnlyHint: false,
16305
+ destructiveHint: true,
16306
+ idempotentHint: false,
16307
+ openWorldHint: false
16308
+ };
16309
+ var CREATES_PAID_OPEN_WORLD = {
16310
+ readOnlyHint: false,
16311
+ destructiveHint: true,
16312
+ idempotentHint: false,
16313
+ openWorldHint: true
16314
+ };
16315
+ var CREATES_OPEN_WORLD = {
16298
16316
  readOnlyHint: false,
16299
16317
  destructiveHint: false,
16300
16318
  idempotentHint: false,
@@ -16310,7 +16328,7 @@ var OVERWRITES_EXTERNAL = {
16310
16328
  readOnlyHint: false,
16311
16329
  destructiveHint: true,
16312
16330
  idempotentHint: false,
16313
- openWorldHint: true
16331
+ openWorldHint: false
16314
16332
  };
16315
16333
  var DailyControlStatusEnum = z69.enum([
16316
16334
  "ok",
@@ -18113,7 +18131,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
18113
18131
 
18114
18132
  REQUERIDOS: images o projectId expl\xEDcito, language y country. Cuando los outputs incluyen video (tambi\xE9n por default), pregunta SIEMPRE videoAngleCount: 1, 2 o 3; es una decisi\xF3n de costo incluso con aiDecidesAll. Si falta una foto local, llama primero \`request_media_upload\`. Pregunta price, offer, paymentMethods y compareAtPrice cuando aplique; nunca asumas country/language.
18115
18133
 
18116
- ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explica que inicia trabajo pagado y espera confirmaci\xF3n expl\xEDcita. aiDecidesAll omitido/false pausa para reviews conversacionales; muestra todos los \xE1ngulos candidatos y permite escoger/editar hasta el m\xE1ximo autorizado. Usa aiDecidesAll=true s\xF3lo si el usuario pidi\xF3 \u201Cdecide todo\u201D o \u201Cno me preguntes\u201D.`, CreateProductTaskInput.shape, CREATES_EXTERNAL, async (input) => {
18134
+ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explica que inicia trabajo pagado y espera confirmaci\xF3n expl\xEDcita. aiDecidesAll omitido/false pausa para reviews conversacionales; muestra todos los \xE1ngulos candidatos y permite escoger/editar hasta el m\xE1ximo autorizado. Usa aiDecidesAll=true s\xF3lo si el usuario pidi\xF3 \u201Cdecide todo\u201D o \u201Cno me preguntes\u201D.`, CreateProductTaskInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
18117
18135
  try {
18118
18136
  const selectedOutputs = input.outputs ?? DEFAULT_PRODUCT_TASK_OUTPUTS;
18119
18137
  const videoPreset = selectedOutputs.includes("video") && input.competitorScanEnabled === true ? "auto" : input.videoPreset;
@@ -18204,7 +18222,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
18204
18222
  throw translateError(e);
18205
18223
  }
18206
18224
  });
18207
- server.tool("create_service_video", createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.", CreateServiceVideoInput.shape, CREATES_EXTERNAL, async (input) => {
18225
+ server.tool("create_service_video", createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.", CreateServiceVideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
18208
18226
  try {
18209
18227
  await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
18210
18228
  const created = await api.postJson("/v2/ingest", {
@@ -19129,7 +19147,7 @@ function resolveLandingSetup(setup) {
19129
19147
  }
19130
19148
  __name(resolveLandingSetup, "resolveLandingSetup");
19131
19149
  function registerCreativeTools(server, api, { transport = "http" } = {}) {
19132
- server.tool("generate_free_video", 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.', FreeVideoInput.shape, CREATES_EXTERNAL, async (input) => {
19150
+ server.tool("generate_free_video", 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.', FreeVideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
19133
19151
  try {
19134
19152
  if (input.freeProModel) {
19135
19153
  throw new Error("freeProModel se elimin\xF3 en MCP 7.0.0. Usa `modelId` para elegir el modelo expl\xEDcitamente (ver la descripci\xF3n del par\xE1metro).");
@@ -19177,7 +19195,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
19177
19195
  throw translateError(e);
19178
19196
  }
19179
19197
  });
19180
- server.tool("generate_video_creative", generateVideoCreativeGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), title, primaryAngle, language, country, aspectRatio, videoAngleCount y creativeSetup. Pregunta SIEMPRE cu\xE1ntos videos quiere (1, 2 o 3): la cantidad cambia el costo y no forma parte de \u2018la IA decide todo\u2019. Si falta una foto local, llama primero `request_media_upload` y usa los assetId; no pidas path ni URL. PREGUNTA price y offer si faltan; no asumas country/language.\n\nFORMATO Y CALIDAD: pregunta videoStructure (Un solo clip o Multiescena) y videoQuality (Econ\xF3mico, Medio o Pro). Un solo clip se genera completo y puede incluir cambios de plano. El sistema elige el proveedor internamente.\n\nCONFIGURACI\xD3N: salvo que el usuario diga expl\xEDcitamente que la IA decida todo, usa creativeSetup.mode=guided y pregunta narrativa solo si no hay estudio de mercado; recoge p\xFAblico comprador, presentador (actor guardado, descripci\xF3n o ninguno) y direcci\xF3n creativa. Si el usuario dice qui\xE9n debe aparecer (mujer, hombre o ambos), env\xEDa creativeGender; no lo preguntes si no lo menciona. creativeDirection=null s\xF3lo despu\xE9s de que el usuario delegue esa decisi\xF3n concreta. No inventes valores de setup.\n\nANTES de invocar, muestra un resumen compacto que incluya cantidad, planificaci\xF3n (estudio de mercado o narrativa), p\xFAblico, presentador y direcci\xF3n y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. Multiescena se factura por escena, as\xED que avisa ese mayor costo. Advierte tambi\xE9n que, si luego el usuario confirma que las fotos son de varios productos (combo), el pipeline r\xE1pido actualmente omite la pausa de guion aunque mantiene las dem\xE1s revisiones.\n\nREVIEWS: guided muestra los \xE1ngulos candidatos y permite escoger hasta videoAngleCount, editar cada \xE1ngulo y revisar sus guiones. automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite ambas reviews. scriptNotes agrega restricciones al guion; get_video_script y approve_video_script manejan la review palabra por palabra.", VideoInput.shape, CREATES_EXTERNAL, async (input) => {
19198
+ server.tool("generate_video_creative", generateVideoCreativeGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), title, primaryAngle, language, country, aspectRatio, videoAngleCount y creativeSetup. Pregunta SIEMPRE cu\xE1ntos videos quiere (1, 2 o 3): la cantidad cambia el costo y no forma parte de \u2018la IA decide todo\u2019. Si falta una foto local, llama primero `request_media_upload` y usa los assetId; no pidas path ni URL. PREGUNTA price y offer si faltan; no asumas country/language.\n\nFORMATO Y CALIDAD: pregunta videoStructure (Un solo clip o Multiescena) y videoQuality (Econ\xF3mico, Medio o Pro). Un solo clip se genera completo y puede incluir cambios de plano. El sistema elige el proveedor internamente.\n\nCONFIGURACI\xD3N: salvo que el usuario diga expl\xEDcitamente que la IA decida todo, usa creativeSetup.mode=guided y pregunta narrativa solo si no hay estudio de mercado; recoge p\xFAblico comprador, presentador (actor guardado, descripci\xF3n o ninguno) y direcci\xF3n creativa. Si el usuario dice qui\xE9n debe aparecer (mujer, hombre o ambos), env\xEDa creativeGender; no lo preguntes si no lo menciona. creativeDirection=null s\xF3lo despu\xE9s de que el usuario delegue esa decisi\xF3n concreta. No inventes valores de setup.\n\nANTES de invocar, muestra un resumen compacto que incluya cantidad, planificaci\xF3n (estudio de mercado o narrativa), p\xFAblico, presentador y direcci\xF3n y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. Multiescena se factura por escena, as\xED que avisa ese mayor costo. Advierte tambi\xE9n que, si luego el usuario confirma que las fotos son de varios productos (combo), el pipeline r\xE1pido actualmente omite la pausa de guion aunque mantiene las dem\xE1s revisiones.\n\nREVIEWS: guided muestra los \xE1ngulos candidatos y permite escoger hasta videoAngleCount, editar cada \xE1ngulo y revisar sus guiones. automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite ambas reviews. scriptNotes agrega restricciones al guion; get_video_script y approve_video_script manejan la review palabra por palabra.", VideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
19181
19199
  try {
19182
19200
  if (!input.images && !input.winnerReference) {
19183
19201
  throw new Error("images o winnerReference es requerido.");
@@ -19241,7 +19259,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
19241
19259
  throw translateError(e);
19242
19260
  }
19243
19261
  });
19244
- server.tool("generate_image_creatives", generateImageCreativesGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), productTitle, language, country y creativeSetup. Si falta una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language. primaryAngle es opcional: si falta, ProductMaker lo genera y guided lo muestra para revisi\xF3n.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. No hagas un interrogatorio campo por campo: presenta UN checklist compacto con arquetipo, tratamiento visual, formato, cantidad, calidad, mezcla condicional, copy, competencia, contexto, direcci\xF3n, colores y copy exacto; propone los defaults recomendados y permite que el usuario delegue los campos con ai_decides o null donde el schema lo admite. La UI ofrece 1, 2, 3, 4 o 6 variantes: para 2\u20134 pregunta styleMix; para 1 o 6 usa null, y 6 activa autom\xE1ticamente una imagen de cada estilo. Premium 2K no admite 4:5.\n\nANTES de invocar, muestra el resumen de esas decisiones y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", ImageInput.shape, CREATES_EXTERNAL, async (input) => {
19262
+ server.tool("generate_image_creatives", generateImageCreativesGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), productTitle, language, country y creativeSetup. Si falta una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language. primaryAngle es opcional: si falta, ProductMaker lo genera y guided lo muestra para revisi\xF3n.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. No hagas un interrogatorio campo por campo: presenta UN checklist compacto con arquetipo, tratamiento visual, formato, cantidad, calidad, mezcla condicional, copy, competencia, contexto, direcci\xF3n, colores y copy exacto; propone los defaults recomendados y permite que el usuario delegue los campos con ai_decides o null donde el schema lo admite. La UI ofrece 1, 2, 3, 4 o 6 variantes: para 2\u20134 pregunta styleMix; para 1 o 6 usa null, y 6 activa autom\xE1ticamente una imagen de cada estilo. Premium 2K no admite 4:5.\n\nANTES de invocar, muestra el resumen de esas decisiones y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", ImageInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
19245
19263
  try {
19246
19264
  if (!input.images && !input.winnerReference) {
19247
19265
  throw new Error("images o winnerReference es requerido.");
@@ -19287,7 +19305,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
19287
19305
  throw translateError(e);
19288
19306
  }
19289
19307
  });
19290
- server.tool("generate_landing", generateLandingGuidance.summary + " No expone landing editable/code mientras siga siendo admin-only. Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), language, country y creativeSetup. Ante \u201Ccrea una landing con este producto\u201D y una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. Presenta UN checklist compacto \u2014no preguntas seriales\u2014 con estrategia, formato, competencia, m\xE9todos de pago, contexto, direcci\xF3n creativa y headline/subheadline exactos opcionales. Prop\xF3n defaults recomendados; null significa que el usuario deleg\xF3 esa decisi\xF3n concreta, nunca que el agente la olvid\xF3.\n\nANTES de invocar, muestra el resumen y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", LandingInput.shape, CREATES_EXTERNAL, async (input) => {
19308
+ server.tool("generate_landing", generateLandingGuidance.summary + " No expone landing editable/code mientras siga siendo admin-only. Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), language, country y creativeSetup. Ante \u201Ccrea una landing con este producto\u201D y una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. Presenta UN checklist compacto \u2014no preguntas seriales\u2014 con estrategia, formato, competencia, m\xE9todos de pago, contexto, direcci\xF3n creativa y headline/subheadline exactos opcionales. Prop\xF3n defaults recomendados; null significa que el usuario deleg\xF3 esa decisi\xF3n concreta, nunca que el agente la olvid\xF3.\n\nANTES de invocar, muestra el resumen y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", LandingInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
19291
19309
  try {
19292
19310
  if (!input.images && !input.winnerReference) {
19293
19311
  throw new Error("images o winnerReference es requerido.");
@@ -19565,7 +19583,7 @@ function registerCreativeVariantTools(server, api) {
19565
19583
  throw translateError(error);
19566
19584
  }
19567
19585
  });
19568
- server.tool("create_creative_variant", createCreativeVariantGuidance.summary + " ES UNA ACCI\xD3N DE PAGO: primero llama estimate_creative_variant, muestra el rango de cr\xE9ditos al usuario y solo despu\xE9s invoca este tool con confirm=true. Las recomendaciones IA tambi\xE9n son acciones pagas a 2x del costo real. clientRequestId es obligatorio: genera un UUID por intenci\xF3n y reutiliza el mismo ante timeouts o transporte ambiguo. Si recibes status=error, pide confirmaci\xF3n para un intento nuevo y usa otro UUID. Reutiliza el producto y referencias del task origen; crea un child task independiente y devuelve variantTaskId. Para landing puedes enviar instructions en texto libre y omitir sectionKey: el backend lo clasifica con IA. No expone ni permite cambiar videoModel, videoTier, videoStyle o narrativeStyle; esos valores se heredan del task origen.", CreateCreativeVariantInputBase.shape, CREATES_EXTERNAL, async (input) => {
19586
+ server.tool("create_creative_variant", createCreativeVariantGuidance.summary + " ES UNA ACCI\xD3N DE PAGO: primero llama estimate_creative_variant, muestra el rango de cr\xE9ditos al usuario y solo despu\xE9s invoca este tool con confirm=true. Las recomendaciones IA tambi\xE9n son acciones pagas a 2x del costo real. clientRequestId es obligatorio: genera un UUID por intenci\xF3n y reutiliza el mismo ante timeouts o transporte ambiguo. Si recibes status=error, pide confirmaci\xF3n para un intento nuevo y usa otro UUID. Reutiliza el producto y referencias del task origen; crea un child task independiente y devuelve variantTaskId. Para landing puedes enviar instructions en texto libre y omitir sectionKey: el backend lo clasifica con IA. No expone ni permite cambiar videoModel, videoTier, videoStyle o narrativeStyle; esos valores se heredan del task origen.", CreateCreativeVariantInputBase.shape, CREATES_PAID, async (input) => {
19569
19587
  try {
19570
19588
  const validatedInput = parseVariantInput(CreateCreativeVariantInput, input);
19571
19589
  const estimateInput = EstimateCreativeVariantInput.parse({
@@ -19720,9 +19738,9 @@ function registerScriptReviewTools(server, api) {
19720
19738
  // Not CREATES_INTERNAL: approving the script is what STARTS the render, so
19721
19739
  // this call dispatches jobs to the video providers and burns credits. Its own
19722
19740
  // description says so ("Tras llamarlo, el render arranca y consume créditos").
19723
- // A host that decides when to interrupt the user by `destructiveHint ||
19724
- // openWorldHint` would otherwise auto-invoke the one call that spends money.
19725
- CREATES_EXTERNAL,
19741
+ // `destructiveHint` keeps a host from treating the credit charge as a
19742
+ // reversible bookkeeping update.
19743
+ CREATES_PAID,
19726
19744
  async (input) => {
19727
19745
  try {
19728
19746
  await requirePaidCreativeConfirmation(server, `Aprobar ${input.scenes.length} escena(s) y comenzar el render pagado del video.`);
@@ -20551,7 +20569,7 @@ var UploadSessionInputBase = z79.object({
20551
20569
  maxFiles: z79.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
20552
20570
  });
20553
20571
  var OpenAiFileReference = z79.object({
20554
- download_url: z79.string().url().optional().describe("Optional host-provided download URL. The App prefers getFileDownloadUrl(file_id) and the server never fetches this URL."),
20572
+ download_url: z79.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
20555
20573
  file_id: z79.string().min(1),
20556
20574
  mime_type: z79.string().min(1).optional(),
20557
20575
  file_name: z79.string().min(1).optional()
@@ -20666,7 +20684,7 @@ __name(resolveEndpointForSession, "resolveEndpointForSession");
20666
20684
  function registerMediaUploadTools(server, api) {
20667
20685
  registerAppTool(server, "request_media_upload", {
20668
20686
  title: "Subir archivos",
20669
- description: requestMediaUploadGuidance.summary + " 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.",
20687
+ description: requestMediaUploadGuidance.summary + " 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 de ChatGPT en files con download_url y file_id. Si otro host no puede proporcionar ambos, omite files para que el App abra el selector inline o el enlace de carga. 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.",
20670
20688
  inputSchema: UploadSessionToolInputShape,
20671
20689
  annotations: CREATES_INTERNAL,
20672
20690
  outputSchema: UniversalUploadStructuredResponse.shape,
@@ -21794,7 +21812,7 @@ async function pollUntilTerminal(api, runId, waitSeconds) {
21794
21812
  }
21795
21813
  __name(pollUntilTerminal, "pollUntilTerminal");
21796
21814
  function registerProductResearchTools(server, api) {
21797
- server.tool("find_winning_products", `${findWinningProductsGuidance.summary} CUESTA ${PRICE_CREDITS} CR\xC9DITOS por ejecuci\xF3n. ANTES de invocar, dile al usuario el costo y espera su aceptaci\xF3n expl\xEDcita; s\xF3lo entonces pasa confirmed: true. Consulta primero list_product_research_runs (GRATIS) \u2014 puede que el usuario ya tenga un reporte pagado para ese pa\xEDs/categor\xEDa y no necesites cobrar de nuevo. Pa\xEDses disponibles: CO, MX, PE, EC, CL. Tarda varios minutos: usa waitSeconds para esperar, y si expira consulta el resultado con get_product_research_run \u2014 el reporte NO se pierde.`, FindInput.shape, CREATES_EXTERNAL, async (input) => {
21815
+ server.tool("find_winning_products", `${findWinningProductsGuidance.summary} CUESTA ${PRICE_CREDITS} CR\xC9DITOS por ejecuci\xF3n. ANTES de invocar, dile al usuario el costo y espera su aceptaci\xF3n expl\xEDcita; s\xF3lo entonces pasa confirmed: true. Consulta primero list_product_research_runs (GRATIS) \u2014 puede que el usuario ya tenga un reporte pagado para ese pa\xEDs/categor\xEDa y no necesites cobrar de nuevo. Pa\xEDses disponibles: CO, MX, PE, EC, CL. Tarda varios minutos: usa waitSeconds para esperar, y si expira consulta el resultado con get_product_research_run \u2014 el reporte NO se pierde.`, FindInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
21798
21816
  const parsed = FindInput.parse(input);
21799
21817
  if (!parsed.confirmed) {
21800
21818
  throw mcp(McpErrorCode.INVALID_INPUT, `This research run costs ${PRICE_CREDITS} credits. Tell the user the cost, get an explicit yes, then call again with confirmed: true.`);
@@ -21849,7 +21867,7 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
21849
21867
  throw translateError(error);
21850
21868
  }
21851
21869
  });
21852
- server.tool("prepare_winning_product_image", prepareWinningProductImageGuidance.summary + " GRATIS. \xDAsalo s\xF3lo despu\xE9s de que el usuario elija un candidato del reporte. Importa de forma segura la foto exacta a ProductMaker, la muestra y luego pide elegir: usarla, usarla y agregar m\xE1s, o subir s\xF3lo fotos propias.", WinnerReferenceInput.shape, CREATES_EXTERNAL, async (input) => {
21870
+ server.tool("prepare_winning_product_image", prepareWinningProductImageGuidance.summary + " GRATIS. \xDAsalo s\xF3lo despu\xE9s de que el usuario elija un candidato del reporte. Importa de forma segura la foto exacta a ProductMaker, la muestra y luego pide elegir: usarla, usarla y agregar m\xE1s, o subir s\xF3lo fotos propias.", WinnerReferenceInput.shape, CREATES_OPEN_WORLD, async (input) => {
21853
21871
  const parsed = WinnerReferenceInput.parse(input);
21854
21872
  try {
21855
21873
  const prepared = WinningProductPreparedImageSchema.parse(await api.postJson(`/v1/product-research/runs/${encodeURIComponent(parsed.runId)}/candidates/${encodeURIComponent(parsed.candidateSourceId)}/image-asset`, {}));
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@productmaker/mcp",
3
- "version": "7.3.0",
3
+ "version": "8.0.0",
4
4
  "type": "module",
5
5
  "private": false,
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.",
6
+ "description": "ProductMaker MCP server — cost products, generate landing pages, UGC videos, and ad creatives, and publish to Shopify, Meta Ads, and TikTok Ads.",
7
7
  "keywords": [
8
8
  "mcp",
9
9
  "mcp-server",
@@ -36,7 +36,7 @@
36
36
  "bugs": {
37
37
  "email": "infoapp@productmaker.app"
38
38
  },
39
- "author": "Product Maker AI <infoapp@productmaker.app> (https://productmaker.app)",
39
+ "author": "BONNIE TECH S.A.S <infoapp@productmaker.app> (https://productmaker.app)",
40
40
  "license": "MIT",
41
41
  "bin": {
42
42
  "productmaker-mcp": "./dist/stdio.js"