@productmaker/mcp 12.2.8 → 12.3.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
@@ -207,7 +207,7 @@ its service-page editor, including its generation progress.
207
207
  | `import_orders_file` | Read the provider's spreadsheet from an ABSOLUTE path on the caller's machine and store its orders. **stdio only** — on the hosted server a path points at OUR disk, so it fails closed. Start with `dryRun: true` and tell the seller what it contains (how many orders, between which dates, which rows could not be read) before writing anything. No column with buyer data is ever read |
208
208
  | `create_operation` | Create the business of one country. The currency is derived from the country, never asked. Needed before anything else about the month: with no operation there is nothing for `get_finances` to assemble. Someone selling in a single country has one and never hears the word again |
209
209
  | `merge_products` | Merge two records of the same product into one. The two ids come from `get_product_control` — never invent them. The source DISAPPEARS and its orders move to the target, so confirm by NAME which one stays. It cannot be undone |
210
- | `get_finances` | Read-only monthly P&L: gross and delivered sales, freight, merchandise cost, gross profit, ad spend, fixed costs and NET profit **before taxes**, plus each rate against its target. Grouped on purpose: a model that needs six calls to answer "how am I doing?" assembles the picture itself between trips, and that is where it invents. `adSpendKnown: false` means ad spend could not be read and the profit is INCOMPLETE; `adSpendSource: "user"` means she corrected it by hand; `unconfirmedExpenses > 0` is inherited from last month and unreviewed. With one operation the server resolves it; with several it returns `operation_ambiguous` with the list |
210
+ | `get_finances` | Read-only monthly P&L before taxes: sales, costs, advertising, fixed costs and net profit. Unknown actual costs or advertising leave confirmed profit INCOMPLETE. Optional `costEstimate` uses current configured product costs: label it an ESTIMATE, never confirmed historical costs. Null/absent means no estimate. `adSpendSource: "user"` identifies manual correction; `unconfirmedExpenses > 0` flags inherited expenses. The server resolves a single operation or returns `operation_ambiguous`. |
211
211
  | `set_monthly_expense` | Save one FIXED cost of the month (rent, salaries, accountant). Writing the same label again REPLACES the amount — it does not add a second expense. Without fixed costs written, the month's profit always reads HIGHER than it is. Not for ad spend: that is `set_ad_spend` |
212
212
  | `set_ad_spend` | Correct by hand what was spent on ads that month. `amount: 0` ASSERTS "I did not advertise"; `null` WITHDRAWS the correction and gives the campaigns back the say. They are not the same |
213
213
  | `prepare_winning_product_image` | Prepare and show the exact photo of a user-selected winning-product candidate for free; securely stages it before the next photo choice. |
package/dist/http.js CHANGED
@@ -10861,6 +10861,8 @@ var CreativeEngineRecipeSchema = z38.object({
10861
10861
  "silent_sfx"
10862
10862
  ])).min(1),
10863
10863
  imageBackendAvailable: z38.boolean(),
10864
+ /** New journals may overlap independent accepted media under one coordinator. */
10865
+ mediaScheduling: z38.literal("bounded_parallel_v1").optional(),
10864
10866
  /** New server recipes require journaled speech QA; old receipts remain readable. */
10865
10867
  speechAssessment: z38.literal("whisper_v1").optional(),
10866
10868
  /** Frozen server review envelope; legacy readers retain their 48-frame limit. */
@@ -10897,6 +10899,8 @@ var CreativeEngineRecipeSchema = z38.object({
10897
10899
  explicitCastingPolicy: z38.literal("seller_explicit_v1").optional(),
10898
10900
  /** Frozen reviewer-only read model; absent keeps historical full request context. */
10899
10901
  reviewerContextPolicy: z38.literal("selected_commercial_v1").optional(),
10902
+ /** New final reviews explicitly account for selected critical technical findings. */
10903
+ finalReviewContextPolicy: z38.literal("selected_candidate_findings_v1").optional(),
10900
10904
  /** New voice requests after localized lengthening override stale timing only. */
10901
10905
  voiceLengthenDirectionPolicy: z38.literal("slot_duration_v1").optional(),
10902
10906
  /**
@@ -11029,6 +11033,8 @@ var CreativeEngineSceneSchema = z38.object({
11029
11033
  }).strict()
11030
11034
  ]),
11031
11035
  dependsOn: z38.array(id2),
11036
+ /** Subset of dependsOn consumed only as an approved human opening, never a final frame. */
11037
+ openingDependencies: z38.array(id2).optional(),
11032
11038
  visibleSpeaker: z38.enum([
11033
11039
  "human",
11034
11040
  "product",
@@ -11113,7 +11119,10 @@ var reviewUnavailabilityReason = z38.enum([
11113
11119
  "invalid_output",
11114
11120
  "reviewer_declined",
11115
11121
  /** #22: the gate's technical evidence could not be assembled after spend. */
11116
- "evidence_unavailable"
11122
+ "evidence_unavailable",
11123
+ /** No new purchase is allowed; an owned, verified final can still be delivered. */
11124
+ "cost_budget_exhausted",
11125
+ "post_budget_exhausted"
11117
11126
  ]);
11118
11127
  var CreativeEngineReviewSchema = z38.object({
11119
11128
  id: id2,
@@ -22307,6 +22316,7 @@ var MonthlyExpensesQuerySchema = z97.object({
22307
22316
 
22308
22317
  // ../../packages/types/src/product-alias.ts
22309
22318
  import { z as z98 } from "zod";
22319
+ var PRODUCT_ALIAS_LABEL_MAX_LENGTH = 200;
22310
22320
  var PRODUCT_ALIAS_PROVIDERS = [
22311
22321
  "shopify",
22312
22322
  "dropi",
@@ -22323,12 +22333,12 @@ var ProductAliasSchema = z98.object({
22323
22333
  */
22324
22334
  externalId: z98.string().trim().min(1).max(64),
22325
22335
  /** El nombre con el que el archivo lo llamó, para que la persona lo reconozca. */
22326
- label: z98.string().trim().max(200).optional()
22336
+ label: z98.string().trim().max(PRODUCT_ALIAS_LABEL_MAX_LENGTH).optional()
22327
22337
  }).strict();
22328
22338
  var ResolveUnmatchedProductSchema = z98.object({
22329
22339
  provider: z98.enum(PRODUCT_ALIAS_PROVIDERS),
22330
22340
  externalId: z98.string().trim().min(1).max(64),
22331
- label: z98.string().trim().min(1).max(200),
22341
+ label: z98.string().trim().min(1).max(PRODUCT_ALIAS_LABEL_MAX_LENGTH),
22332
22342
  operationId: z98.string().uuid(),
22333
22343
  /** Presente ⇒ es el producto al que pertenece. Ausente ⇒ es uno nuevo. */
22334
22344
  productControlId: z98.string().uuid().optional()
@@ -22460,6 +22470,15 @@ var SyncShopifyOrdersSchema = z99.object({
22460
22470
 
22461
22471
  // ../../packages/types/src/product-control.ts
22462
22472
  import { z as z100 } from "zod";
22473
+ var MonthlyCostEstimateSchema = z100.object({
22474
+ source: z100.literal("product_costing"),
22475
+ linesEstimated: z100.number().int().positive(),
22476
+ merchandiseCost: z100.number().finite().nonnegative(),
22477
+ freightCost: z100.number().finite().nonnegative(),
22478
+ grossProfit: z100.number().finite(),
22479
+ netProfit: z100.number().finite(),
22480
+ netMarginOnDelivered: z100.number().finite().nullable()
22481
+ });
22463
22482
  var ProductControlDailyCountsSchema = z100.object({
22464
22483
  date: z100.string().regex(/^\d{4}-\d{2}-\d{2}$/),
22465
22484
  orders: z100.number().int().nullable(),
@@ -30904,7 +30923,7 @@ var ApiClient = class {
30904
30923
  };
30905
30924
 
30906
30925
  // src/index.ts
30907
- var MCP_VERSION = "12.2.8";
30926
+ var MCP_VERSION = "12.3.0";
30908
30927
 
30909
30928
  // src/meta-upload-app.ts
30910
30929
  import { readFileSync } from "fs";
@@ -40999,7 +41018,7 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
40999
41018
  }
41000
41019
  });
41001
41020
  server.registerTool("get_finances", {
41002
- description: getFinancesGuidance.summary + ' Contesta la pregunta que de verdad importa --- \xABeste negocio gana plata?\xBB --- con el mes armado: ventas totales y entregadas, fletes, costo de los productos, utilidad bruta, publicidad, gastos fijos y utilidad NETA. Esa utilidad es ANTES de impuestos y hay que decirlo asi: el contador es un gasto mas, no un calculo nuestro. Trae tambien los porcentajes contra sus metas. Si `deliveredSalesKnown` no es true, faltan importes de ventas entregadas: la utilidad y los m\xE1rgenes no est\xE1n completos. `grossSalesKnown` distinto de true indica ventas totales parciales. Si `costsKnown` viene en `false`, esos pedidos llegaron de una fuente que NO sabe cuanto costaron \u2014la tienda, o la API del proveedor\u2014 y la utilidad BRUTA esta incompleta: no es que el producto salga gratis. Si `adSpendKnown` viene en `false`, la publicidad NO se pudo leer y la utilidad esta INCOMPLETA: dilo antes de que alguien celebre un mes que perdio plata. `adSpendSource: "user"` significa que ella corrigio la cifra a mano, y eso se revisa distinto de una leida. Si `unconfirmedExpenses` es mayor que cero, ese monto viene heredado del mes pasado y ella no lo ha revisado. Es READ-ONLY: nunca pausa ni modifica una campana.',
41021
+ description: getFinancesGuidance.summary + ' Contesta la pregunta que de verdad importa --- \xABeste negocio gana plata?\xBB --- con el mes armado: ventas totales y entregadas, fletes, costo de los productos, utilidad bruta, publicidad, gastos fijos y utilidad NETA. Esa utilidad es ANTES de impuestos y hay que decirlo asi: el contador es un gasto mas, no un calculo nuestro. Trae tambien los porcentajes contra sus metas. Si `deliveredSalesKnown` no es true, faltan importes de ventas entregadas: la utilidad y los m\xE1rgenes no est\xE1n completos. `grossSalesKnown` distinto de true indica ventas totales parciales. Si `costsKnown` viene en `false`, esos pedidos llegaron de una fuente que NO sabe cuanto costaron \u2014la tienda, o la API del proveedor\u2014 y la utilidad BRUTA esta incompleta: no es que el producto salga gratis. Si `adSpendKnown` viene en `false`, la publicidad NO se pudo leer y la utilidad esta INCOMPLETA: dilo antes de que alguien celebre un mes que perdio plata. `adSpendSource: "user"` significa que ella corrigio la cifra a mano, y eso se revisa distinto de una leida. Si `unconfirmedExpenses` es mayor que cero, ese monto viene heredado del mes pasado y ella no lo ha revisado. Es READ-ONLY: nunca pausa ni modifica una campana. Si viene `costEstimate` con `source: "product_costing"`, presenta sus importes como ESTIMACI\xD3N antes de impuestos, usando los costos actuales configurados del producto: no son costos reales confirmados de esos pedidos. Conserva el aviso de `costsKnown: false` y distingue esta estimaci\xF3n de los importes reales del libro. `linesEstimated` indica cu\xE1ntas l\xEDneas usan costos configurados. La API s\xF3lo ofrece esta estimaci\xF3n cuando cubre todos los costos faltantes con perfiles asociados del mismo pa\xEDs y moneda, y conoce ventas entregadas, publicidad y gastos revisados. Si `costEstimate` es null o no existe, no inventes una estimaci\xF3n ni completes importes faltantes.',
41003
41022
  inputSchema: GetFinancesInput.shape,
41004
41023
  annotations: READS_INTERNAL
41005
41024
  }, async (input) => {
package/dist/stdio.js CHANGED
@@ -10636,6 +10636,8 @@ var CreativeEngineRecipeSchema = z38.object({
10636
10636
  "silent_sfx"
10637
10637
  ])).min(1),
10638
10638
  imageBackendAvailable: z38.boolean(),
10639
+ /** New journals may overlap independent accepted media under one coordinator. */
10640
+ mediaScheduling: z38.literal("bounded_parallel_v1").optional(),
10639
10641
  /** New server recipes require journaled speech QA; old receipts remain readable. */
10640
10642
  speechAssessment: z38.literal("whisper_v1").optional(),
10641
10643
  /** Frozen server review envelope; legacy readers retain their 48-frame limit. */
@@ -10672,6 +10674,8 @@ var CreativeEngineRecipeSchema = z38.object({
10672
10674
  explicitCastingPolicy: z38.literal("seller_explicit_v1").optional(),
10673
10675
  /** Frozen reviewer-only read model; absent keeps historical full request context. */
10674
10676
  reviewerContextPolicy: z38.literal("selected_commercial_v1").optional(),
10677
+ /** New final reviews explicitly account for selected critical technical findings. */
10678
+ finalReviewContextPolicy: z38.literal("selected_candidate_findings_v1").optional(),
10675
10679
  /** New voice requests after localized lengthening override stale timing only. */
10676
10680
  voiceLengthenDirectionPolicy: z38.literal("slot_duration_v1").optional(),
10677
10681
  /**
@@ -10804,6 +10808,8 @@ var CreativeEngineSceneSchema = z38.object({
10804
10808
  }).strict()
10805
10809
  ]),
10806
10810
  dependsOn: z38.array(id2),
10811
+ /** Subset of dependsOn consumed only as an approved human opening, never a final frame. */
10812
+ openingDependencies: z38.array(id2).optional(),
10807
10813
  visibleSpeaker: z38.enum([
10808
10814
  "human",
10809
10815
  "product",
@@ -10888,7 +10894,10 @@ var reviewUnavailabilityReason = z38.enum([
10888
10894
  "invalid_output",
10889
10895
  "reviewer_declined",
10890
10896
  /** #22: the gate's technical evidence could not be assembled after spend. */
10891
- "evidence_unavailable"
10897
+ "evidence_unavailable",
10898
+ /** No new purchase is allowed; an owned, verified final can still be delivered. */
10899
+ "cost_budget_exhausted",
10900
+ "post_budget_exhausted"
10892
10901
  ]);
10893
10902
  var CreativeEngineReviewSchema = z38.object({
10894
10903
  id: id2,
@@ -22082,6 +22091,7 @@ var MonthlyExpensesQuerySchema = z97.object({
22082
22091
 
22083
22092
  // ../../packages/types/src/product-alias.ts
22084
22093
  import { z as z98 } from "zod";
22094
+ var PRODUCT_ALIAS_LABEL_MAX_LENGTH = 200;
22085
22095
  var PRODUCT_ALIAS_PROVIDERS = [
22086
22096
  "shopify",
22087
22097
  "dropi",
@@ -22098,12 +22108,12 @@ var ProductAliasSchema = z98.object({
22098
22108
  */
22099
22109
  externalId: z98.string().trim().min(1).max(64),
22100
22110
  /** El nombre con el que el archivo lo llamó, para que la persona lo reconozca. */
22101
- label: z98.string().trim().max(200).optional()
22111
+ label: z98.string().trim().max(PRODUCT_ALIAS_LABEL_MAX_LENGTH).optional()
22102
22112
  }).strict();
22103
22113
  var ResolveUnmatchedProductSchema = z98.object({
22104
22114
  provider: z98.enum(PRODUCT_ALIAS_PROVIDERS),
22105
22115
  externalId: z98.string().trim().min(1).max(64),
22106
- label: z98.string().trim().min(1).max(200),
22116
+ label: z98.string().trim().min(1).max(PRODUCT_ALIAS_LABEL_MAX_LENGTH),
22107
22117
  operationId: z98.string().uuid(),
22108
22118
  /** Presente ⇒ es el producto al que pertenece. Ausente ⇒ es uno nuevo. */
22109
22119
  productControlId: z98.string().uuid().optional()
@@ -22235,6 +22245,15 @@ var SyncShopifyOrdersSchema = z99.object({
22235
22245
 
22236
22246
  // ../../packages/types/src/product-control.ts
22237
22247
  import { z as z100 } from "zod";
22248
+ var MonthlyCostEstimateSchema = z100.object({
22249
+ source: z100.literal("product_costing"),
22250
+ linesEstimated: z100.number().int().positive(),
22251
+ merchandiseCost: z100.number().finite().nonnegative(),
22252
+ freightCost: z100.number().finite().nonnegative(),
22253
+ grossProfit: z100.number().finite(),
22254
+ netProfit: z100.number().finite(),
22255
+ netMarginOnDelivered: z100.number().finite().nullable()
22256
+ });
22238
22257
  var ProductControlDailyCountsSchema = z100.object({
22239
22258
  date: z100.string().regex(/^\d{4}-\d{2}-\d{2}$/),
22240
22259
  orders: z100.number().int().nullable(),
@@ -29231,7 +29250,7 @@ var ApiClient = class {
29231
29250
  };
29232
29251
 
29233
29252
  // src/index.ts
29234
- var MCP_VERSION = "12.2.8";
29253
+ var MCP_VERSION = "12.3.0";
29235
29254
 
29236
29255
  // src/meta-upload-app.ts
29237
29256
  import { readFileSync } from "fs";
@@ -39484,7 +39503,7 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
39484
39503
  }
39485
39504
  });
39486
39505
  server.registerTool("get_finances", {
39487
- description: getFinancesGuidance.summary + ' Contesta la pregunta que de verdad importa --- \xABeste negocio gana plata?\xBB --- con el mes armado: ventas totales y entregadas, fletes, costo de los productos, utilidad bruta, publicidad, gastos fijos y utilidad NETA. Esa utilidad es ANTES de impuestos y hay que decirlo asi: el contador es un gasto mas, no un calculo nuestro. Trae tambien los porcentajes contra sus metas. Si `deliveredSalesKnown` no es true, faltan importes de ventas entregadas: la utilidad y los m\xE1rgenes no est\xE1n completos. `grossSalesKnown` distinto de true indica ventas totales parciales. Si `costsKnown` viene en `false`, esos pedidos llegaron de una fuente que NO sabe cuanto costaron \u2014la tienda, o la API del proveedor\u2014 y la utilidad BRUTA esta incompleta: no es que el producto salga gratis. Si `adSpendKnown` viene en `false`, la publicidad NO se pudo leer y la utilidad esta INCOMPLETA: dilo antes de que alguien celebre un mes que perdio plata. `adSpendSource: "user"` significa que ella corrigio la cifra a mano, y eso se revisa distinto de una leida. Si `unconfirmedExpenses` es mayor que cero, ese monto viene heredado del mes pasado y ella no lo ha revisado. Es READ-ONLY: nunca pausa ni modifica una campana.',
39506
+ description: getFinancesGuidance.summary + ' Contesta la pregunta que de verdad importa --- \xABeste negocio gana plata?\xBB --- con el mes armado: ventas totales y entregadas, fletes, costo de los productos, utilidad bruta, publicidad, gastos fijos y utilidad NETA. Esa utilidad es ANTES de impuestos y hay que decirlo asi: el contador es un gasto mas, no un calculo nuestro. Trae tambien los porcentajes contra sus metas. Si `deliveredSalesKnown` no es true, faltan importes de ventas entregadas: la utilidad y los m\xE1rgenes no est\xE1n completos. `grossSalesKnown` distinto de true indica ventas totales parciales. Si `costsKnown` viene en `false`, esos pedidos llegaron de una fuente que NO sabe cuanto costaron \u2014la tienda, o la API del proveedor\u2014 y la utilidad BRUTA esta incompleta: no es que el producto salga gratis. Si `adSpendKnown` viene en `false`, la publicidad NO se pudo leer y la utilidad esta INCOMPLETA: dilo antes de que alguien celebre un mes que perdio plata. `adSpendSource: "user"` significa que ella corrigio la cifra a mano, y eso se revisa distinto de una leida. Si `unconfirmedExpenses` es mayor que cero, ese monto viene heredado del mes pasado y ella no lo ha revisado. Es READ-ONLY: nunca pausa ni modifica una campana. Si viene `costEstimate` con `source: "product_costing"`, presenta sus importes como ESTIMACI\xD3N antes de impuestos, usando los costos actuales configurados del producto: no son costos reales confirmados de esos pedidos. Conserva el aviso de `costsKnown: false` y distingue esta estimaci\xF3n de los importes reales del libro. `linesEstimated` indica cu\xE1ntas l\xEDneas usan costos configurados. La API s\xF3lo ofrece esta estimaci\xF3n cuando cubre todos los costos faltantes con perfiles asociados del mismo pa\xEDs y moneda, y conoce ventas entregadas, publicidad y gastos revisados. Si `costEstimate` es null o no existe, no inventes una estimaci\xF3n ni completes importes faltantes.',
39488
39507
  inputSchema: GetFinancesInput.shape,
39489
39508
  annotations: READS_INTERNAL
39490
39509
  }, async (input) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@productmaker/mcp",
3
- "version": "12.2.8",
3
+ "version": "12.3.0",
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.",
@@ -67,8 +67,8 @@
67
67
  "typescript": "^7.0.2",
68
68
  "vitest": "5.0.3",
69
69
  "@packages/product-economics": "0.1.0",
70
- "@packages/types": "0.1.0",
71
- "@packages/utils": "0.1.0"
70
+ "@packages/utils": "0.1.0",
71
+ "@packages/types": "0.1.0"
72
72
  },
73
73
  "publishConfig": {
74
74
  "access": "public"