@wix/mcp 1.0.86 → 1.0.88

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.
@@ -71552,6 +71552,7 @@ function rethrowIfUnauthorized(error2) {
71552
71552
 
71553
71553
  // src/config/api-request-rules.ts
71554
71554
  var ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
71555
+ var WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
71555
71556
 
71556
71557
  // src/config/default-config.ts
71557
71558
  var AGENT_GOAL = dedent_default`
@@ -71652,7 +71653,7 @@ var SITE_CREATION_COPY = {
71652
71653
  var SITE_GUIDANCE = dedent_default`
71653
71654
  A new-site request has two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
71654
71655
 
71655
- One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. Send them to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
71656
+ One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. For a full agentic flow, read the recipe first and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it walks you through creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply (you can't reach the file bytes, or something fails), fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
71656
71657
 
71657
71658
  Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
71658
71659
  If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
@@ -71711,18 +71712,56 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
71711
71712
  siteId?: string;
71712
71713
  method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
71713
71714
  url: string;
71715
+ // Plain object → JSON. A string is sent verbatim (set your own Content-Type,
71716
+ // e.g. multipart/form-data). A Uint8Array/ArrayBuffer is sent as raw bytes
71717
+ // for binary uploads (set your own Content-Type).
71714
71718
  body?: unknown;
71715
71719
  headers?: Record<string, string>;
71720
+ // "base64" returns the response body as a base64 string (data), with
71721
+ // encoding: "base64" on the result — use it for binary downloads (zip,
71722
+ // image, pdf); decoding those as text corrupts them. Binary content types
71723
+ // are returned as base64 automatically even without this. Decode, edit and
71724
+ // re-upload binary WITHIN this script and return only a small summary. If you
71725
+ // must return the bytes, return the wix.request response object itself (so
71726
+ // encoding: "base64" is preserved and it isn't truncated); a bare base64
71727
+ // string you return is treated as plain text and may be truncated.
71728
+ responseType?: "base64";
71716
71729
  }
71717
71730
  interface WixResponse<T = unknown> {
71718
71731
  status: number;
71719
71732
  data: T;
71733
+ encoding?: "base64";
71720
71734
  json(): Promise<T>;
71721
71735
  }
71722
71736
  declare const wix: {
71723
71737
  request<T = unknown>(options: WixRequestOptions): Promise<WixResponse<T>>;
71738
+ // Build a multipart/form-data body from files (defaults to the \`files\`
71739
+ // global). Each file becomes a part named fieldName (default "files") with
71740
+ // its path as the filename. Pass body + contentType to wix.request.
71741
+ multipart(
71742
+ files?: Array<{ path: string; content: string; contentType?: string }>,
71743
+ options?: { fieldName?: string }
71744
+ ): { body: string; contentType: string };
71724
71745
  };
71725
71746
  declare const siteId: string | undefined;
71747
+ // Files from the ExecuteWixAPI \`files\` param (raw content, no escaping).
71748
+ declare const files: Array<{ path: string; content: string }>;
71749
+ \`\`\`
71750
+
71751
+ FILE UPLOADS: pass file bodies via the \`files\` param (not inside \`code\` — no escaping), then build the multipart body with \`wix.multipart()\`:
71752
+ \`\`\`javascript
71753
+ // files param: "=== FILE: index.html ===\\n<!doctype html>...\\n=== FILE: app.js ===\\nconsole.log(1)"
71754
+ async () => {
71755
+ const mp = wix.multipart(); // parts named "files", filename = each path
71756
+ const res = await wix.request({
71757
+ scope: "account",
71758
+ method: "POST",
71759
+ url: "https://www.wixapis.com/.../upload",
71760
+ headers: { "Content-Type": mp.contentType },
71761
+ body: mp.body
71762
+ });
71763
+ return res.data;
71764
+ }
71726
71765
  \`\`\`
71727
71766
  `;
71728
71767
  var EXECUTE_WIX_API_WQL = dedent_default`
@@ -71855,6 +71894,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
71855
71894
  ReadFullDocsArticle: dedent_default`
71856
71895
  Fetches the full Wix docs article or method article with code examples for using the method.
71857
71896
  Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
71897
+ Take the URL from the user's message or an earlier tool result. To reach an article you have no URL for, search or browse the docs first.
71858
71898
  For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
71859
71899
  ${reminder}
71860
71900
  `,
@@ -71987,7 +72027,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
71987
72027
  `,
71988
72028
  "import-claude-design-from-url": dedent_default`
71989
72029
  Import a design created in Claude's design tool into Wix. Takes the signed claudeusercontent.com URL Claude Design produces for its self-contained HTML bundle (all images, fonts, and styles inlined); any other host is rejected. Creates a live Wix-hosted site and returns its URL.
71990
- NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool: send the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
72030
+ NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
71991
72031
  `,
71992
72032
  RunWixCliCommand: dedent_default`
71993
72033
  Executes Wix CLI commands for Wix app development and management.
@@ -72414,7 +72454,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72414
72454
  CreateWixBusinessGuide: dedent_default`
72415
72455
  Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
72416
72456
  Call this ONLY when the user explicitly asks for a headless site, a Wix Classic Editor site, or manual/advanced account/API-based site creation — these don't need the site's purpose first. For normal site-creation ${SITE_CREATION_COPY.normalCreationRoute.nonWidget}; for a specific template id, call \`CreateSiteFromTemplate\`.
72417
- Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool — send them to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
72457
+ Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
72418
72458
 
72419
72459
  ## What This Tool Contains
72420
72460
 
@@ -73013,7 +73053,10 @@ var paramDescriptions = {
73013
73053
  ARRAY_QUERY_PARAMS_RULE
73014
73054
  ].join("\n"),
73015
73055
  method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
73016
- body: 'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
73056
+ body: [
73057
+ 'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
73058
+ WQL_FILTER_RULE
73059
+ ].join("\n"),
73017
73060
  reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
73018
73061
  sourceDocUrl: [
73019
73062
  "The URL of the documentation or recipe where you found this API endpoint.",
@@ -73337,15 +73380,17 @@ Failed to fetch content: ${errorMsg}`
73337
73380
  const baseContentsPromise = Promise.all(
73338
73381
  baseDocsWithoutRecipes.map(fetchDoc)
73339
73382
  );
73340
- const skillsContentPromise = getSkillsByPortal(httpClient, {
73383
+ const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient, {
73341
73384
  portalId: REST_PORTAL_ID,
73342
73385
  ...repo && { repo },
73343
73386
  ...commitHash && { commitHash },
73344
- ...skillsTags && skillsTags.length > 0 && { tags: skillsTags }
73387
+ tags: skillsTags
73345
73388
  }).catch((err) => {
73346
73389
  console.error("[WixREADME] Failed to fetch skills by portal:", err);
73347
73390
  return null;
73348
- });
73391
+ }) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
73392
+ (doc) => doc?.text ?? null
73393
+ );
73349
73394
  const filter = {};
73350
73395
  if (siteId) filter.siteId = siteId;
73351
73396
  else if (siteName) filter.siteName = siteName;
@@ -85253,6 +85298,14 @@ var EMPTY_COMPLETION_RESULT = {
85253
85298
 
85254
85299
  // src/tool-utils.ts
85255
85300
  var REST_METHOD_CONTRACT_RETRY_HINT = "Before retrying, make sure you have everything needed for a correct call: the right endpoint URL, HTTP method, request body shape, and response shape. Use the SearchWixRESTDocumentation tool or BrowseWixRESTDocsMenu tool to find the correct method or relevant related articles, the ReadFullDocsArticle tool to read the method description and all code examples, and the SearchWixAPISpec tool for precise field names and schema details.";
85301
+ var SINGLE_OPERATOR_PER_FIELD_HINT = 'WQL takes one operator per field object. Split the conditions into separate expressions under the matching logical operator \u2014 `{"$and": [{"field": {"$gte": ...}}, {"field": {"$lte": ...}}]}` \u2014 and retry without re-searching the docs.';
85302
+ var FIELD_CAPABILITIES_HINT = "This endpoint declares its filterable and sortable fields with their operators. Read the map with SearchWixAPISpec (`queryMethodData.queryFieldsCapabilitiesMap`, or `searchMethodData.searchFieldsCapabilitiesMap` on search methods) and use only what it lists; otherwise fetch a bounded page and filter or sort the results yourself.";
85303
+ var getRetryHint = (errorDetails) => {
85304
+ if (!/Filter contains unsupported operator/i.test(errorDetails)) {
85305
+ return REST_METHOD_CONTRACT_RETRY_HINT;
85306
+ }
85307
+ return /"operator":"\{/.test(errorDetails) ? SINGLE_OPERATOR_PER_FIELD_HINT : FIELD_CAPABILITIES_HINT;
85308
+ };
85256
85309
  var DEFAULT_OPENAI_SECURITY_SCHEMES = [
85257
85310
  { type: "oauth2", scopes: ["offline_access"] }
85258
85311
  ];
@@ -85279,7 +85332,7 @@ var buildErrorMessage = ({
85279
85332
  ].filter((str) => !!str).join("\n");
85280
85333
  return `${baseMessage}
85281
85334
 
85282
- ${REST_METHOD_CONTRACT_RETRY_HINT}`;
85335
+ ${getRetryHint(String(errorDetails))}`;
85283
85336
  };
85284
85337
  var handleWixAPIResponse = async (response) => {
85285
85338
  const requestId = response.headers?.["x-wix-request-id"];
@@ -35867,6 +35867,14 @@ var EMPTY_COMPLETION_RESULT = {
35867
35867
 
35868
35868
  // src/tool-utils.ts
35869
35869
  var REST_METHOD_CONTRACT_RETRY_HINT = "Before retrying, make sure you have everything needed for a correct call: the right endpoint URL, HTTP method, request body shape, and response shape. Use the SearchWixRESTDocumentation tool or BrowseWixRESTDocsMenu tool to find the correct method or relevant related articles, the ReadFullDocsArticle tool to read the method description and all code examples, and the SearchWixAPISpec tool for precise field names and schema details.";
35870
+ var SINGLE_OPERATOR_PER_FIELD_HINT = 'WQL takes one operator per field object. Split the conditions into separate expressions under the matching logical operator \u2014 `{"$and": [{"field": {"$gte": ...}}, {"field": {"$lte": ...}}]}` \u2014 and retry without re-searching the docs.';
35871
+ var FIELD_CAPABILITIES_HINT = "This endpoint declares its filterable and sortable fields with their operators. Read the map with SearchWixAPISpec (`queryMethodData.queryFieldsCapabilitiesMap`, or `searchMethodData.searchFieldsCapabilitiesMap` on search methods) and use only what it lists; otherwise fetch a bounded page and filter or sort the results yourself.";
35872
+ var getRetryHint = (errorDetails) => {
35873
+ if (!/Filter contains unsupported operator/i.test(errorDetails)) {
35874
+ return REST_METHOD_CONTRACT_RETRY_HINT;
35875
+ }
35876
+ return /"operator":"\{/.test(errorDetails) ? SINGLE_OPERATOR_PER_FIELD_HINT : FIELD_CAPABILITIES_HINT;
35877
+ };
35870
35878
  var DEFAULT_OPENAI_SECURITY_SCHEMES = [
35871
35879
  { type: "oauth2", scopes: ["offline_access"] }
35872
35880
  ];
@@ -35893,7 +35901,7 @@ var buildErrorMessage = ({
35893
35901
  ].filter((str) => !!str).join("\n");
35894
35902
  return `${baseMessage}
35895
35903
 
35896
- ${REST_METHOD_CONTRACT_RETRY_HINT}`;
35904
+ ${getRetryHint(String(errorDetails))}`;
35897
35905
  };
35898
35906
  var handleWixAPIResponse = async (response) => {
35899
35907
  const requestId = response.headers?.["x-wix-request-id"];
@@ -37160,6 +37168,7 @@ function rethrowIfUnauthorized(error2) {
37160
37168
 
37161
37169
  // src/config/api-request-rules.ts
37162
37170
  var ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
37171
+ var WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
37163
37172
 
37164
37173
  // src/config/default-config.ts
37165
37174
  var AGENT_GOAL = dedent_default`
@@ -37260,7 +37269,7 @@ var SITE_CREATION_COPY = {
37260
37269
  var SITE_GUIDANCE = dedent_default`
37261
37270
  A new-site request has two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
37262
37271
 
37263
- One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. Send them to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
37272
+ One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. For a full agentic flow, read the recipe first and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it walks you through creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply (you can't reach the file bytes, or something fails), fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
37264
37273
 
37265
37274
  Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
37266
37275
  If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
@@ -37319,18 +37328,56 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
37319
37328
  siteId?: string;
37320
37329
  method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
37321
37330
  url: string;
37331
+ // Plain object → JSON. A string is sent verbatim (set your own Content-Type,
37332
+ // e.g. multipart/form-data). A Uint8Array/ArrayBuffer is sent as raw bytes
37333
+ // for binary uploads (set your own Content-Type).
37322
37334
  body?: unknown;
37323
37335
  headers?: Record<string, string>;
37336
+ // "base64" returns the response body as a base64 string (data), with
37337
+ // encoding: "base64" on the result — use it for binary downloads (zip,
37338
+ // image, pdf); decoding those as text corrupts them. Binary content types
37339
+ // are returned as base64 automatically even without this. Decode, edit and
37340
+ // re-upload binary WITHIN this script and return only a small summary. If you
37341
+ // must return the bytes, return the wix.request response object itself (so
37342
+ // encoding: "base64" is preserved and it isn't truncated); a bare base64
37343
+ // string you return is treated as plain text and may be truncated.
37344
+ responseType?: "base64";
37324
37345
  }
37325
37346
  interface WixResponse<T = unknown> {
37326
37347
  status: number;
37327
37348
  data: T;
37349
+ encoding?: "base64";
37328
37350
  json(): Promise<T>;
37329
37351
  }
37330
37352
  declare const wix: {
37331
37353
  request<T = unknown>(options: WixRequestOptions): Promise<WixResponse<T>>;
37354
+ // Build a multipart/form-data body from files (defaults to the \`files\`
37355
+ // global). Each file becomes a part named fieldName (default "files") with
37356
+ // its path as the filename. Pass body + contentType to wix.request.
37357
+ multipart(
37358
+ files?: Array<{ path: string; content: string; contentType?: string }>,
37359
+ options?: { fieldName?: string }
37360
+ ): { body: string; contentType: string };
37332
37361
  };
37333
37362
  declare const siteId: string | undefined;
37363
+ // Files from the ExecuteWixAPI \`files\` param (raw content, no escaping).
37364
+ declare const files: Array<{ path: string; content: string }>;
37365
+ \`\`\`
37366
+
37367
+ FILE UPLOADS: pass file bodies via the \`files\` param (not inside \`code\` — no escaping), then build the multipart body with \`wix.multipart()\`:
37368
+ \`\`\`javascript
37369
+ // files param: "=== FILE: index.html ===\\n<!doctype html>...\\n=== FILE: app.js ===\\nconsole.log(1)"
37370
+ async () => {
37371
+ const mp = wix.multipart(); // parts named "files", filename = each path
37372
+ const res = await wix.request({
37373
+ scope: "account",
37374
+ method: "POST",
37375
+ url: "https://www.wixapis.com/.../upload",
37376
+ headers: { "Content-Type": mp.contentType },
37377
+ body: mp.body
37378
+ });
37379
+ return res.data;
37380
+ }
37334
37381
  \`\`\`
37335
37382
  `;
37336
37383
  var EXECUTE_WIX_API_WQL = dedent_default`
@@ -37463,6 +37510,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
37463
37510
  ReadFullDocsArticle: dedent_default`
37464
37511
  Fetches the full Wix docs article or method article with code examples for using the method.
37465
37512
  Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
37513
+ Take the URL from the user's message or an earlier tool result. To reach an article you have no URL for, search or browse the docs first.
37466
37514
  For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
37467
37515
  ${reminder}
37468
37516
  `,
@@ -37595,7 +37643,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
37595
37643
  `,
37596
37644
  "import-claude-design-from-url": dedent_default`
37597
37645
  Import a design created in Claude's design tool into Wix. Takes the signed claudeusercontent.com URL Claude Design produces for its self-contained HTML bundle (all images, fonts, and styles inlined); any other host is rejected. Creates a live Wix-hosted site and returns its URL.
37598
- NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool: send the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
37646
+ NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
37599
37647
  `,
37600
37648
  RunWixCliCommand: dedent_default`
37601
37649
  Executes Wix CLI commands for Wix app development and management.
@@ -38022,7 +38070,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
38022
38070
  CreateWixBusinessGuide: dedent_default`
38023
38071
  Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
38024
38072
  Call this ONLY when the user explicitly asks for a headless site, a Wix Classic Editor site, or manual/advanced account/API-based site creation — these don't need the site's purpose first. For normal site-creation ${SITE_CREATION_COPY.normalCreationRoute.nonWidget}; for a specific template id, call \`CreateSiteFromTemplate\`.
38025
- Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool — send them to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
38073
+ Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
38026
38074
 
38027
38075
  ## What This Tool Contains
38028
38076
 
@@ -38659,7 +38707,10 @@ var paramDescriptions = {
38659
38707
  ARRAY_QUERY_PARAMS_RULE
38660
38708
  ].join("\n"),
38661
38709
  method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
38662
- body: 'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
38710
+ body: [
38711
+ 'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
38712
+ WQL_FILTER_RULE
38713
+ ].join("\n"),
38663
38714
  reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
38664
38715
  sourceDocUrl: [
38665
38716
  "The URL of the documentation or recipe where you found this API endpoint.",
@@ -38983,15 +39034,17 @@ Failed to fetch content: ${errorMsg}`
38983
39034
  const baseContentsPromise = Promise.all(
38984
39035
  baseDocsWithoutRecipes.map(fetchDoc)
38985
39036
  );
38986
- const skillsContentPromise = getSkillsByPortal(httpClient6, {
39037
+ const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient6, {
38987
39038
  portalId: REST_PORTAL_ID,
38988
39039
  ...repo && { repo },
38989
39040
  ...commitHash && { commitHash },
38990
- ...skillsTags && skillsTags.length > 0 && { tags: skillsTags }
39041
+ tags: skillsTags
38991
39042
  }).catch((err) => {
38992
39043
  console.error("[WixREADME] Failed to fetch skills by portal:", err);
38993
39044
  return null;
38994
- });
39045
+ }) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
39046
+ (doc) => doc?.text ?? null
39047
+ );
38995
39048
  const filter = {};
38996
39049
  if (siteId) filter.siteId = siteId;
38997
39050
  else if (siteName) filter.siteName = siteName;
@@ -52009,12 +52062,12 @@ function addImportClaudeDesignTool(server, authStrategy, options) {
52009
52062
  designUrl = new URL(args.url);
52010
52063
  } catch {
52011
52064
  return errorResult(
52012
- "Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry: send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
52065
+ "Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md \u2014 it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
52013
52066
  );
52014
52067
  }
52015
52068
  if (designUrl.protocol !== "https:" || !designUrl.hostname.endsWith(CLAUDE_USER_CONTENT_HOST_SUFFIX)) {
52016
52069
  return errorResult(
52017
- "Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry: send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
52070
+ "Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md \u2014 it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
52018
52071
  );
52019
52072
  }
52020
52073
  const accountHeaders = await authStrategy.getAccountAuthHeaders();
@@ -53072,12 +53125,31 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
53072
53125
  reportBi?.({
53073
53126
  originalLength: typeof data.result === "string" ? data.result.length : JSON.stringify(data.result)?.length
53074
53127
  });
53128
+ const base64Text = base64PayloadText(data.result);
53129
+ if (base64Text !== null) {
53130
+ if (base64Text.length <= MAX_ALLOWED_RESPONSE_CHARS) {
53131
+ return { content: [{ type: "text", text: base64Text }] };
53132
+ }
53133
+ const approxKb = Math.ceil(base64Text.length / 1024).toLocaleString();
53134
+ const limitKb = Math.floor(
53135
+ MAX_ALLOWED_RESPONSE_CHARS / 1024
53136
+ ).toLocaleString();
53137
+ return executeErrorResult(
53138
+ `Binary (base64) result is ~${approxKb} KB, too large to return intact (limit ~${limitKb} KB); truncating it would corrupt the base64. Process the bytes inside your ExecuteWixAPI script \u2014 decode, edit, and re-upload in the same call \u2014 and return only a small summary.`
53139
+ );
53140
+ }
53075
53141
  return {
53076
53142
  content: [
53077
53143
  { type: "text", text: truncateResponse(data.result, maxResponseSize) }
53078
53144
  ]
53079
53145
  };
53080
53146
  }
53147
+ function base64PayloadText(result) {
53148
+ if (result !== null && typeof result === "object" && result.encoding === "base64" && typeof result.data === "string") {
53149
+ return JSON.stringify(result);
53150
+ }
53151
+ return null;
53152
+ }
53081
53153
  function addExecuteTool(server, options) {
53082
53154
  const {
53083
53155
  codeModeBaseUrl,
@@ -53109,6 +53181,14 @@ function addExecuteTool(server, options) {
53109
53181
  visitor ? "Whether this code creates, updates, deletes, publishes, imports, uploads, or otherwise mutates site data on the visitor\u2019s behalf. Set this to true for create/update/delete/bulk create/import/upload calls even if the reason is inspection, verification, or response-shape discovery. Read-only GET/query/list/search calls can use false." : "Whether this code creates, updates, deletes, publishes, installs, imports, uploads, or otherwise mutates Wix data or site/account state. Set this to true for create/update/delete/bulk create/import/upload calls even if the reason is inspection, verification, or response-shape discovery. Read-only GET/query/list/search calls can use false."
53110
53182
  ),
53111
53183
  sourceDocUrls: external_exports.array(external_exports.string()).describe(d2.sourceDocUrls),
53184
+ files: external_exports.string().optional().describe(
53185
+ [
53186
+ "Optional bundle of raw file contents for uploads, so file bytes never go through the `code` JavaScript (no escaping, no string-literal/`${}`/backtick pitfalls).",
53187
+ "Format: one or more sections, each a line `=== FILE: <path> ===` on its own, followed by that file's raw text content; `<path>` is the path relative to the site root (e.g. `index.html`, `assets/app.js`). Example: `=== FILE: index.html ===\\n<!doctype html>...\\n=== FILE: assets/app.js ===\\nconsole.log(1)`.",
53188
+ 'In `code`, the parsed files are the `files` global (array of `{ path, content }`), and `wix.multipart(files)` returns `{ body, contentType }` for a `multipart/form-data` upload \u2014 e.g. `const mp = wix.multipart(); await wix.request({ scope: "account", method: "POST", url, headers: { "Content-Type": mp.contentType }, body: mp.body });`.',
53189
+ "Text files only; for binary assets pass bytes as a base64 request body instead. A file whose content itself contains a line exactly like the delimiter is not supported."
53190
+ ].join(" ")
53191
+ ),
53112
53192
  // Visitor mode takes an agent-supplied token and pins the site; account/site
53113
53193
  // mode lets the agent pick the site.
53114
53194
  ...visitor ? {
@@ -53123,7 +53203,7 @@ function addExecuteTool(server, options) {
53123
53203
  },
53124
53204
  { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
53125
53205
  async (rawArgs, extra) => {
53126
- const { code, reason, hasMutations, sourceDocUrls, visitorToken } = rawArgs;
53206
+ const { code, reason, hasMutations, sourceDocUrls, visitorToken, files } = rawArgs;
53127
53207
  const siteId = visitor ? visitor.siteId : rawArgs.siteId;
53128
53208
  logger2.log(
53129
53209
  `[ExecuteWixAPI]${visitor ? " (visitor)" : ""} Executing code (${code.length} chars), siteId=${siteId ?? "none"}, hasMutations=${hasMutations}, sourceDocUrls=${JSON.stringify(sourceDocUrls)}, reason="${reason}"`
@@ -53168,7 +53248,8 @@ function addExecuteTool(server, options) {
53168
53248
  siteToken: visitor ? visitorToken : siteHeaders?.Authorization,
53169
53249
  accountToken: visitor ? visitorToken : accountHeaders?.Authorization,
53170
53250
  accountId: accountHeaders?.["wix-account-id"],
53171
- siteAuthContext
53251
+ siteAuthContext,
53252
+ ...files ? { files } : {}
53172
53253
  },
53173
53254
  visitor ? visitorToken : accountHeaders?.Authorization ?? siteHeaders?.Authorization,
53174
53255
  codeModeFetch