@productmaker/mcp 2.9.4 → 2.10.1

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <meta name="color-scheme" content="light dark" />
7
- <title>Carga segura para Meta · ProductMaker</title>
7
+ <title>Upload media · ProductMaker</title>
8
8
  <style>
9
9
  :root {
10
10
  color-scheme: light dark;
@@ -1011,7 +1011,7 @@
1011
1011
  async function initializeStandardHost() {
1012
1012
  try {
1013
1013
  const result = await rpcRequest("ui/initialize", {
1014
- appInfo: { name: "ProductMaker Meta upload", version: "1.0.0" },
1014
+ appInfo: { name: "ProductMaker media upload", version: "1.0.0" },
1015
1015
  appCapabilities: {
1016
1016
  availableDisplayModes: ["inline", "fullscreen"],
1017
1017
  },
@@ -1179,6 +1179,15 @@
1179
1179
  const mediaKind = candidate.mediaKind;
1180
1180
  const assetRole = candidate.assetRole;
1181
1181
  const expiresAt = boundedString(candidate.expiresAt, 100);
1182
+ const checkToolName = [
1183
+ "check_media_upload",
1184
+ "check_meta_media_upload",
1185
+ ].includes(candidate.checkToolName)
1186
+ ? candidate.checkToolName
1187
+ : "check_meta_media_upload";
1188
+ const resolveEndpoint =
1189
+ boundedString(candidate.resolveEndpoint, 200) ||
1190
+ "/api/meta-upload/resolve";
1182
1191
  if (!sessionId || !["image", "video", "mixed"].includes(mediaKind))
1183
1192
  return null;
1184
1193
  if (!["media", "thumbnail"].includes(assetRole)) return null;
@@ -1196,6 +1205,8 @@
1196
1205
  assetRole,
1197
1206
  maxFiles: candidate.maxFiles,
1198
1207
  expiresAt,
1208
+ checkToolName,
1209
+ resolveEndpoint,
1199
1210
  };
1200
1211
  }
1201
1212
 
@@ -1534,7 +1545,7 @@
1534
1545
  attempts: 0,
1535
1546
  error: "",
1536
1547
  failureStage: "",
1537
- stagingAssetId: "",
1548
+ assetId: "",
1538
1549
  previewUrl: "",
1539
1550
  };
1540
1551
  }
@@ -1832,7 +1843,7 @@
1832
1843
  renderItems();
1833
1844
  },
1834
1845
  );
1835
- item.stagingAssetId = resolved.stagingAssetId;
1846
+ item.assetId = resolved.assetId;
1836
1847
  return;
1837
1848
  } catch (error) {
1838
1849
  if (error && error.message === "session_expired") throw error;
@@ -1853,14 +1864,16 @@
1853
1864
  const uploadPage = new URL(state.session.uploadPageUrl);
1854
1865
  if (!safeUploadPageUrl(uploadPage))
1855
1866
  throw new Error("unsafe_upload_page");
1856
- const token = uploadPage.searchParams.get("token");
1867
+ const token =
1868
+ uploadPage.searchParams.get("token") ||
1869
+ new URLSearchParams(uploadPage.hash.slice(1)).get("token");
1857
1870
  if (!token) {
1858
1871
  const error = new Error("missing_token");
1859
1872
  error.safeStage = "resolve";
1860
1873
  throw error;
1861
1874
  }
1862
1875
  const resolveUrl = new URL(
1863
- "/api/meta-upload/resolve",
1876
+ state.session.resolveEndpoint,
1864
1877
  uploadPage.origin,
1865
1878
  );
1866
1879
  const response = await fetch(resolveUrl.toString(), {
@@ -1888,14 +1901,17 @@
1888
1901
  const body = await response.json();
1889
1902
  if (!isRecord(body)) throw new Error("invalid_resolve_response");
1890
1903
  const uploadUrl = boundedString(body.uploadUrl, 3000);
1891
- const stagingAssetId = boundedString(body.stagingAssetId, 300);
1904
+ const assetId = boundedString(
1905
+ body.assetId || body.stagingAssetId,
1906
+ 300,
1907
+ );
1892
1908
  const parsedUploadUrl = new URL(uploadUrl);
1893
- if (!safeWebProtocol(parsedUploadUrl) || !stagingAssetId) {
1909
+ if (!safeWebProtocol(parsedUploadUrl) || !assetId) {
1894
1910
  const error = new Error("invalid_resolve_response");
1895
1911
  error.safeStage = "resolve";
1896
1912
  throw error;
1897
1913
  }
1898
- return { uploadUrl: parsedUploadUrl.toString(), stagingAssetId };
1914
+ return { uploadUrl: parsedUploadUrl.toString(), assetId };
1899
1915
  }
1900
1916
 
1901
1917
  function createClientUuid() {
@@ -2178,7 +2194,7 @@
2178
2194
  const requestedSessionId = state.session.sessionId;
2179
2195
  setSessionStatus("Comprobando el staging privado…", "neutral");
2180
2196
  try {
2181
- const result = await callReadOnlyTool("check_meta_media_upload", {
2197
+ const result = await callReadOnlyTool(state.session.checkToolName, {
2182
2198
  sessionId: requestedSessionId,
2183
2199
  });
2184
2200
  if (
@@ -2239,7 +2255,9 @@
2239
2255
  }
2240
2256
 
2241
2257
  async function callReadOnlyTool(name, args) {
2242
- if (name !== "check_meta_media_upload") {
2258
+ if (
2259
+ !["check_media_upload", "check_meta_media_upload"].includes(name)
2260
+ ) {
2243
2261
  throw new Error("tool_not_allowed");
2244
2262
  }
2245
2263
  const bridge = openAiBridge();
@@ -2286,7 +2304,10 @@
2286
2304
 
2287
2305
  function parseStatusResult(result, expectedSessionId) {
2288
2306
  const payload = resultPayload(result);
2289
- if (payload.sessionId !== expectedSessionId)
2307
+ if (
2308
+ state.session.checkToolName === "check_meta_media_upload" &&
2309
+ payload.sessionId !== expectedSessionId
2310
+ )
2290
2311
  throw new Error("status_session_mismatch");
2291
2312
  const status = payload.status;
2292
2313
  if (!["pending", "uploaded"].includes(status))
@@ -2294,10 +2315,13 @@
2294
2315
  const assets = Array.isArray(payload.assets)
2295
2316
  ? payload.assets.slice(0, MAX_FILES).flatMap((asset) => {
2296
2317
  if (!isRecord(asset)) return [];
2297
- const stagingAssetId = boundedString(asset.stagingAssetId, 300);
2318
+ const assetId = boundedString(
2319
+ asset.assetId || asset.stagingAssetId,
2320
+ 300,
2321
+ );
2298
2322
  const mediaKind = asset.mediaKind;
2299
- return stagingAssetId && ["image", "video"].includes(mediaKind)
2300
- ? [{ stagingAssetId, mediaKind }]
2323
+ return assetId && ["image", "video"].includes(mediaKind)
2324
+ ? [{ assetId, mediaKind }]
2301
2325
  : [];
2302
2326
  })
2303
2327
  : [];
@@ -2322,7 +2346,7 @@
2322
2346
  : null;
2323
2347
  if (inferredMediaKind) {
2324
2348
  assets.push({
2325
- stagingAssetId: legacyStagingAssetId,
2349
+ assetId: legacyStagingAssetId,
2326
2350
  mediaKind: inferredMediaKind,
2327
2351
  });
2328
2352
  } else {
@@ -2344,11 +2368,13 @@
2344
2368
  setPickerAvailability();
2345
2369
  renderCompletionAction();
2346
2370
  const assets = state.assets
2347
- .map(
2348
- (asset) => `${asset.mediaKind} asset_id ${asset.stagingAssetId}`,
2349
- )
2371
+ .map((asset) => `${asset.mediaKind} asset_id ${asset.assetId}`)
2350
2372
  .join(", ");
2351
- const message = `The ProductMaker upload is complete. Continue my previous request using these uploaded assets: ${assets}. Do not ask me to upload them again. Do not publish anything until you have asked me for the Meta portfolio, ad account, and Facebook Page.`;
2373
+ const metaGuard =
2374
+ state.session.checkToolName === "check_meta_media_upload"
2375
+ ? " Do not publish anything until you have asked me for the Meta portfolio, ad account, and Facebook Page."
2376
+ : "";
2377
+ const message = `The ProductMaker upload is complete. Continue my previous request using these uploaded assets: ${assets}. Do not ask me to upload them again.${metaGuard}`;
2352
2378
  try {
2353
2379
  const bridge = openAiBridge();
2354
2380
  if (bridge && typeof bridge.sendFollowUpMessage === "function") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@productmaker/mcp",
3
- "version": "2.9.4",
3
+ "version": "2.10.1",
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.",