@wix/mcp 1.0.93 → 1.0.95

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.
Files changed (84) hide show
  1. package/README.md +2 -2
  2. package/build/bin-standalone.js +1200 -455
  3. package/build/cjs/index.cjs +3237 -1264
  4. package/build/cjs/toolkit.cjs +2177 -469
  5. package/build/dts/api-call/headless-release.d.ts +56 -0
  6. package/build/dts/api-call/headless-release.js +135 -0
  7. package/build/dts/api-call/index.d.ts +9 -1
  8. package/build/dts/api-call/index.js +19 -10
  9. package/build/dts/api-call/site-files.d.ts +42 -0
  10. package/build/dts/api-call/site-files.js +290 -0
  11. package/build/dts/api-call/upload-headless-website-files.d.ts +118 -0
  12. package/build/dts/api-call/upload-headless-website-files.js +624 -0
  13. package/build/dts/api-call/upload-image-tool.d.ts +2 -0
  14. package/build/dts/api-call/upload-image-tool.js +8 -4
  15. package/build/dts/bin.d.ts +1 -1
  16. package/build/dts/bin.js +4 -5
  17. package/build/dts/code-mode/attachments.js +1 -1
  18. package/build/dts/code-mode/index.d.ts +6 -1
  19. package/build/dts/code-mode/index.js +47 -13
  20. package/build/dts/code-mode/truncate-response.js +5 -1
  21. package/build/dts/config/default-config.d.ts +35 -9
  22. package/build/dts/config/default-config.js +348 -207
  23. package/build/dts/config/file-params.d.ts +22 -0
  24. package/build/dts/config/file-params.js +24 -0
  25. package/build/dts/config/param-descriptions.d.ts +14 -2
  26. package/build/dts/config/param-descriptions.js +34 -15
  27. package/build/dts/constants.d.ts +1 -0
  28. package/build/dts/constants.js +1 -0
  29. package/build/dts/docs/docs.d.ts +16 -3
  30. package/build/dts/docs/docs.js +211 -39
  31. package/build/dts/docs/fetch-article.d.ts +21 -0
  32. package/build/dts/docs/fetch-article.js +70 -5
  33. package/build/dts/docs/get-to-know.d.ts +7 -2
  34. package/build/dts/docs/get-to-know.js +37 -15
  35. package/build/dts/docs/mintlify-docs.d.ts +121 -0
  36. package/build/dts/docs/mintlify-docs.js +391 -0
  37. package/build/dts/docs/semanticSearch.d.ts +2 -1
  38. package/build/dts/docs/semanticSearch.js +14 -7
  39. package/build/dts/docs/start-deploy-website.d.ts +7 -6
  40. package/build/dts/docs/start-deploy-website.js +13 -8
  41. package/build/dts/docs/start-headless-build.d.ts +17 -0
  42. package/build/dts/docs/start-headless-build.js +60 -0
  43. package/build/dts/graphql/index.js +3 -1
  44. package/build/dts/import-claude-design-tool/index.js +2 -2
  45. package/build/dts/index.d.ts +3 -2
  46. package/build/dts/index.js +3 -2
  47. package/build/dts/infra/redact-personal-data.d.ts +4 -0
  48. package/build/dts/infra/redact-personal-data.js +79 -0
  49. package/build/dts/site-widget-tools/constants.d.ts +49 -1
  50. package/build/dts/site-widget-tools/constants.js +64 -7
  51. package/build/dts/site-widget-tools/index.d.ts +1 -0
  52. package/build/dts/site-widget-tools/index.js +1 -0
  53. package/build/dts/site-widget-tools/pick-images-tool/index.d.ts +14 -0
  54. package/build/dts/site-widget-tools/pick-images-tool/index.js +138 -0
  55. package/build/dts/site-widget-tools/search-site-templates-tool/index.js +33 -9
  56. package/build/dts/site-widget-tools/site-builder-tool/index.js +22 -2
  57. package/build/dts/site-widget-tools/site-creation-tool/index.d.ts +7 -1
  58. package/build/dts/site-widget-tools/site-creation-tool/index.js +22 -51
  59. package/build/dts/site-widget-tools/suggested-domain-tool/index.js +6 -3
  60. package/build/dts/support/index.d.ts +4 -0
  61. package/build/dts/support/index.js +13 -7
  62. package/build/dts/toolkit-entry.d.cts +19 -12
  63. package/build/dts/toolkit-entry.d.ts +19 -12
  64. package/build/dts/toolkit.d.ts +2 -2
  65. package/build/dts/toolkit.js +23 -7
  66. package/build/dts/wix-mcp-server.d.ts +11 -0
  67. package/build/dts/wix-mcp-server.js +28 -6
  68. package/build/dts/wixel/constants.d.ts +8 -1
  69. package/build/dts/wixel/constants.js +8 -1
  70. package/build/dts/wixel/index.d.ts +1 -1
  71. package/build/dts/wixel/index.js +2 -2
  72. package/build/dts/wixel/wixel-a2a-client.d.ts +83 -0
  73. package/build/dts/wixel/wixel-a2a-client.js +166 -0
  74. package/build/dts/wixel/wixel-bi.d.ts +2 -1
  75. package/build/dts/wixel/wixel-bi.js +2 -1
  76. package/build/dts/wixel/{external-agent-api.d.ts → wixel-session-entries.d.ts} +11 -33
  77. package/build/dts/wixel/{external-agent-api.js → wixel-session-entries.js} +33 -54
  78. package/build/dts/wixel/wixel-session-tools.d.ts +21 -26
  79. package/build/dts/wixel/wixel-session-tools.js +494 -599
  80. package/build/esm/index.js +3335 -1376
  81. package/build/esm/toolkit.js +2273 -565
  82. package/package.json +4 -4
  83. package/build/dts/docs/create-site-guide.d.ts +0 -3
  84. package/build/dts/docs/create-site-guide.js +0 -109
@@ -71066,6 +71066,8 @@ var runSemanticSearch = async (toolName, toolParams, maxResults = 20, rerank = f
71066
71066
  kbNames.push("VELO_DOCS_KB_ID", "VELO_METHODS_KB_ID");
71067
71067
  } else if (toolName === "CLI") {
71068
71068
  kbNames.push("CLI_KB_ID");
71069
+ } else if (toolName === "HELP_CENTER") {
71070
+ kbNames.push("HELP_CENTER_KB_ID");
71069
71071
  }
71070
71072
  logger2.log(
71071
71073
  `[SemanticSearch] Tool: ${toolName}, KBs: [${kbNames.join(", ")}], Query: "${toolParams.searchTerm}"`
@@ -71098,9 +71100,9 @@ var runSemanticSearch = async (toolName, toolParams, maxResults = 20, rerank = f
71098
71100
  );
71099
71101
  return data?.results;
71100
71102
  };
71101
- var runPlatformizedSemanticSearch = async (toolName, searchTerm, maxResults = 20, linesInEachResult, extraDocumentTypes) => {
71103
+ var runPlatformizedSemanticSearch = async (toolName, searchTerm, maxResults = 20, linesInEachResult, extraDocumentTypes, documentTypesOverride) => {
71102
71104
  const startTime = Date.now();
71103
- const documentTypes = extraDocumentTypes?.length ? [toolName, ...extraDocumentTypes] : void 0;
71105
+ const documentTypes = documentTypesOverride?.length ? documentTypesOverride : extraDocumentTypes?.length ? [toolName, ...extraDocumentTypes] : void 0;
71104
71106
  logger2.log(
71105
71107
  `[SemanticSearch/v2] Tool: ${documentTypes ? documentTypes.join("+") : toolName}, Query: "${searchTerm}"`
71106
71108
  );
@@ -71144,15 +71146,17 @@ var runSemanticSearchAndFormat = async ({
71144
71146
  rerank,
71145
71147
  linesInEachResult,
71146
71148
  usePlatformizedSearch = true,
71147
- extraDocumentTypes
71149
+ extraDocumentTypes,
71150
+ documentTypes
71148
71151
  }) => {
71149
- if (usePlatformizedSearch) {
71152
+ if (usePlatformizedSearch || documentTypes?.length) {
71150
71153
  return runPlatformizedSemanticSearch(
71151
71154
  toolName,
71152
71155
  toolParams.searchTerm,
71153
71156
  maxResults,
71154
71157
  linesInEachResult,
71155
- extraDocumentTypes
71158
+ extraDocumentTypes,
71159
+ documentTypes
71156
71160
  );
71157
71161
  } else {
71158
71162
  const results = await runSemanticSearch(
@@ -71168,6 +71172,7 @@ var runSemanticSearchAndFormat = async ({
71168
71172
  // src/constants.ts
71169
71173
  var RAW_DOCS_API_URL = "https://dev.wix.com/rawdocs/api";
71170
71174
  var GET_ARTICLE_CONTENT_URL = `${RAW_DOCS_API_URL}/get-article-content`;
71175
+ var GET_SOURCE_CONTENT_URL = `${RAW_DOCS_API_URL}/get-source-content`;
71171
71176
  var PORTAL_INDEX_URL = `${RAW_DOCS_API_URL}/portal-index`;
71172
71177
  var DOCS_API_BASE_URL = "https://dev.wix.com/docs/api/v1";
71173
71178
  var GET_SKILLS_BY_PORTAL_URL = `${DOCS_API_BASE_URL}/docs-web-app/menu-node/get-skills-by-portal`;
@@ -71177,10 +71182,16 @@ var REST_PORTAL_ID = "d1972c09-74e2-4d36-a6f2-54e3310d4ad9";
71177
71182
  var RECIPES_INDEX_URL = "https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills/wix-management-recipes-index";
71178
71183
  var DOCS_URL_PREFIX = "https://dev.wix.com/docs/";
71179
71184
  var SKILLS_REGISTRY_URL = new RegExp(
71180
- "^https://(?:dev\\.wix\\.com(?:/docs)?|www\\.wix\\.com(?:/velo/reference)?)/skills(?:[/.?#]|$)"
71185
+ "^https://(?:dev\\.wix\\.com(?:/docs)?|www\\.wix\\.com(?:/velo/reference)?)/skills(?:[/.?#]|$)|^https://www\\.wix\\.com/headless/"
71181
71186
  );
71182
71187
  function isSkillsRegistryUrl(url) {
71183
- return SKILLS_REGISTRY_URL.test(url.trim());
71188
+ return SKILLS_REGISTRY_URL.test(normalizeSkillsUrl(url));
71189
+ }
71190
+ var GITHUB_SKILLS_URL = /^https:\/\/(?:www\.)?github\.com\/wix\/skills\/(?:blob|raw|tree)\/[^/]+\/skills\/([^#?]+)/;
71191
+ function normalizeSkillsUrl(url) {
71192
+ const apex = url.trim().replace(/^https:\/\/wix\.com\//, "https://www.wix.com/");
71193
+ const gh = apex.match(GITHUB_SKILLS_URL);
71194
+ return gh ? `https://www.wix.com/skills/${gh[1]}` : apex;
71184
71195
  }
71185
71196
  async function fetchSkillsRegistryPage(httpClient, url) {
71186
71197
  let data;
@@ -71278,6 +71289,40 @@ async function fetchArticleContentFromDigor(httpClient, articleUrl, mode, stripH
71278
71289
  }
71279
71290
  return articleContent;
71280
71291
  }
71292
+ function parseSourceContentUrl(url) {
71293
+ let parsed;
71294
+ try {
71295
+ parsed = new URL(url);
71296
+ } catch {
71297
+ return void 0;
71298
+ }
71299
+ if (`${parsed.origin}${parsed.pathname}` !== GET_SOURCE_CONTENT_URL) {
71300
+ return void 0;
71301
+ }
71302
+ const repo = parsed.searchParams.get("repo");
71303
+ const path10 = parsed.searchParams.get("path");
71304
+ const commitHash = parsed.searchParams.get("commitHash");
71305
+ if (!repo || !path10) return void 0;
71306
+ return commitHash ? { repo, path: path10, commitHash } : { repo, path: path10 };
71307
+ }
71308
+ async function fetchSourceContent(httpClient, repo, path10, commitHash) {
71309
+ const url = new URL(GET_SOURCE_CONTENT_URL);
71310
+ url.searchParams.set("repo", repo);
71311
+ url.searchParams.set("path", path10);
71312
+ if (commitHash) url.searchParams.set("commitHash", commitHash);
71313
+ let data;
71314
+ try {
71315
+ ({ data } = await httpClient.get(url.toString()));
71316
+ } catch (error2) {
71317
+ const { message, status } = getHttpErrorDetails(error2);
71318
+ const statusSuffix = status ? ` (status ${status})` : "";
71319
+ throw new Error(`${message}${statusSuffix}`);
71320
+ }
71321
+ if (!data?.content) {
71322
+ throw new Error("Source content is empty");
71323
+ }
71324
+ return data.content;
71325
+ }
71281
71326
  async function fetchArticleContent(httpClient, articleUrl, mode, stripHeader = false, skillsPortalUrl, repo, commitHash, fetchMcpWhiteList) {
71282
71327
  const effectiveUrl = applyPortalUrlOverride(articleUrl, skillsPortalUrl);
71283
71328
  const isOverridden = effectiveUrl !== articleUrl;
@@ -71291,7 +71336,10 @@ async function fetchArticleContent(httpClient, articleUrl, mode, stripHeader = f
71291
71336
  `[fetch] Override failed for ${effectiveUrl}, falling back to ${articleUrl}:`,
71292
71337
  error2 instanceof Error ? error2.message : error2
71293
71338
  );
71294
- content = isSkillsRegistryUrl(articleUrl) ? await fetchSkillsRegistryPage(httpClient, articleUrl) : await fetchArticleContentFromDigor(
71339
+ content = isSkillsRegistryUrl(articleUrl) ? await fetchSkillsRegistryPage(
71340
+ httpClient,
71341
+ normalizeSkillsUrl(articleUrl)
71342
+ ) : await fetchArticleContentFromDigor(
71295
71343
  httpClient,
71296
71344
  articleUrl,
71297
71345
  mode,
@@ -71299,7 +71347,10 @@ async function fetchArticleContent(httpClient, articleUrl, mode, stripHeader = f
71299
71347
  );
71300
71348
  }
71301
71349
  } else if (isSkillsRegistryUrl(articleUrl)) {
71302
- content = await fetchSkillsRegistryPage(httpClient, articleUrl);
71350
+ content = await fetchSkillsRegistryPage(
71351
+ httpClient,
71352
+ normalizeSkillsUrl(articleUrl)
71353
+ );
71303
71354
  } else if (mode === "raw") {
71304
71355
  let parsedUrl;
71305
71356
  try {
@@ -71586,56 +71637,96 @@ function rethrowIfUnauthorized(error2) {
71586
71637
  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).";
71587
71638
  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.";
71588
71639
 
71640
+ // src/config/file-params.ts
71641
+ var FILE_PARAM_CLIENTS = "OpenAI clients (ChatGPT, Codex)";
71642
+ function fileParamNote(otherwise) {
71643
+ return `${FILE_PARAM_CLIENTS} only: pass each file as you have it (attached in the chat or created in your sandbox, by its file id or path) and the client swaps it for { download_url, file_id, file_name?, mime_type? } before the call reaches Wix. No other client does this swap, so elsewhere a path or file:// URL here fails at once; leave this out and ${otherwise}.`;
71644
+ }
71645
+
71646
+ // src/site-widget-tools/constants.ts
71647
+ var WIX_BUSINESS_FEATURES = "a store, bookings or appointments, rentals, events and tickets, a restaurant menu with online orders or reservations, a blog, a portfolio, pricing plans and memberships, donations, Wix Forms, members and login, a CMS, payments";
71648
+ var SITE_CREATION_DEFAULT_ACTIONS = "add products, set up bookings, and adjust your content";
71649
+ var SITE_CREATION_CUSTOM_ACTIONS_GUIDANCE = `2\u20133 specific, high-value setup actions for the site's industry, written as a comma-separated phrase (it slots into "\u2026ask me to ___ right here in the chat"). Use the following domain patterns as guidance:
71650
+ * E-commerce / Retail: "add products, set up payment methods, and organize collections"
71651
+ * Restaurants / Food / Bakeries: "add menu items, set up online ordering, and collect table reservations"
71652
+ * Services / Fitness / Salons / Consultants: "set up booking slots, add service pricing, and manage appointments"
71653
+ * Creative / Portfolios / Photographers: "upload project galleries, feature client reviews, and customize contact forms"
71654
+ * Events / Weddings / Real Estate: "add event schedules, display listings, and manage RSVP forms"
71655
+ * General / Unspecified: "${SITE_CREATION_DEFAULT_ACTIONS}"
71656
+ If none of these patterns fit the site, infer 2\u20133 actions that suit what that kind of business would manage on its site.`;
71657
+ var SITE_BUILDER_CHOICE = {
71658
+ here: {
71659
+ label: "Build it here with me",
71660
+ pitch: "I build it in code right here, and you change anything by asking me"
71661
+ },
71662
+ editor: {
71663
+ label: "Design it in Wix's editor",
71664
+ pitch: "Wix designs a first version or you start from a template, then you edit it in Wix"
71665
+ },
71666
+ /** The editor's second step, in the widget and its reply. */
71667
+ editorStart: {
71668
+ wix: {
71669
+ label: "Let Wix design it",
71670
+ pitch: "Wix designs a first version from your description for you to edit"
71671
+ },
71672
+ template: {
71673
+ label: "Browse templates",
71674
+ pitch: "start from a ready-made design and edit it in Wix"
71675
+ }
71676
+ },
71677
+ /** Asked in chat when no widget is shown: who builds it. */
71678
+ whoQuestion: "Do you want me to build it here, so you can change anything just by asking me, or do you want to design it yourself in Wix's editor?",
71679
+ /** Asked next, only when the user chose Wix's editor. */
71680
+ editorQuestion: "Should Wix design a first version for you to edit, or do you want to start from a template?",
71681
+ /** What the widget sends as the user's message when they pick "Build it here with me". */
71682
+ hereFollowUp: "Build it here with me, in code, so I can keep changing it by asking you."
71683
+ };
71684
+
71589
71685
  // src/config/default-config.ts
71590
71686
  var AGENT_GOAL = dedent_default`
71591
- You are an agent that helps the user manage their Wix site.
71592
- Your goal is to get the user's prompt/task and execute it by using the appropriate tools eventually calling the correct Wix APIs with the correct parameters until the task is completed.
71687
+ You help the user with their Wix sites and account.
71688
+ Work out what the task needs and do it: read the Wix skills, docs and API schemas that cover it, and write and run the code that calls Wix APIs, until the task is done.
71593
71689
  `;
71690
+ var CALL_WIX_SITE_API_RECONNECT_LINE = "If the Wix MCP offers no ExecuteWixAPI at all, your Wix connection is likely an old or cached version: tell the user once to reconnect the Wix connector or restart the client, and use this tool until then.";
71691
+ var CALL_WIX_SITE_API_NO_EXECUTE_LINE = "If ExecuteWixAPI isn't in your tool list, use this tool.";
71594
71692
  var DISCOVERY_FLOWS = [
71595
- "- CONVERSATION CONTEXT BASED: find relevant docs article or API example for the user's prompt/task in the conversation context -> call API using CallWixSiteAPI() based on the docs article or API example",
71596
- "- METHOD CODE EXAMPLE BASED: BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() to get method code examples -> call API using CallWixSiteAPI() based on the method code examples",
71597
- "- FULL SCHEMA BASED: BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() -> no method code examples found -> inspect the method schema using SearchWixAPISpec or ReadFullDocsMethodSchema -> call API using CallWixSiteAPI() based on the schema"
71693
+ "- CONVERSATION CONTEXT BASED: find relevant docs article or API example for the user's prompt/task in the conversation context -> call the API with ExecuteWixAPI based on the docs article or API example",
71694
+ "- METHOD CODE EXAMPLE BASED: BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() to get method code examples -> call the API with ExecuteWixAPI based on the method code examples",
71695
+ "- FULL SCHEMA BASED: BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() -> no method code examples found -> inspect the method schema using SearchWixAPISpec or ReadFullDocsMethodSchema -> call the API with ExecuteWixAPI based on the schema"
71598
71696
  ];
71697
+ function directRouteLines(includeReadme, includeImageUploadGuidance) {
71698
+ return [
71699
+ ...includeReadme ? [
71700
+ `- **Creating a new site.** Skip the docs too. A site is written in code and uploaded: StartDeployWebsite returns the upload guide; StartHeadlessBuild returns the headless guide, for a site that needs Wix business features (${WIX_BUSINESS_FEATURES}). Call one right away, without asking the user anything first: StartHeadlessBuild when the site needs Wix business features, otherwise StartDeployWebsite. WixSiteBuilder or SearchSiteTemplates only when the user asked for Wix's editor, the Wix Harmony Editor, a template, Wix Studio or the Classic Editor. Never create a site through ManageWixSite, CallWixSiteAPI or ExecuteWixAPI.`
71701
+ ] : [],
71702
+ "- **Listing, showing or finding their Wix sites**: call ListWixSites directly.",
71703
+ ...includeImageUploadGuidance ? [
71704
+ "- **Uploading local or attached image files to a Wix site**: call UploadImageToWixSite directly, with no docs, schema or API calls. Do NOT use ExecuteWixAPI, SearchWixAPISpec, or any Media Manager REST API for image uploads."
71705
+ ] : []
71706
+ ];
71707
+ }
71599
71708
  function buildSystemReminderGuidelines(includeReadme, includeImageUploadGuidance) {
71600
- const exception = includeReadme ? "**Exception:** " : "";
71601
71709
  const lines = [];
71602
- if (includeReadme) {
71603
- lines.push(
71604
- "if the WixREADME tool is available to you, YOU MUST USE IT AT THE BEGINNING OF ANY CONVERSATION and then continue with calling the other tools and calling the Wix APIs until the task is completed.",
71605
- "**Exception \u2014 creating a new Wix site/website:** For a normal creation request \u2014 and only then \u2014 skip WixREADME and the docs search, and route straight to the Wix site-creation tools available to you; their descriptions carry the routing rules. Everything else starts with WixREADME as usual.",
71606
- "If the user explicitly asks for a headless site, Wix Classic Editor site, or manual account/API-based site creation, call CreateWixBusinessGuide right away \u2014 these don't need the site's purpose first.",
71607
- "If the user \u2014 or you, earlier in this conversation \u2014 already have a finished page or site in any form (HTML/CSS/JS files, a static build, a zip, another builder's export, a design you can export to HTML) and want it live on Wix, call StartDeployWebsite right away \u2014 not a site-creation tool, not the docs.",
71608
- "Never default to AI or search templates unless the user explicitly requests it. When the user named no creation method - let the user make that choice as the site-creation tools' descriptions direct. Never route normal site creation through ManageWixSite, CallWixSiteAPI, or ExecuteWixAPI."
71609
- );
71610
- }
71611
71710
  lines.push(
71612
- `${exception}If the user asks to list, show, or find their Wix sites, ${includeReadme ? "skip WixREADME and " : ""}call ListWixSites directly.`
71711
+ includeReadme ? "Start every Wix task with WixREADME, questions included, then use the other tools and the Wix APIs until the task is done. If WixREADME is not available, follow the flows without it. These requests skip it and go straight to their own tool:" : "These requests go straight to their own tool, with no docs or API calls first:"
71613
71712
  );
71614
- if (includeImageUploadGuidance) {
71615
- lines.push(
71616
- `${exception}If the user wants to upload local or attached image files to a Wix site, skip ${includeReadme ? "WixREADME and " : ""}all docs/schema/API flows \u2014 call UploadImageToWixSite directly. Do NOT use ExecuteWixAPI, SearchWixAPISpec, or any Media Manager REST API for image uploads.`
71617
- );
71618
- }
71619
- if (includeReadme) {
71620
- lines.push(
71621
- "If the WixREADME tool is not available to you, you should use the other flows as described without using the WixREADME tool until the task is completed."
71622
- );
71623
- }
71713
+ lines.push(...directRouteLines(includeReadme, includeImageUploadGuidance));
71624
71714
  lines.push(
71625
- `This applies to QUESTIONS too, not only action tasks (the ${includeReadme ? "exceptions" : "direct-tool routes"} above still apply \u2014 question-shaped variants of those intents, e.g. "can you show my sites?", follow their ${includeReadme ? "exception's " : ""}direct tool): never answer a Wix-specific question from memory, and never reply that you lack the tools or APIs to answer, without first ${includeReadme ? "calling the WixREADME tool (if available) and checking its recipes index, searching the docs," : "searching the docs"} and reading the matching docs articles \u2014 many questions (including ones that need no API call) are answered by a ${includeReadme ? "recipe or docs article" : "docs article"}.`,
71626
- "If the user prompt / task is an instruction to do something in Wix, You should not tell the user what Docs to read or what API to call, your task is to do the work and complete the task in minimal steps and time with minimal back and forth with the user, unless absolutely necessary."
71715
+ `A question follows the same routes: one about those requests goes to its tool ("can you show my sites?" is ListWixSites). Any other Wix question is answered from ${includeReadme ? "WixREADME, the Wix skills, " : ""}the docs search and the matching docs articles, never from memory, and never with a reply that you lack the tools or APIs to answer. Many questions, including ones that need no API call, are answered by a ${includeReadme ? "Wix skill or docs article" : "docs article"}.`,
71716
+ "When the user asks you to do something in Wix, do it, in as few steps and questions as you can; don't tell them which docs to read or which API to call."
71627
71717
  );
71628
71718
  return lines.join("\n");
71629
71719
  }
71630
71720
  function buildSystemReminderFlows(includeReadme) {
71631
71721
  const lines = ["Wix MCP Site Management Flows"];
71722
+ const noSkill = "no Wix skill covers the user's prompt/task -> ";
71632
71723
  if (includeReadme) {
71633
71724
  lines.push(
71634
71725
  "With WixREADME tool:",
71635
- "- RECIPE BASED (PREFERRED!): WixREADME() -> find relevant recipe for the user's prompt/task -> read recipe using ReadFullDocsArticle() -> call Wix API using CallWixSiteAPI() based on the recipe",
71726
+ "- SKILL BASED (PREFERRED!): WixREADME() -> find the Wix skill for the user's prompt/task (WixREADME says how to read one) -> follow it -> call the API with ExecuteWixAPI based on it",
71636
71727
  DISCOVERY_FLOWS[0],
71637
- "- EXAMPLE BASED: WixREADME() -> no relevant recipe found for user's prompt/task -> BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() to get method code examples -> call API using CallWixSiteAPI() based on the method code examples",
71638
- "- SCHEMA BASED, FALLBACK: WixREADME() -> no relevant recipe found for user's prompt/task -> BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() -> no method code examples found -> inspect the method schema using SearchWixAPISpec or ReadFullDocsMethodSchema -> call API using CallWixSiteAPI() based on the schema",
71728
+ `- EXAMPLE BASED: WixREADME() -> ${noSkill}BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() to get method code examples -> call the API with ExecuteWixAPI based on the method code examples`,
71729
+ `- SCHEMA BASED, FALLBACK: WixREADME() -> ${noSkill}BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() -> no method code examples found -> inspect the method schema using SearchWixAPISpec or ReadFullDocsMethodSchema -> call the API with ExecuteWixAPI based on the schema`,
71639
71730
  "Without WixREADME tool:"
71640
71731
  );
71641
71732
  }
@@ -71653,9 +71744,8 @@ function buildSystemReminder(includeReadme, includeImageUploadGuidance = true) {
71653
71744
  );
71654
71745
  const flows = buildSystemReminderFlows(includeReadme);
71655
71746
  return dedent_default`
71656
- <agent-mandatory-instructions>
71657
- YOU MUST READ AND FOLLOW THE AGENT-MANDATORY-INSTRUCTIONS BELOW
71658
- A FAILURE TO DO SO WILL RESULT IN ERRORS AND CRITICAL ISSUES.
71747
+ <wix-usage-guide>
71748
+ How to work with Wix through these tools. Following these steps avoids failed or incorrect API calls.
71659
71749
  <goal>
71660
71750
  ${AGENT_GOAL}
71661
71751
  </goal>
@@ -71665,49 +71755,27 @@ function buildSystemReminder(includeReadme, includeImageUploadGuidance = true) {
71665
71755
  <flow-description>
71666
71756
  ${flows}
71667
71757
  </flow-description>
71668
- </agent-mandatory-instructions>
71758
+ </wix-usage-guide>
71669
71759
  `;
71670
71760
  }
71671
71761
  var SYSTEM_REMINDER = buildSystemReminder(true);
71762
+ var HELP_CENTER_IS_FOR_PEOPLE = "The Help Center is written for people doing things by hand in Wix's dashboard and editors. To act on a site yourself, the Wix developer docs come first: find the method with SearchWixRESTDocumentation or BrowseWixRESTDocsMenu.";
71672
71763
  var SITE_CREATION_COPY = {
71673
71764
  templatePick: {
71674
71765
  nonWidget: "After the user selects a template, call `CreateSiteFromTemplate`.",
71675
71766
  widget: "The gallery creates the site when the user picks one."
71676
- },
71677
- unstatedMethod: {
71678
- nonWidget: "you MUST ask whether they want to build with AI or start from a template, and create nothing and show nothing until they answer",
71679
- widget: "you MUST call `WixSiteCreation` and let them choose"
71680
- },
71681
- normalCreationRoute: {
71682
- nonWidget: "route those through `WixSiteBuilder` or `SearchSiteTemplates`",
71683
- widget: "route those through `WixSiteCreation`"
71684
71767
  }
71685
71768
  };
71686
- var SITE_GUIDANCE = dedent_default`
71687
- First decide which of two different things is being asked for:
71688
- - The site is code the user or you control — hand-written HTML/CSS/JS, a static build, a zip, another AI builder's export, or a page or design you made earlier in this conversation — and it should go live on Wix. This is also the route whenever the user wants to keep working on the site here, with you: a Wix Headless site is a regular coded site, so you keep full control of the design and can change and redeploy it from this conversation at any time, and Wix business capabilities can be added to it as a backend when they are needed. Call StartDeployWebsite: it returns the recipe to host those exact files as a Wix Headless site (updates reuse the same site and URL; the drop page is only its fallback). Do not offer AI or templates for this and do not call any site-creation tool.
71689
- - Wix should create the site — generated with AI from a description, or started from a template — and the user will design and edit it in Wix rather than through you. That is what the site-creation tools do; they never take files you already have.
71690
-
71691
- For a new site there are 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.
71692
-
71693
- 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.
71694
- 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.
71695
- Once the purpose is clear, unless the user already named a method, ${SITE_CREATION_COPY.unstatedMethod.nonWidget}. A method they named is settled — never re-open it. Never default to AI or to templates, and never ask the user to choose between Harmony and Wix Studio; infer that from their words.
71696
- With the purpose and the method known, that's enough to begin — route and refine the specifics with the user afterward.
71697
-
71698
- Preferred question when the user has given no site context at all:
71699
- Happy to help. To give you the right starting point, tell me a bit more about what you have in mind:
71700
- - What's the site for? (e.g. an online clothing store, a yoga studio that takes bookings, a restaurant)
71701
- - What's the vibe? (e.g. sleek and modern, cozy and rustic, bold and energetic)
71702
- Give me a quick summary and I'll take it from there
71703
-
71704
- Tone: helpful, practical, short. Speak about the user's site — what you're making and what comes next — not the tools, payloads, or routing behind it.`;
71769
+ var EDITOR_TAIL = `When the user wants Wix's editor, or to design the site themselves, without saying how to start, ask them first: "${SITE_BUILDER_CHOICE.editorQuestion}" A new site is otherwise written in code and uploaded: call StartDeployWebsite, or StartHeadlessBuild when it needs Wix business features, right away and without asking the user anything first.`;
71705
71770
  var toWidget = (text) => Object.values(SITE_CREATION_COPY).reduce(
71706
71771
  (acc, { nonWidget, widget }) => acc.replaceAll(nonWidget, widget),
71707
71772
  text
71708
71773
  );
71774
+ var WIX_API_DATA = "products, inventory, carts, checkouts, orders, bookings, services, staff, time slots, rentals, restaurant menus, online orders, reservations, events, tickets, RSVPs, blog posts, CMS collections and items, pricing plans, subscriptions, portfolios, gift cards, coupons, donations, forms, form submissions, contacts, members, loyalty points, groups, reviews, inbox messages, CRM tasks, automations, email campaigns, payments, invoices, SEO, redirects, translations, locations, analytics, media files, site properties, installed apps, and the account's sites and domains";
71709
71775
  var EXECUTE_WIX_API_INTRO = dedent_default`
71710
- Execute JavaScript code against the Wix REST API when code is useful for chaining related calls, pagination, loops, branching, or in-memory transformation.
71776
+ Reads and changes the data of a Wix site or account: query, list, count, create, update and delete it with one JavaScript function over the Wix REST API.
71777
+ One function holds the whole task: chained calls, pagination, loops, branching, and the reads that feed its writes.
71778
+ Putting a site live or changing a headless site's files starts with StartDeployWebsite; building a new site in code with StartHeadlessBuild.
71711
71779
 
71712
71780
  CODE CONTRACT:
71713
71781
  - Pass an async function expression: \`async function() { ... }\` or \`async () => { ... }\`. Put every declaration, \`await\`, and \`return\` inside it, and do not invoke it yourself.
@@ -71792,7 +71860,7 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
71792
71860
  declare const files: Array<{ path: string; content: string; encoding?: "base64" }>;
71793
71861
  \`\`\`
71794
71862
 
71795
- FILE UPLOADS: files never go inline in \`code\`; two params feed the \`files\` global. \`attachments\` takes files attached in the chat or created in your file sandbox, of any type and size up to 10 MB per call (a zip of a whole site, HTML, images, PDFs): pass the files themselves, all in one call, and the platform resolves each into \`{ download_url, file_id, file_name?, mime_type? }\` — the bytes are fetched for you and arrive as base64 entries named by file name. The \`files\` param takes content you have as text here: text goes raw; a small binary (icon, logo, font) rides as a \`base64\`-tagged entry — large images/video are referenced by URL (\`<img src="https://...">\`), not bundled. \`wix.multipart()\` turns the whole set into one upload body (bytes, so binary is safe):
71863
+ FILE UPLOADS: files never go inline in \`code\`; two params feed the \`files\` global. \`attachments\`: ${fileParamNote("upload from your shell if it reaches the internet")} Any type, up to 10 MB per call, all in one call: a zip of a whole site, HTML, images, PDFs; the bytes arrive as base64 entries named by file name. The \`files\` param takes content you have as text here: text goes raw; a small binary (icon, logo, font) rides as a \`base64\`-tagged entry — large images/video are referenced by URL (\`<img src="https://...">\`), not bundled. \`wix.multipart()\` turns the whole set into one upload body (bytes, so binary is safe):
71796
71864
  \`\`\`javascript
71797
71865
  // files param:
71798
71866
  // === FILE: index.html ===
@@ -71807,6 +71875,7 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
71807
71875
  return res.data;
71808
71876
  }
71809
71877
  \`\`\`
71878
+ HEADLESS SITE EDITS: \`wix.headless.files.list({siteId, prefix?, offset?, limit?})\` returns file metadata; \`read({siteId, path})\` returns UTF-8 text (up to 256 KB); \`patch({siteId, files?, deletePaths?, agent?})\` applies changed files and explicit deletions while preserving everything else. Patch defaults to the Execute \`files\` global (including resolved attachments and ZIPs). Paths are literal site-relative paths; no wrapping-folder stripping. It returns added/replaced/deleted/unchanged/missingDeletes path lists. List/read reuse one downloaded ZIP snapshot for the current site within an Execute call; switching sites discards the previous snapshot, and a new call downloads afresh. Patch downloads a fresh ZIP, then drops the full merged site and clears the read snapshot. Serialize edits to the same site; there is no atomic concurrency guarantee. For a full replacement, use the existing upload/drop path. See the upload-static-site recipe for examples and older-server fallback.
71810
71879
  A site zip passed through \`attachments\` is one base64 entry; unzip it and upload the entries:
71811
71880
  \`\`\`javascript
71812
71881
  // attachments: [site.zip] → files = [{ path: "site.zip", content: "<base64>", encoding: "base64" }]
@@ -71930,22 +71999,37 @@ var executeWixApiDescription = dedent_default`
71930
71999
 
71931
72000
  ${EXECUTE_WIX_API_MULTI_SITE_EXAMPLE}
71932
72001
  `;
71933
- function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true) {
71934
- const reminder = buildSystemReminder(
72002
+ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true, { usageGuideOnce = false } = {}) {
72003
+ const usageGuide = buildSystemReminder(
71935
72004
  includeReadme,
71936
72005
  includeImageUploadGuidance
71937
72006
  );
71938
- return {
72007
+ const reminder = includeReadme && usageGuideOnce ? "" : usageGuide;
72008
+ const descriptions = {
72009
+ // Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
71939
72010
  WixREADME: dedent_default`
71940
72011
  # Tool: WixREADME
71941
- **Directive:** \`WixREADME\` is the **MANDATORY FIRST STEP** for all Wix-related tasks. Its output (including relevant linked documents) provides foundational context for all other Wix tools. Adherence to this protocol is **NON-NEGOTIABLE**.
71942
-
71943
- **Mid-conversation site switching:** If the user references a different site by name or ID after WixREADME has already been called, use \`GetSiteContext\` directly — no need to call WixREADME again.
71944
- ${reminder}
72012
+ The context every other Wix tool assumes. Call it first, once per conversation, for any Wix task or question; for another site later in the conversation, call \`GetSiteContext\` instead of calling this again.
72013
+ A Wix task includes reading or changing a site's or account's data: ${WIX_API_DATA}.
72014
+ These requests skip it and go straight to their own tool:
72015
+ ${directRouteLines(includeReadme, includeImageUploadGuidance).join("\n")}
72016
+ A question about one of those goes to the same tool ("can you show my sites?" is ListWixSites). Any other Wix question is answered from a Wix skill or the docs, never from memory, and never with a reply that you lack the tools to answer.
72017
+ It returns, in full:
72018
+ - **Source of truth**: nothing Wix-specific from memory. Every URL, ID, setting location, product fact, request shape and field name comes from the docs tools, a Wix skill, an earlier tool result in the conversation, or the user.
72019
+ - **The site**: the account's sites with their properties and installed apps. The \`siteId\` comes from there (ask when several fit); a business solution's API works only on a site with its app installed, and an app's version changes its endpoints.
72020
+ - **Find the method**: an earlier tool result, else a Wix skill's recipe (wix-manage to manage a site, wix-headless-kit to build a headless one), else the docs: SearchWixRESTDocumentation or BrowseWixRESTDocsMenu, then ReadFullDocsArticle; the SDK, CLI, headless and apps docs for code.
72021
+ - **The exact shape**: model a call only on an example that matches the case; fill the rest with SearchWixAPISpec on the method's docs URL (request and response schemas, \`method.publicUrl\` for REST, \`method.sdk\` for the JavaScript SDK). A query's filter and sort fields and operators are a closed list per method.
72022
+ - **The call, or the code**: ExecuteWixAPI runs one async function holding every step code can resolve, the reads and the writes they feed together, \`hasMutations: true\` when anything writes. Code the user keeps (an app, a headless site, a script over REST or the JavaScript SDK) is written from the same shapes; the headless skills are a shortcut on that path.
72023
+ - **When a call fails**: the error says what was wrong and carries a Wix request id; fix that, never resend unchanged or guess.
72024
+ - **Wix skills**, what each is for and how to read one: from disk when installed (the Wix plugin, or \`npx skills add wix/skills\`, \`--skill <name>\` for one, \`-g\` for the user's home, into \`.agents/skills/<skill>/\` or a similar folder the client reads, such as \`.claude/skills/<skill>/\`), else online with ReadFullDocsArticle at \`https://www.wix.com/skills/<skill>/<path>\`.
72025
+ - **wix-manage**: REST recipes for managing a site's business solutions, one per task; follow the recipe and make its calls with ExecuteWixAPI, its docs URL in \`sourceDocUrls\`. Its list of recipes is \`SKILL.md\` in the installed skill, or online https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills/wix-management-recipes-index.md, and each API area has its own \`<API section>/skills.md\` (for example https://dev.wix.com/docs/api-reference/business-solutions/bookings/skills.md).
72026
+ - **wix-headless-kit**: builds a Wix Headless site on shipped, verified code from wix-headless-templates, a \`@wix/sdk\` React core or the same data layer as plain REST calls: scaffold with the CLI, deploy, seed, design on the shipped hooks, release. https://www.wix.com/skills/headless-kit/SKILL.md
72027
+ - **wix-headless-templates**: the code wix-headless-kit builds from, one folder per Wix Business Solution. https://www.wix.com/skills/headless-templates/
72028
+ When the user asks you to do something in Wix, do it yourself, in as few steps and questions as you can; don't tell them which docs to read or which API to call.
71945
72029
  `,
71946
72030
  SearchWixRESTDocumentation: dedent_default`
71947
72031
  **Searches the official Wix REST API documentation — the starting point for any Wix REST API task.** Unless you already have the exact method \`docsUrl\` in context, begin the task here; this is how you discover the right endpoint. Reach for it before \`SearchWixAPISpec\`, and avoid writing code that scans or filters \`lightIndex\` to find an endpoint (e.g. \`lightIndex.filter(...)\`, \`lightIndex.flatMap(...)\`, or substring-matching on \`docsUrl\`/\`name\`/\`summary\`) — that has no relevance ranking and silently misses composite and method-level operations. This is the ranked semantic-search discovery tool over the Wix REST API docs: describe your intent in natural language and it returns the matching REST endpoints/methods (with their \`docsUrl\`) ranked by relevance. It is the first step whenever you need to do something on a Wix site via HTTP and don't already have the exact \`docsUrl\` in context — for creating, reading, updating, or deleting any kind of Wix entity, across every business domain.
71948
- It covers all Wix REST domains equally — Stores, eCommerce/orders, Bookings, CRM/contacts, Members, CMS/data collections, Events, Blog, Forms, Marketing, Media, site settings, SEO, and the rest. Just describe the resource, action, or goal in plain words (e.g. 'add a catalog item with inventory', 'book a service', 'update a data collection item', 'create a discount', 'list contacts', 'get site details endpoint', 'REST authentication'); the ranking handles matching your wording to the right API regardless of domain.
72032
+ It covers all Wix REST domains equally, every product's data: ${WIX_API_DATA}, and the rest. Just describe the resource, action, or goal in plain words (e.g. 'add a catalog item with inventory', 'book a service', 'update a data collection item', 'create a discount', 'list contacts', 'get site details endpoint', 'REST authentication'); the ranking handles matching your wording to the right API regardless of domain.
71949
72033
  **Next step after this tool:** take the \`docsUrl\` it returns and inspect that method's exact request/response schema with \`SearchWixAPISpec\` (\`getResourceSchemaByUrl(docsUrl)\`), then execute. \`SearchWixAPISpec\` is only for INSPECTING a \`docsUrl\` you already have — it is NOT a discovery tool. Skipping this step to hand-search \`lightIndex\` yourself is a mistake: raw index filtering has no relevance ranking and misses operations this ranked search finds. Discover here first, every time.
71950
72034
  If you can't find what you need, rephrase your search term or use a bigger maxResults value.
71951
72035
  ${reminder}
@@ -71953,7 +72037,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
71953
72037
  ReadFullDocsArticle: dedent_default`
71954
72038
  Fetches the full Wix docs article or method article with code examples for using the method.
71955
72039
  Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
71956
- Also reads Wix skills pages — https://www.wix.com/skills/<skill>, https://dev.wix.com/docs/skills/<skill>, and the files they link (e.g. .../<skill>/references/<file>.md) — exactly as served.
72040
+ Also reads Wix skills pages — https://www.wix.com/skills/<skill>, https://dev.wix.com/docs/skills/<skill>, and the files they link (e.g. .../<skill>/references/<file>.md) — and Wix Headless agent pages under https://www.wix.com/headless/ (e.g. https://www.wix.com/headless/skill.md), exactly as served.
71957
72041
  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.
71958
72042
  For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
71959
72043
  ${reminder}
@@ -71967,6 +72051,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
71967
72051
  `,
71968
72052
  CallWixSiteAPI: dedent_default`
71969
72053
  Call Wix apis on a business or site. Use this to create, read, update, and delete data and other Wix entities in your Wix site.
72054
+ ExecuteWixAPI is the preferred tool for Wix API calls: one function holds every call of the task, the reads and the writes they feed together, where this tool makes one call per invocation. If your client loads tools on demand (tool search, deferred tools), load ExecuteWixAPI before using this tool. ${CALL_WIX_SITE_API_RECONNECT_LINE}
71970
72055
  Site-level: this tool reads and writes inside the single site named by the required \`siteId\`.
71971
72056
  **Prefer using the "ListWixSites" tool when the user asks to list or show their sites.** Only use this tool for site listing if the user needs advanced filtering or specific site details beyond what ListWixSites provides.
71972
72057
  For POST/PATCH/PUT requests, pass the request body as a JSON object or array in the "body" parameter with all the required fields and values as described in the API schema, code examples, or docs you retrieved (e.g. body: {"name": "value", "nested": {"key": "value"}} or body: [{"key": "value"}]).
@@ -71981,6 +72066,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
71981
72066
  Docs urls like https://dev.wix.com/docs/... are not api urls, if you want to read the docs, use the "ReadFullDocsArticle" tool
71982
72067
  ${reminder}
71983
72068
  `,
72069
+ // Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
71984
72070
  ListWixSites: dedent_default`
71985
72071
  **Use this tool whenever the user asks to list, show, get, or find their Wix sites.** This is the dedicated tool for listing Wix sites for the current user. By default it returns all sites, but you can filter by name.${includeReadme ? "\n\n**Do NOT use WixREADME before this tool.** When the user asks to list their sites, call this tool directly \u2014 no need to read documentation first." : ""}
71986
72072
 
@@ -72001,13 +72087,14 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72001
72087
  ${reminder}
72002
72088
  `,
72003
72089
  ManageWixSite: dedent_default`
72004
- Use account level API in order to create a site and update a site.
72090
+ Use account level API in order to update a site.
72005
72091
  Account-level only: this tool acts on the account itself, or on sites as objects within it, and sends no site context. Anything that reads or writes inside a site is site-level and does not belong here — use a site-level tool with that site's \`siteId\`.
72006
72092
  For POST/PATCH/PUT requests, pass the request body as a JSON object or array in the "body" parameter with all the required fields and values as described in the API schema, code examples, or docs you retrieved (e.g. body: {"name": "value", "nested": {"key": "value"}} or body: [{"key": "value"}]).
72007
72093
  The API endpoint url param MUST ALWAYS be taken from the conversation context.
72008
72094
  By conversation context we mean the endpoint url was given in the user prompt or got into the conversation context ${includeReadme ? 'by the "WixREADME" tool or ' : ""}by the "SearchWixRESTDocumentation" tool or by the "BrowseWixRESTDocsMenu" tool or by the "ReadFullDocsArticle" tool.
72009
72095
  ${reminder}
72010
72096
  `,
72097
+ // Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
72011
72098
  UploadImageToWixSite: dedent_default`
72012
72099
  Upload one or more images to a Wix site's Media Manager. Returns wixstatic.com URL and media ID.
72013
72100
  Do NOT use ExecuteWixAPI or code execution for image uploads — use this tool directly.
@@ -72017,34 +72104,39 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72017
72104
  NEVER call this tool with a missing, empty, or guessed siteId — ask first instead.
72018
72105
 
72019
72106
  Parameters — provide image input via image and/or imageUrls, OR imageBase64:
72020
- • image (array): chat file ATTACHMENTS — files the user attached, or files you created in your own file sandbox. Each item is an object with download_url and file_id (both required), plus optional file_name and mime_type. Pass ALL attachments in one call.
72107
+ • image (array): ${fileParamNote("send the image as imageBase64 (the whole file, one per call) or as a public URL in imageUrls")} Pass ALL of them in one call.
72021
72108
  • imageUrls (array): plain public image URLs the user pasted or other tools produced (no file_id). Pass ALL URLs in one call. Can be combined with image.
72022
72109
  • imageBase64 (string): base64-encoded image + mimeType. One image at a time. Do NOT combine with image/imageUrls.
72023
72110
 
72024
72111
  Delivering the bytes — this is where uploads most often fail:
72025
- • Pass a file as a file, in image: the platform resolves it into download_url and file_id before it reaches this tool — this includes files you created in your sandbox. This server does not share your filesystem, so a bare path string (e.g. /mnt/..., /home/user/..., /Users/...) is not a file. Without a file to pass, use a public http(s) URL (imageUrls) or the complete base64 (imageBase64).
72112
+ • This server does not share your filesystem: outside image's clients, a file you can only reach by path (e.g. /mnt/..., /home/user/..., /Users/...) goes as imageBase64 (the whole file, one per call) or, if it is public, as imageUrls.
72026
72113
  • imageBase64 must be the WHOLE file, not truncated. For large images prefer imageUrls, since long base64 is easily cut off and will be rejected as unreadable.
72027
72114
  `,
72028
- SupportAndFeedback: dedent_default`
72029
- Send the user's feedback about the experience of building with Wix — the Wix MCP tools, APIs, docs, and tooling — to Wix, attributed to the authenticated user.
72030
- This is meta-feedback about building with Wix; it is NOT a support channel and not for the user's own site content.
72115
+ // Registered for Claude clients only, beside UploadImageToWixSite.
72116
+ PickImagesForWixMedia: dedent_default`
72117
+ Shows a file picker where the user selects images from their device; they upload to the site's Media Manager and the result (each image's media ID and wixstatic URL) comes back in the conversation.
72118
+ Use it only when you can't deliver the image yourself with UploadImageToWixSite: the image is on the user's device and not in your files, or it is a file in your sandbox that you can't pass as a file, a public URL or base64. When UploadImageToWixSite can take it, use that.
72119
+ `,
72120
+ ReportIssueToWix: dedent_default`
72121
+ Report one specific problem with Wix's tools, APIs or docs to the Wix team, attributed to the authenticated user: an API error or a confusing API, wrong or missing docs, a Wix MCP tool or auth dead end. It is NOT a support channel and not for the user's own site content.
72031
72122
 
72032
72123
  When to offer it (user-approved only — NEVER auto-send):
72033
- - The user explicitly asks to send feedback / report something to Wix ("tell Wix that...", "report this", "send feedback"). Then just confirm the wording and send.
72034
- - The user complains, is frustrated, or reports a Wix bug in the course of the work ("this API is broken", "the docs are wrong", "why is this so hard"). Acknowledge, then offer to pass it on.
72035
- - The session hit substantial friction — repeated API failures, wrong/missing docs, a tooling dead end, or a workaround you had to invent. When you notice the pattern, offer: "This tripped us up a few times — want me to send it to Wix as feedback?"
72036
-
72037
- When you offer, invite the user to add anything in their own words — whatever they give you goes into the message verbatim.
72038
-
72039
- What to send — a summary of the whole run, not just the last error. Structure it in four layers:
72040
- 1. Provenance — agent/model; Wix tooling used; platform/hosting; Wix areas/APIs touched; Wix products; project type/frontend; site id; relevant links (dashboard, docs pages, live site, repos); skill areas/recipes involved; other ids created this run.
72041
- 2. Narrative — user intent and run summary (what they set out to build, what worked vs. what fought back); a condensed play-by-play of the session (key exchanges, tool calls, decisions, course-corrections).
72042
- 3. Friction points — for each friction point: the step/endpoint, HTTP status and error message, the gap, the workaround you had to invent, and what you expected instead. Include ones you recovered from silently — a retry that eventually worked is exactly the signal Wix wants.
72043
- 4. Attribution — per friction point, where the fault likely lives: API behavior / API schema / API reference docs / docs articles or examples / Wix tooling / other/unsure. Don't force a tag; "unsure" beats a wrong route.
72044
- End with a bottom line: one or two sentences on the single most important problem and its impact — a plain engineering assessment, not softened or hedged.
72045
-
72046
- **IMPORTANT**: This tool actually sends the message to Wix. Confirm the final wording with the user and call it only after an explicit yes.
72047
- Do not send on a single transient error, and never more than once for the same issue. Feedback cannot be replied to or tracked by the user.
72124
+ - The user asks to report something to Wix ("tell Wix that...", "report this", "send feedback"). Then confirm the wording and send.
72125
+ - The user complains or reports a Wix bug in the course of the work ("this API is broken", "the docs are wrong"). Acknowledge, then offer to pass it on.
72126
+ - A Wix API, tool or doc kept failing, or you had to invent a workaround for it. Offer: "This tripped us up — want me to report it to Wix?"
72127
+
72128
+ When you offer, invite the user to add anything in their own words — whatever they give you goes into the report verbatim.
72129
+
72130
+ What to send — that one issue, not the session:
72131
+ - What was being attempted, in a sentence.
72132
+ - Where it failed: the tool or endpoint, the HTTP status and error message, and the request id if there is one (pass it as requestId).
72133
+ - What you expected instead, and the workaround if you found one.
72134
+ - Where the fault likely lives: API behavior / API schema / API reference docs / docs articles or examples / Wix tooling / unsure.
72135
+ - Only the context needed to reproduce it: agent/model, site id, the Wix area or API.
72136
+ No session summary or play-by-play, and nothing unrelated to the issue. Several distinct issues are separate reports, each approved by the user.
72137
+
72138
+ **IMPORTANT**: This tool actually sends the report to Wix. Confirm the final wording with the user and call it only after an explicit yes.
72139
+ Do not send on a single transient error, and never more than once for the same issue. Reports cannot be replied to or tracked by the user.
72048
72140
  `,
72049
72141
  BrowseWixRESTDocsMenu: dedent_default`
72050
72142
  Browse the Wix REST API documentation menu hierarchy.
@@ -72066,28 +72158,11 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72066
72158
  ${reminder}
72067
72159
  `,
72068
72160
  WixSiteCreation: dedent_default`
72069
- ${SITE_GUIDANCE}
72070
-
72071
- Opens the in-chat Wix site creation chooser as an interactive widget where the user chooses between "Build with AI" and "Pick a template."
72072
-
72073
- **Once you can tell what the site is for, call this tool directly** — no ${includeReadme ? "WixREADME, skill," : "skill"} or docs search first.${includeReadme ? " Any other Wix request still starts with WixREADME as usual." : ""}
72074
-
72075
- Call this for normal new Wix site creation requests when the user's site intent is clear, but they have not chosen AI, templates, or Wix Studio.
72076
- Do not guess, and never default to AI — even after the user answers a clarifying question about the site's purpose or features.
72077
- This chooser is how the builder choice gets made — never ask in chat whether they want AI or a template; that choice is made in the widget.
72078
- The widget also does the creating: once the user picks, it runs that path itself and the site is created there, so never call \`WixSiteBuilder\`, \`SearchSiteTemplates\`, or \`CreateSiteFromTemplate\` yourself after opening it.
72079
- After calling, reply with the message it returns, which presents both options and the next steps.
72080
-
72081
- Do not call this if the user explicitly asks to build with AI; call \`WixSiteBuilder\` instead.
72082
- Do not call this if the user asks for templates or Wix Studio; call \`SearchSiteTemplates\` instead.
72083
-
72084
- When calling this tool, infer \`customActions\` from the user's request so the reply can be tailored — 2-3 concrete, industry-specific setup actions for the site (see the input's guidance).
72085
-
72086
- After calling, you MUST speak the message provided in the tool result to the user as your reply — do not stay silent and do not replace it with a one-line pointer to the widget. Write out ALL of it, word for word: its opening line (the "Ready to set up your … site?" question INCLUDING "Choose your path in the widget above:"), BOTH of its option bullets, and its "Next up:" line, each on its own line and in that order. Do not summarize, shorten, drop any line, invent your own opener, rename the options, or add an intro or outro.
72161
+ A new Wix site is written in code and uploaded: call StartDeployWebsite for the upload guide, or StartHeadlessBuild when the site needs Wix business features. WixSiteBuilder or SearchSiteTemplates only when the user asked for the Wix Harmony Editor, a template, Wix Studio or the Classic Editor.
72087
72162
  `,
72088
72163
  "import-claude-design-from-url": dedent_default`
72089
- 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.
72090
- NOT for a page or site that exists in any other form (the user's own HTML/CSS/JS, a static build, a zip, another builder's export, a page you made in this conversation) — for those call StartDeployWebsite instead; it returns the recipe to publish the files yourself.
72164
+ Import a design created in Claude's design tool into Wix. Only for the signed \`claudeusercontent.com\` bundle URL Claude Design's "Send to Wix" produces (a self-contained HTML bundle with all images, fonts, and styles inlined). Creates a live Wix-hosted site and returns its URL.
72165
+ NOT for claude.ai share or artifact links, GitHub, Drive, chatgpt.com or any other URL, and not for files: those go to StartDeployWebsite, which returns the recipe to publish the files yourself.
72091
72166
  `,
72092
72167
  RunWixCliCommand: dedent_default`
72093
72168
  Executes Wix CLI commands for Wix app development and management.
@@ -72113,6 +72188,13 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72113
72188
  `,
72114
72189
  SearchWixWDSDocumentation: dedent_default`
72115
72190
  Searches the Wix Design System (WDS) documentation.
72191
+ `,
72192
+ SearchWixHelpCenter: dedent_default`
72193
+ Searches the Wix Help Center (support.wix.com): how site owners do things in the Wix dashboard and editors, such as connecting a domain, managing a Premium plan, setting up a store or bookings, and fixing account or site issues.
72194
+ ${HELP_CENTER_IS_FOR_PEOPLE}
72195
+ Use it for "how do I ... in Wix" questions about the product, or to give the user click-by-click steps for something no API covers.
72196
+ Not for building with code: for Wix APIs, SDK, CLI, apps, or Headless, use the matching developer documentation search.
72197
+ Results are excerpts; read a full article by passing its support.wix.com link to \`ReadFullDocsArticle\`.
72116
72198
  `,
72117
72199
  SearchWixSDKDocumentation: dedent_default`
72118
72200
  Searches the Wix JavaScript SDK documentation.
@@ -72123,7 +72205,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72123
72205
  `,
72124
72206
  SearchDevelopmentDocumentation: dedent_default`
72125
72207
  Broad Wix development documentation (platform concepts, developer guides, getting started). **Last resort — development tasks only.**
72126
- Skip it entirely for general, business, support, or Wix-editor questions.
72208
+ Skip it entirely for general, business, support, or Wix-editor questions; for those, use \`SearchWixHelpCenter\`.
72127
72209
  Call it only after the specific search for your task returned nothing useful: \`SearchWixRESTDocumentation\` (REST), \`SearchWixSDKDocumentation\` (JS SDK), \`SearchWixCLIDocumentation\` (CLI), \`SearchBuildAppsDocumentation\` (apps), \`SearchWixHeadlessDocumentation\` (Headless), \`SearchWixWDSDocumentation\` (WDS). Never use it as a first search.
72128
72210
  `,
72129
72211
  SearchWixHeadlessDocumentation: dedent_default`
@@ -72135,7 +72217,8 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72135
72217
  // `sdk` is simply absent on methods the SDK docs don't list.
72136
72218
  SearchWixAPISpec: dedent_default`
72137
72219
  Inspect the Wix REST API spec, and the JavaScript SDK call for each method, by writing JavaScript code that runs in a sandboxed read-only environment.
72138
- **Precondition:** you already have a method \`docsUrl\` — from \`SearchWixRESTDocumentation\`, \`SearchWixSDKDocumentation\` (its \`?apiView=SDK\` URLs work here as-is), \`BrowseWixRESTDocsMenu\`, \`ReadFullDocsArticle\`, ${includeReadme ? "a `WixREADME` recipe, " : ""}or a prior tool result / the user's message in this conversation. If you don't have one yet, call \`SearchWixRESTDocumentation\` (or \`SearchWixSDKDocumentation\` when writing SDK code) FIRST to discover it; do not use this tool to search for or choose an endpoint.
72220
+ The spec covers every Wix product's methods and their data: ${WIX_API_DATA}.
72221
+ **Precondition:** you already have a method \`docsUrl\` — from \`SearchWixRESTDocumentation\`, \`SearchWixSDKDocumentation\` (its \`?apiView=SDK\` URLs work here as-is), \`BrowseWixRESTDocsMenu\`, \`ReadFullDocsArticle\`, ${includeReadme ? "a Wix skill, " : ""}or a prior tool result / the user's message in this conversation. If you don't have one yet, call \`SearchWixRESTDocumentation\` (or \`SearchWixSDKDocumentation\` when writing SDK code) FIRST to discover it; do not use this tool to search for or choose an endpoint.
72139
72222
  **Never pass a \`docsUrl\` you produced from memory.** If the exact URL you are about to pass to \`getResourceSchemaByUrl\` did not appear verbatim in an earlier tool result (or the user's message), it is a guess — call \`SearchWixRESTDocumentation\` first and use a URL from its ranked results. A guessed URL that merely looks plausible routinely resolves to the WRONG sibling method (e.g. \`.../products-v3/create-product\` when the task needs \`.../products-v3/create-product-with-inventory\`), sending the whole turn down a dead end. When in doubt, discover — don't guess.
72140
72223
  **This tool's job is to INSPECT the exact schema of a method you have ALREADY located — its request/response shape, nested types, and enums, and its SDK call (\`method.sdk\`). It is NOT a discovery tool for choosing which method to use.**
72141
72224
  With a method \`docsUrl\` in hand, call \`getResourceSchemaByUrl(methodDocsUrl)\` to get the resource schema, then read the target method from \`schema.methods\` and resolve any nested \`{ $circular: name }\` types via \`schema.components.schemas[name]\`.
@@ -72516,31 +72599,22 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72516
72599
  \`\`\`
72517
72600
  `,
72518
72601
  ExecuteWixAPI: executeWixApiDescription,
72602
+ // Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
72519
72603
  WixSiteBuilder: dedent_default`
72520
- ${SITE_GUIDANCE}
72521
-
72522
- Tool for generating a Wix site with AI (creating / building a site in Wix Harmony) from a description. It does not take pages or files you already have — those go to StartDeployWebsite.
72523
-
72524
- Call this ONLY when the user's own words name AI (for example "create a site using AI" or "build it with AI") and the site intent is clear. A description of what the site should do — reservations, online ordering, a store, bookings, menus, a portfolio, and the like — is NOT a request for AI and NOT enough to call this tool; never infer AI from features or industry.
72525
- Never default to this tool: if the user hasn't explicitly named AI, don't call this tool — ${SITE_CREATION_COPY.unstatedMethod.nonWidget}.
72526
-
72527
- For templates or Wix Studio, call \`SearchSiteTemplates\`; for a specific template by \`metaSiteId\` or \`templateId\`, call \`CreateSiteFromTemplate\`; for a headless or classic Wix Editor site, or manual/account-API creation, call \`CreateWixBusinessGuide\`.
72528
-
72529
- Do NOT suggest HTML code, prompt templates, or alternative approaches instead of building — actually build the site through this tool. (HTML the user already has is the StartDeployWebsite case, not a reason to build.)
72604
+ A secondary site-creation tool, only for a user who asked for the Wix Harmony Editor or for Wix to design the site. Don't call it for any other site request, not even to check with the flag false. A new site is otherwise written in code and uploaded, with StartDeployWebsite, or StartHeadlessBuild when it needs Wix business features.
72605
+ Builds a site with the Wix Harmony Editor: Wix designs a first version from the user's description, and the user keeps designing it in Wix's editor. Shows the build's progress and a preview.
72606
+ Call it when the user asked for the Wix Harmony Editor, or for Wix to design the site, in their own words or as their answer to your question. ${EDITOR_TAIL}
72530
72607
  `,
72608
+ // Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
72531
72609
  SearchSiteTemplates: dedent_default`
72532
- ${SITE_GUIDANCE}
72533
-
72534
- Searches Wix templates and shows the template gallery, from the Harmony or the Studio template source.
72535
-
72536
- Call this ONLY when the user's own words ask for a template or for Wix Studio (for example "start from a template", "show me some templates", "build it in Wix Studio") and you can already tell what the site is for. If they mention Wix Studio, search Studio templates; otherwise search Harmony templates.
72537
- ${SITE_CREATION_COPY.templatePick.nonWidget}
72538
-
72539
- A description of what the site should do — bookings, a store, a menu, a portfolio, and the like — is NOT a request for templates or for Wix Studio; never infer either from features or industry. Templates are not the default: if the site intent is clear but no method is named, do not guess — ${SITE_CREATION_COPY.unstatedMethod.nonWidget}.`,
72610
+ A secondary site-creation tool, only for a user who asked for a template, Wix Studio or the Classic Editor. Don't call it for any other site request, not even to check with the flag false. A new site is otherwise written in code and uploaded, with StartDeployWebsite, or StartHeadlessBuild when it needs Wix business features.
72611
+ Shows a gallery of Wix templates, from Harmony, Wix Studio or the Classic Editor, for a site the user will design in Wix's editor. Wix templates come with Wix's business features (a store, online ordering, bookings, forms), so a request for a template comes here even when the site needs them.
72612
+ Call it when the user asked for a template, Wix Studio or the Classic Editor, in their own words or as their answer to your question. ${EDITOR_TAIL} ${SITE_CREATION_COPY.templatePick.nonWidget}
72613
+ `,
72540
72614
  CreateSiteFromTemplate: dedent_default`
72541
72615
  Creates a Wix site from a specific template (by \`metaSiteId\` or \`templateId\`), publishes it when possible, and shows a live preview with links to the editor and the published site.
72542
72616
 
72543
- Call this when the user provides a specific template by \`metaSiteId\` or \`templateId\`. Use this only when the user gives a valid \`metaSiteId\` or \`templateId\` directly. To browse or choose a template first, call \`SearchSiteTemplates\`.
72617
+ Call this when the user provides a specific template by \`metaSiteId\` or \`templateId\`. Use this only when the user gives a valid \`metaSiteId\` or \`templateId\` directly. To browse or choose a template first, call \`SearchSiteTemplates\` (\`builder: classic\` for a Classic Editor site).
72544
72618
 
72545
72619
  `,
72546
72620
  SearchWixGraphQLOperations: dedent_default`
@@ -72569,118 +72643,216 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
72569
72643
  Results: each root field fails independently — \`errors[].path\` names the failing field and \`errors[].extensions.message\` the cause (e.g. PERMISSION_DENIED); \`data\` still holds the fields that succeeded. Mutations return the created/updated entity — read the IDs from it and do not re-query to verify. Large results are truncated: narrow the selection or page size instead of re-running.
72570
72644
  Set \`hasMutations: true\` for any document containing a mutation root field.
72571
72645
  `,
72646
+ UploadHeadlessWebsiteFiles: dedent_default`
72647
+ The upload step of the StartDeployWebsite and StartHeadlessBuild guides, and nothing else: puts a finished website's files — a static site (index.html plus its CSS/JS/images, a static build, or a zip of the site) or a Wix Astro build — onto an existing Wix Headless site by its metaSiteId. Call it ONLY after one of them has returned its guide in this conversation and the site exists: for a new site, first run the recipe's provision call and pass the metaSiteId it returns; for a site deployed earlier, pass its metaSiteId. It does not create sites. Every upload replaces the whole file set and the URL stays. Returns the live URL and the dashboard link, and points back to the recipe for what comes next.
72648
+ Pass the files themselves: in ${FILE_PARAM_CLIENTS} as \`attachments\` (any type, a zip is unpacked), elsewhere as the \`files\` text bundle (\`=== FILE: <path> ===\` sections, \`base64\` tag for small binaries). A static site must contain index.html at its root. A Wix Astro build with no file handle, from a shell that reaches the internet, goes in two calls: zip the build, call with \`prepare: true\` and the zip's \`size\` in bytes, PUT the zips it names with the \`curl\` commands it returns (the build, and the project source when the site's repository accepts it), then call again with the \`uploadKey\` it returned; that releases the build. The two calls, literally: {siteId, prepare: true, size} then {siteId, uploadKey, sourceUploadId?, expectedHeadRevisionId?, releaseNotes?}. A sandbox whose network is limited to a few hosts cannot upload to those URLs. A static site does not use the two calls. A Wix Astro build (the project's .wix/ and dist/ after \`astro build\` with the Wix hosting adapter, zipped from the project root) needs no index.html: it is released to the site's Wix hosting instead, server-rendered pages, the same site and URL. The project's source is stored with the release when the upload holds the project and the site's repository accepts it.
72649
+ NOT a site-creation tool: a request to create, build, design or generate a site — with or without a description — never comes here first. Unless the user asked for Wix's editor or a template (WixSiteBuilder, SearchSiteTemplates), call StartDeployWebsite right away, without asking the user anything: it also takes files the user brought, uploaded first even when the site needs business features. StartHeadlessBuild instead for a new site with no files that needs Wix business features. Also NOT for media uploads to an existing site (UploadImageToWixSite) or any other API call (ExecuteWixAPI).
72650
+ `,
72651
+ // Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
72572
72652
  StartDeployWebsite: dedent_default`
72573
- The user — or you, earlier in this conversation — ALREADY HAVE a finished page or site, in any form, and it should be live on Wix — or an already-deployed Wix Headless site whose files should be replaced. The site can be HTML/CSS/JS files, a static build (dist/, out/), a zip, another AI builder's export, or a page/design you created in this conversation (export it to HTML first — a finished design IS a finished page). Call this when the user says deploy, host, publish, put online, make it live, get a URL, update my site, or upload my site / index.html.
72574
- Updates keep the same site and URL. Also for implementing a backend on such a site as a Wix Headless project — same site, same URL. Works with or without a Wix login (anonymous deploy with a save link), through the Wix MCP alone or from a shell.
72575
- Missing real functionality — a fake checkout, a form that goes nowhere, bookings — is NOT a reason to rebuild the site with a site-creation tool: deploy the page as is, then add the backend afterwards (the recipe covers it).
72576
- Returns the full recipe; follow it and run the flow yourself. The drop page is only the fallback when you can't.
72577
- NOT for: a screenshot, mockup or reference image of a site the user WANTS (nothing exists to deploy yet — that is site creation: WixSiteBuilder / templates); a Claude Design share URL (import-claude-design-from-url); migrating a live site by URL or CSV exports; adding HTML or code into an existing Wix site; uploading images or documents to a site's media (UploadImageToWixSite).
72653
+ Creates a website on Wix and puts it live, or replaces the files of one deployed earlier. You write the site's code, or take the files the user brought (HTML/CSS/JS, a static build, a zip, another builder's export), and this returns the guide to create the site and upload them. Updates keep the same site and URL. Works with or without a Wix login (anonymous deploy with a save link), through the Wix MCP alone or from a shell. Call it right away, without asking the user anything first.
72654
+ When a new site needs Wix business features (${WIX_BUSINESS_FEATURES}), call StartHeadlessBuild instead. When the user brought files and the site needs those features, upload the files here first; the upload's result then points to StartHeadlessBuild to connect them.
72655
+ Returns the guide; follow it and do the work yourself. Upload with UploadHeadlessWebsiteFiles once the site exists; the drop page is only the fallback.
72656
+ NOT for: a user who asked for Wix's editor, the Wix Harmony Editor, a template, Wix Studio or the Classic Editor (WixSiteBuilder, SearchSiteTemplates); a Claude Design bundle URL (import-claude-design-from-url); migrating a live site by URL or CSV exports; adding HTML or code into an existing Wix editor site; uploading images or documents to a site's media (UploadImageToWixSite).
72578
72657
  `,
72579
- CreateWixBusinessGuide: dedent_default`
72580
- Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
72581
- 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\`.
72582
- Exception, even when the user says "headless": if a finished page or site already exists in any form (their own HTML/CSS/JS, a static build, a zip, an AI-builder export, a page you made in this conversation) and they want it hosted, don't call this tool — call StartDeployWebsite, which returns the recipe to publish the files yourself. This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
72583
-
72584
- ## What This Tool Contains
72585
-
72586
- This tool provides complete documentation including:
72587
- - Template selection (empty sites or designed templates)
72588
- - Wix Editor vs Wix Studio options
72589
- - Regular vs Headless site creation (CLI-based; returns setup instructions)
72590
- - API endpoint details and parameters
72591
- - Post-creation steps (OAuth for headless, publishing for regular sites)
72592
- - App installation instructions
72593
-
72594
- ## After Reading This Documentation
72595
-
72596
- **After reading this documentation:**
72597
- 1. Use ManageWixSite for account-level site creation API calls
72598
- 2. Use CallWixSiteAPI / ExecuteWixAPI for site-level follow-up API calls (like install apps if needed)`
72658
+ // Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
72659
+ StartHeadlessBuild: dedent_default`
72660
+ Returns Wix's headless guide, for a site that needs Wix business features (${WIX_BUSINESS_FEATURES}), run by Wix as a Wix Headless site. You write the site; the guide creates it, connects the features, and uploads it. Also to add those features to an existing Wix Headless site (one deployed from files is one), from a project download link, or to move a Wix site to code.
72661
+ Call it right away: it only returns the guide, and the site's details are not needed first.
72662
+ NOT for: a site that needs no Wix business feature, or files the user brought that are not live yet (StartDeployWebsite: upload them first, then come back here for the features); a user who asked for Wix's editor, the Wix Harmony Editor, a template, Wix Studio or the Classic Editor, even when the site needs business features (WixSiteBuilder, SearchSiteTemplates); a Claude Design URL (import-claude-design-from-url).
72663
+ `
72599
72664
  };
72600
- }
72601
- var defaultToolDescriptions = buildToolDescriptions(true);
72665
+ descriptions.SupportAndFeedback = descriptions.ReportIssueToWix;
72666
+ return descriptions;
72667
+ }
72668
+ var defaultToolDescriptions = buildToolDescriptions(true, true, { usageGuideOnce: true });
72669
+ var WIX_SKILLS_README_SECTION = dedent_default`
72670
+ ## Wix skills
72671
+
72672
+ Wix publishes agent skills: folders of instructions, scripts and shipped code for building on Wix, each with a \`SKILL.md\` at its root that says what the skill does and which of its files to read when. The source is https://github.com/wix/skills. Three of them matter here:
72673
+
72674
+ - **wix-headless-kit**: builds a Wix Headless site on shipped, verified code. In the Wix plugin. Its contents are below.
72675
+ - **wix-headless-templates**: the code wix-headless-kit builds from, one folder per Wix Business Solution. In the Wix plugin for Codex and Cursor. Its contents are below.
72676
+ - **wix-manage**: REST recipes to configure and manage a site's business solutions. In the Wix plugin. Its \`SKILL.md\` is the index of every recipe by area, with what it does and a link to read it.
72677
+
72678
+ On a site built in code (one deployed through StartDeployWebsite, started through StartHeadlessBuild, or any Wix Headless project), wix-headless-kit carries the work, with wix-headless-templates as its code, and it names the wix-manage recipes it uses as steps.
72679
+
72680
+ ### How to read a skill
72681
+
72682
+ A skill is a folder, and every file in it has a path inside that folder (\`SKILL.md\`, \`guides/api-run.md\`). The same path finds the file on disk and online, so the paths below work either way.
72683
+
72684
+ 1. **From disk, when it is already there.** This is the preferred way: the files are complete and need no network. The Wix plugin loads its skills into the client; \`npx skills add\` puts them under \`.agents/skills/<skill>/\` in the project, or in the user's home with \`-g\`; an earlier install may have left them wherever the client keeps skills (for example \`.claude/skills/\` or the plugin's folder). Open \`<skill folder>/SKILL.md\` and the files it names. An installed copy can be an older snapshot. A file whose byte size differs from the one in the skill's manifest (below) is out of date, so read it online; a matching size makes a file likely current, not certain, so when a file decides the work, read it online too.
72685
+ 2. **Install them, with a shell that reaches the internet.** \`npx skills add wix/skills\` installs every skill; \`npx skills add wix/skills --skill wix-headless-kit\` installs one. Then read them from disk. To keep them across projects, the user can install the Wix plugin instead (in Claude Code: \`/plugin marketplace add wix/skills\`, then \`/plugin install wix@wix\`).
72686
+ 3. **Read them online, with ReadFullDocsArticle**, when neither works: no shell, or a sandbox without internet. Call ReadFullDocsArticle with the URL as \`articleUrl\`; it returns the file whole, where a client's own web tool often cannot reach www.wix.com or summarizes what it fetches. The skills registry mirrors every skill from the main branch of wix/skills:
72687
+ - **A file**: \`https://www.wix.com/skills/<skill>/<path>\`, with \`<path>\` its path inside the skill folder. Start with \`<path>\` = \`SKILL.md\`, then read the files it names.
72688
+ - **A folder**: \`https://www.wix.com/skills/<skill>/<folder>\` returns the full URL of every file under it, at any depth. \`https://www.wix.com/skills/<skill>/<folder>/_content\` returns those files' contents in one response, each under a heading with its URL, Markdown first; binary files and lockfiles are left out, and past 150K characters the rest are named by URL, to read one by one.
72689
+ - **The skill's file list**: \`https://www.wix.com/skills/<skill>/\`, with the trailing slash, returns the full URL of every file in the skill; without the slash it returns the SKILL.md.
72690
+ - **Every file in the skill**: \`https://www.wix.com/skills/<skill>.manifest.json\` lists each path with its size, under a \`base\` URL.
72691
+ - **Names and hosts**: \`<skill>\` is the folder name with or without its \`wix-\` prefix (\`wix-headless-kit\` or \`headless-kit\`), and \`dev.wix.com\` works in place of \`www.wix.com\`.
72692
+ - **What comes back**: a Markdown file comes with a short note on top (it is mirrored from the main branch of wix/skills; the skill's manifest, folder listings, \`_content\`, and ReadFullDocsArticle) and its relative links turned into full URLs; code, scripts and JSON come as they are.
72693
+ - **A wrong path**: the answer names the files with that name elsewhere in the skill and the manifest URL, so one more call reaches the right file. ReadFullDocsArticle shows that answer as an error.
72694
+ - **Not served**: a whole skill as one page (\`<skill>-full\`) returns 404; read the skill's files instead.
72695
+
72696
+ The wix-manage recipes are also published in the Wix docs, as articles at \`…/skills/<recipe>\` under each API's section. Find the one that matches the task in the skill's recipe index (\`SKILL.md\`) or with SearchWixRESTDocumentation, and read it with ReadFullDocsArticle. Only wix-manage is in the docs. For example, one recipe in all three places:
72697
+ - on disk: \`<wix-manage folder>/references/sites/upload-static-site.md\`;
72698
+ - in the registry: https://www.wix.com/skills/manage/references/sites/upload-static-site.md;
72699
+ - in the docs: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.
72700
+
72701
+ ### wix-manage
72702
+
72703
+ REST recipes for managing a site's business solutions: one recipe per task (installing apps, products, booking services, CMS items, SEO, domains and more), each with the exact endpoints, request bodies and order of steps. Open the recipe for a task before calling its APIs.
72704
+
72705
+ Ways to find and read a recipe, in this order:
72706
+ 1. **On disk**: the Wix plugin's wix-manage folder, or \`.agents/skills/wix-manage/\` after \`npx skills add wix/skills --skill wix-manage\`. \`SKILL.md\` lists every recipe by area with what it does; the recipe itself is under \`references/<area>/\` (ecommerce nests one more folder, such as \`references/ecommerce/shipping/\`), so open the path \`SKILL.md\` gives rather than building it. An installed copy can be an older snapshot: when a recipe decides the work, read it online too.
72707
+ 2. **Online**: the list of every recipe by area, each a link to its docs article, is https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills/wix-management-recipes-index.md. Read it with ReadFullDocsArticle, or with \`curl\` from a shell, then read the recipe for the task the same way. It is public: no sign-in or token.
72708
+
72709
+ Using a recipe: follow its steps, and make its calls with ExecuteWixAPI, passing the recipe's docs URL in \`sourceDocUrls\`. When a recipe's example doesn't fit a call, read that method's schema with SearchWixAPISpec first. When no recipe matches the task, find the method with SearchWixRESTDocumentation or BrowseWixRESTDocsMenu, read it with ReadFullDocsArticle, and call it the same way.
72710
+ Each API area also has a page that lists only its own recipes: the area's docs section with \`/skills.md\` appended. These are the ones today, but it is not a closed list: areas are added, so look a task up in the full list first, and for an API not named here try its section URL with \`/skills.md\` appended.
72711
+ - Accessibility: https://dev.wix.com/docs/api-reference/site/accessibility/skills.md
72712
+ - Analytics: https://dev.wix.com/docs/api-reference/business-management/analytics/skills.md
72713
+ - App Installation: https://dev.wix.com/docs/api-reference/business-management/app-installation/skills.md
72714
+ - App tools: https://dev.wix.com/docs/api-reference/app-management/app-tools/skills.md
72715
+ - Automations: https://dev.wix.com/docs/api-reference/business-management/automations/skills.md
72716
+ - Blog: https://dev.wix.com/docs/api-reference/business-solutions/blog/skills.md
72717
+ - Bookings: https://dev.wix.com/docs/api-reference/business-solutions/bookings/skills.md
72718
+ - Calendar: https://dev.wix.com/docs/api-reference/business-management/calendar/skills.md
72719
+ - CMS: https://dev.wix.com/docs/api-reference/business-solutions/cms/skills.md
72720
+ - Contacts: https://dev.wix.com/docs/api-reference/crm/members-contacts/contacts/skills.md
72721
+ - Domains: https://dev.wix.com/docs/api-reference/account-level/domains/skills.md
72722
+ - eCommerce: https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills.md
72723
+ - Events: https://dev.wix.com/docs/api-reference/business-solutions/events/skills.md
72724
+ - Forms: https://dev.wix.com/docs/api-reference/crm/forms/skills.md
72725
+ - Get Paid: https://dev.wix.com/docs/api-reference/business-management/get-paid/skills.md
72726
+ - Google Ads: https://dev.wix.com/docs/api-reference/business-management/marketing/ads/google-ads/skills.md
72727
+ - Google Business Profile: https://dev.wix.com/docs/api-reference/business-management/google-business-profile/skills.md
72728
+ - Google Search Console: https://dev.wix.com/docs/api-reference/business-management/seo/google-search-console/skills.md
72729
+ - Headless: https://dev.wix.com/docs/api-reference/business-management/headless/skills.md
72730
+ - Marketing: https://dev.wix.com/docs/api-reference/business-management/marketing/skills.md
72731
+ - Media: https://dev.wix.com/docs/api-reference/assets/media/skills.md
72732
+ - Pricing Plans: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/skills.md
72733
+ - Restaurants: https://dev.wix.com/docs/api-reference/business-solutions/restaurants/skills.md
72734
+ - Rich Content: https://dev.wix.com/docs/api-reference/assets/rich-content/skills.md
72735
+ - SEO: https://dev.wix.com/docs/api-reference/business-management/seo/skills.md
72736
+ - SEO redirects: https://dev.wix.com/docs/api-reference/business-management/seo/redirects/skills.md
72737
+ - Site Properties: https://dev.wix.com/docs/api-reference/business-management/site-properties/skills.md
72738
+ - Sites: https://dev.wix.com/docs/api-reference/account-level/sites/skills.md
72739
+ - Stores: https://dev.wix.com/docs/api-reference/business-solutions/stores/skills.md
72740
+ - Wix MCP: https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills.md
72741
+
72742
+ ### wix-headless-kit
72743
+
72744
+ Builds a Wix Headless site on shipped, verified code instead of writing the integration: each Wix Business Solution comes with a typed data layer, hooks, components, pages and a seed script that are already correct. The data layer ships twice, on \`@wix/sdk\` for the React core and as plain REST calls for a stack that cannot run it (\`guides/reference-mode.md\`), and the agent's work narrows to brand, layout, copy and wiring. It runs as a CLI flow from a shell that reaches Wix, and as Wix API calls through this MCP when it cannot.
72745
+
72746
+ Paths are inside the skill folder; online, each is \`https://www.wix.com/skills/headless-kit/<path>\`.
72747
+ - Before the skill: the cold start installs it, signs in and hands off. It is another skill's file, https://www.wix.com/skills/headless-cold-start/headless-kit.md, and StartHeadlessBuild returns it.
72748
+ - \`SKILL.md\`: the steps of a build and the table of Business Solutions the kit ships.
72749
+ - \`guides/api-run.md\`: the whole run as Wix API calls through this MCP, for an agent whose shell cannot reach Wix or that has no shell.
72750
+ - \`guides/capabilities.md\`: which Wix product owns which feature, and what the kit ships for it.
72751
+ - \`guides/existing-site.md\`: a new frontend for a Wix site that already has its content.
72752
+ - \`guides/migration.md\`: a site moving to code after "Go Headless" in its dashboard.
72753
+ - \`guides/reference-mode.md\`: a stack that cannot run the shipped React code (a static site, a server-rendered app in another language).
72754
+ - \`guides/feedback.md\`: sending the user's building-with-Wix feedback to Wix.
72755
+ - \`install/\`: the bootstrap, setup, deploy and templates scripts, and \`install/pins.json\` with the pinned CLI and templates versions.
72756
+
72757
+ ### wix-headless-templates
72758
+
72759
+ The code wix-headless-kit builds from, one folder per Wix Business Solution: \`storefront\`, \`bookings\`, \`rentals\`, \`blog\`, \`cms\`, \`forms\`, \`members\`, \`events\`, \`restaurants\`, \`donations\`, \`pricing-plans\`, \`portfolio\`, \`faq\`. It holds no flow of its own; wix-headless-kit fetches it and copies, deploys and seeds from it.
72760
+
72761
+ Paths are inside the skill folder; online, each is \`https://www.wix.com/skills/headless-templates/<path>\`. Every Business Solution folder has the same parts, with \`<solution>\` one of the names above:
72762
+ - \`<solution>/INSTRUCTIONS.md\`: the playbook, covering what ships, what you build, and each page's contract.
72763
+ - \`<solution>/app/\`: the typed React core: the data layer under \`wix/<solution>/\`, hooks and components.
72764
+ - \`<solution>/app-astro/\`: the Astro page skeletons for Wix-managed Astro sites (every solution but \`forms\`).
72765
+ - \`<solution>/project/\`: the whole runnable project for that solution.
72766
+ - \`<solution>/rest/\`: the same data layer as plain REST calls, for stacks that cannot run the React core.
72767
+ - \`<solution>/seed/SEED.md\`: how to seed that solution's content, with the script that creates it in the right order.
72768
+
72769
+ Shared by every solution:
72770
+ - \`shared/DESIGN.md\`: the design floor when the brief gives no design direction.
72771
+ - \`shared/CONTENT.md\`: the copy floor for every page written.
72772
+ - \`shared/SUPPLIED-CONTENT.md\`: content the user brings (a CSV, a menu, a folder of photos) as the seed plan.
72773
+ - \`shared/CUSTOM_OPERATIONS.md\`: operations beyond what the shipped code covers.
72774
+ - \`shared/rest/client.ts\`: the REST client the \`rest/\` layers use.
72775
+
72776
+ Online, a solution's folder lists everything it ships: https://www.wix.com/skills/headless-templates/storefront returns the URLs of the store's files, and \`…/storefront/app\` those of its React core. A part is often small enough to read whole in one call: https://www.wix.com/skills/headless-templates/storefront/seed/_content returns the store's seeding guide and scripts together. A whole solution passes the 150K cap, so read it part by part.
72777
+ `;
72602
72778
  var recipesIndexDoc = {
72603
72779
  url: "https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills/wix-management-recipes-index",
72604
72780
  action: "include"
72605
72781
  };
72606
72782
  var README_INTRO = dedent_default`
72607
- <agent-mandatory-instructions>
72783
+ # How to work with Wix through these tools
72608
72784
 
72609
- YOU MUST READ AND FOLLOW THE AGENT-MANDATORY-INSTRUCTIONS BELOW:
72785
+ ## Source of truth
72610
72786
 
72611
- <source-of-truth>
72612
- Do not answer from memory about anything Wix-specific — this covers every part of your answer, not only API calls: any URL, link, ID, setting location, or product fact you give the user must come from the docs tools, the recipes below, a previous tool result in this conversation, or the user's own message (identifiers and URLs the user supplies are fine to use as given). If a recipe in the index below matches what the user asked for, read it before answering. For APIs, use the search, browse, read-docs, and schema tools as the source of truth for the exact URL, HTTP method, request body shape, response shape, field names, required fields, and enum values before calling an API.
72613
- </source-of-truth>
72787
+ Do not answer from memory about anything Wix-specific — this covers every part of your answer, not only API calls: any URL, link, ID, setting location, or product fact you give the user must come from the docs tools, a Wix skill (installed, or read online as the Wix skills section below explains), a previous tool result in this conversation, or the user's own message (identifiers and URLs the user supplies are fine to use as given). When a Wix skill covers what the user asked for, read it before answering. For APIs, use the search, browse, read-docs, and schema tools as the source of truth for the exact URL, HTTP method, request body shape, response shape, field names, required fields, and enum values before calling an API.
72614
72788
 
72615
- <management-flow>
72616
- <goal>
72789
+ ## Goal
72617
72790
  `;
72618
- var README_FLOWS_HEADING = dedent_default`
72619
- </goal>
72791
+ var README_FLOWS_HEADING = "## Wix MCP Flows";
72792
+ var README_FLOWS_SITE = dedent_default`
72793
+ ### The site
72620
72794
 
72621
- ## Wix MCP Site Management Flows
72795
+ The site context below lists the account's sites with their installed apps. Take the \`siteId\` from there; when more than one site fits and the user's words don't pick one, ask which before any read or write. A business solution's API (Stores, Bookings, CMS and the rest) works only on a site with that app installed, and some apps have versions with different endpoints (Wix Stores V1 vs V3): check the site's apps first, and when the app is missing, install it (a Wix skill has the steps) before using its API.
72622
72796
  `;
72623
- var README_BODY = dedent_default`
72624
- ### Discovery & Call Flow
72797
+ var README_FIND_SOURCES = dedent_default`
72798
+ ### Find the method
72625
72799
 
72626
- Common paths (use the highest you can satisfy for each method you'll call):
72627
- - Already have what you need from previous tool results in this conversation (not from memory) → ExecuteWixAPI
72628
- - Pick a matching article from the Recipes index below → ReadFullDocsArticle (find relevant code examples) → (probe SearchWixAPISpec for response shapes if needed) → ExecuteWixAPI
72629
- - SearchWixRESTDocumentation or BrowseWixRESTDocsMenu → ReadFullDocsArticle (find relevant code examples) → (probe SearchWixAPISpec for response shapes if needed) → ExecuteWixAPI
72630
- - SearchWixRESTDocumentation or BrowseWixRESTDocsMenu → ReadFullDocsArticle (no usable example) → SearchWixAPISpec for request schemas → ExecuteWixAPI
72800
+ A task may need several API methods. For each, take the first source that gives it:
72801
+ - A previous tool result in this conversation (not memory) already shows its request: go straight to the call.
72802
+ - A Wix skill that covers the task (the Wix skills section below says what each is for): follow it, from disk or online. When its example for a call matches your case, that is the source: pass its docs URL in \`sourceDocUrls\` instead of searching for the method pages (when it has no docs URL, one SearchWixRESTDocumentation call on its title finds the article).
72803
+ - The docs: SearchWixRESTDocumentation (semantic search) or BrowseWixRESTDocsMenu (menu hierarchy), then ReadFullDocsArticle on the method's article for its code examples. For SDK code, the CLI, a headless site or an app, start from those docs instead: SearchWixSDKDocumentation, SearchWixCLIDocumentation, SearchWixHeadlessDocumentation, SearchBuildAppsDocumentation.
72631
72804
 
72632
- Fallbacks: use ReadFullDocsMethodSchema in place of SearchWixAPISpec when SearchWixAPISpec is unavailable or didn't return enough detail; use CallWixSiteAPI in place of ExecuteWixAPI when a single REST call is enough and code adds no value.
72805
+ Keep each method's docs URL even when no source gives a usable example: the shape comes from its schema, as the next section says.
72806
+ `;
72807
+ var README_FLOWS_BODY = dedent_default`
72808
+ ### The exact shape
72633
72809
 
72634
- Tools (relevant for the management flow):
72635
- - SearchWixRESTDocumentation — semantic search over the Wix REST docs by keywords or natural-language queries.
72636
- - BrowseWixRESTDocsMenu — navigate the Wix REST docs by menu hierarchy; alternative to keyword search.
72637
- - ReadFullDocsArticle — fetch a full docs article by its docs URL; returns prose, fields, and code examples.
72638
- - SearchWixAPISpec — JS-sandboxed query over the REST API spec; returns request schema, response schema, and the executable \`method.publicUrl\`.
72639
- - ExecuteWixAPI — runs an async JS function in a sandbox with \`wix.request()\`; a single invocation can chain multiple API calls, paginate, loop, transform, and branch.
72810
+ A code example is the model for your call only when it matches your case, with every field your case needs. Fill the rest from the method's schema: SearchWixAPISpec on its docs URL (REST or SDK) returns the request and response schemas, \`method.publicUrl\` and \`method.sdk\`; ReadFullDocsMethodSchema when SearchWixAPISpec isn't available. A query's filter and sort fields and operators are a closed list per method: use only what its schema declares.
72640
72811
 
72641
- Steps:
72812
+ None of this comes from memory.
72642
72813
 
72643
- 1. A single user task may need one or more API methods. For each method you'll call, find a code example that fits the user's intent — you'll model the API call (URL, method, body) on it. An example only "fits" if it is **complete** (not truncated) AND matches your exact case — same operation and same variant/shape (e.g. the same \`productType\`), with every field your case needs actually shown. **If the closest example is truncated (it shows a \`... N more lines ...\` marker), do NOT call the API off it; continue discovery first: \`ReadFullDocsArticle\` for the complete example, or \`SearchWixAPISpec\` for the exact request schema.** Never fill in required fields from memory. Skip this step for any method you already have from a previous tool result in this conversation (not from memory):
72644
- a. First try the WixREADME Recipes index below (pre-curated guides for common tasks). If a recipe matches, ReadFullDocsArticle on its docs URL to find relevant code examples; many recipes cover multi-step flows and supply code examples for several methods in one article.
72645
- b. If no recipe matches the user's intent, or the matched recipe didn't yield the code examples you need, discover each missing method's docs URL via SearchWixRESTDocumentation (semantic search) or BrowseWixRESTDocsMenu (menu hierarchy), then ReadFullDocsArticle on each to find relevant code examples.
72646
- c. If neither path turns up a usable code example for some method, continue without one for that method — step 2 will derive its request directly from the schema. Make sure you've still captured the docs URL of each method.
72814
+ ### The call, or the code that makes it
72647
72815
 
72648
- 2. Before calling, fill any remaining gaps with SearchWixAPISpec on each method's docs URL. It returns both request and response schemas. For each method, check:
72649
- - **Request** (URL, HTTP method, body fields) — skip the probe if a code example already shows them; otherwise SearchWixAPISpec returns publicUrl + exact request shape.
72650
- - **Response shape** (field paths your code will read) — only relevant if your code reads response fields; skip the probe if the article(s) already made it clear; otherwise probe SearchWixAPISpec for the response schema.
72651
- - **Filter and sort** (query/search methods only) — an example proves only the fields and operators it uses. Each method declares which fields it can filter and sort by, and with which operators; that list is closed for fields and their operators and covers that method only — \`$and\`/\`$or\`/\`$not\` are filter syntax and never appear in it. Anything else errors or silently returns the wrong rows. A listed operator is valid on its own, since a field takes a single operator; to combine conditions, use the logical operators instead — \`$and\` and \`$or\` take an array of expressions, \`$not\` takes one, and they can nest.
72652
- - Never guess any of this from memory.
72816
+ **Call it with ExecuteWixAPI**: one async JS function with \`wix.request()\`, holding every step of the task that code can resolve. The reads that fetch an ID, check whether a record exists or list items to choose from go in the same function as the writes they feed; step numbers in a guide or skill give logical order, not separate calls. Set \`hasMutations: true\` when any step writes. Return the write's response as is and report from it; don't read again to confirm. A new invocation only for what code can't resolve: the user's answer, or a job that finishes later. One function chains calls, paginates, lists all, loops, transforms and branches. Without ExecuteWixAPI, make each call with CallWixSiteAPI (a site's APIs) or ManageWixSite (the account's), from the same exact shape.
72653
72817
 
72654
- 3. Before calling: collapse ALL planned steps — preliminary reads AND mutations — into a single async function. Step numbers in any guide or skill doc describe logical order for human comprehension — they do NOT define invocation boundaries. Steps that feed into each other belong in a single invocation: read, use the result, write, and return. A read that fetches IDs or checks existence before a create/update is part of that mutation's invocation, not a separate preceding call. This includes any read whose result feeds directly into a subsequent write — fetching a required ID, checking whether a record already exists, listing items to choose one — all belong in the same invocation as the write that follows. Set hasMutations: true whenever any step in the function writes. Return the mutation response directly — do not follow up with a read to confirm what was just created or updated; trust the response. Only split into multiple invocations when a later step genuinely depends on information you cannot resolve in code (e.g. a user decision or an out-of-band event). A single invocation can chain several related calls, paginate, "list all", loop, transform, and branch on responses.
72818
+ **Write the code** when the task is code the user keeps: an app (built and run with the Wix CLI), a headless site, or a script that calls the REST API or the JavaScript SDK. The path is the same: find the method, learn its exact shape, then write the call from \`method.publicUrl\` (REST) or \`method.sdk\` (the JavaScript SDK), never from memory. Every way of building against Wix in code is this path; the headless skills are a shortcut on it, not a different one. wix-headless-kit builds a Wix Headless site from shipped, verified code (wix-headless-templates holds it, one folder per business solution: a \`@wix/sdk\` React core, and the same data layer as plain REST calls for a stack that cannot run it): scaffold with the CLI, deploy, seed, design the presentation on the shipped code, release. What no shipped solution covers is written from the docs, as above. A new site is written in code and uploaded: StartDeployWebsite returns the upload guide (create the site, upload its files, change them later); StartHeadlessBuild returns the headless guide, for a site that needs Wix business features: you write the site, and the guide creates it, connects the features and uploads it, through the cold start that hands off to the kit (or the same run as API calls when there is no shell).
72655
72819
 
72656
- </management-flow>
72820
+ ### When a call fails
72657
72821
 
72658
- <other-uses>
72659
- Beyond managing user sites, the Wix MCP tools can be used for any other purpose they support — for example, reading Wix SDK docs to write code against the SDK, using the Wix CLI to create apps, answering documentation questions, and so on.
72660
- </other-uses>
72661
- </agent-mandatory-instructions>
72822
+ The error carries the failed call's status and message and a Wix request id. Read it: it says what was wrong, and that is what to fix before calling again, whether the request (from the schema), the site and what is installed on it, or what the account is allowed to do. Never resend the same request unchanged, and never guess a fix. When you report the failure to the user, include the request id.
72662
72823
  `;
72663
- var defaultReadmeDocs = [
72664
- {
72665
- action: "text",
72666
- content: [
72667
- README_INTRO,
72668
- AGENT_GOAL,
72669
- README_FLOWS_HEADING,
72670
- "",
72671
- README_BODY
72672
- ].join("\n")
72673
- },
72674
- recipesIndexDoc
72675
- ];
72824
+ function buildReadmeDocs({
72825
+ recipesIndex = true
72826
+ } = {}) {
72827
+ return [
72828
+ {
72829
+ action: "text",
72830
+ content: [
72831
+ README_INTRO,
72832
+ "",
72833
+ AGENT_GOAL,
72834
+ "",
72835
+ README_FLOWS_HEADING,
72836
+ "",
72837
+ README_FLOWS_SITE,
72838
+ "",
72839
+ README_FIND_SOURCES,
72840
+ "",
72841
+ README_FLOWS_BODY
72842
+ ].join("\n")
72843
+ },
72844
+ { action: "text", content: WIX_SKILLS_README_SECTION },
72845
+ ...recipesIndex ? [recipesIndexDoc] : []
72846
+ ];
72847
+ }
72848
+ var defaultReadmeDocs = buildReadmeDocs();
72676
72849
  var widgetSiteCreationConfig = {
72677
72850
  toolDescriptions: Object.fromEntries(
72678
72851
  [
72679
72852
  "WixSiteBuilder",
72680
72853
  "WixSiteCreation",
72681
72854
  "SearchSiteTemplates",
72682
- "CreateSiteFromTemplate",
72683
- "CreateWixBusinessGuide"
72855
+ "CreateSiteFromTemplate"
72684
72856
  ].map((tool) => [tool, toWidget(defaultToolDescriptions[tool])])
72685
72857
  )
72686
72858
  };
@@ -72824,6 +72996,9 @@ function renderApps(apps, knownApps) {
72824
72996
  if (app.catalogVersion) {
72825
72997
  line += ` \u2014 Catalog app version: **${app.catalogVersion}**`;
72826
72998
  }
72999
+ if (app.invoicesVersion) {
73000
+ line += ` \u2014 Invoices app version: **${app.invoicesVersion}**`;
73001
+ }
72827
73002
  lines.push(line);
72828
73003
  }
72829
73004
  return lines.join("\n");
@@ -72844,6 +73019,11 @@ function renderCustomAppsWithSkillsTools(apps) {
72844
73019
  }
72845
73020
  return lines.join("\n");
72846
73021
  }
73022
+ function renderCompanionApp(installedApps) {
73023
+ const appId = installedApps.find((app) => app.companionApp === true)?.appId;
73024
+ if (!appId || !GUID_PATTERN.test(appId)) return "";
73025
+ return `The site's code lives in its companion app (ID: \`${appId}\`).`;
73026
+ }
72847
73027
  function renderProperties(props) {
72848
73028
  const sections = [];
72849
73029
  const regionalFormat = [];
@@ -72870,7 +73050,7 @@ ${contact.join("\n")}`);
72870
73050
  }
72871
73051
  return sections.join("\n\n");
72872
73052
  }
72873
- function renderSite(site, index, knownApps) {
73053
+ function renderSite(site, index, knownApps, includeCompanionApp) {
72874
73054
  const lines = [];
72875
73055
  const heading = site.displayName ?? `Site ${index}`;
72876
73056
  lines.push(`## ${index}. ${heading}`);
@@ -72915,6 +73095,13 @@ function renderSite(site, index, knownApps) {
72915
73095
  lines.push("");
72916
73096
  lines.push(customAppsWithSkillsToolsContent);
72917
73097
  }
73098
+ const companionAppContent = includeCompanionApp ? renderCompanionApp(site.installedApps ?? []) : "";
73099
+ if (companionAppContent) {
73100
+ lines.push("");
73101
+ lines.push("### Site code (companion app)");
73102
+ lines.push("");
73103
+ lines.push(companionAppContent);
73104
+ }
72918
73105
  lines.push("");
72919
73106
  lines.push("---");
72920
73107
  lines.push("");
@@ -72934,6 +73121,7 @@ function enrichDynamicContext(data, knownApps = {}, options = {}) {
72934
73121
  const response = snakeToCamel(parsed);
72935
73122
  const includePartnerContext = options.includePartnerContext ?? false;
72936
73123
  const includeAccountContext = options.includeAccountContext ?? false;
73124
+ const includeCompanionApp = options.includeCompanionApp ?? false;
72937
73125
  const sections = [];
72938
73126
  const allSites = response.sites ?? [];
72939
73127
  const maxSites = options.maxSites ?? Infinity;
@@ -72986,9 +73174,18 @@ function enrichDynamicContext(data, knownApps = {}, options = {}) {
72986
73174
  );
72987
73175
  sections.push("");
72988
73176
  }
73177
+ const hasInvoicesVersion = sitesToRender.some(
73178
+ (site) => site.installedApps?.some((app) => app.appId && knownApps[app.appId] && app.invoicesVersion)
73179
+ );
73180
+ if (hasInvoicesVersion) {
73181
+ sections.push(
73182
+ "> **Wix Invoices \u2014 Version**: Some sites below have Wix Invoices installed and show their Invoices version (V1/V2). When working on an Invoices task, check the version for that site \u2014 only read recipes and call endpoints that match its version. Never use an Invoices V2 skill or API on a V1 site, and vice versa."
73183
+ );
73184
+ sections.push("");
73185
+ }
72989
73186
  if (sitesToRender.length) {
72990
73187
  for (let i2 = 0; i2 < sitesToRender.length; i2++) {
72991
- sections.push(renderSite(sitesToRender[i2], i2 + 1, knownApps));
73188
+ sections.push(renderSite(sitesToRender[i2], i2 + 1, knownApps, includeCompanionApp));
72992
73189
  }
72993
73190
  }
72994
73191
  if (!response.account && !siteCount && (!includePartnerContext || !hasPartnerContext(response.partnerContext))) {
@@ -72996,9 +73193,11 @@ function enrichDynamicContext(data, knownApps = {}, options = {}) {
72996
73193
  }
72997
73194
  return sections.join("\n");
72998
73195
  }
73196
+ var GUID_PATTERN;
72999
73197
  var init_enrich = __esm2({
73000
73198
  "src/enrich.ts"() {
73001
73199
  "use strict";
73200
+ GUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
73002
73201
  }
73003
73202
  });
73004
73203
  init_enrich();
@@ -73061,6 +73260,7 @@ async function getDynamicContext(auth, httpClient, filter, options) {
73061
73260
  } : options;
73062
73261
  const includePartnerContext = contextOptions?.partnerContextEnabled ?? true;
73063
73262
  const includeAccountContext = contextOptions?.includeAccountContext ?? true;
73263
+ const includeCompanionApp = contextOptions?.includeCompanionApp ?? false;
73064
73264
  try {
73065
73265
  const accountHeaders = await auth.getAccountAuthHeaders();
73066
73266
  const noFilter = !filter?.siteId && !filter?.siteName;
@@ -73114,6 +73314,7 @@ async function getDynamicContext(auth, httpClient, filter, options) {
73114
73314
  const context2 = enrichDynamicContext2(response.data, known_apps_default, {
73115
73315
  includePartnerContext,
73116
73316
  includeAccountContext,
73317
+ includeCompanionApp,
73117
73318
  // Cap the account-wide view to the first N sites; a targeted fetch returns one site.
73118
73319
  ...noFilter ? { maxSites: MAX_SITES_FOR_DYNAMIC_CONTEXT, totalSiteCount } : {}
73119
73320
  });
@@ -73167,6 +73368,21 @@ function isApiUrlAllowed(url) {
73167
73368
  }
73168
73369
 
73169
73370
  // src/config/param-descriptions.ts
73371
+ var REPORT_ISSUE_TO_WIX_PARAMS = {
73372
+ message: [
73373
+ "The report of one issue, sent to Wix as free text. Only this issue \u2014 no session summary, play-by-play or unrelated problems:",
73374
+ "- What was being attempted, in a sentence.",
73375
+ "- The tool or endpoint, the HTTP status and the error message.",
73376
+ "- What you expected instead, and the workaround if any.",
73377
+ "- Where the fault likely lives (API behavior / API schema / docs / Wix tooling / unsure), and whether you confirmed it.",
73378
+ "- The context needed to reproduce it: agent/model, site id, the Wix area or API.",
73379
+ "- The user's own words, verbatim, if they added any.",
73380
+ "NEVER include secrets \u2014 no bearer tokens, API keys, or credentials \u2014 and no personal data beyond what the report needs."
73381
+ ].join("\n"),
73382
+ requestId: "Optional request id (x-wix-request-id) of the failed Wix API call this report is about."
73383
+ };
73384
+ var WHY_NOT_EXECUTE_RECONNECT = "if the Wix MCP doesn't offer it at all, say so here, and tell the user once that their Wix connection may be an old or cached version that a reconnect refreshes.";
73385
+ var WHY_NOT_EXECUTE_NO_EXECUTE = "if it isn't in your tool list, say so.";
73170
73386
  var paramDescriptions = {
73171
73387
  CallWixSiteAPI: {
73172
73388
  siteId: "The id of the site selected using site selection tool",
@@ -73183,6 +73399,7 @@ var paramDescriptions = {
73183
73399
  WQL_FILTER_RULE
73184
73400
  ].join("\n"),
73185
73401
  reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
73402
+ whyNotExecuteWixAPI: `One sentence: why this call goes through CallWixSiteAPI and not ExecuteWixAPI, the preferred tool. If ExecuteWixAPI isn't loaded, load it through your client's tool search before calling this tool; ${WHY_NOT_EXECUTE_RECONNECT}`,
73186
73403
  sourceDocUrl: [
73187
73404
  "The URL of the documentation or recipe where you found this API endpoint.",
73188
73405
  "MAKE SURE THE ENDPOINT URL IS REALLY THERE AND YOUR ARE NOT GUESSING IT !!!",
@@ -73218,18 +73435,9 @@ var paramDescriptions = {
73218
73435
  'Use ["other"] ONLY IF YOU HAVE A VERY GOOD REASON TO DO SO'
73219
73436
  ].join("\n")
73220
73437
  },
73221
- SupportAndFeedback: {
73222
- message: [
73223
- "The composed feedback message to send to Wix. Wix receives only free text, so a bare sentence is low-signal \u2014 send a summary of the whole session, not just the last error. Structure it in three layers:",
73224
- "1. Provenance \u2014 labelled lines (omit ones that do not apply): agent/model, Wix tooling used, Wix areas/APIs touched, Wix products (stores, bookings, ...), site id, relevant links (dashboard, docs pages read, live site) and other ids created this run.",
73225
- `2. Narrative \u2014 "In the user's words": anything the user added when you offered, quoted verbatim (redact secrets only). Then user intent + run summary (what they set out to build, what worked vs. what fought back), a condensed play-by-play of the session (key exchanges, tool calls, decisions), and the friction points \u2014 every place something got in the way, each with specifics: the step/endpoint, HTTP status and error message, the gap, the workaround, and what you expected instead. Include issues you recovered from.`,
73226
- '3. Attribution \u2014 for each significant friction point, your best diagnosis of where the fault lives: API behavior / API schema / API reference docs / docs articles or examples / Wix tooling (MCP tools, auth flow) / other-unsure \u2014 plus whether you confirmed it or are assuming. Do not force a tag; "unsure" beats a wrong route.',
73227
- "End with a bottom line: one or two sentences naming the single most important problem and its impact \u2014 a concise engineering assessment, not softened or hedged.",
73228
- "Write it as a scannable few paragraphs or a short bulleted list \u2014 thorough on the friction, distilled rather than a transcript dump.",
73229
- "NEVER include secrets \u2014 no bearer tokens, API keys, or credentials \u2014 and no personal data beyond what the feedback needs."
73230
- ].join("\n"),
73231
- requestId: "Optional request id (x-wix-request-id) returned from a failed Wix API call this feedback relates to."
73232
- },
73438
+ ReportIssueToWix: REPORT_ISSUE_TO_WIX_PARAMS,
73439
+ // The tool's former name, kept for importers that read it by that key.
73440
+ SupportAndFeedback: REPORT_ISSUE_TO_WIX_PARAMS,
73233
73441
  SearchWixWDSDocumentation: {
73234
73442
  searchTerm: "The search term to search for in the Wix Design System Documentation",
73235
73443
  maxResults: "The maximum number of results to return, default is 10, max is 15"
@@ -73268,8 +73476,13 @@ var paramDescriptions = {
73268
73476
  maxResults: "The maximum number of results to return, default is 10, max is 15",
73269
73477
  reason: "One sentence describing the original user request and the task you are trying to accomplish with this search."
73270
73478
  },
73479
+ SearchWixHelpCenter: {
73480
+ searchTerm: 'What the site owner wants to do or fix, in plain words (e.g. "connect a domain bought elsewhere", "cancel a Premium plan")',
73481
+ maxResults: "The maximum number of articles to return (1\u201315, default 15). Each article is returned with up to 60 lines.",
73482
+ reason: "One sentence describing the original user request and the task you are trying to accomplish with this search."
73483
+ },
73271
73484
  ReadFullDocsArticle: {
73272
- articleUrl: "The URL of the docs article or method article to fetch. Should be something like https://dev.wix.com/docs/.../... For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include the query param ?apiView=SDK (e.g. https://dev.wix.com/docs/...?apiView=SDK). Wix skills pages (https://www.wix.com/skills/..., https://dev.wix.com/docs/skills/...) are read as-is, including their referenced files."
73485
+ articleUrl: "The URL of the docs article or method article to fetch. Should be something like https://dev.wix.com/docs/.../... For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include the query param ?apiView=SDK (e.g. https://dev.wix.com/docs/...?apiView=SDK). Wix Help Center articles (https://support.wix.com/en/article/...) are read as-is. Wix skills pages (https://www.wix.com/skills/..., https://dev.wix.com/docs/skills/...) and Wix Headless agent pages (https://www.wix.com/headless/..., e.g. https://www.wix.com/headless/skill.md) are read as-is, including their referenced files. Source links (https://dev.wix.com/rawdocs/api/get-source-content?repo=...&path=...) found in skills and recipes are read as-is."
73273
73486
  },
73274
73487
  ReadFullDocsMethodSchema: {
73275
73488
  articleUrl: "The URL of the documentation to fetch. Should be something like https://dev.wix.com/docs/.../... For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include the query param ?apiView=SDK (e.g. https://dev.wix.com/docs/...?apiView=SDK).",
@@ -73285,7 +73498,7 @@ var paramDescriptions = {
73285
73498
  },
73286
73499
  UploadImageToWixSite: {
73287
73500
  siteId: "The ID (UUID) of the Wix site to upload to. REQUIRED. If the user has not clearly specified which site, ASK them which site to upload to (or use ListWixSites to help them pick) BEFORE calling this tool. NEVER call this tool with a missing, empty, placeholder, or guessed siteId \u2014 ask first instead.",
73288
- image: "Array of file ATTACHMENTS: files the user uploaded in the chat, or files you created in your own file sandbox. Each item requires download_url and file_id, and may optionally include file_name and mime_type \u2014 the platform resolves a file passed here into these fields automatically, so just include the files. For plain image URLs the user pasted, use imageUrls instead. ALWAYS pass ALL attachments together in a single call \u2014 NEVER call this tool once per image. Do NOT use together with imageBase64.",
73501
+ image: `${fileParamNote("send the image as imageBase64 (the whole file, one per call) or as a public URL in imageUrls")} For plain image URLs the user pasted, use imageUrls instead. ALWAYS pass ALL files together in a single call \u2014 NEVER call this tool once per image. Do NOT use together with imageBase64.`,
73289
73502
  imageUrls: "Array of publicly accessible image URLs (e.g. links the user pasted or URLs produced by other tools). Use this for plain URLs that are NOT chat attachments \u2014 no file_id is needed. ALWAYS pass ALL URLs together in a single call. Can be combined with image; do NOT use together with imageBase64.",
73290
73503
  imageBase64: 'Base64-encoded image data. Use when the client can read a file and encode it as base64. May include a data URL prefix (e.g. "data:image/jpeg;base64,...") or be raw base64. Do NOT use together with image.',
73291
73504
  mimeType: 'MIME type of the image (e.g. "image/jpeg", "image/png", "image/webp"). Required when imageBase64 does not include a data URL prefix.',
@@ -73309,7 +73522,7 @@ var paramDescriptions = {
73309
73522
  operationName: "Operation to run when the document defines more than one named operation.",
73310
73523
  siteId: "The Wix site to run against. Required for site-level operations (anything reading or writing inside a site \u2014 products, orders, contacts, bookings, CMS, blog, members ...). Resolve it with GetSiteContext or ListWixSites; never pass a guessed value.",
73311
73524
  scope: '"site" (default when siteId is given) runs with a site-scoped credential; "account" runs account-level operations (sites, account settings) and ignores siteId.',
73312
- hasMutations: "Whether this document creates, updates, deletes or otherwise mutates Wix data. True for any mutation root field (in any operation of the document) even when the intent is inspection; false only for pure queries. This flag alone decides whether a transient server error may be retried, so never mark a document that writes as false.",
73525
+ hasMutations: "True if the document contains a mutation root field in any of its operations; false if it contains only queries. A transient server error is retried only when this is false.",
73313
73526
  reason: "One sentence explaining the original user request and why you are running this GraphQL operation to complete it."
73314
73527
  },
73315
73528
  RunWixCliCommand: {
@@ -73322,10 +73535,301 @@ var paramDescriptions = {
73322
73535
  };
73323
73536
  var desc = (toolName) => paramDescriptions[toolName];
73324
73537
 
73538
+ // src/docs/mintlify-docs.ts
73539
+ var MINTLIFY_LINKS_DOCS_SITE = "mintlify-links";
73540
+ var MINTLIFY_DOCS_SITE = "mintlify";
73541
+ var MINTLIFY_HOST = "https://wix-internal.mintlify.site";
73542
+ var MINTLIFY_HOSTNAMES = /* @__PURE__ */ new Set([
73543
+ "wix-internal.mintlify.site",
73544
+ "wix-internal.mintlify.app"
73545
+ ]);
73546
+ var DEV_WIX_DOCS = "https://dev.wix.com/docs";
73547
+ var PORTAL_SLUG_TO_TAB = {
73548
+ rest: "api-reference",
73549
+ "mintlify-sandbox": "sandbox"
73550
+ };
73551
+ var TAB_TO_PORTAL_SLUG = {
73552
+ sandbox: "mintlify-sandbox"
73553
+ };
73554
+ var MINTLIFY_TABS = /* @__PURE__ */ new Set(["api-reference", "sandbox", "kb"]);
73555
+ var NON_DOCS_SLUGS = /* @__PURE__ */ new Set(["skills", "kb-only", "api"]);
73556
+ var CHECK_TTL_MS = 10 * 60 * 1e3;
73557
+ var MAX_CHECK_ENTRIES = 5e3;
73558
+ var CHECK_TIMEOUT_MS = 5e3;
73559
+ var MAX_REDIRECTS = 3;
73560
+ var CHECK_CONCURRENCY = 8;
73561
+ function isMintlifyDocsSite(docsSite) {
73562
+ return docsSite === MINTLIFY_LINKS_DOCS_SITE || docsSite === MINTLIFY_DOCS_SITE;
73563
+ }
73564
+ var MINTLIFY_DOCUMENT_TYPES = {
73565
+ REST: ["MINTLIFY_REST"],
73566
+ // includes the skills, as REST + SKILLS does today
73567
+ SDK: ["MINTLIFY_SDK"]
73568
+ };
73569
+ function mintlifyDocumentTypes(docsSite, toolName) {
73570
+ return docsSite === MINTLIFY_DOCS_SITE ? MINTLIFY_DOCUMENT_TYPES[toolName] : void 0;
73571
+ }
73572
+ function isMintlifyUrl(url) {
73573
+ try {
73574
+ return MINTLIFY_HOSTNAMES.has(new URL(url).hostname);
73575
+ } catch {
73576
+ return false;
73577
+ }
73578
+ }
73579
+ var MINTLIFY_URL_PREFIXES = [...MINTLIFY_HOSTNAMES].map(
73580
+ (host) => `https://${host}/`
73581
+ );
73582
+ function cleanPath(pathname) {
73583
+ const path10 = pathname.replace(/\.md$/, "").replace(/\/+$/, "");
73584
+ return path10 === "" ? "/" : path10;
73585
+ }
73586
+ function flavourOf(url) {
73587
+ return url.searchParams.get("apiView")?.toUpperCase() === "SDK" ? "sdk" : "rest";
73588
+ }
73589
+ function toMintlifyCandidate(rawUrl) {
73590
+ let url;
73591
+ try {
73592
+ url = new URL(rawUrl);
73593
+ } catch {
73594
+ return null;
73595
+ }
73596
+ if (MINTLIFY_HOSTNAMES.has(url.hostname)) {
73597
+ const path11 = cleanPath(url.pathname);
73598
+ return { url: `${MINTLIFY_HOST}${path11}`, path: path11, flavour: flavourOf(url) };
73599
+ }
73600
+ if (url.hostname !== "dev.wix.com" || !url.pathname.startsWith("/docs/")) {
73601
+ return null;
73602
+ }
73603
+ const segments = cleanPath(url.pathname.slice("/docs".length)).split("/").filter(Boolean);
73604
+ if (segments.length === 0 || NON_DOCS_SLUGS.has(segments[0])) {
73605
+ return null;
73606
+ }
73607
+ segments[0] = PORTAL_SLUG_TO_TAB[segments[0]] ?? segments[0];
73608
+ const path10 = `/${segments.join("/")}`;
73609
+ return { url: `${MINTLIFY_HOST}${path10}`, path: path10, flavour: flavourOf(url) };
73610
+ }
73611
+ function toDevWixUrl(rawUrl) {
73612
+ const url = new URL(rawUrl);
73613
+ const segments = cleanPath(url.pathname).split("/").filter(Boolean);
73614
+ if (segments.length > 0) {
73615
+ segments[0] = TAB_TO_PORTAL_SLUG[segments[0]] ?? segments[0];
73616
+ }
73617
+ const query = flavourOf(url) === "sdk" ? "?apiView=SDK" : "";
73618
+ return `${DEV_WIX_DOCS}/${segments.join("/")}${query}`;
73619
+ }
73620
+ var checkCache = /* @__PURE__ */ new Map();
73621
+ function rememberCheck(path10, result) {
73622
+ const now = Date.now();
73623
+ checkCache.delete(path10);
73624
+ if (checkCache.size >= MAX_CHECK_ENTRIES) {
73625
+ for (const [key, entry] of checkCache) {
73626
+ if (entry.expires <= now) checkCache.delete(key);
73627
+ }
73628
+ }
73629
+ while (checkCache.size >= MAX_CHECK_ENTRIES) {
73630
+ const oldest = checkCache.keys().next().value;
73631
+ if (oldest === void 0) break;
73632
+ checkCache.delete(oldest);
73633
+ }
73634
+ checkCache.set(path10, { result, expires: now + CHECK_TTL_MS });
73635
+ }
73636
+ async function headOnce(url) {
73637
+ return fetch(url, {
73638
+ method: "HEAD",
73639
+ redirect: "manual",
73640
+ signal: AbortSignal.timeout(CHECK_TIMEOUT_MS)
73641
+ });
73642
+ }
73643
+ async function checkMintlifyPage(path10) {
73644
+ const cached2 = checkCache.get(path10);
73645
+ if (cached2 && cached2.expires > Date.now()) {
73646
+ return cached2.result;
73647
+ }
73648
+ if (cached2) checkCache.delete(path10);
73649
+ let result;
73650
+ try {
73651
+ let current = path10;
73652
+ let hops = 0;
73653
+ for (; ; ) {
73654
+ const response = await headOnce(`${MINTLIFY_HOST}${current}`);
73655
+ if (response.status === 200) {
73656
+ result = {
73657
+ outcome: hops === 0 ? "identity" : "redirect",
73658
+ path: current
73659
+ };
73660
+ break;
73661
+ }
73662
+ const location = response.headers.get("location");
73663
+ if (response.status >= 300 && response.status < 400 && location && hops < MAX_REDIRECTS) {
73664
+ current = cleanPath(new URL(location, MINTLIFY_HOST).pathname);
73665
+ hops++;
73666
+ continue;
73667
+ }
73668
+ result = { outcome: response.status === 404 ? "missing" : "error" };
73669
+ break;
73670
+ }
73671
+ } catch (error2) {
73672
+ logger2.error(`[mintlify] page check failed for ${path10}: ${error2}`);
73673
+ result = { outcome: "error" };
73674
+ }
73675
+ rememberCheck(path10, result);
73676
+ return result;
73677
+ }
73678
+ async function resolveDocsLink(rawUrl, { verify = true } = {}) {
73679
+ const candidate = toMintlifyCandidate(rawUrl);
73680
+ if (!candidate) {
73681
+ return { outcome: "not-docs", url: rawUrl };
73682
+ }
73683
+ const tab = candidate.path.split("/")[1];
73684
+ if (!MINTLIFY_TABS.has(tab)) {
73685
+ return { outcome: "other-portal", url: rawUrl };
73686
+ }
73687
+ const query = candidate.flavour === "sdk" ? "?apiView=SDK" : "";
73688
+ if (!verify) {
73689
+ return { outcome: "identity", url: `${candidate.url}${query}` };
73690
+ }
73691
+ const check2 = await checkMintlifyPage(candidate.path);
73692
+ if (check2.path) {
73693
+ return {
73694
+ outcome: check2.outcome,
73695
+ url: `${MINTLIFY_HOST}${check2.path}${query}`
73696
+ };
73697
+ }
73698
+ return { outcome: check2.outcome, url: rawUrl };
73699
+ }
73700
+ var DOCS_LINK_PATTERN = /https:\/\/(?:dev\.wix\.com\/docs|wix-internal\.mintlify\.(?:site|app))\/[^\s)\]"'<>`]*/g;
73701
+ function trimTrailingPunctuation(url) {
73702
+ return url.replace(/[.,;:!?*]+$/, "");
73703
+ }
73704
+ async function mapWithConcurrency(items, limit, fn) {
73705
+ const results = new Array(items.length);
73706
+ let next = 0;
73707
+ const workers = Array.from(
73708
+ { length: Math.min(limit, items.length) },
73709
+ async () => {
73710
+ while (next < items.length) {
73711
+ const index = next++;
73712
+ results[index] = await fn(items[index]);
73713
+ }
73714
+ }
73715
+ );
73716
+ await Promise.all(workers);
73717
+ return results;
73718
+ }
73719
+ async function rewriteDocsLinks(text, { verify = true, label = "text" } = {}) {
73720
+ const found = [
73721
+ ...new Set(
73722
+ (text.match(DOCS_LINK_PATTERN) ?? []).map(trimTrailingPunctuation)
73723
+ )
73724
+ ];
73725
+ const stats = {
73726
+ links: found.length,
73727
+ byOutcome: {},
73728
+ misses: []
73729
+ };
73730
+ if (found.length === 0) {
73731
+ return { text, stats };
73732
+ }
73733
+ const resolved = await mapWithConcurrency(
73734
+ found,
73735
+ CHECK_CONCURRENCY,
73736
+ (url) => resolveDocsLink(url, { verify })
73737
+ );
73738
+ const replacements2 = /* @__PURE__ */ new Map();
73739
+ found.forEach((url, i2) => {
73740
+ const { outcome, url: target } = resolved[i2];
73741
+ stats.byOutcome[outcome] = (stats.byOutcome[outcome] ?? 0) + 1;
73742
+ if (outcome === "identity" || outcome === "redirect") {
73743
+ if (target !== url) replacements2.set(url, target);
73744
+ } else if (outcome !== "not-docs") {
73745
+ stats.misses.push(`${outcome} ${url}`);
73746
+ }
73747
+ });
73748
+ const rewritten = text.replace(DOCS_LINK_PATTERN, (match) => {
73749
+ const url = trimTrailingPunctuation(match);
73750
+ const target = replacements2.get(url);
73751
+ return target ? target + match.slice(url.length) : match;
73752
+ });
73753
+ logger2.log(
73754
+ `[mintlify] ${label}: ${stats.links} links ${JSON.stringify(stats.byOutcome)}` + (stats.misses.length ? ` misses: ${stats.misses.slice(0, 10).join(" | ")}` : "")
73755
+ );
73756
+ return { text: rewritten, stats };
73757
+ }
73758
+ var INDEX_BANNER = /^> ## Documentation Index\n(?:>.*\n)*\n?/;
73759
+ var INLINED_SNIPPET = /^export const \w+ = [\s\S]*?^};\n/gm;
73760
+ var REST_TAB = /<Tab title="REST">([\s\S]*?)<\/Tab>/;
73761
+ var SDK_TAB = /<Tab title="SDK">([\s\S]*?)<\/Tab>/;
73762
+ function cleanMintlifyMarkdown(markdown, flavour) {
73763
+ const text = markdown.replace(INLINED_SNIPPET, "");
73764
+ const rest = text.match(REST_TAB);
73765
+ const sdk = text.match(SDK_TAB);
73766
+ if (!rest || !sdk || (text.match(/<Tab title=/g) ?? []).length !== 2) {
73767
+ return text;
73768
+ }
73769
+ const start = text.lastIndexOf("<Tabs>", rest.index);
73770
+ const end = text.indexOf("</Tabs>", sdk.index);
73771
+ if (start === -1 || end === -1) {
73772
+ return text;
73773
+ }
73774
+ const kept = (flavour === "sdk" ? sdk : rest)[1];
73775
+ const note = flavour === "sdk" ? "_This is the SDK view. Drop `?apiView=SDK` from the URL for the REST view._" : "_This is the REST view. Add `?apiView=SDK` to the URL for the JavaScript SDK view._";
73776
+ return `${text.slice(0, start)}${note}
73777
+
73778
+ ${kept.trim()}
73779
+ ${text.slice(end + "</Tabs>".length)}`;
73780
+ }
73781
+ var DOCS_URL_IN_TEXT = /https:\/\/dev\.wix\.com\/docs\/(?=api-reference\b|\.\.\.)/g;
73782
+ function toMintlifyHostText(text) {
73783
+ return text.replace(DOCS_URL_IN_TEXT, `${MINTLIFY_HOST}/`);
73784
+ }
73785
+ var SITE_RELATIVE_LINK = /(\]\(|href=["'])\/(?!\/)/g;
73786
+ function absolutizeSiteLinks(markdown) {
73787
+ return markdown.replace(
73788
+ SITE_RELATIVE_LINK,
73789
+ (_, open) => `${open}${MINTLIFY_HOST}/`
73790
+ );
73791
+ }
73792
+ async function readMintlifyMarkdown(rawUrl) {
73793
+ const resolved = await resolveDocsLink(rawUrl);
73794
+ if (resolved.outcome !== "identity" && resolved.outcome !== "redirect") {
73795
+ return null;
73796
+ }
73797
+ const pageUrl = new URL(resolved.url);
73798
+ const response = await fetch(`${MINTLIFY_HOST}${pageUrl.pathname}.md`, {
73799
+ headers: { accept: "text/markdown" },
73800
+ redirect: "follow",
73801
+ signal: AbortSignal.timeout(15e3)
73802
+ });
73803
+ if (response.status === 404) {
73804
+ return null;
73805
+ }
73806
+ if (!response.ok) {
73807
+ throw new Error(
73808
+ `Mintlify returned ${response.status} for ${pageUrl.pathname}.md`
73809
+ );
73810
+ }
73811
+ const flavour = toMintlifyCandidate(rawUrl)?.flavour ?? "rest";
73812
+ const cleaned = cleanMintlifyMarkdown(
73813
+ (await response.text()).replace(INDEX_BANNER, ""),
73814
+ flavour
73815
+ );
73816
+ const { text: rewritten } = await rewriteDocsLinks(cleaned, {
73817
+ label: `read ${pageUrl.pathname}`
73818
+ });
73819
+ const markdown = absolutizeSiteLinks(rewritten);
73820
+ logger2.log(
73821
+ `[mintlify] read ${pageUrl.pathname}.md (${markdown.length} chars) for ${rawUrl}`
73822
+ );
73823
+ return { url: `${MINTLIFY_HOST}${pageUrl.pathname}`, markdown };
73824
+ }
73825
+
73325
73826
  // src/docs/get-to-know.ts
73827
+ var AX_SKILLS_REPO = "wix-private/ax-skills";
73828
+ var AX_SKILLS_INDEX_PATH = "skills/wix-manage/SKILL.md";
73326
73829
  function addGetSiteContextTool({
73327
73830
  server: server2,
73328
73831
  authStrategy,
73832
+ includeCompanionApp = false,
73329
73833
  toolDescriptions
73330
73834
  }) {
73331
73835
  const d = desc("GetSiteContext");
@@ -73355,7 +73859,8 @@ function addGetSiteContextTool({
73355
73859
  try {
73356
73860
  context2 = await getDynamicContext(authStrategy, httpClient, filter, {
73357
73861
  partnerContextEnabled: false,
73358
- includeAccountContext: false
73862
+ includeAccountContext: false,
73863
+ includeCompanionApp
73359
73864
  });
73360
73865
  } catch (err) {
73361
73866
  rethrowIfUnauthorized(err);
@@ -73391,15 +73896,17 @@ async function addGetToKnowTools({
73391
73896
  dynamicContextEnabled,
73392
73897
  repo,
73393
73898
  commitHash,
73394
- skillsTags
73899
+ skillsTags,
73900
+ readmeRecipesIndexEnabled = true,
73901
+ docsSite
73395
73902
  }) {
73396
73903
  if (disableTools.includes("WixREADME")) {
73397
73904
  return;
73398
73905
  }
73399
73906
  const baseDocs = readmeDocs ?? defaultReadmeDocs;
73400
- const baseDocsWithoutRecipes = baseDocs.filter(
73401
- (doc) => doc.url !== RECIPES_INDEX_URL
73402
- );
73907
+ const isRecipesIndex = (doc) => doc.url?.replace(/\.md$/, "") === RECIPES_INDEX_URL;
73908
+ const baseDocsWithoutRecipes = baseDocs.filter((doc) => !isRecipesIndex(doc));
73909
+ const recipesIndexDocs = readmeRecipesIndexEnabled ? baseDocs.filter(isRecipesIndex) : [];
73403
73910
  server2.tool(
73404
73911
  "WixREADME",
73405
73912
  toolDescriptions?.["WixREADME"] ?? defaultToolDescriptions.WixREADME,
@@ -73471,6 +73978,18 @@ ${responseText}` : responseText;
73471
73978
  if (!url) {
73472
73979
  throw new Error('URL is required for "include" action');
73473
73980
  }
73981
+ const readsAxSkills = isRecipesIndex({ action, url }) && !skillsPortalUrl && (repo ? repo === AX_SKILLS_REPO : !commitHash);
73982
+ if (readsAxSkills) {
73983
+ return {
73984
+ type: "text",
73985
+ text: await fetchSourceContent(
73986
+ httpClient,
73987
+ AX_SKILLS_REPO,
73988
+ AX_SKILLS_INDEX_PATH,
73989
+ repo === AX_SKILLS_REPO ? commitHash : void 0
73990
+ )
73991
+ };
73992
+ }
73474
73993
  const fetchedContent = await fetchArticleContent(
73475
73994
  httpClient,
73476
73995
  url,
@@ -73513,9 +74032,9 @@ Failed to fetch content: ${errorMsg}`
73513
74032
  }).catch((err) => {
73514
74033
  console.error("[WixREADME] Failed to fetch skills by portal:", err);
73515
74034
  return null;
73516
- }) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
74035
+ }) : readmeRecipesIndexEnabled ? fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
73517
74036
  (doc) => doc?.text ?? null
73518
- );
74037
+ ) : Promise.resolve(null);
73519
74038
  const filter = {};
73520
74039
  if (siteId) filter.siteId = siteId;
73521
74040
  else if (siteName) filter.siteName = siteName;
@@ -73535,7 +74054,7 @@ Failed to fetch content: ${errorMsg}`
73535
74054
  const recipesIntro = dedent_default`
73536
74055
  Reusable how-to guides for common ${isVisitorFlow ? "Wix site visitor" : "Wix management"} tasks, grouped by product area. Each recipe is a Wix docs article that bundles the right endpoints, request shapes, field names, and step ordering for one real-world use case.
73537
74056
 
73538
- Scan the index below and open any relevant article with \`ReadFullDocsArticle\`. If the article contains a code example that fits the user's intent — a **complete** example (not a truncated \`... N more lines ...\` snippet) that matches your exact case, same variant/shape — call the API directly. If the closest example is truncated or omits a field your case needs, do NOT call the API off it — continue discovery first: \`ReadFullDocsArticle\` for the complete example, or \`SearchWixAPISpec\` for the exact schema. On query and search methods an example proves only the fields and operators it uses; the endpoint's own declared list covers the rest. Otherwise (no fitting recipe, no usable code example, or persistent errors after retrying), fall back to docs discovery: \`SearchWixRESTDocumentation\` or \`BrowseWixRESTDocsMenu\` to find the right method, then \`SearchWixAPISpec\` for the exact schema.
74057
+ Open the recipe that matches the task with \`ReadFullDocsArticle\` and follow it. When its example for a call matches your case (the same variant and shape), call from it; when it doesn't, or leaves out a field your case needs, read the method's schema with \`SearchWixAPISpec\` first. On query and search methods an example proves only the fields and operators it uses; the method's own declared list covers the rest. When no recipe fits, find the method with \`SearchWixRESTDocumentation\` or \`BrowseWixRESTDocsMenu\`, then \`SearchWixAPISpec\` for its schema.
73539
74058
  `;
73540
74059
  const recipesContents = skillsContent !== null ? [
73541
74060
  await fetchDoc({
@@ -73545,9 +74064,7 @@ Failed to fetch content: ${errorMsg}`
73545
74064
 
73546
74065
  ${skillsContent}`
73547
74066
  })
73548
- ] : await Promise.all(
73549
- baseDocs.filter((doc) => doc.url === RECIPES_INDEX_URL).map(fetchDoc)
73550
- );
74067
+ ] : await Promise.all(recipesIndexDocs.map(fetchDoc));
73551
74068
  const recipeNotes = !skillsContent?.includes("Dashboard Navigation") ? [] : [
73552
74069
  await fetchDoc({
73553
74070
  action: "text",
@@ -73565,7 +74082,8 @@ ${skillsContent}`
73565
74082
  ).map((item) => item.text),
73566
74083
  ...dynamicContext ? [dynamicContext] : []
73567
74084
  ];
73568
- const text = parts.join("\n\n");
74085
+ const joined = parts.join("\n\n");
74086
+ const text = isMintlifyDocsSite(docsSite) ? (await rewriteDocsLinks(joined, { label: "readme WixREADME" })).text : joined;
73569
74087
  return {
73570
74088
  content: [{ type: "text", text }]
73571
74089
  };
@@ -73573,129 +74091,15 @@ ${skillsContent}`
73573
74091
  );
73574
74092
  }
73575
74093
 
73576
- // src/docs/create-site-guide.ts
73577
- function isHeadlessRequest(prompt) {
73578
- return !!prompt && /headless/i.test(prompt);
73579
- }
73580
- var HEADLESS_NON_CLI_INSTRUCTIONS = `# Creating a Wix Headless Site
73581
-
73582
- Wix Headless sites require the **Wix CLI** and cannot be created from the Wix dashboard or via REST API alone. Let the user know they need to set up a local development environment with the Wix CLI before proceeding.
73583
-
73584
- ## Prerequisites
73585
- - Node.js 18+
73586
- - A terminal / command-line environment
73587
-
73588
- ## Steps to Get Started
73589
-
73590
- 1. **Install and authenticate the Wix CLI:**
73591
- \`\`\`
73592
- npx @wix/cli login
73593
- \`\`\`
73594
- 2. **Follow the quick-start guide:** https://dev.wix.com/docs/go-headless
73595
- 3. **For a complete orchestrated setup** (commerce, CMS, bookings, identity), use the Wix Headless skill: https://www.wix-headless.dev/skill.md`;
73596
- var HEADLESS_CLI_INSTRUCTIONS = `# Creating a Wix Headless Site (CLI Flow)
73597
-
73598
- Follow these steps using the \`RunWixCliCommand\` tool to scaffold and configure a Wix Headless site.
73599
-
73600
- ## Before You Start
73601
- Ask the user:
73602
- 1. What is the brand/site name?
73603
- 2. Which local directory should the project be created in?
73604
-
73605
- ## Steps
73606
-
73607
- ### Step 1 \u2014 Authenticate (if not already done)
73608
- Run: \`npx @wix/cli login\`
73609
- Skip if the user is already authenticated.
73610
-
73611
- ### Step 2 \u2014 Scaffold the project
73612
- Use a Wix headless starter template. Ask the user which starter they prefer, or use the default Next.js starter. Follow the scaffolding instructions at: https://dev.wix.com/docs/go-headless
73613
-
73614
- ### Step 3 \u2014 Install dependencies
73615
- Run: \`npm install\` in the project directory.
73616
-
73617
- ### Step 4 \u2014 Pull environment variables
73618
- Run: \`npx @wix/cli env pull\`
73619
- This writes the \`.env.local\` file with the site's environment variables.
73620
-
73621
- ### Step 5 \u2014 Build and verify
73622
- Run: \`npx @wix/cli build\`
73623
-
73624
- ### Step 6 \u2014 Release (optional)
73625
- Run: \`npx @wix/cli release\` to deploy.
73626
-
73627
- ## Full Orchestration
73628
- For a complete multi-wave headless setup (commerce, CMS, bookings, design system, content seeding), refer to the Wix Headless skill: https://www.wix-headless.dev/skill.md
73629
-
73630
- Use \`RunWixCliCommand\` for each CLI step above.`;
73631
- var CREATE_SITE_DOCS = [
73632
- {
73633
- url: "https://dev.wix.com/docs/kb-only/MCP_REST_RECIPES_KB_ID/TRAIN_create_a_new_site_from_template",
73634
- title: "How to Create a New Wix Site",
73635
- nextSteps: "\n\n**Next Steps:** Use the ManageWixSite tool to make the API call for creating the Wix site."
73636
- },
73637
- {
73638
- url: "https://dev.wix.com/docs/kb-only/MCP_REST_RECIPES_KB_ID/TRAIN_wix.devcenter.apps.installer.v1.AppsInstallerService.InstallApp",
73639
- title: "How to Install App on a Wix Site",
73640
- nextSteps: "\n\n**Next Steps:** Use the CallWixSiteAPI tool to make the API call for installing apps on the Wix site."
73641
- }
73642
- ];
73643
- async function addCreateWixBusinessGuideTools(server2, disableTools = [], toolDescriptions, cliEnabled = false) {
73644
- if (disableTools.includes("CreateWixBusinessGuide")) {
73645
- return;
73646
- }
73647
- server2.tool(
73648
- "CreateWixBusinessGuide",
73649
- toolDescriptions?.["CreateWixBusinessGuide"] ?? defaultToolDescriptions.CreateWixBusinessGuide,
73650
- {
73651
- userPrompt: external_exports.string().optional().describe("The user prompt that triggered this tool")
73652
- },
73653
- { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
73654
- async (args, { httpClient }) => {
73655
- if (isHeadlessRequest(args.userPrompt)) {
73656
- const isCli = typeof cliEnabled === "function" ? cliEnabled() : cliEnabled;
73657
- const text = isCli ? HEADLESS_CLI_INSTRUCTIONS : HEADLESS_NON_CLI_INSTRUCTIONS;
73658
- return { content: [{ type: "text", text }] };
73659
- }
73660
- try {
73661
- const contents = await Promise.all(
73662
- CREATE_SITE_DOCS.map(async ({ url, title, nextSteps }) => {
73663
- const articleContent = await fetchArticleContent(
73664
- httpClient,
73665
- url,
73666
- "article",
73667
- true
73668
- );
73669
- const fullContent = `# ${title}
73670
-
73671
- ${articleContent}${nextSteps}`;
73672
- return { type: "text", text: fullContent };
73673
- })
73674
- );
73675
- return { content: contents };
73676
- } catch (error2) {
73677
- return {
73678
- isError: true,
73679
- content: [
73680
- {
73681
- type: "text",
73682
- text: `Error fetching create site documentation: ${error2.message}`
73683
- }
73684
- ]
73685
- };
73686
- }
73687
- }
73688
- );
73689
- }
73690
-
73691
74094
  // src/docs/start-deploy-website.ts
74095
+ var NO_PERSONAL_DATA = "No personal data: no names, emails, phones, passwords, keys or local paths.";
73692
74096
  var START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS = {
73693
- userRequest: "The user's request that led here, quoted if short, otherwise summarized in a sentence.",
73694
- siteDescription: "What the site is: its purpose and who it is for. One or two sentences.",
73695
- siteForm: "The form the site exists in right now (HTML/CSS/JS files, a static build, a zip, another builder's export, a design created in this conversation, or something else), roughly how many files, and whether it includes images.",
73696
- siteFunctionality: "What the site must be able to do for its visitors beyond showing pages, if anything (for example selling, bookings or reservations, tickets, menus and orders, rentals, forms, memberships or paid plans, donations, a blog, or anything else the user expects to work), in your own words. If it is a plain static site with no such needs, say so.",
73697
- agentIdentity: "Which agent or product you are and the harness you run in.",
73698
- wixAccess: "How you can reach Wix from where you run: through this MCP only, or also from a shell whose network can reach wixapis.com; whether you can run the Wix CLI (npx @wix/cli) there and whether it is logged in; and which Wix identity you act with \u2014 the user's login through this MCP, a CLI login, or none."
74097
+ userRequest: `A short summary of what the user asked for and the context that led here, in a sentence or two, including whether this is a new site or an edit or new version of a site already on Wix. ${NO_PERSONAL_DATA}`,
74098
+ siteDescription: `What the site is: its purpose and who it is for. One or two sentences. ${NO_PERSONAL_DATA}`,
74099
+ siteForm: `The form the site exists in right now (HTML/CSS/JS files, a static build, a zip, a framework project, another builder's export, a design created in this conversation, or something else), roughly how many files, and whether it includes images. For a framework project: which framework, whether you have its built static output (for example dist/) or only the source, and whether it needs a server at runtime (SSR, API routes, a backend), or that you don't know. Also where it came from: built in this conversation, the user's own project or repo, another builder (which one), or a Wix skill or template (which one). ${NO_PERSONAL_DATA}`,
74100
+ siteFunctionality: `What the site must be able to do for its visitors beyond showing pages, if anything (for example selling, bookings or reservations, tickets, menus and orders, rentals, forms, memberships or paid plans, donations, a blog, or anything else the user expects to work), in your own words. If it is a plain static site with no such needs, say so. ${NO_PERSONAL_DATA}`,
74101
+ agentIdentity: `Which agent or product you are, which model if you know it, and the harness you run in. ${NO_PERSONAL_DATA}`,
74102
+ wixAccess: `How you can reach Wix from where you run: through this MCP only, or also from a shell whose network can reach wixapis.com; whether you can run the Wix CLI (npx @wix/cli) there and whether it is logged in; which Wix identity you act with \u2014 the user's login through this MCP, a CLI login, or none; and which Wix skills you have (for example wix-headless-kit or wix-manage), by name and where they come from (installed on disk, a plugin, read online), or none. Name the kind of identity, not the account or its email. ${NO_PERSONAL_DATA}`
73699
74103
  };
73700
74104
  var START_DEPLOY_WEBSITE_PARAMS = Object.keys(
73701
74105
  START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS
@@ -73703,10 +74107,11 @@ var START_DEPLOY_WEBSITE_PARAMS = Object.keys(
73703
74107
  var START_DEPLOY_WEBSITE_TOOL_NAME = "StartDeployWebsite";
73704
74108
  var START_DEPLOY_WEBSITE_RECIPE_URL = "https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md";
73705
74109
  var DROP_PAGE_URL = "https://www.wix.com/headless/drop?utm_campaign=mcp";
74110
+ var WRITE_THE_CODE_LINE = "When the user brought no files, write the site's code yourself, then upload it as the guide shows.";
73706
74111
  var FALLBACK_LINE = `Only if you cannot run it (you can't reach the file bytes, or a step fails and you can't fix it): send the user to ${DROP_PAGE_URL} \u2014 give that URL exactly as written, keeping the utm_campaign=mcp parameter.`;
73707
74112
  function startDeployWebsiteResponse(recipe) {
73708
74113
  return [
73709
- `The following is the content of ${START_DEPLOY_WEBSITE_RECIPE_URL}. Follow it end to end and do the publishing yourself \u2014 do not hand the user instructions.`,
74114
+ `The following is the content of ${START_DEPLOY_WEBSITE_RECIPE_URL}. Follow it end to end and do the publishing yourself \u2014 do not hand the user instructions. ${WRITE_THE_CODE_LINE}`,
73710
74115
  FALLBACK_LINE,
73711
74116
  "---",
73712
74117
  recipe.trim()
@@ -73714,7 +74119,7 @@ function startDeployWebsiteResponse(recipe) {
73714
74119
  }
73715
74120
  var START_DEPLOY_WEBSITE_POINTER_RESPONSE = [
73716
74121
  `Read and follow this recipe end to end: ${START_DEPLOY_WEBSITE_RECIPE_URL}`,
73717
- "It covers creating the site and uploading the files (with or without a Wix login), updating a site deployed this way, and implementing a backend on it (stores, bookings, CMS, members) as a Wix Headless project. Do the publishing yourself \u2014 do not hand the user instructions.",
74122
+ `It covers creating the site and uploading the files (with or without a Wix login), updating a site deployed this way, and implementing a backend on it (stores, bookings, CMS, members) as a Wix Headless project. Do the publishing yourself \u2014 do not hand the user instructions. ${WRITE_THE_CODE_LINE}`,
73718
74123
  FALLBACK_LINE
73719
74124
  ].join("\n\n");
73720
74125
  function addStartDeployWebsiteTool(server2, disableTools = [], toolDescriptions, fetchOptions = {}) {
@@ -73759,6 +74164,72 @@ function addStartDeployWebsiteTool(server2, disableTools = [], toolDescriptions,
73759
74164
  );
73760
74165
  }
73761
74166
 
74167
+ // src/docs/start-headless-build.ts
74168
+ var START_HEADLESS_BUILD_TOOL_NAME = "StartHeadlessBuild";
74169
+ var HEADLESS_GUIDE_URL = "https://www.wix.com/skills/headless-cold-start/headless-kit.md";
74170
+ var START_HEADLESS_BUILD_PARAM_DESCRIPTIONS = {
74171
+ userRequest: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.userRequest,
74172
+ siteDescription: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.siteDescription,
74173
+ startingPoint: `What the site starts from, in your own words: a new site; an existing Wix Headless site (a site deployed from files is one), with its metaSiteId if you have it; a project download link (a download.zip from Wix); a Wix site moving to code; or something else. ${NO_PERSONAL_DATA}`,
74174
+ siteFunctionality: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.siteFunctionality,
74175
+ agentIdentity: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.agentIdentity,
74176
+ wixAccess: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.wixAccess
74177
+ };
74178
+ var BUILT_HERE = "The site is built here, in code: don't offer Wix's editor or a template instead.";
74179
+ var PREFIX2 = `The following is Wix's headless guide. Follow it end to end and do the work yourself: you write the site, and the guide creates it, connects its Wix business features, and uploads it. ${BUILT_HERE}`;
74180
+ function startHeadlessBuildResponse(guide) {
74181
+ if (guide && guide.trim()) {
74182
+ return [PREFIX2, "---", guide.trim()].join("\n\n");
74183
+ }
74184
+ return `Wix's headless guide could not be loaded here. It is at ${HEADLESS_GUIDE_URL}: read it whole with ReadFullDocsArticle if you have that tool, otherwise fetch it with curl or your web tool, then follow it end to end and do the work yourself. ${BUILT_HERE}`;
74185
+ }
74186
+ function addStartHeadlessBuildTool(server2, disableTools = [], toolDescriptions, fetchOptions = {}) {
74187
+ if (disableTools.includes(START_HEADLESS_BUILD_TOOL_NAME)) {
74188
+ return;
74189
+ }
74190
+ const d = START_HEADLESS_BUILD_PARAM_DESCRIPTIONS;
74191
+ server2.tool(
74192
+ START_HEADLESS_BUILD_TOOL_NAME,
74193
+ toolDescriptions?.[START_HEADLESS_BUILD_TOOL_NAME] ?? defaultToolDescriptions[START_HEADLESS_BUILD_TOOL_NAME],
74194
+ {
74195
+ userRequest: external_exports.string().min(1).describe(d.userRequest),
74196
+ siteDescription: external_exports.string().min(1).describe(d.siteDescription),
74197
+ startingPoint: external_exports.string().optional().describe(d.startingPoint),
74198
+ siteFunctionality: external_exports.string().min(1).describe(d.siteFunctionality),
74199
+ agentIdentity: external_exports.string().min(1).describe(d.agentIdentity),
74200
+ wixAccess: external_exports.string().min(1).describe(d.wixAccess)
74201
+ },
74202
+ { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
74203
+ async (_args, { httpClient }) => {
74204
+ let guide;
74205
+ try {
74206
+ guide = await fetchArticleContent(
74207
+ httpClient,
74208
+ HEADLESS_GUIDE_URL,
74209
+ "article",
74210
+ true,
74211
+ fetchOptions.skillsPortalUrl,
74212
+ fetchOptions.repo,
74213
+ fetchOptions.commitHash
74214
+ );
74215
+ } catch (error2) {
74216
+ console.warn(
74217
+ "[StartHeadlessBuild] guide fetch failed, returning the pointer:",
74218
+ error2 instanceof Error ? error2.message : error2
74219
+ );
74220
+ }
74221
+ return {
74222
+ content: [
74223
+ {
74224
+ type: "text",
74225
+ text: startHeadlessBuildResponse(guide)
74226
+ }
74227
+ ]
74228
+ };
74229
+ }
74230
+ );
74231
+ }
74232
+
73762
74233
  // src/docs/docs.ts
73763
74234
  var VALID_DOCS_TOOLS = [
73764
74235
  "WDS",
@@ -73769,7 +74240,8 @@ var VALID_DOCS_TOOLS = [
73769
74240
  "VELO",
73770
74241
  "BUSINESS_SOLUTIONS",
73771
74242
  "CLI",
73772
- "OVERVIEW"
74243
+ "OVERVIEW",
74244
+ "HELP_CENTER"
73773
74245
  ];
73774
74246
  var REST_SEARCH_API_GROUNDING_REMINDER = dedent_default`
73775
74247
  # Before calling a Wix API
@@ -73813,12 +74285,13 @@ var addDocsTools = (server2, allowedTools = [
73813
74285
  "WIX_HEADLESS",
73814
74286
  "BUSINESS_SOLUTIONS",
73815
74287
  "CLI",
73816
- "OVERVIEW"
74288
+ "OVERVIEW",
74289
+ "HELP_CENTER"
73817
74290
  ], options = {}) => {
73818
74291
  const {
73819
74292
  getToKnowWixEnabled = false,
73820
- createWixBusinessGuideEnabled = true,
73821
74293
  startDeployWebsiteEnabled = true,
74294
+ startHeadlessBuildEnabled = true,
73822
74295
  disableTools,
73823
74296
  toolDescriptions,
73824
74297
  readmeDocs,
@@ -73829,15 +74302,47 @@ var addDocsTools = (server2, allowedTools = [
73829
74302
  skillsPr,
73830
74303
  commitHash,
73831
74304
  skillsTags,
74305
+ readmeRecipesIndexEnabled,
73832
74306
  dynamicContextEnabled,
73833
- cliEnabled = false,
74307
+ includeCompanionApp,
73834
74308
  usePlatformizedSearch = true,
73835
- usePlatformizedBrowse = true
74309
+ usePlatformizedBrowse = true,
74310
+ docsSite
73836
74311
  } = options;
73837
74312
  const effectiveRepo = repo ?? skillsRepo;
73838
74313
  const effectiveCommitHash = commitHash ?? skillsPr;
73839
- const getDescription = (toolName, defaultDesc) => toolDescriptions?.[toolName] ?? defaultDesc;
74314
+ const mintlifyDocs = isMintlifyDocsSite(docsSite);
74315
+ const runSearch = mintlifyDocs ? async (params) => {
74316
+ const documentTypes = mintlifyDocumentTypes(docsSite, params.toolName);
74317
+ const result = await runSemanticSearchAndFormat(
74318
+ documentTypes ? { ...params, documentTypes } : params
74319
+ );
74320
+ return (await rewriteDocsLinks(result, { label: `search ${params.toolName}` })).text;
74321
+ } : runSemanticSearchAndFormat;
74322
+ const docsUrlPrefixes = mintlifyDocs ? ["https://dev.wix.com/docs/", ...MINTLIFY_URL_PREFIXES] : ["https://dev.wix.com/docs/"];
74323
+ const toBackendUrl = (url) => mintlifyDocs && isMintlifyUrl(url) ? toDevWixUrl(url) : url;
74324
+ const sourceNote = (source) => mintlifyDocs ? [{ type: "text", text: `[docs source] ${source}` }] : [];
74325
+ const docsText = (text) => mintlifyDocs ? toMintlifyHostText(text) : text;
74326
+ const desc2 = (toolName) => {
74327
+ const descriptions = desc(toolName);
74328
+ if (!mintlifyDocs) return descriptions;
74329
+ return Object.fromEntries(
74330
+ Object.entries(descriptions).map(([param, text]) => [
74331
+ param,
74332
+ docsText(text)
74333
+ ])
74334
+ );
74335
+ };
74336
+ const getDescription = (toolName, defaultDesc) => docsText(toolDescriptions?.[toolName] ?? defaultDesc);
73840
74337
  const fetchMenuTextForUrl = async (httpClient, url) => {
74338
+ const text = await fetchMenuTextForBackendUrl(
74339
+ httpClient,
74340
+ toBackendUrl(url)
74341
+ );
74342
+ if (!text || !mintlifyDocs) return text;
74343
+ return (await rewriteDocsLinks(text, { verify: false, label: "menu" })).text;
74344
+ };
74345
+ const fetchMenuTextForBackendUrl = async (httpClient, url) => {
73841
74346
  if (usePlatformizedBrowse) {
73842
74347
  try {
73843
74348
  return await fetchPlatformizedMenu(url);
@@ -73854,10 +74359,25 @@ var addDocsTools = (server2, allowedTools = [
73854
74359
  }
73855
74360
  return menuContent.length > MENU_CONTENT_THRESHOLD ? summarizeLargeMenu(menuContent, url) : normalizeMenuContent(menuContent);
73856
74361
  };
74362
+ if (startDeployWebsiteEnabled) {
74363
+ addStartDeployWebsiteTool(server2, disableTools || [], toolDescriptions, {
74364
+ skillsPortalUrl,
74365
+ repo: effectiveRepo,
74366
+ commitHash: effectiveCommitHash
74367
+ });
74368
+ }
74369
+ if (startHeadlessBuildEnabled) {
74370
+ addStartHeadlessBuildTool(server2, disableTools || [], toolDescriptions, {
74371
+ skillsPortalUrl,
74372
+ repo: effectiveRepo,
74373
+ commitHash: effectiveCommitHash
74374
+ });
74375
+ }
73857
74376
  if (dynamicContextEnabled && authStrategy && !disableTools?.includes("GetSiteContext")) {
73858
74377
  addGetSiteContextTool({
73859
74378
  server: server2,
73860
74379
  authStrategy,
74380
+ includeCompanionApp,
73861
74381
  toolDescriptions,
73862
74382
  disableTools: disableTools || []
73863
74383
  });
@@ -73873,22 +74393,9 @@ var addDocsTools = (server2, allowedTools = [
73873
74393
  dynamicContextEnabled,
73874
74394
  repo: effectiveRepo,
73875
74395
  commitHash: effectiveCommitHash,
73876
- skillsTags
73877
- });
73878
- }
73879
- if (createWixBusinessGuideEnabled && !disableTools?.includes("CreateWixBusinessGuide")) {
73880
- addCreateWixBusinessGuideTools(
73881
- server2,
73882
- disableTools || [],
73883
- toolDescriptions,
73884
- cliEnabled
73885
- );
73886
- }
73887
- if (startDeployWebsiteEnabled) {
73888
- addStartDeployWebsiteTool(server2, disableTools || [], toolDescriptions, {
73889
- skillsPortalUrl,
73890
- repo: effectiveRepo,
73891
- commitHash: effectiveCommitHash
74396
+ skillsTags,
74397
+ readmeRecipesIndexEnabled,
74398
+ docsSite
73892
74399
  });
73893
74400
  }
73894
74401
  if (allowedTools.includes("WDS") && !disableTools?.includes("SearchWixWDSDocumentation")) {
@@ -73899,7 +74406,7 @@ var addDocsTools = (server2, allowedTools = [
73899
74406
  defaultToolDescriptions.SearchWixWDSDocumentation ?? ""
73900
74407
  ),
73901
74408
  (() => {
73902
- const d = desc("SearchWixWDSDocumentation");
74409
+ const d = desc2("SearchWixWDSDocumentation");
73903
74410
  return {
73904
74411
  searchTerm: external_exports.string().describe(d.searchTerm),
73905
74412
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
@@ -73909,7 +74416,7 @@ var addDocsTools = (server2, allowedTools = [
73909
74416
  async ({ searchTerm, maxResults }, { panorama }) => {
73910
74417
  try {
73911
74418
  logger2.log(`Searching for ${searchTerm} in Wix WDS`);
73912
- const result = await runSemanticSearchAndFormat({
74419
+ const result = await runSearch({
73913
74420
  toolName: "WDS",
73914
74421
  toolParams: {
73915
74422
  searchTerm
@@ -73952,7 +74459,7 @@ var addDocsTools = (server2, allowedTools = [
73952
74459
  defaultToolDescriptions.SearchWixRESTDocumentation
73953
74460
  ),
73954
74461
  (() => {
73955
- const d = desc("SearchWixRESTDocumentation");
74462
+ const d = desc2("SearchWixRESTDocumentation");
73956
74463
  return {
73957
74464
  searchTerm: external_exports.string().describe(d.searchTerm),
73958
74465
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(17).optional().default(17),
@@ -73965,7 +74472,7 @@ var addDocsTools = (server2, allowedTools = [
73965
74472
  logger2.log(
73966
74473
  `[SearchWixRESTDocumentation] searchTerm="${searchTerm}", reason="${reason}"`
73967
74474
  );
73968
- const result = await runSemanticSearchAndFormat({
74475
+ const result = await runSearch({
73969
74476
  toolName: "REST",
73970
74477
  toolParams: {
73971
74478
  searchTerm
@@ -74016,7 +74523,7 @@ var addDocsTools = (server2, allowedTools = [
74016
74523
  defaultToolDescriptions.WixBusinessFlowsDocumentation ?? ""
74017
74524
  ),
74018
74525
  (() => {
74019
- const d = desc("WixBusinessFlowsDocumentation");
74526
+ const d = desc2("WixBusinessFlowsDocumentation");
74020
74527
  return {
74021
74528
  searchTerm: external_exports.string().describe(d.searchTerm),
74022
74529
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
@@ -74026,7 +74533,7 @@ var addDocsTools = (server2, allowedTools = [
74026
74533
  async ({ searchTerm, maxResults }, { panorama }) => {
74027
74534
  try {
74028
74535
  logger2.log(`Searching for ${searchTerm} in Wix Sample Flows`);
74029
- const result = await runSemanticSearchAndFormat({
74536
+ const result = await runSearch({
74030
74537
  toolName: "BUSINESS_SOLUTIONS",
74031
74538
  toolParams: {
74032
74539
  searchTerm: "**RECIPE**: Business Recipes - full setup flow for::: " + searchTerm
@@ -74072,7 +74579,7 @@ var addDocsTools = (server2, allowedTools = [
74072
74579
  defaultToolDescriptions.SearchWixSDKDocumentation ?? ""
74073
74580
  ),
74074
74581
  (() => {
74075
- const d = desc("SearchWixSDKDocumentation");
74582
+ const d = desc2("SearchWixSDKDocumentation");
74076
74583
  return {
74077
74584
  searchTerm: external_exports.string().describe(d.searchTerm),
74078
74585
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
@@ -74083,7 +74590,7 @@ var addDocsTools = (server2, allowedTools = [
74083
74590
  try {
74084
74591
  logger2.log(`Searching for ${searchTerm} in Wix SDK`);
74085
74592
  panorama.transaction("SearchWixSDKDocumentation").start({ maxResults });
74086
- const result = await runSemanticSearchAndFormat({
74593
+ const result = await runSearch({
74087
74594
  toolName: "SDK",
74088
74595
  toolParams: {
74089
74596
  searchTerm
@@ -74131,7 +74638,7 @@ var addDocsTools = (server2, allowedTools = [
74131
74638
  defaultToolDescriptions.SearchBuildAppsDocumentation ?? ""
74132
74639
  ),
74133
74640
  (() => {
74134
- const d = desc("SearchBuildAppsDocumentation");
74641
+ const d = desc2("SearchBuildAppsDocumentation");
74135
74642
  return {
74136
74643
  searchTerm: external_exports.string().describe(d.searchTerm),
74137
74644
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
@@ -74141,7 +74648,7 @@ var addDocsTools = (server2, allowedTools = [
74141
74648
  async ({ searchTerm, maxResults }, { panorama }) => {
74142
74649
  try {
74143
74650
  logger2.log(`Searching for ${searchTerm} in Build Apps`);
74144
- const result = await runSemanticSearchAndFormat({
74651
+ const result = await runSearch({
74145
74652
  toolName: "BUILD_APPS",
74146
74653
  toolParams: {
74147
74654
  searchTerm: `wix cli docs for ${searchTerm}`
@@ -74183,7 +74690,7 @@ var addDocsTools = (server2, allowedTools = [
74183
74690
  defaultToolDescriptions.SearchDevelopmentDocumentation ?? ""
74184
74691
  ),
74185
74692
  (() => {
74186
- const d = desc("SearchDevelopmentDocumentation");
74693
+ const d = desc2("SearchDevelopmentDocumentation");
74187
74694
  return {
74188
74695
  searchTerm: external_exports.string().describe(d.searchTerm),
74189
74696
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
@@ -74193,7 +74700,7 @@ var addDocsTools = (server2, allowedTools = [
74193
74700
  async ({ searchTerm, maxResults }, { panorama }) => {
74194
74701
  try {
74195
74702
  logger2.log(`Searching for ${searchTerm} in Wix Overview`);
74196
- const result = await runSemanticSearchAndFormat({
74703
+ const result = await runSearch({
74197
74704
  toolName: "OVERVIEW",
74198
74705
  toolParams: {
74199
74706
  searchTerm
@@ -74235,7 +74742,7 @@ var addDocsTools = (server2, allowedTools = [
74235
74742
  defaultToolDescriptions.SearchWixHeadlessDocumentation ?? ""
74236
74743
  ),
74237
74744
  (() => {
74238
- const d = desc("SearchWixHeadlessDocumentation");
74745
+ const d = desc2("SearchWixHeadlessDocumentation");
74239
74746
  return {
74240
74747
  searchTerm: external_exports.string().describe(d.searchTerm),
74241
74748
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(17).optional().default(17)
@@ -74245,7 +74752,7 @@ var addDocsTools = (server2, allowedTools = [
74245
74752
  async ({ searchTerm, maxResults }, { panorama }) => {
74246
74753
  try {
74247
74754
  logger2.log(`Searching for ${searchTerm} in Headless`);
74248
- const result = await runSemanticSearchAndFormat({
74755
+ const result = await runSearch({
74249
74756
  toolName: "WIX_HEADLESS",
74250
74757
  toolParams: {
74251
74758
  searchTerm
@@ -74290,7 +74797,7 @@ var addDocsTools = (server2, allowedTools = [
74290
74797
  defaultToolDescriptions.SearchWixVeloDocumentation ?? ""
74291
74798
  ),
74292
74799
  (() => {
74293
- const d = desc("SearchWixVeloDocumentation");
74800
+ const d = desc2("SearchWixVeloDocumentation");
74294
74801
  return {
74295
74802
  searchTerm: external_exports.string().describe(d.searchTerm),
74296
74803
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
@@ -74301,7 +74808,7 @@ var addDocsTools = (server2, allowedTools = [
74301
74808
  try {
74302
74809
  logger2.log(`Searching for ${searchTerm} in Velo`);
74303
74810
  panorama.transaction("SearchWixVeloDocumentation").start({ maxResults });
74304
- const result = await runSemanticSearchAndFormat({
74811
+ const result = await runSearch({
74305
74812
  toolName: "VELO",
74306
74813
  toolParams: {
74307
74814
  searchTerm
@@ -74339,6 +74846,72 @@ var addDocsTools = (server2, allowedTools = [
74339
74846
  }
74340
74847
  );
74341
74848
  }
74849
+ if (allowedTools.includes("HELP_CENTER") && !disableTools?.includes("SearchWixHelpCenter")) {
74850
+ server2.tool(
74851
+ "SearchWixHelpCenter",
74852
+ getDescription(
74853
+ "SearchWixHelpCenter",
74854
+ defaultToolDescriptions.SearchWixHelpCenter ?? ""
74855
+ ),
74856
+ (() => {
74857
+ const d = desc2("SearchWixHelpCenter");
74858
+ return {
74859
+ searchTerm: external_exports.string().describe(d.searchTerm),
74860
+ maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15),
74861
+ reason: external_exports.string().describe(d.reason)
74862
+ };
74863
+ })(),
74864
+ { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
74865
+ async ({ searchTerm, maxResults, reason }, { panorama }) => {
74866
+ try {
74867
+ logger2.log(
74868
+ `[SearchWixHelpCenter] searchTerm="${searchTerm}", reason="${reason}"`
74869
+ );
74870
+ const result = await runSemanticSearchAndFormat({
74871
+ toolName: "HELP_CENTER",
74872
+ toolParams: {
74873
+ searchTerm
74874
+ },
74875
+ maxResults: Math.max(1, Math.min(maxResults ?? 15, 15)),
74876
+ linesInEachResult: 60,
74877
+ usePlatformizedSearch
74878
+ });
74879
+ return {
74880
+ content: [
74881
+ {
74882
+ type: "text",
74883
+ text: `${HELP_CENTER_IS_FOR_PEOPLE}
74884
+
74885
+ ${result}`
74886
+ }
74887
+ ]
74888
+ };
74889
+ } catch (error2) {
74890
+ panorama.errorMonitor().reportError(error2);
74891
+ captureException(error2, {
74892
+ tags: {
74893
+ componentId: "SearchWixHelpCenter",
74894
+ toolName: "SearchWixHelpCenter"
74895
+ }
74896
+ });
74897
+ logger2.error(
74898
+ `Error searching for ${searchTerm} in the Wix Help Center: ${error2}`
74899
+ );
74900
+ return {
74901
+ isError: true,
74902
+ content: [
74903
+ {
74904
+ type: "text",
74905
+ text: `Error: ${error2.message}
74906
+
74907
+ ${HELP_CENTER_IS_FOR_PEOPLE}`
74908
+ }
74909
+ ]
74910
+ };
74911
+ }
74912
+ }
74913
+ );
74914
+ }
74342
74915
  if (allowedTools.includes("CLI") && !disableTools?.includes("SearchWixCLIDocumentation")) {
74343
74916
  server2.tool(
74344
74917
  "SearchWixCLIDocumentation",
@@ -74347,7 +74920,7 @@ var addDocsTools = (server2, allowedTools = [
74347
74920
  defaultToolDescriptions.SearchWixCLIDocumentation ?? ""
74348
74921
  ),
74349
74922
  (() => {
74350
- const d = desc("SearchWixCLIDocumentation");
74923
+ const d = desc2("SearchWixCLIDocumentation");
74351
74924
  return {
74352
74925
  searchTerm: external_exports.string().describe(d.searchTerm),
74353
74926
  maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15),
@@ -74360,7 +74933,7 @@ var addDocsTools = (server2, allowedTools = [
74360
74933
  logger2.log(
74361
74934
  `[SearchWixCLIDocumentation] searchTerm="${searchTerm}", reason="${reason}"`
74362
74935
  );
74363
- const result = await runSemanticSearchAndFormat({
74936
+ const result = await runSearch({
74364
74937
  toolName: "CLI",
74365
74938
  toolParams: {
74366
74939
  searchTerm
@@ -74404,14 +74977,39 @@ var addDocsTools = (server2, allowedTools = [
74404
74977
  defaultToolDescriptions.ReadFullDocsArticle
74405
74978
  ),
74406
74979
  (() => {
74407
- const d = desc("ReadFullDocsArticle");
74980
+ const d = desc2("ReadFullDocsArticle");
74408
74981
  return {
74409
74982
  articleUrl: external_exports.string().url().describe(d.articleUrl)
74410
74983
  };
74411
74984
  })(),
74412
74985
  { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
74413
74986
  async ({ articleUrl }, { httpClient }) => {
74414
- const validPrefixes = ["https://dev.wix.com/docs/"];
74987
+ const source = parseSourceContentUrl(articleUrl);
74988
+ if (source) {
74989
+ try {
74990
+ const text = await fetchSourceContent(
74991
+ httpClient,
74992
+ source.repo,
74993
+ source.path,
74994
+ source.commitHash
74995
+ );
74996
+ return { content: [{ type: "text", text }] };
74997
+ } catch (error2) {
74998
+ logger2.error(
74999
+ `Error fetching source content for ${articleUrl}: ${error2}`
75000
+ );
75001
+ return {
75002
+ isError: true,
75003
+ content: [
75004
+ {
75005
+ type: "text",
75006
+ text: formatDocsReadError("source content", error2)
75007
+ }
75008
+ ]
75009
+ };
75010
+ }
75011
+ }
75012
+ const validPrefixes = [...docsUrlPrefixes, "https://support.wix.com/"];
74415
75013
  if (skillsPortalUrl) validPrefixes.push(skillsPortalUrl);
74416
75014
  const isSkillsPage = isSkillsRegistryUrl(articleUrl);
74417
75015
  if (!isSkillsPage && !validPrefixes.some((p) => articleUrl.startsWith(p))) {
@@ -74420,7 +75018,7 @@ var addDocsTools = (server2, allowedTools = [
74420
75018
  content: [
74421
75019
  {
74422
75020
  type: "text",
74423
- text: `Invalid article URL: must start with https://dev.wix.com/docs/, or be a Wix skills page (https://www.wix.com/skills/...). Got: "${articleUrl}"`
75021
+ text: `Invalid article URL: must start with https://dev.wix.com/docs/ or https://support.wix.com/, or be a Wix skills page (https://www.wix.com/skills/..., https://www.wix.com/headless/..., or that file's github.com/wix/skills source). Got: "${articleUrl}"`
74424
75022
  }
74425
75023
  ]
74426
75024
  };
@@ -74428,6 +75026,27 @@ var addDocsTools = (server2, allowedTools = [
74428
75026
  if (!isSkillsPage && articleUrl.startsWith("https://dev.wix.com/docs/")) {
74429
75027
  articleUrl = articleUrl.replace(/\.md$/, "");
74430
75028
  }
75029
+ if (mintlifyDocs && !isSkillsPage) {
75030
+ try {
75031
+ const page = await readMintlifyMarkdown(articleUrl);
75032
+ if (page) {
75033
+ return {
75034
+ content: [
75035
+ {
75036
+ type: "text",
75037
+ text: isQueryOrSearchEndpoint(page.url) ? [page.markdown, ARTICLE_CAPABILITY_NOTE].join("\n\n") : page.markdown
75038
+ },
75039
+ ...sourceNote(`Mintlify site: ${page.url}.md`)
75040
+ ]
75041
+ };
75042
+ }
75043
+ } catch (error2) {
75044
+ logger2.error(
75045
+ `[mintlify] reading ${articleUrl} from Mintlify failed, falling back: ${error2}`
75046
+ );
75047
+ }
75048
+ articleUrl = toBackendUrl(articleUrl);
75049
+ }
74431
75050
  try {
74432
75051
  const articleContent = await fetchArticleContent(
74433
75052
  httpClient,
@@ -74448,7 +75067,10 @@ var addDocsTools = (server2, allowedTools = [
74448
75067
  // The article's own URL, never its body — a filter/sort reference page links query
74449
75068
  // methods in its prose but isn't one.
74450
75069
  text: isQueryOrSearchEndpoint(articleUrl) ? [articleContent, ARTICLE_CAPABILITY_NOTE].join("\n\n") : articleContent
74451
- }
75070
+ },
75071
+ ...sourceNote(
75072
+ isSkillsPage ? `skills registry: ${articleUrl}` : `today's backend (dev.wix.com/rawdocs, ingvar), not on the Mintlify site: ${articleUrl}`
75073
+ )
74452
75074
  ]
74453
75075
  };
74454
75076
  } catch (error2) {
@@ -74494,7 +75116,7 @@ ${text}`
74494
75116
  defaultToolDescriptions.ReadFullDocsMethodSchema
74495
75117
  ),
74496
75118
  (() => {
74497
- const d = desc("ReadFullDocsMethodSchema");
75119
+ const d = desc2("ReadFullDocsMethodSchema");
74498
75120
  return {
74499
75121
  articleUrl: external_exports.string().url().describe(d.articleUrl),
74500
75122
  reason: external_exports.string().describe(d.reason)
@@ -74502,7 +75124,7 @@ ${text}`
74502
75124
  })(),
74503
75125
  { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
74504
75126
  async ({ articleUrl, reason }, { httpClient }) => {
74505
- const validPrefixes = ["https://dev.wix.com/docs/"];
75127
+ const validPrefixes = [...docsUrlPrefixes];
74506
75128
  if (skillsPortalUrl) validPrefixes.push(skillsPortalUrl);
74507
75129
  if (!validPrefixes.some((p) => articleUrl.startsWith(p))) {
74508
75130
  return {
@@ -74518,6 +75140,7 @@ ${text}`
74518
75140
  if (articleUrl.startsWith("https://dev.wix.com/docs/")) {
74519
75141
  articleUrl = articleUrl.replace(/\.md$/, "");
74520
75142
  }
75143
+ articleUrl = toBackendUrl(articleUrl);
74521
75144
  try {
74522
75145
  logger2.log(
74523
75146
  `[ReadFullDocsMethodSchema] url="${articleUrl}", reason="${reason}"`
@@ -74535,12 +75158,18 @@ ${text}`
74535
75158
  if (!articleContent) {
74536
75159
  throw new Error("Method schema is empty");
74537
75160
  }
75161
+ const schemaText = mintlifyDocs ? (await rewriteDocsLinks(articleContent, {
75162
+ label: "schema ReadFullDocsMethodSchema"
75163
+ })).text : articleContent;
74538
75164
  return {
74539
75165
  content: [
74540
75166
  {
74541
75167
  type: "text",
74542
- text: articleContent
74543
- }
75168
+ text: schemaText
75169
+ },
75170
+ ...sourceNote(
75171
+ `PAPI, through today's backend (dev.wix.com/rawdocs, ingvar): ${articleUrl}`
75172
+ )
74544
75173
  ]
74545
75174
  };
74546
75175
  } catch (error2) {
@@ -74586,7 +75215,7 @@ ${text}`
74586
75215
  defaultToolDescriptions.BrowseWixRESTDocsMenu
74587
75216
  ),
74588
75217
  (() => {
74589
- const d = desc("BrowseWixRESTDocsMenu");
75218
+ const d = desc2("BrowseWixRESTDocsMenu");
74590
75219
  return {
74591
75220
  menuUrl: external_exports.string().optional().describe(d.menuUrl),
74592
75221
  reason: external_exports.string().describe(d.reason)
@@ -74595,7 +75224,7 @@ ${text}`
74595
75224
  { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
74596
75225
  async ({ menuUrl, reason }, { httpClient }) => {
74597
75226
  try {
74598
- if (menuUrl && !menuUrl.startsWith("https://dev.wix.com/docs/")) {
75227
+ if (menuUrl && !docsUrlPrefixes.some((p) => menuUrl.startsWith(p))) {
74599
75228
  return {
74600
75229
  content: [
74601
75230
  {
@@ -85684,6 +86313,69 @@ function createToolBiEvent(params) {
85684
86313
  return wixMcpRequestSrc39Evid1607(params);
85685
86314
  }
85686
86315
 
86316
+ // src/infra/redact-personal-data.ts
86317
+ var FREE_TEXT_INFO_PARAMS = [
86318
+ "userRequest",
86319
+ "siteDescription",
86320
+ "siteForm",
86321
+ "siteFunctionality",
86322
+ "agentIdentity",
86323
+ "wixAccess",
86324
+ "reason",
86325
+ "whyNotExecuteWixAPI"
86326
+ ];
86327
+ var EMAIL = /[A-Z0-9._%+-]+@[A-Z0-9-]+(?:\.[A-Z0-9-]+)*\.[A-Z]{2,}/gi;
86328
+ var NAMED_SECRET = /\b(passwords?|passwd|pwd|passcodes?|secrets?|tokens?|api[ _-]?keys?|access[ _-]?keys?|credentials?)(\s*[:=]\s*|\s+(?:is|was|to)\s+)(?:"[^"]*"|'[^']*'|`[^`]*`|[^\s"'`,;][^,;\n]*?(?=[.!?]\s|[,;\n]|$))/gi;
86329
+ var BEARER = /\bBearer\s+[A-Za-z0-9._~+/=-]+/gi;
86330
+ var JWT = /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
86331
+ var KEY_PREFIXES = /\b(?:sk-[A-Za-z0-9_-]{16,}|gh[pousr]_[A-Za-z0-9]{20,}|github_pat_\w{20,}|xox[abprs]-[A-Za-z0-9-]{10,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35})\b/g;
86332
+ var BACKTICK = "`";
86333
+ var UNIX_ROOT = String.raw`(?<![\w.:/~-])(?:~|/(?:Users|home|root|mnt|tmp|private|var|Volumes|workspace|work))`;
86334
+ var WINDOWS_ROOT = String.raw`(?<!\w)[A-Za-z]:(?=\\\w)`;
86335
+ var PATH_ROOT = `(?:${UNIX_ROOT}|${WINDOWS_ROOT})`;
86336
+ var QUOTED_PATH = new RegExp(
86337
+ String.raw`(?<![\w])(["'${BACKTICK}])${PATH_ROOT}[^"'${BACKTICK}\n]*\1`,
86338
+ "g"
86339
+ );
86340
+ var FOLDER = String.raw`[^\s/\\"'${BACKTICK},;()<>]+(?: [^\s/\\"'${BACKTICK},;()<>]+)*`;
86341
+ var LOCAL_PATH = new RegExp(
86342
+ String.raw`${PATH_ROOT}(?:[/\\]${FOLDER}(?=[/\\]))*[/\\][^\s"'${BACKTICK},;()<>]*`,
86343
+ "g"
86344
+ );
86345
+ var PHONE_CANDIDATE = /(?<![\w-])\+?\(?\d[\d\s().-]{7,}\d(?![\w-])/g;
86346
+ var DATE_START = /^\d{4}-\d{2}-\d{2}/;
86347
+ function redactPhone(match, offset, text) {
86348
+ if (DATE_START.test(match) || /^:\d{2}\b/.test(text.slice(offset + match.length))) {
86349
+ return match;
86350
+ }
86351
+ const digits = match.replace(/\D/g, "").length;
86352
+ return digits >= 9 && digits <= 15 ? "[phone]" : match;
86353
+ }
86354
+ function redactPersonalData(text) {
86355
+ return text.replace(EMAIL, "[email]").replace(BEARER, "Bearer [secret]").replace(JWT, "[secret]").replace(KEY_PREFIXES, "[secret]").replace(NAMED_SECRET, "$1$2[secret]").replace(QUOTED_PATH, "$1[path]$1").replace(LOCAL_PATH, "[path]").replace(PHONE_CANDIDATE, redactPhone);
86356
+ }
86357
+ function redactInfoParams(value) {
86358
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
86359
+ return value;
86360
+ }
86361
+ const record2 = value;
86362
+ if (!FREE_TEXT_INFO_PARAMS.some((key) => typeof record2[key] === "string")) {
86363
+ return value;
86364
+ }
86365
+ const redacted = { ...record2 };
86366
+ for (const key of FREE_TEXT_INFO_PARAMS) {
86367
+ if (typeof redacted[key] === "string") {
86368
+ redacted[key] = redactPersonalData(redacted[key]);
86369
+ }
86370
+ }
86371
+ return redacted;
86372
+ }
86373
+ function serializeToolParamsForBi(args) {
86374
+ return JSON.stringify(
86375
+ Array.isArray(args) ? args.map(redactInfoParams) : redactInfoParams(args)
86376
+ );
86377
+ }
86378
+
85687
86379
  // src/wix-mcp-server.ts
85688
86380
  var WixMcpServer = class extends McpServer {
85689
86381
  constructor(serverInfo, options, context2) {
@@ -85708,18 +86400,34 @@ var WixMcpServer = class extends McpServer {
85708
86400
  gptAppSchemesEnabled = false;
85709
86401
  openAiMcpAppsEnabled = false;
85710
86402
  mcpAppsInMcpEnabled = true;
86403
+ registeredTools = /* @__PURE__ */ new Map();
85711
86404
  setUserIdGetter(getUserId) {
85712
86405
  this.getUserId = getUserId;
85713
86406
  }
85714
86407
  getSessionId() {
85715
86408
  return this.sessionId;
85716
86409
  }
86410
+ /** The connected client's name: the host's getter (initialize name, then User-Agent) first, then clientInfo. */
86411
+ clientName() {
86412
+ return this.getClientName?.() ?? this.server.getClientVersion()?.name;
86413
+ }
85717
86414
  setClientNameGetter(getClientName) {
85718
86415
  this.getClientName = getClientName;
85719
86416
  }
85720
86417
  setUserAgentGetter(getUserAgent) {
85721
86418
  this.getUserAgent = getUserAgent;
85722
86419
  }
86420
+ /** True when every named tool is registered and enabled in this session. */
86421
+ hasTools(...names) {
86422
+ return names.every((name) => this.registeredTools.get(name)?.enabled);
86423
+ }
86424
+ /**
86425
+ * Sets the `instructions` the server returns at initialize. Call it before the transport
86426
+ * connects. The SDK keeps them on the low-level server and has no setter for them.
86427
+ */
86428
+ setInstructions(instructions) {
86429
+ this.server._instructions = instructions;
86430
+ }
85723
86431
  setGptAppSchemesEnabled(enabled) {
85724
86432
  this.gptAppSchemesEnabled = enabled;
85725
86433
  }
@@ -85775,6 +86483,7 @@ var WixMcpServer = class extends McpServer {
85775
86483
  args[cbIndex] = this.wrapToolCallback(toolName, originalCb);
85776
86484
  }
85777
86485
  const registeredTool = super.tool.apply(this, args);
86486
+ this.registeredTools.set(args[0], registeredTool);
85778
86487
  if (this.isGptAppSchemesEnabled() && !registeredTool._meta?.securitySchemes) {
85779
86488
  registeredTool.update({
85780
86489
  _meta: {
@@ -85796,11 +86505,13 @@ var WixMcpServer = class extends McpServer {
85796
86505
  };
85797
86506
  }
85798
86507
  const wrappedCb = this.wrapToolCallback(name, cb);
85799
- return super.registerTool(
86508
+ const registeredTool = super.registerTool(
85800
86509
  name,
85801
86510
  config3,
85802
86511
  wrappedCb
85803
86512
  );
86513
+ this.registeredTools.set(name, registeredTool);
86514
+ return registeredTool;
85804
86515
  }
85805
86516
  wrapToolCallback(toolName, originalCb) {
85806
86517
  const isDevEnvironment = DEV_ENVIRONMENTS.includes(this.nodeEnv);
@@ -85842,7 +86553,7 @@ var WixMcpServer = class extends McpServer {
85842
86553
  });
85843
86554
  panorama.transaction(toolName).start({
85844
86555
  toolInvocationId,
85845
- params: JSON.stringify(argsBeforeExtra)
86556
+ params: serializeToolParamsForBi(argsBeforeExtra)
85846
86557
  });
85847
86558
  }
85848
86559
  const startTime = performance.now();
@@ -85859,7 +86570,8 @@ var WixMcpServer = class extends McpServer {
85859
86570
  cbResult,
85860
86571
  {
85861
86572
  returnedRows: toolBiParams.returnedRows,
85862
- originalLength: toolBiParams.originalLength
86573
+ originalLength: toolBiParams.originalLength,
86574
+ upload: toolBiParams.upload
85863
86575
  },
85864
86576
  {
85865
86577
  name: this.getClientName?.() || this.server.getClientVersion()?.name,
@@ -85875,7 +86587,7 @@ var WixMcpServer = class extends McpServer {
85875
86587
  context: {
85876
86588
  toolName,
85877
86589
  toolInvocationId,
85878
- params: JSON.stringify(argsBeforeExtra),
86590
+ params: serializeToolParamsForBi(argsBeforeExtra),
85879
86591
  error: JSON.stringify(cbResult, null, 2)
85880
86592
  }
85881
86593
  });
@@ -85889,7 +86601,7 @@ var WixMcpServer = class extends McpServer {
85889
86601
  context: {
85890
86602
  toolName,
85891
86603
  toolInvocationId,
85892
- params: JSON.stringify(argsBeforeExtra),
86604
+ params: serializeToolParamsForBi(argsBeforeExtra),
85893
86605
  error: errorBody
85894
86606
  }
85895
86607
  });
@@ -85938,7 +86650,7 @@ var WixMcpServer = class extends McpServer {
85938
86650
  errorBody,
85939
86651
  toolInvocationId,
85940
86652
  toolName,
85941
- params: JSON.stringify(argsBeforeExtra),
86653
+ params: serializeToolParamsForBi(argsBeforeExtra),
85942
86654
  origin: this.nodeEnv,
85943
86655
  sessionId: this.sessionId,
85944
86656
  executionResult: toolSucceeded ? "Success" : "Error",
@@ -86181,7 +86893,7 @@ function resolveBase64Image(imageBase64, mimeType) {
86181
86893
  function errorResponse(text) {
86182
86894
  return { isError: true, content: [{ type: "text", text }] };
86183
86895
  }
86184
- async function uploadFromUrl(item, authHeaders, displayName) {
86896
+ async function uploadFromUrl(item, authHeaders, displayName, imagePickerToolName) {
86185
86897
  if (!item.download_url) {
86186
86898
  return {
86187
86899
  success: false,
@@ -86191,7 +86903,7 @@ async function uploadFromUrl(item, authHeaders, displayName) {
86191
86903
  if (!/^https?:\/\//i.test(item.download_url)) {
86192
86904
  return {
86193
86905
  success: false,
86194
- error: `download_url must be a publicly accessible http(s) URL, not a local or sandbox file path (got: "${item.download_url}"). For a user-attached file, pass the file so the platform resolves it to a real download_url; if you only have the raw bytes, use imageBase64 instead.`
86906
+ error: `This server can't read files on your machine or sandbox (got: "${item.download_url}"). Send this image as imageBase64 (the whole file, one per call) or as a public URL in imageUrls${imagePickerToolName ? `, or call ${imagePickerToolName} so the user picks it` : ""}.`
86195
86907
  };
86196
86908
  }
86197
86909
  try {
@@ -86289,7 +87001,10 @@ function formatBatchResults(results) {
86289
87001
  };
86290
87002
  }
86291
87003
  function addUploadImageTool(server2, strategy, options) {
86292
- const description = options?.description ?? defaultToolDescriptions.UploadImageToWixSite;
87004
+ const imagePickerToolName = options?.imagePickerToolName;
87005
+ const baseDescription = options?.description || defaultToolDescriptions.UploadImageToWixSite;
87006
+ const description = imagePickerToolName ? `${baseDescription}
87007
+ If you can't deliver the image any of these ways, call ${imagePickerToolName} so the user picks it.` : baseDescription;
86293
87008
  const hints = {
86294
87009
  readOnlyHint: options?.hints?.readOnlyHint ?? false,
86295
87010
  destructiveHint: options?.hints?.destructiveHint ?? false,
@@ -86356,7 +87071,9 @@ function addUploadImageTool(server2, strategy, options) {
86356
87071
  try {
86357
87072
  const authHeaders = await strategy.getSiteAuthHeaders(siteId);
86358
87073
  const urlResults = await Promise.all(
86359
- urlItems.map((item) => uploadFromUrl(item, authHeaders, displayName))
87074
+ urlItems.map(
87075
+ (item) => uploadFromUrl(item, authHeaders, displayName, imagePickerToolName)
87076
+ )
86360
87077
  );
86361
87078
  let base64Result = null;
86362
87079
  if (imageBase64) {
@@ -86423,7 +87140,8 @@ function formatApiResponse(responseData, maxResponseSize = DEFAULT_MAX_RESPONSE_
86423
87140
  }
86424
87141
  return { text: responseText, isError: false, originalLength, returnedRows };
86425
87142
  }
86426
- function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "ListWixSites", "ManageWixSite"], disableTools = [], enableTools = [], toolDescriptions, toolHints, maxResponseSize) {
87143
+ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "ListWixSites", "ManageWixSite"], disableTools = [], enableTools = [], toolDescriptions, toolHints, maxResponseSize, options) {
87144
+ const executeAdvice = (text, reconnect, plain) => options?.executeWixAPIServed ? text : text.replace(reconnect, plain);
86427
87145
  const effectiveAllowedTools = [
86428
87146
  .../* @__PURE__ */ new Set([...allowedTools, ...enableTools])
86429
87147
  ].filter((tool) => !disableTools.includes(tool));
@@ -86436,7 +87154,14 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
86436
87154
  if (effectiveAllowedTools.includes("CallWixSiteAPI") && !disableTools.includes("CallWixSiteAPI")) {
86437
87155
  server2.tool(
86438
87156
  "CallWixSiteAPI",
86439
- getDescription("CallWixSiteAPI", defaultToolDescriptions.CallWixSiteAPI),
87157
+ executeAdvice(
87158
+ getDescription(
87159
+ "CallWixSiteAPI",
87160
+ defaultToolDescriptions.CallWixSiteAPI
87161
+ ),
87162
+ CALL_WIX_SITE_API_RECONNECT_LINE,
87163
+ CALL_WIX_SITE_API_NO_EXECUTE_LINE
87164
+ ),
86440
87165
  (() => {
86441
87166
  const d = desc("CallWixSiteAPI");
86442
87167
  return {
@@ -86445,17 +87170,34 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
86445
87170
  method: external_exports.string().describe(d.method),
86446
87171
  body: external_exports.union([external_exports.object({}).passthrough(), external_exports.array(external_exports.unknown())]).optional().describe(d.body),
86447
87172
  reason: external_exports.string().describe(d.reason),
87173
+ whyNotExecuteWixAPI: external_exports.string().optional().describe(
87174
+ executeAdvice(
87175
+ d.whyNotExecuteWixAPI,
87176
+ WHY_NOT_EXECUTE_RECONNECT,
87177
+ WHY_NOT_EXECUTE_NO_EXECUTE
87178
+ )
87179
+ ),
86448
87180
  sourceDocUrl: external_exports.string().describe(d.sourceDocUrl)
86449
87181
  };
86450
87182
  })(),
87183
+ // openWorldHint true: a free-form URL into the whole Wix REST surface is an
87184
+ // open-ended target, even though auth is bounded to the user's account.
86451
87185
  getHints("CallWixSiteAPI", {
86452
87186
  readOnlyHint: false,
86453
87187
  destructiveHint: true,
86454
- openWorldHint: false
87188
+ openWorldHint: true
86455
87189
  }),
86456
- async ({ url, body, method, siteId, reason, sourceDocUrl }, { httpClient, setToolBiParams }) => {
87190
+ async ({
87191
+ url,
87192
+ body,
87193
+ method,
87194
+ siteId,
87195
+ reason,
87196
+ whyNotExecuteWixAPI,
87197
+ sourceDocUrl
87198
+ }, { httpClient, setToolBiParams }) => {
86457
87199
  logger2.log(
86458
- `[CallWixSiteAPI] siteId=${siteId}, method=${method}, url=${url}, sourceDocUrl=${sourceDocUrl}, reason="${reason}", body=${JSON.stringify(body)}`
87200
+ `[CallWixSiteAPI] siteId=${siteId}, method=${method}, url=${url}, sourceDocUrl=${sourceDocUrl}, reason="${reason}", whyNotExecuteWixAPI="${whyNotExecuteWixAPI ?? ""}", body=${JSON.stringify(body)}`
86459
87201
  );
86460
87202
  const requestHeaders = {
86461
87203
  // Ask the Wix API edge for JSON error bodies (it serves a branded HTML
@@ -86628,7 +87370,7 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
86628
87370
  getHints("ManageWixSite", {
86629
87371
  readOnlyHint: false,
86630
87372
  destructiveHint: true,
86631
- openWorldHint: false
87373
+ openWorldHint: true
86632
87374
  }),
86633
87375
  async ({ url, body, method, reason }, { httpClient, setToolBiParams }) => {
86634
87376
  logger2.log(
@@ -86698,7 +87440,8 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
86698
87440
  if (effectiveAllowedTools.includes("UploadImageToWixSite") && !disableTools.includes("UploadImageToWixSite")) {
86699
87441
  addUploadImageTool(server2, strategy, {
86700
87442
  description: getDescription("UploadImageToWixSite", ""),
86701
- hints: toolHints?.["UploadImageToWixSite"]
87443
+ hints: toolHints?.["UploadImageToWixSite"],
87444
+ imagePickerToolName: options?.imagePickerToolName
86702
87445
  });
86703
87446
  }
86704
87447
  }
@@ -86978,10 +87721,14 @@ function truncateResponse(content, maxChars = DEFAULT_MAX_CHARS) {
86978
87721
  const truncated = text.slice(0, effectiveMax);
86979
87722
  const estimatedTokens = Math.ceil(text.length / CHARS_PER_TOKEN);
86980
87723
  const limitTokens = Math.ceil(effectiveMax / CHARS_PER_TOKEN);
86981
- return `${truncated}
87724
+ const cutChars = text.length - effectiveMax;
87725
+ const note = `Response was ~${estimatedTokens.toLocaleString()} tokens (limit: ${limitTokens.toLocaleString()}). Showing the first ${effectiveMax.toLocaleString()} of ${text.length.toLocaleString()} characters; the last ${cutChars.toLocaleString()} were cut. To get the rest, run again and return less per call \u2014 only the fields you need, the next page (cursor or offset), or the next slice of a large array \u2014 and repeat until you have it all.`;
87726
+ return `[TRUNCATED: ${note}]
87727
+
87728
+ ${truncated}
86982
87729
 
86983
87730
  --- TRUNCATED ---
86984
- Response was ~${estimatedTokens.toLocaleString()} tokens (limit: ${limitTokens.toLocaleString()}). Refine your code to return less data.`;
87731
+ ${note}`;
86985
87732
  }
86986
87733
 
86987
87734
  // src/graphql/constants.ts
@@ -87641,7 +88388,8 @@ function addExecuteGraphqlTool(server2, description, authStrategy, options) {
87641
88388
  hasMutations: external_exports.boolean().describe(d.hasMutations),
87642
88389
  reason: external_exports.string().describe(d.reason)
87643
88390
  },
87644
- { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
88391
+ // openWorldHint true: any operation in the Wix GraphQL schema, chosen at call time.
88392
+ { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
87645
88393
  async ({ query, variables, operationName, siteId, scope, hasMutations, reason }, extra) => {
87646
88394
  const effectiveScope = scope ?? (siteId ? "site" : "account");
87647
88395
  logger2.log(
@@ -87741,6 +88489,7 @@ var EXPERIMENTAL_TOOLS = [
87741
88489
  "CLI_COMMAND",
87742
88490
  "GET_TO_KNOW_WIX",
87743
88491
  "CREATE_WIX_BUSINESS_GUIDE",
88492
+ // accepted so old configs still start; the tool was removed
87744
88493
  "VELO_README",
87745
88494
  "WIX_API_THROUGH_FS",
87746
88495
  "GRAPHQL"
@@ -87811,18 +88560,14 @@ var docsTools = activeTools.filter(
87811
88560
  );
87812
88561
  var isWixCliAuth = Boolean(parsedArgs["wixCliAuth"]);
87813
88562
  var hasGetToKnowWix = activeTools.includes("GET_TO_KNOW_WIX") || isWixCliAuth;
87814
- var hasCreateWixBusinessGuide = activeTools.includes(
87815
- "CREATE_WIX_BUSINESS_GUIDE"
87816
- );
87817
88563
  var hasDynamicContext = Boolean(parsedArgs["dynamicContext"]) || isWixCliAuth;
87818
- if (docsTools.length > 0 || hasGetToKnowWix || hasCreateWixBusinessGuide) {
88564
+ if (docsTools.length > 0 || hasGetToKnowWix) {
87819
88565
  logger2.log("Adding docs tools:", docsTools);
87820
88566
  addDocsTools(server, docsTools, {
87821
88567
  getToKnowWixEnabled: hasGetToKnowWix,
87822
- createWixBusinessGuideEnabled: hasCreateWixBusinessGuide,
87823
88568
  dynamicContextEnabled: hasDynamicContext,
87824
- cliEnabled: true
87825
- // bin.ts is always a CLI client (e.g. Claude Code)
88569
+ // Mintlify docs: --docsSite=mintlify-links (or WIX_MCP_DOCS_SITE).
88570
+ docsSite: parsedArgs["docsSite"] ?? process.env.WIX_MCP_DOCS_SITE
87826
88571
  });
87827
88572
  }
87828
88573
  if (activeTools.includes("VELO_README")) {