@productmaker/mcp 3.4.1 → 3.4.2
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 +58 -6
- package/dist/stdio.js +58 -6
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -3692,6 +3692,32 @@ var StatusResponse = z24.object({
|
|
|
3692
3692
|
requiresAction: z24.boolean().optional(),
|
|
3693
3693
|
/** True when the task needs the user's attention rather than passive progress. */
|
|
3694
3694
|
needsReview: z24.boolean().optional(),
|
|
3695
|
+
/**
|
|
3696
|
+
* THE answer to "does this task still owe the seller a question — now OR later
|
|
3697
|
+
* in this run?". The chat leaves for /tasks/:id only on an explicit `false`,
|
|
3698
|
+
* and /tasks/:id bounces her back on `true`. ONE field drives BOTH directions
|
|
3699
|
+
* on purpose: deciding them on two different facts is what looped
|
|
3700
|
+
* /tasks/:id ↔ wizard before (see apps/web/lib/task-routing.ts).
|
|
3701
|
+
*
|
|
3702
|
+
* STRICTLY WIDER THAN `needsReview`, and the difference is the whole point:
|
|
3703
|
+
* · `needsReview` answers "is a gate open RIGHT NOW", and it under-reports —
|
|
3704
|
+
* `buildPendingUserAction` only serves the reference-grouping question when
|
|
3705
|
+
* it is RENDERABLE, so an unconfirmed target reports `false` while
|
|
3706
|
+
* `angles.worker` will still pause at the END of the angles stage.
|
|
3707
|
+
* · this field adds the gates that are GUARANTEED to open: both pause flags,
|
|
3708
|
+
* plus that same worker prediction, through the one shared helper.
|
|
3709
|
+
*
|
|
3710
|
+
* Absent (undefined) means "an older API that cannot answer" — the client must
|
|
3711
|
+
* treat that as `true` and stay put. Uncertainty resolves to staying: a false
|
|
3712
|
+
* positive costs her a wait, a false negative strands her on a screen that
|
|
3713
|
+
* cannot render the gate (prod bd4d0bb1 / 52dc15a7, both refunded and
|
|
3714
|
+
* undelivered).
|
|
3715
|
+
*
|
|
3716
|
+
* ALWAYS false on a terminal task. `pauseForAngleReview` SURVIVES on completed
|
|
3717
|
+
* tasks, so without that guard a finished landing would report `true` forever
|
|
3718
|
+
* and get bounced into a chat with nothing left to ask.
|
|
3719
|
+
*/
|
|
3720
|
+
willAskAgain: z24.boolean().optional(),
|
|
3695
3721
|
/** True when an open gate exists that somebody can actually ANSWER. A strictly
|
|
3696
3722
|
* narrower fact than `needsReview` — see the identical field on `TaskSummary`
|
|
3697
3723
|
* below for why conflating the two produced a call to action that led nowhere. */
|
|
@@ -3826,6 +3852,9 @@ var CostEstimationType = z25.enum([
|
|
|
3826
3852
|
"landing-regenerate",
|
|
3827
3853
|
"landing-creative",
|
|
3828
3854
|
"campaign-copy",
|
|
3855
|
+
"brand-extract",
|
|
3856
|
+
"persona-suggest",
|
|
3857
|
+
"chat-parse",
|
|
3829
3858
|
"service-creative",
|
|
3830
3859
|
"actor-grid"
|
|
3831
3860
|
]);
|
|
@@ -3991,11 +4020,14 @@ var LandingCreativeEstimationOptions = z25.object({
|
|
|
3991
4020
|
landingStrategy: LandingStrategySchema.optional()
|
|
3992
4021
|
});
|
|
3993
4022
|
var CampaignCopyEstimationOptions = z25.object({
|
|
3994
|
-
/** Number of creatives
|
|
3995
|
-
nCreatives: z25.number().int().min(1).max(
|
|
3996
|
-
/** Number of image creatives that
|
|
3997
|
-
nImages: z25.number().int().min(0).max(
|
|
3998
|
-
});
|
|
4023
|
+
/** Number of creatives in the one copy-completion request (1-10). */
|
|
4024
|
+
nCreatives: z25.number().int().min(1).max(10),
|
|
4025
|
+
/** Number of image creatives that can each use one vision analysis (0-10). */
|
|
4026
|
+
nImages: z25.number().int().min(0).max(10).default(0)
|
|
4027
|
+
});
|
|
4028
|
+
var BrandExtractEstimationOptions = z25.object({}).strict();
|
|
4029
|
+
var PersonaSuggestEstimationOptions = z25.object({}).strict();
|
|
4030
|
+
var ChatParseEstimationOptions = z25.object({}).strict();
|
|
3999
4031
|
var ServiceCreativeEstimationOptions = z25.object({
|
|
4000
4032
|
mediaAssetCount: z25.number().int().min(0).max(8).optional(),
|
|
4001
4033
|
uploadedVideoDurationSeconds: z25.number().min(0).max(240).optional()
|
|
@@ -4034,6 +4066,18 @@ var CostEstimationRequest = z25.discriminatedUnion("type", [
|
|
|
4034
4066
|
type: z25.literal("campaign-copy"),
|
|
4035
4067
|
options: CampaignCopyEstimationOptions
|
|
4036
4068
|
}),
|
|
4069
|
+
z25.object({
|
|
4070
|
+
type: z25.literal("brand-extract"),
|
|
4071
|
+
options: BrandExtractEstimationOptions
|
|
4072
|
+
}),
|
|
4073
|
+
z25.object({
|
|
4074
|
+
type: z25.literal("persona-suggest"),
|
|
4075
|
+
options: PersonaSuggestEstimationOptions
|
|
4076
|
+
}),
|
|
4077
|
+
z25.object({
|
|
4078
|
+
type: z25.literal("chat-parse"),
|
|
4079
|
+
options: ChatParseEstimationOptions
|
|
4080
|
+
}),
|
|
4037
4081
|
z25.object({
|
|
4038
4082
|
type: z25.literal("service-creative"),
|
|
4039
4083
|
options: ServiceCreativeEstimationOptions
|
|
@@ -4533,6 +4577,9 @@ var VideoMixQaJobSchema = z30.object({
|
|
|
4533
4577
|
});
|
|
4534
4578
|
var BrandExtractJobSchema = z30.object({
|
|
4535
4579
|
brandId: z30.string().uuid(),
|
|
4580
|
+
// Generation is part of the durable paid-spend identity. Default 1 keeps
|
|
4581
|
+
// pre-migration BullMQ payloads parseable; their DB state fails safe.
|
|
4582
|
+
generation: z30.number().int().positive().default(1),
|
|
4536
4583
|
url: z30.string().url().refine((value) => {
|
|
4537
4584
|
const protocol = new URL(value).protocol;
|
|
4538
4585
|
return protocol === "http:" || protocol === "https:";
|
|
@@ -11631,7 +11678,7 @@ var ApiClient = class {
|
|
|
11631
11678
|
};
|
|
11632
11679
|
|
|
11633
11680
|
// src/index.ts
|
|
11634
|
-
var MCP_VERSION = "3.4.
|
|
11681
|
+
var MCP_VERSION = "3.4.2";
|
|
11635
11682
|
|
|
11636
11683
|
// src/meta-upload-app.ts
|
|
11637
11684
|
import { readFileSync } from "fs";
|
|
@@ -11943,6 +11990,7 @@ __name(resolveOne, "resolveOne");
|
|
|
11943
11990
|
|
|
11944
11991
|
// src/status-poller.ts
|
|
11945
11992
|
var TERMINAL = /* @__PURE__ */ new Set([
|
|
11993
|
+
"done",
|
|
11946
11994
|
"complete",
|
|
11947
11995
|
"error"
|
|
11948
11996
|
]);
|
|
@@ -12618,6 +12666,7 @@ var McpErrorCode = {
|
|
|
12618
12666
|
REVOKED_API_KEY: "REVOKED_API_KEY",
|
|
12619
12667
|
// Rate limit / quota
|
|
12620
12668
|
RATE_LIMITED: "RATE_LIMITED",
|
|
12669
|
+
CREDIT_ADMISSION_UNAVAILABLE: "CREDIT_ADMISSION_UNAVAILABLE",
|
|
12621
12670
|
// Input
|
|
12622
12671
|
INVALID_INPUT: "INVALID_INPUT",
|
|
12623
12672
|
INSUFFICIENT_CREDITS: "INSUFFICIENT_CREDITS",
|
|
@@ -12806,6 +12855,7 @@ var CODE_MESSAGES = {
|
|
|
12806
12855
|
REVOKED_API_KEY: "API key revoked. Generate a new one at https://productmaker.app/account/api-keys.",
|
|
12807
12856
|
// Rate
|
|
12808
12857
|
RATE_LIMITED: "Too many requests. Wait a few seconds.",
|
|
12858
|
+
CREDIT_ADMISSION_UNAVAILABLE: "Credit admission is temporarily unavailable. Do not retry a paid action until ProductMaker can verify the balance.",
|
|
12809
12859
|
INSUFFICIENT_CREDITS: "Insufficient credits for this action. Check your balance and add credits at https://productmaker.app before retrying.",
|
|
12810
12860
|
TASK_QUOTA_EXCEEDED: "You reached the active-task limit. Wait for a task to finish before creating another variant.",
|
|
12811
12861
|
// Generic
|
|
@@ -12900,6 +12950,7 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
12900
12950
|
McpErrorCode.NO_META_AD_ACCOUNTS
|
|
12901
12951
|
]);
|
|
12902
12952
|
var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
12953
|
+
McpErrorCode.CREDIT_ADMISSION_UNAVAILABLE,
|
|
12903
12954
|
McpErrorCode.INSUFFICIENT_CREDITS,
|
|
12904
12955
|
McpErrorCode.TASK_QUOTA_EXCEEDED,
|
|
12905
12956
|
McpErrorCode.DROPSHIPPING_PROJECT_NOT_FOUND,
|
|
@@ -12998,6 +13049,7 @@ __name(looksLikeMeaningfulBackendMessage, "looksLikeMeaningfulBackendMessage");
|
|
|
12998
13049
|
function resolveMessage(code, backendMessage) {
|
|
12999
13050
|
const mapped = CODE_MESSAGES[code];
|
|
13000
13051
|
const backend = typeof backendMessage === "string" ? backendMessage.trim() : "";
|
|
13052
|
+
if (code === McpErrorCode.CREDIT_ADMISSION_UNAVAILABLE && mapped) return mapped;
|
|
13001
13053
|
if (mapped && backend && looksLikeMeaningfulBackendMessage(backend, mapped)) {
|
|
13002
13054
|
return `${mapped} (Detail: ${backend})`;
|
|
13003
13055
|
}
|
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.
|
|
267
|
+
var MCP_VERSION = "3.4.2";
|
|
268
268
|
|
|
269
269
|
// src/meta-upload-app.ts
|
|
270
270
|
import { readFileSync } from "fs";
|
|
@@ -576,6 +576,7 @@ __name(resolveOne, "resolveOne");
|
|
|
576
576
|
|
|
577
577
|
// src/status-poller.ts
|
|
578
578
|
var TERMINAL = /* @__PURE__ */ new Set([
|
|
579
|
+
"done",
|
|
579
580
|
"complete",
|
|
580
581
|
"error"
|
|
581
582
|
]);
|
|
@@ -4313,6 +4314,32 @@ var StatusResponse = z24.object({
|
|
|
4313
4314
|
requiresAction: z24.boolean().optional(),
|
|
4314
4315
|
/** True when the task needs the user's attention rather than passive progress. */
|
|
4315
4316
|
needsReview: z24.boolean().optional(),
|
|
4317
|
+
/**
|
|
4318
|
+
* THE answer to "does this task still owe the seller a question — now OR later
|
|
4319
|
+
* in this run?". The chat leaves for /tasks/:id only on an explicit `false`,
|
|
4320
|
+
* and /tasks/:id bounces her back on `true`. ONE field drives BOTH directions
|
|
4321
|
+
* on purpose: deciding them on two different facts is what looped
|
|
4322
|
+
* /tasks/:id ↔ wizard before (see apps/web/lib/task-routing.ts).
|
|
4323
|
+
*
|
|
4324
|
+
* STRICTLY WIDER THAN `needsReview`, and the difference is the whole point:
|
|
4325
|
+
* · `needsReview` answers "is a gate open RIGHT NOW", and it under-reports —
|
|
4326
|
+
* `buildPendingUserAction` only serves the reference-grouping question when
|
|
4327
|
+
* it is RENDERABLE, so an unconfirmed target reports `false` while
|
|
4328
|
+
* `angles.worker` will still pause at the END of the angles stage.
|
|
4329
|
+
* · this field adds the gates that are GUARANTEED to open: both pause flags,
|
|
4330
|
+
* plus that same worker prediction, through the one shared helper.
|
|
4331
|
+
*
|
|
4332
|
+
* Absent (undefined) means "an older API that cannot answer" — the client must
|
|
4333
|
+
* treat that as `true` and stay put. Uncertainty resolves to staying: a false
|
|
4334
|
+
* positive costs her a wait, a false negative strands her on a screen that
|
|
4335
|
+
* cannot render the gate (prod bd4d0bb1 / 52dc15a7, both refunded and
|
|
4336
|
+
* undelivered).
|
|
4337
|
+
*
|
|
4338
|
+
* ALWAYS false on a terminal task. `pauseForAngleReview` SURVIVES on completed
|
|
4339
|
+
* tasks, so without that guard a finished landing would report `true` forever
|
|
4340
|
+
* and get bounced into a chat with nothing left to ask.
|
|
4341
|
+
*/
|
|
4342
|
+
willAskAgain: z24.boolean().optional(),
|
|
4316
4343
|
/** True when an open gate exists that somebody can actually ANSWER. A strictly
|
|
4317
4344
|
* narrower fact than `needsReview` — see the identical field on `TaskSummary`
|
|
4318
4345
|
* below for why conflating the two produced a call to action that led nowhere. */
|
|
@@ -4447,6 +4474,9 @@ var CostEstimationType = z25.enum([
|
|
|
4447
4474
|
"landing-regenerate",
|
|
4448
4475
|
"landing-creative",
|
|
4449
4476
|
"campaign-copy",
|
|
4477
|
+
"brand-extract",
|
|
4478
|
+
"persona-suggest",
|
|
4479
|
+
"chat-parse",
|
|
4450
4480
|
"service-creative",
|
|
4451
4481
|
"actor-grid"
|
|
4452
4482
|
]);
|
|
@@ -4612,11 +4642,14 @@ var LandingCreativeEstimationOptions = z25.object({
|
|
|
4612
4642
|
landingStrategy: LandingStrategySchema.optional()
|
|
4613
4643
|
});
|
|
4614
4644
|
var CampaignCopyEstimationOptions = z25.object({
|
|
4615
|
-
/** Number of creatives
|
|
4616
|
-
nCreatives: z25.number().int().min(1).max(
|
|
4617
|
-
/** Number of image creatives that
|
|
4618
|
-
nImages: z25.number().int().min(0).max(
|
|
4619
|
-
});
|
|
4645
|
+
/** Number of creatives in the one copy-completion request (1-10). */
|
|
4646
|
+
nCreatives: z25.number().int().min(1).max(10),
|
|
4647
|
+
/** Number of image creatives that can each use one vision analysis (0-10). */
|
|
4648
|
+
nImages: z25.number().int().min(0).max(10).default(0)
|
|
4649
|
+
});
|
|
4650
|
+
var BrandExtractEstimationOptions = z25.object({}).strict();
|
|
4651
|
+
var PersonaSuggestEstimationOptions = z25.object({}).strict();
|
|
4652
|
+
var ChatParseEstimationOptions = z25.object({}).strict();
|
|
4620
4653
|
var ServiceCreativeEstimationOptions = z25.object({
|
|
4621
4654
|
mediaAssetCount: z25.number().int().min(0).max(8).optional(),
|
|
4622
4655
|
uploadedVideoDurationSeconds: z25.number().min(0).max(240).optional()
|
|
@@ -4655,6 +4688,18 @@ var CostEstimationRequest = z25.discriminatedUnion("type", [
|
|
|
4655
4688
|
type: z25.literal("campaign-copy"),
|
|
4656
4689
|
options: CampaignCopyEstimationOptions
|
|
4657
4690
|
}),
|
|
4691
|
+
z25.object({
|
|
4692
|
+
type: z25.literal("brand-extract"),
|
|
4693
|
+
options: BrandExtractEstimationOptions
|
|
4694
|
+
}),
|
|
4695
|
+
z25.object({
|
|
4696
|
+
type: z25.literal("persona-suggest"),
|
|
4697
|
+
options: PersonaSuggestEstimationOptions
|
|
4698
|
+
}),
|
|
4699
|
+
z25.object({
|
|
4700
|
+
type: z25.literal("chat-parse"),
|
|
4701
|
+
options: ChatParseEstimationOptions
|
|
4702
|
+
}),
|
|
4658
4703
|
z25.object({
|
|
4659
4704
|
type: z25.literal("service-creative"),
|
|
4660
4705
|
options: ServiceCreativeEstimationOptions
|
|
@@ -5154,6 +5199,9 @@ var VideoMixQaJobSchema = z30.object({
|
|
|
5154
5199
|
});
|
|
5155
5200
|
var BrandExtractJobSchema = z30.object({
|
|
5156
5201
|
brandId: z30.string().uuid(),
|
|
5202
|
+
// Generation is part of the durable paid-spend identity. Default 1 keeps
|
|
5203
|
+
// pre-migration BullMQ payloads parseable; their DB state fails safe.
|
|
5204
|
+
generation: z30.number().int().positive().default(1),
|
|
5157
5205
|
url: z30.string().url().refine((value) => {
|
|
5158
5206
|
const protocol = new URL(value).protocol;
|
|
5159
5207
|
return protocol === "http:" || protocol === "https:";
|
|
@@ -11367,6 +11415,7 @@ var McpErrorCode = {
|
|
|
11367
11415
|
REVOKED_API_KEY: "REVOKED_API_KEY",
|
|
11368
11416
|
// Rate limit / quota
|
|
11369
11417
|
RATE_LIMITED: "RATE_LIMITED",
|
|
11418
|
+
CREDIT_ADMISSION_UNAVAILABLE: "CREDIT_ADMISSION_UNAVAILABLE",
|
|
11370
11419
|
// Input
|
|
11371
11420
|
INVALID_INPUT: "INVALID_INPUT",
|
|
11372
11421
|
INSUFFICIENT_CREDITS: "INSUFFICIENT_CREDITS",
|
|
@@ -11555,6 +11604,7 @@ var CODE_MESSAGES = {
|
|
|
11555
11604
|
REVOKED_API_KEY: "API key revoked. Generate a new one at https://productmaker.app/account/api-keys.",
|
|
11556
11605
|
// Rate
|
|
11557
11606
|
RATE_LIMITED: "Too many requests. Wait a few seconds.",
|
|
11607
|
+
CREDIT_ADMISSION_UNAVAILABLE: "Credit admission is temporarily unavailable. Do not retry a paid action until ProductMaker can verify the balance.",
|
|
11558
11608
|
INSUFFICIENT_CREDITS: "Insufficient credits for this action. Check your balance and add credits at https://productmaker.app before retrying.",
|
|
11559
11609
|
TASK_QUOTA_EXCEEDED: "You reached the active-task limit. Wait for a task to finish before creating another variant.",
|
|
11560
11610
|
// Generic
|
|
@@ -11649,6 +11699,7 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
11649
11699
|
McpErrorCode.NO_META_AD_ACCOUNTS
|
|
11650
11700
|
]);
|
|
11651
11701
|
var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
11702
|
+
McpErrorCode.CREDIT_ADMISSION_UNAVAILABLE,
|
|
11652
11703
|
McpErrorCode.INSUFFICIENT_CREDITS,
|
|
11653
11704
|
McpErrorCode.TASK_QUOTA_EXCEEDED,
|
|
11654
11705
|
McpErrorCode.DROPSHIPPING_PROJECT_NOT_FOUND,
|
|
@@ -11747,6 +11798,7 @@ __name(looksLikeMeaningfulBackendMessage, "looksLikeMeaningfulBackendMessage");
|
|
|
11747
11798
|
function resolveMessage(code, backendMessage) {
|
|
11748
11799
|
const mapped = CODE_MESSAGES[code];
|
|
11749
11800
|
const backend = typeof backendMessage === "string" ? backendMessage.trim() : "";
|
|
11801
|
+
if (code === McpErrorCode.CREDIT_ADMISSION_UNAVAILABLE && mapped) return mapped;
|
|
11750
11802
|
if (mapped && backend && looksLikeMeaningfulBackendMessage(backend, mapped)) {
|
|
11751
11803
|
return `${mapped} (Detail: ${backend})`;
|
|
11752
11804
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productmaker/mcp",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.2",
|
|
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.",
|