@wix/mcp 1.0.94 → 1.0.96

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 (86) hide show
  1. package/README.md +2 -2
  2. package/build/bin-standalone.js +1457 -332
  3. package/build/cjs/index.cjs +3379 -1333
  4. package/build/cjs/toolkit.cjs +2158 -373
  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 +36 -8
  9. package/build/dts/api-call/site-files.d.ts +14 -0
  10. package/build/dts/api-call/site-files.js +106 -10
  11. package/build/dts/api-call/upload-headless-website-files.d.ts +117 -5
  12. package/build/dts/api-call/upload-headless-website-files.js +565 -20
  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 +3 -1
  17. package/build/dts/code-mode/attachments.d.ts +9 -6
  18. package/build/dts/code-mode/attachments.js +23 -16
  19. package/build/dts/code-mode/index.d.ts +6 -1
  20. package/build/dts/code-mode/index.js +32 -12
  21. package/build/dts/code-mode/truncate-response.js +5 -1
  22. package/build/dts/config/default-config.d.ts +35 -5
  23. package/build/dts/config/default-config.js +339 -182
  24. package/build/dts/config/file-params.d.ts +22 -0
  25. package/build/dts/config/file-params.js +24 -0
  26. package/build/dts/config/param-descriptions.d.ts +14 -2
  27. package/build/dts/config/param-descriptions.js +33 -14
  28. package/build/dts/constants.d.ts +1 -0
  29. package/build/dts/constants.js +1 -0
  30. package/build/dts/docs/docs.d.ts +12 -1
  31. package/build/dts/docs/docs.js +274 -43
  32. package/build/dts/docs/fetch-article.d.ts +21 -0
  33. package/build/dts/docs/fetch-article.js +66 -4
  34. package/build/dts/docs/get-to-know.d.ts +7 -2
  35. package/build/dts/docs/get-to-know.js +36 -14
  36. package/build/dts/docs/guessed-url.d.ts +41 -0
  37. package/build/dts/docs/guessed-url.js +185 -0
  38. package/build/dts/docs/mintlify-docs.d.ts +121 -0
  39. package/build/dts/docs/mintlify-docs.js +391 -0
  40. package/build/dts/docs/semanticSearch.d.ts +2 -1
  41. package/build/dts/docs/semanticSearch.js +14 -7
  42. package/build/dts/docs/start-deploy-website.d.ts +7 -6
  43. package/build/dts/docs/start-deploy-website.js +13 -8
  44. package/build/dts/docs/start-headless-build.d.ts +8 -10
  45. package/build/dts/docs/start-headless-build.js +14 -28
  46. package/build/dts/index.d.ts +2 -2
  47. package/build/dts/index.js +2 -2
  48. package/build/dts/infra/redact-personal-data.d.ts +4 -0
  49. package/build/dts/infra/redact-personal-data.js +148 -0
  50. package/build/dts/site-widget-tools/constants.d.ts +50 -2
  51. package/build/dts/site-widget-tools/constants.js +65 -8
  52. package/build/dts/site-widget-tools/index.d.ts +1 -0
  53. package/build/dts/site-widget-tools/index.js +1 -0
  54. package/build/dts/site-widget-tools/pick-images-tool/index.d.ts +14 -0
  55. package/build/dts/site-widget-tools/pick-images-tool/index.js +138 -0
  56. package/build/dts/site-widget-tools/pull-site-creation-job-tool/index.js +1 -1
  57. package/build/dts/site-widget-tools/search-site-templates-tool/index.js +25 -2
  58. package/build/dts/site-widget-tools/site-builder-tool/index.js +35 -3
  59. package/build/dts/site-widget-tools/site-creation-tool/index.d.ts +7 -1
  60. package/build/dts/site-widget-tools/site-creation-tool/index.js +22 -51
  61. package/build/dts/site-widget-tools/suggested-domain-tool/index.js +26 -12
  62. package/build/dts/support/index.d.ts +4 -0
  63. package/build/dts/support/index.js +13 -7
  64. package/build/dts/tool-utils.d.ts +8 -1
  65. package/build/dts/tool-utils.js +26 -2
  66. package/build/dts/toolkit-entry.d.cts +15 -10
  67. package/build/dts/toolkit-entry.d.ts +15 -10
  68. package/build/dts/toolkit.d.ts +2 -2
  69. package/build/dts/toolkit.js +21 -8
  70. package/build/dts/wix-mcp-server.d.ts +10 -1
  71. package/build/dts/wix-mcp-server.js +25 -7
  72. package/build/dts/wixel/constants.d.ts +8 -1
  73. package/build/dts/wixel/constants.js +8 -1
  74. package/build/dts/wixel/index.d.ts +1 -1
  75. package/build/dts/wixel/index.js +2 -2
  76. package/build/dts/wixel/wixel-a2a-client.d.ts +83 -0
  77. package/build/dts/wixel/wixel-a2a-client.js +166 -0
  78. package/build/dts/wixel/wixel-bi.d.ts +2 -1
  79. package/build/dts/wixel/wixel-bi.js +2 -1
  80. package/build/dts/wixel/{external-agent-api.d.ts → wixel-session-entries.d.ts} +11 -33
  81. package/build/dts/wixel/{external-agent-api.js → wixel-session-entries.js} +33 -54
  82. package/build/dts/wixel/wixel-session-tools.d.ts +21 -26
  83. package/build/dts/wixel/wixel-session-tools.js +494 -599
  84. package/build/esm/index.js +3422 -1388
  85. package/build/esm/toolkit.js +2158 -373
  86. package/package.json +4 -4
@@ -2,9 +2,10 @@ import { z } from 'zod';
2
2
  import { createHttpClient } from '@wix/http-client';
3
3
  import { getWidgetHtml } from '../../widget-manifest.js';
4
4
  import { RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server';
5
- import { SITE_BUILDER_TOOL_NAME, SITE_WIDGET_MCP_CSP, OPEN_AI_SITE_WIDGET_CSP, OPENAI_WIDGET_MIME_TYPE } from '../constants.js';
5
+ import { EDITOR_NOT_REQUESTED_MESSAGE, NOT_REQUESTED_WIDGET_PAYLOAD, SITE_BUILDER_TOOL_NAME, SITE_WIDGET_MCP_CSP, OPEN_AI_SITE_WIDGET_CSP, OPENAI_WIDGET_MIME_TYPE } from '../constants.js';
6
6
  import { defaultToolDescriptions } from '../../config/default-config.js';
7
7
  import { withJsonContent } from '../../tool-utils.js';
8
+ import { NO_PERSONAL_DATA, START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS } from '../../docs/start-deploy-website.js';
8
9
  const httpClient = createHttpClient();
9
10
  const CREATE_SITE_WIDGET_URI = 'ui://widget/site-builder.html';
10
11
  export function addCreateSiteWidgetTool(server, authStrategy, options) {
@@ -67,7 +68,19 @@ export function addCreateSiteWidgetTool(server, authStrategy, options) {
67
68
  suggestedSiteName: z
68
69
  .string()
69
70
  .optional()
70
- .describe('You must provide this on every call, including updates to an existing job, in English. A short name for the site: the business name the user gave, or one you derive from the site prompt.')
71
+ .describe('You must provide this on every call, including updates to an existing job, in English. A short name for the site: the business name the user gave, or one you derive from the site prompt.'),
72
+ wixEditorExplicitlyRequested: z
73
+ .boolean()
74
+ .optional()
75
+ .describe("Did the user, in their own words or their answer to your question, ask for the Wix Harmony Editor, or for Wix to design the site in Wix's editor? Asking for a site on Wix, or for Wix to build or make one, is not that. Wanting Wix's editor, or to design the site themselves, is not that either: ask them how to start first. Nor are a site's business, features or look."),
76
+ editorRequest: z
77
+ .string()
78
+ .optional()
79
+ .describe(`On a new build: the user's own words that asked for the Wix Harmony Editor or for Wix to design the site, quoted from their message or their answer to your question. Empty when they asked for neither; then wixEditorExplicitlyRequested is false. Recorded, not checked. ${NO_PERSONAL_DATA}`),
80
+ agentIdentity: z
81
+ .string()
82
+ .optional()
83
+ .describe(START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.agentIdentity)
71
84
  },
72
85
  _meta: toolDefinitionMeta,
73
86
  annotations: {
@@ -77,8 +90,27 @@ export function addCreateSiteWidgetTool(server, authStrategy, options) {
77
90
  }
78
91
  }, async (args, { setToolBiParams, panorama }) => {
79
92
  const isAnonymous = authStrategy.isAnonymous?.() ?? false;
93
+ // A new build runs unless the agent says the user did not ask for it. Only an explicit
94
+ // false is refused: clients that hold the previous definition never send the flag, and
95
+ // resuming a job does not ask again.
96
+ if (!args.jobId && args.wixEditorExplicitlyRequested === false) {
97
+ return withJsonContent({
98
+ content: [
99
+ { type: 'text', text: EDITOR_NOT_REQUESTED_MESSAGE }
100
+ ],
101
+ structuredContent: {
102
+ success: false,
103
+ status: 'not_requested',
104
+ jobId: null
105
+ },
106
+ _meta: { widgetPayload: NOT_REQUESTED_WIDGET_PAYLOAD }
107
+ });
108
+ }
80
109
  console.log(`[${SITE_BUILDER_TOOL_NAME}] 🚀 tool invoked`, {
81
- ...args,
110
+ jobId: args.jobId,
111
+ suggestedSiteName: args.suggestedSiteName,
112
+ wixEditorExplicitlyRequested: args.wixEditorExplicitlyRequested,
113
+ hasEditorRequest: !!args.editorRequest,
82
114
  isAnonymous
83
115
  });
84
116
  let jobId;
@@ -1,6 +1,12 @@
1
1
  import { McpAuthenticationStrategy } from '../../auth/index.js';
2
2
  import { WixMcpServer } from '../../wix-mcp-server.js';
3
3
  import { SiteWidgetToolOptions } from '../site-builder-tool/index.js';
4
- /** Entry tool for the site creation flow — opens the "create with AI" vs. "use a template" chooser widget when the build method is unstated. */
4
+ /**
5
+ * WixSiteCreation no longer opens a chooser. It keeps its name, so a client that still holds
6
+ * the previous definition never gets "tool not found", and it answers with where a new site
7
+ * goes: written in code and uploaded. Its definition carries no widget. The widget resource
8
+ * stays registered for clients whose frozen definition still points at it (ChatGPT until
9
+ * OpenAI approves this one); it renders a one-line card with a button that restarts the turn.
10
+ */
5
11
  export declare function addWixSiteCreationTool(server: WixMcpServer, _authStrategy: McpAuthenticationStrategy, options?: SiteWidgetToolOptions): void;
6
12
  //# sourceMappingURL=index.d.ts.map
@@ -1,27 +1,22 @@
1
1
  import { z } from 'zod';
2
- import { v4 as uuidv4 } from 'uuid';
3
2
  import { getWidgetHtml } from '../../widget-manifest.js';
4
3
  import { RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server';
5
- import { WIX_SITE_CREATION_TOOL_NAME, SITE_WIDGET_MCP_CSP, OPEN_AI_SITE_WIDGET_CSP, buildSiteCreationSelectorMessage, SITE_CREATION_CUSTOM_ACTIONS_GUIDANCE } from '../constants.js';
4
+ import { WIX_SITE_CREATION_TOOL_NAME, SITE_WIDGET_MCP_CSP, OPEN_AI_SITE_WIDGET_CSP, SITE_CREATION_ROUTE_MESSAGE } from '../constants.js';
6
5
  import { defaultToolDescriptions } from '../../config/default-config.js';
7
6
  import { withJsonContent } from '../../tool-utils.js';
8
7
  const WIX_SITE_CREATION_WIDGET_URI = 'ui://widget/wix-site-creation.html';
9
- /** Entry tool for the site creation flow — opens the "create with AI" vs. "use a template" chooser widget when the build method is unstated. */
8
+ /**
9
+ * WixSiteCreation no longer opens a chooser. It keeps its name, so a client that still holds
10
+ * the previous definition never gets "tool not found", and it answers with where a new site
11
+ * goes: written in code and uploaded. Its definition carries no widget. The widget resource
12
+ * stays registered for clients whose frozen definition still points at it (ChatGPT until
13
+ * OpenAI approves this one); it renders a one-line card with a button that restarts the turn.
14
+ */
10
15
  export function addWixSiteCreationTool(server, _authStrategy, options) {
11
- const toolDefinitionMeta = {
12
- ui: {
13
- resourceUri: WIX_SITE_CREATION_WIDGET_URI,
14
- visibility: ['app', 'model']
15
- },
16
- securitySchemes: [{ type: 'oauth2', scopes: ['offline_access'] }],
17
- 'openai/toolInvocation/invoking': 'Opening site creation...',
18
- 'openai/toolInvocation/invoked': 'Ready',
19
- 'openai/outputTemplate': WIX_SITE_CREATION_WIDGET_URI
20
- };
21
16
  const resourceMeta = {
22
17
  ui: { csp: SITE_WIDGET_MCP_CSP },
23
18
  'openai/widgetCSP': OPEN_AI_SITE_WIDGET_CSP,
24
- 'openai/widgetDescription': 'Renders the Wix site creation step: either a chooser (create with AI vs. pick a template) or a gallery of Wix Studio templates to preview and use.'
19
+ 'openai/widgetDescription': 'Says the site is being built here in chat, with a button that continues the conversation.'
25
20
  };
26
21
  server.registerResource(`${WIX_SITE_CREATION_TOOL_NAME}_RESOURCE`, WIX_SITE_CREATION_WIDGET_URI, {}, async (uri) => {
27
22
  console.log(`[${WIX_SITE_CREATION_TOOL_NAME}] Resource requested`, {
@@ -46,25 +41,23 @@ export function addWixSiteCreationTool(server, _authStrategy, options) {
46
41
  title: 'Wix Site Creation',
47
42
  description: options?.toolDescriptions?.[WIX_SITE_CREATION_TOOL_NAME] ??
48
43
  defaultToolDescriptions[WIX_SITE_CREATION_TOOL_NAME],
44
+ // The previous definition's parameters, all optional, so a call made from it still validates.
49
45
  inputSchema: {
50
46
  query: z
51
- .string()
52
- .min(1)
53
- .describe('The few most important keywords describing the site, used to search templates — e.g. "yoga studio", "wedding photographer".'),
54
- sitePrompt: z
55
- .string()
56
- .min(1)
57
- .describe('The prompt to build the site. If not provided, the user will be asked to provide a prompt.'),
58
- suggestedSiteName: z
59
47
  .string()
60
48
  .optional()
61
- .describe('Suggested site name based on the request, used alongside sitePrompt if the user picks "Create with AI".'),
62
- customActions: z
49
+ .describe('A few keywords describing the site.'),
50
+ sitePrompt: z
63
51
  .string()
64
52
  .optional()
65
- .describe(SITE_CREATION_CUSTOM_ACTIONS_GUIDANCE)
53
+ .describe('A description of the site.'),
54
+ suggestedSiteName: z.string().optional().describe('A site name.'),
55
+ customActions: z.string().optional().describe('Unused.'),
56
+ editorChosen: z.boolean().optional().describe('Unused.')
57
+ },
58
+ _meta: {
59
+ securitySchemes: [{ type: 'oauth2', scopes: ['offline_access'] }]
66
60
  },
67
- _meta: toolDefinitionMeta,
68
61
  annotations: {
69
62
  readOnlyHint: true,
70
63
  destructiveHint: false,
@@ -72,34 +65,12 @@ export function addWixSiteCreationTool(server, _authStrategy, options) {
72
65
  idempotentHint: true
73
66
  }
74
67
  }, async (args) => {
75
- console.log(`[${WIX_SITE_CREATION_TOOL_NAME}] 🚀 tool invoked`, {
68
+ console.log(`[${WIX_SITE_CREATION_TOOL_NAME}] routed to the code path`, {
76
69
  query: args.query
77
70
  });
78
- const widgetPayload = {
79
- query: args.query,
80
- sitePrompt: args.sitePrompt,
81
- suggestedSiteName: args.suggestedSiteName,
82
- viewUUID: uuidv4(),
83
- extras: server.getWidgetExtras()
84
- };
85
- // Reply instruction: a fixed SHAPE (question + the two options + a "Next up:" line) built
86
- // from the query (site type) and the inferred customActions, with the two option lines left
87
- // for the model to tailor to the industry. Returned as-is; the tool description also
88
- // instructs the model to write it out (both are load-bearing). Microsoft Copilot gets the
89
- // message without the preamble: its safety filter blocks the reply otherwise.
90
- const message = buildSiteCreationSelectorMessage(args.query, args.customActions, { plain: server.isMicrosoftCopilotClient() });
91
71
  return withJsonContent({
92
- content: [
93
- {
94
- type: 'text',
95
- text: message
96
- }
97
- ],
98
- structuredContent: {
99
- success: true,
100
- query: args.query
101
- },
102
- _meta: { widgetPayload }
72
+ content: [{ type: 'text', text: SITE_CREATION_ROUTE_MESSAGE }],
73
+ structuredContent: { success: true, route: 'code' }
103
74
  });
104
75
  });
105
76
  }
@@ -31,11 +31,16 @@ export function addSuggestedDomainTool(server, authStrategy) {
31
31
  server.registerTool(GET_SUGGESTED_DOMAINS_TOOL_NAME, {
32
32
  title: 'Get Suggested Domains',
33
33
  description: dedent `
34
- Suggests available domain names for a business, brand, or Wix site.
34
+ Suggests domain name ideas for a business, brand, or Wix site. Returns a list of domain names related to the input.
35
35
 
36
- Call this when the user asks for domain name ideas, wants to know which domains are available, or wants a domain for a new or existing site.
36
+ Call this when the user:
37
+ - asks for domain name ideas in general, e.g. "domain ideas for a bakery"
38
+ - wants to find a domain for their site, new or existing
39
+ - wants alternatives or variations of a domain name, e.g. "something similar to mybakery.com"
37
40
 
38
- Provide either a free-text \`query\` (the user's own words, e.g. "pancakes business", "modern yoga studio") OR a \`siteId\` to base the suggestions on that site's name. At least one of them is required.
41
+ Do not use this tool to check domain availability.
42
+
43
+ Provide either a free-text \`query\` (e.g. "pancakes business", "modern yoga studio") OR a \`siteId\` to base the suggestions on that site's name. At least one of them is required.
39
44
 
40
45
  Present the returned domains to the user as a short list. This tool only suggests domains — it does not purchase or connect them.
41
46
  `,
@@ -63,7 +68,10 @@ export function addSuggestedDomainTool(server, authStrategy) {
63
68
  openWorldHint: false
64
69
  },
65
70
  _meta: {
66
- securitySchemes: [{ type: 'oauth2', scopes: ['offline_access'] }],
71
+ securitySchemes: [
72
+ { type: 'noauth' },
73
+ { type: 'oauth2', scopes: ['offline_access'] }
74
+ ],
67
75
  // Model-visible so hosts (e.g. Microsoft 365 Copilot) can call it directly and show it
68
76
  // in their debug info; 'app' keeps it callable from the site-builder widget.
69
77
  ui: { visibility: ['app', 'model'] },
@@ -72,13 +80,6 @@ export function addSuggestedDomainTool(server, authStrategy) {
72
80
  }
73
81
  }, async (args, { panorama }) => {
74
82
  console.log('[getSuggestedDomains] Invoked with args:', args);
75
- if (isAnonymous?.()) {
76
- console.log('[getSuggestedDomains] Returning empty response for anonymous user');
77
- return {
78
- content: [{ type: 'text', text: '' }],
79
- structuredContent: { domains: [], success: true }
80
- };
81
- }
82
83
  const { query, siteId, tlds, limit } = args;
83
84
  if (!query && !siteId) {
84
85
  return {
@@ -92,9 +93,22 @@ export function addSuggestedDomainTool(server, authStrategy) {
92
93
  structuredContent: { domains: [] }
93
94
  };
94
95
  }
96
+ const anonymous = isAnonymous?.() ?? false;
97
+ if (anonymous && !query) {
98
+ return {
99
+ isError: true,
100
+ content: [
101
+ {
102
+ type: 'text',
103
+ text: "Without a connected Wix account the site's name can't be read: pass a query (the business or site name) instead of the siteId"
104
+ }
105
+ ],
106
+ structuredContent: { domains: [] }
107
+ };
108
+ }
95
109
  try {
96
110
  let resolvedQuery = query;
97
- if (siteId) {
111
+ if (siteId && !anonymous) {
98
112
  try {
99
113
  const siteHeaders = await getSiteAuthHeaders(siteId);
100
114
  const siteName = await fetchSiteDisplayName(siteHeaders.Authorization, siteId);
@@ -1,4 +1,8 @@
1
1
  import { WixMcpServer } from '../wix-mcp-server.js';
2
2
  import { McpAuthenticationStrategy } from '../auth/index.js';
3
+ /** Sends one issue to Wix's feedback channel. */
4
+ export declare const REPORT_ISSUE_TOOL_NAME = "ReportIssueToWix";
5
+ /** The tool's former name, still honored in disableTools and toolDescriptions. */
6
+ export declare const LEGACY_REPORT_ISSUE_TOOL_NAME = "SupportAndFeedback";
3
7
  export declare function addSupportTool(server: WixMcpServer, strategy: McpAuthenticationStrategy, disableTools?: string[], toolDescriptions?: Record<string, string>): void;
4
8
  //# sourceMappingURL=index.d.ts.map
@@ -7,19 +7,25 @@ import { rethrowIfUnauthorized } from '../auth/index.js';
7
7
  // mcp-serverless /feedback web function — relays the message to the
8
8
  // #mcp-user-feedback Slack channel, attributed to the calling user.
9
9
  const FEEDBACK_API_URL = 'https://www.wixapis.com/mcp-serverless/v1/feedback';
10
+ /** Sends one issue to Wix's feedback channel. */
11
+ export const REPORT_ISSUE_TOOL_NAME = 'ReportIssueToWix';
12
+ /** The tool's former name, still honored in disableTools and toolDescriptions. */
13
+ export const LEGACY_REPORT_ISSUE_TOOL_NAME = 'SupportAndFeedback';
10
14
  export function addSupportTool(server, strategy, disableTools = [], toolDescriptions) {
11
- if (disableTools.includes('SupportAndFeedback')) {
15
+ if (disableTools.includes(REPORT_ISSUE_TOOL_NAME) ||
16
+ disableTools.includes(LEGACY_REPORT_ISSUE_TOOL_NAME)) {
12
17
  return;
13
18
  }
14
- server.tool('SupportAndFeedback', toolDescriptions?.['SupportAndFeedback'] ??
15
- defaultToolDescriptions.SupportAndFeedback, (() => {
16
- const d = desc('SupportAndFeedback');
19
+ server.tool(REPORT_ISSUE_TOOL_NAME, toolDescriptions?.[REPORT_ISSUE_TOOL_NAME] ??
20
+ toolDescriptions?.[LEGACY_REPORT_ISSUE_TOOL_NAME] ??
21
+ defaultToolDescriptions.ReportIssueToWix, (() => {
22
+ const d = desc('ReportIssueToWix');
17
23
  return {
18
24
  message: z.string().describe(d.message),
19
25
  requestId: z.string().optional().describe(d.requestId)
20
26
  };
21
27
  })(), { readOnlyHint: false, destructiveHint: false, openWorldHint: false }, async ({ message, requestId }, { httpClient, setToolBiParams }) => {
22
- logger.log(`[SupportAndFeedback] sending feedback${requestId ? `, requestId=${requestId}` : ''}`);
28
+ logger.log(`[ReportIssueToWix] sending report${requestId ? `, requestId=${requestId}` : ''}`);
23
29
  const fullMessage = requestId
24
30
  ? `${message}\n\nrequest id: ${requestId}`
25
31
  : message;
@@ -37,7 +43,7 @@ export function addSupportTool(server, strategy, disableTools = [], toolDescript
37
43
  content: [
38
44
  {
39
45
  type: 'text',
40
- text: 'Feedback sent to Wix. Let the user know it was delivered — note that feedback cannot be replied to or tracked.'
46
+ text: 'Report sent to Wix. Let the user know it was delivered — note that reports cannot be replied to or tracked.'
41
47
  }
42
48
  ]
43
49
  };
@@ -55,7 +61,7 @@ export function addSupportTool(server, strategy, disableTools = [], toolDescript
55
61
  }
56
62
  }
57
63
  setToolBiParams({ requestId: feedbackRequestId });
58
- const errorMessage = `Failed to send feedback to Wix: ${error}.${errorDetails}${feedbackRequestId ? ` Request ID: ${feedbackRequestId}` : ''}`;
64
+ const errorMessage = `Failed to send the report to Wix: ${error}.${errorDetails}${feedbackRequestId ? ` Request ID: ${feedbackRequestId}` : ''}`;
59
65
  logger.error(errorMessage);
60
66
  throw new Error(errorMessage);
61
67
  }
@@ -1,13 +1,20 @@
1
1
  import type { HttpResponse } from '@wix/http-client';
2
+ /**
3
+ * Whether an account-scoped call failed for want of a site: `certain` when the API says so,
4
+ * `likely` for the empty 403 site APIs answer without one, null otherwise.
5
+ */
6
+ export declare function missingSiteContext(status: number | undefined, responseData: unknown): 'certain' | 'likely' | null;
2
7
  export declare const DEFAULT_OPENAI_SECURITY_SCHEMES: {
3
8
  type: "oauth2";
4
9
  scopes: string[];
5
10
  }[];
6
- export declare const buildErrorMessage: ({ status, statusText, requestId, responseData }: {
11
+ export declare const buildErrorMessage: ({ status, statusText, requestId, responseData, retryHint }: {
7
12
  status?: number;
8
13
  statusText?: string;
9
14
  requestId: string | null;
10
15
  responseData?: any;
16
+ /** Replaces the hint picked from the error details. */
17
+ retryHint?: string;
11
18
  }) => string;
12
19
  export declare const handleWixAPIResponse: <T = any>(response: HttpResponse) => Promise<T>;
13
20
  export declare function withJsonContent(result: any): any;
@@ -11,6 +11,30 @@ const getRetryHint = (errorDetails) => {
11
11
  ? SINGLE_OPERATOR_PER_FIELD_HINT
12
12
  : FIELD_CAPABILITIES_HINT;
13
13
  };
14
+ // What site APIs answer when a call carries no site: an explicit "no site in the request" in
15
+ // one of its many spellings, or a 403 with an empty body.
16
+ const NO_SITE_IN_REQUEST = /META_SITE_NOT_FOUND|MetaSite(?:Id)? (?:context )?(?:is missing|was not found|not found)|NO_METASITE_IN_CALL_CONTEXT|MISSING_METASITE_ID|MISSING_REQUEST_SITE_CONTEXT|metasiteId from the request context/i;
17
+ /**
18
+ * Whether an account-scoped call failed for want of a site: `certain` when the API says so,
19
+ * `likely` for the empty 403 site APIs answer without one, null otherwise.
20
+ */
21
+ export function missingSiteContext(status, responseData) {
22
+ const details = typeof responseData === 'string'
23
+ ? responseData
24
+ : JSON.stringify(responseData ?? '');
25
+ if (NO_SITE_IN_REQUEST.test(details))
26
+ return 'certain';
27
+ const parsed = typeof responseData === 'string'
28
+ ? safeParseJSON(responseData)
29
+ : responseData;
30
+ if (status === 403 &&
31
+ parsed &&
32
+ typeof parsed === 'object' &&
33
+ !parsed.message) {
34
+ return 'likely';
35
+ }
36
+ return null;
37
+ }
14
38
  export const DEFAULT_OPENAI_SECURITY_SCHEMES = [
15
39
  { type: 'oauth2', scopes: ['offline_access'] }
16
40
  ];
@@ -22,7 +46,7 @@ const safeParseJSON = (text) => {
22
46
  return text;
23
47
  }
24
48
  };
25
- export const buildErrorMessage = ({ status, statusText, requestId, responseData }) => {
49
+ export const buildErrorMessage = ({ status, statusText, requestId, responseData, retryHint }) => {
26
50
  const responseDataObject = typeof responseData === 'string'
27
51
  ? safeParseJSON(responseData)
28
52
  : responseData;
@@ -39,7 +63,7 @@ export const buildErrorMessage = ({ status, statusText, requestId, responseData
39
63
  ]
40
64
  .filter((str) => !!str)
41
65
  .join('\n');
42
- return `${baseMessage}\n\n${getRetryHint(String(errorDetails))}`;
66
+ return `${baseMessage}\n\n${retryHint ?? getRetryHint(String(errorDetails))}`;
43
67
  };
44
68
  export const handleWixAPIResponse = async (response) => {
45
69
  const requestId = response.headers?.['x-wix-request-id'];
@@ -107,7 +107,8 @@ declare const VALID_DOCS_TOOLS: readonly [
107
107
  "VELO",
108
108
  "BUSINESS_SOLUTIONS",
109
109
  "CLI",
110
- "OVERVIEW"
110
+ "OVERVIEW",
111
+ "HELP_CENTER"
111
112
  ];
112
113
  export type DocsTool = (typeof VALID_DOCS_TOOLS)[number];
113
114
  /**
@@ -151,16 +152,27 @@ export interface DocsToolsOptions {
151
152
  commitHash?: string;
152
153
  /** Tags to filter skills by (e.g. ['velo', 'cms']) */
153
154
  skillsTags?: string[];
155
+ /** Append the management recipes list (every recipe by area, each a link to its article) to the end of WixREADME, for every client. Default true; false leaves it out, and the README then points at the wix-manage skill and the public list only. */
156
+ readmeRecipesIndexEnabled?: boolean;
154
157
  /** Enable dynamic context fetch */
155
158
  dynamicContextEnabled?: boolean;
156
159
  /** Enable partner context section in dynamic context output */
157
160
  partnerContextEnabled?: boolean;
161
+ /** GetSiteContext renders the site's companion app. Off by default: only Aria (via the toolkit) needs it. */
162
+ includeCompanionApp?: boolean;
158
163
  /** @deprecated Only CreateWixBusinessGuide read it, and that tool was removed; ignored. */
159
164
  cliEnabled?: boolean | (() => boolean);
160
165
  /** Use the new platformized semantic search API (POST /v1/docs/search) instead of the legacy GET endpoint */
161
166
  usePlatformizedSearch?: boolean;
162
167
  /** Use the platformized menu browse API (POST /v1/docs/menu/browse) instead of scraping the legacy get-menu-content markdown. Falls back to legacy on transport errors. */
163
168
  usePlatformizedBrowse?: boolean;
169
+ /**
170
+ * The Mintlify docs site (see ./mintlify-docs.ts). Off by default.
171
+ * `'mintlify'`: REST and SDK search read the Mintlify KBs, and articles are
172
+ * read from Mintlify's `.md`. `'mintlify-links'`: search reads today's KBs and
173
+ * resolves the links in tool output to the Mintlify site.
174
+ */
175
+ docsSite?: string;
164
176
  }
165
177
  export interface ToolHintsConfig {
166
178
  readOnlyHint?: boolean;
@@ -258,8 +270,8 @@ export interface WixToolkitApiConfig {
258
270
  toolHints?: Record<string, ToolHintsConfig>;
259
271
  /**
260
272
  * Max response size in chars before truncation. Applies to CallWixSiteAPI/
261
- * ListWixSites/ManageWixSite (default: 50,000) and to ExecuteWixAPI/
262
- * SearchWixAPISpec (default: 24,000). Always clamped to a hard ceiling
273
+ * ListWixSites/ManageWixSite (default: 50,000), ExecuteWixAPI (default:
274
+ * 100,000) and SearchWixAPISpec (default: 64,000). Always clamped to a hard ceiling
263
275
  * regardless of what's requested here — see MAX_ALLOWED_RESPONSE_CHARS.
264
276
  */
265
277
  maxResponseSize?: number;
@@ -416,13 +428,6 @@ export declare const SYSTEM_REMINDER: string;
416
428
  */
417
429
  export declare const defaultToolDescriptions: Record<string, string>;
418
430
  export declare const executeCodeModeToolDescriptions: Record<string, string>;
419
- /**
420
- * Default readme docs - content for WixREADME tool response.
421
- * Assumes both ExecuteWixAPI and SearchWixAPISpec are available (execute-and-search mode).
422
- *
423
- * Joined rather than interpolated into one `dedent` — `dedent` reads indentation from the literal
424
- * parts only, so a multi-line interpolation gets flattened.
425
- */
426
431
  export declare const defaultReadmeDocs: ReadmeDocConfig$1[];
427
432
  /**
428
433
  * Merge base config with overrides
@@ -107,7 +107,8 @@ declare const VALID_DOCS_TOOLS: readonly [
107
107
  "VELO",
108
108
  "BUSINESS_SOLUTIONS",
109
109
  "CLI",
110
- "OVERVIEW"
110
+ "OVERVIEW",
111
+ "HELP_CENTER"
111
112
  ];
112
113
  export type DocsTool = (typeof VALID_DOCS_TOOLS)[number];
113
114
  /**
@@ -151,16 +152,27 @@ export interface DocsToolsOptions {
151
152
  commitHash?: string;
152
153
  /** Tags to filter skills by (e.g. ['velo', 'cms']) */
153
154
  skillsTags?: string[];
155
+ /** Append the management recipes list (every recipe by area, each a link to its article) to the end of WixREADME, for every client. Default true; false leaves it out, and the README then points at the wix-manage skill and the public list only. */
156
+ readmeRecipesIndexEnabled?: boolean;
154
157
  /** Enable dynamic context fetch */
155
158
  dynamicContextEnabled?: boolean;
156
159
  /** Enable partner context section in dynamic context output */
157
160
  partnerContextEnabled?: boolean;
161
+ /** GetSiteContext renders the site's companion app. Off by default: only Aria (via the toolkit) needs it. */
162
+ includeCompanionApp?: boolean;
158
163
  /** @deprecated Only CreateWixBusinessGuide read it, and that tool was removed; ignored. */
159
164
  cliEnabled?: boolean | (() => boolean);
160
165
  /** Use the new platformized semantic search API (POST /v1/docs/search) instead of the legacy GET endpoint */
161
166
  usePlatformizedSearch?: boolean;
162
167
  /** Use the platformized menu browse API (POST /v1/docs/menu/browse) instead of scraping the legacy get-menu-content markdown. Falls back to legacy on transport errors. */
163
168
  usePlatformizedBrowse?: boolean;
169
+ /**
170
+ * The Mintlify docs site (see ./mintlify-docs.ts). Off by default.
171
+ * `'mintlify'`: REST and SDK search read the Mintlify KBs, and articles are
172
+ * read from Mintlify's `.md`. `'mintlify-links'`: search reads today's KBs and
173
+ * resolves the links in tool output to the Mintlify site.
174
+ */
175
+ docsSite?: string;
164
176
  }
165
177
  export interface ToolHintsConfig {
166
178
  readOnlyHint?: boolean;
@@ -258,8 +270,8 @@ export interface WixToolkitApiConfig {
258
270
  toolHints?: Record<string, ToolHintsConfig>;
259
271
  /**
260
272
  * Max response size in chars before truncation. Applies to CallWixSiteAPI/
261
- * ListWixSites/ManageWixSite (default: 50,000) and to ExecuteWixAPI/
262
- * SearchWixAPISpec (default: 24,000). Always clamped to a hard ceiling
273
+ * ListWixSites/ManageWixSite (default: 50,000), ExecuteWixAPI (default:
274
+ * 100,000) and SearchWixAPISpec (default: 64,000). Always clamped to a hard ceiling
263
275
  * regardless of what's requested here — see MAX_ALLOWED_RESPONSE_CHARS.
264
276
  */
265
277
  maxResponseSize?: number;
@@ -416,13 +428,6 @@ export declare const SYSTEM_REMINDER: string;
416
428
  */
417
429
  export declare const defaultToolDescriptions: Record<string, string>;
418
430
  export declare const executeCodeModeToolDescriptions: Record<string, string>;
419
- /**
420
- * Default readme docs - content for WixREADME tool response.
421
- * Assumes both ExecuteWixAPI and SearchWixAPISpec are available (execute-and-search mode).
422
- *
423
- * Joined rather than interpolated into one `dedent` — `dedent` reads indentation from the literal
424
- * parts only, so a multi-line interpolation gets flattened.
425
- */
426
431
  export declare const defaultReadmeDocs: ReadmeDocConfig$1[];
427
432
  /**
428
433
  * Merge base config with overrides
@@ -107,8 +107,8 @@ export interface WixToolkitApiConfig {
107
107
  toolHints?: Record<string, ToolHintsConfig>;
108
108
  /**
109
109
  * Max response size in chars before truncation. Applies to CallWixSiteAPI/
110
- * ListWixSites/ManageWixSite (default: 50,000) and to ExecuteWixAPI/
111
- * SearchWixAPISpec (default: 24,000). Always clamped to a hard ceiling
110
+ * ListWixSites/ManageWixSite (default: 50,000), ExecuteWixAPI (default:
111
+ * 100,000) and SearchWixAPISpec (default: 64,000). Always clamped to a hard ceiling
112
112
  * regardless of what's requested here — see MAX_ALLOWED_RESPONSE_CHARS.
113
113
  */
114
114
  maxResponseSize?: number;
@@ -42,6 +42,7 @@ import { createBiLogger } from './infra/bi-logger.js';
42
42
  import { DEV_ENVIRONMENTS, getEnvironment } from './infra/environment.js';
43
43
  import { logger } from './infra/logger.js';
44
44
  import { createToolBiEvent, extractText, formatToolResultAdditionalFields } from './infra/tool-bi.js';
45
+ import { serializeToolParamsForBi } from './infra/redact-personal-data.js';
45
46
  /**
46
47
  * Normalize auth config into a McpAuthenticationStrategy.
47
48
  */
@@ -177,6 +178,7 @@ export function createWixToolkit(options) {
177
178
  readmeDocs,
178
179
  authStrategy,
179
180
  dynamicContextEnabled: true,
181
+ includeCompanionApp: true,
180
182
  // README-free defaults first so consumer overrides still win.
181
183
  toolDescriptions: {
182
184
  ...descriptionsWithoutReadme,
@@ -189,6 +191,7 @@ export function createWixToolkit(options) {
189
191
  addDocsTools(server, undefined, {
190
192
  authStrategy,
191
193
  dynamicContextEnabled: true,
194
+ includeCompanionApp: true,
192
195
  toolDescriptions: descriptionsWithoutReadme
193
196
  });
194
197
  }
@@ -214,7 +217,9 @@ export function createWixToolkit(options) {
214
217
  authStrategy,
215
218
  disableTools,
216
219
  toolDescriptions: effectiveToolDescriptions,
217
- maxResponseSize
220
+ maxResponseSize,
221
+ // The connection's docs site (`docs.docsSite`) applies to spec search too.
222
+ docsSite: docs?.docsSite
218
223
  });
219
224
  }
220
225
  if (requestedTools.has('ExecuteWixAPI') &&
@@ -233,7 +238,13 @@ export function createWixToolkit(options) {
233
238
  addUploadHeadlessWebsiteFilesTool(server, {
234
239
  authStrategy,
235
240
  toolDescriptions: effectiveToolDescriptions,
236
- clientName
241
+ clientName,
242
+ // The headless guide the drop reply carries is read the way the docs tools read it.
243
+ guide: {
244
+ skillsPortalUrl: docs?.skillsPortalUrl,
245
+ repo: docs?.repo ?? docs?.skillsRepo,
246
+ commitHash: docs?.commitHash ?? docs?.skillsPr
247
+ }
237
248
  });
238
249
  }
239
250
  // GraphQL tools register only the ones requested (each is opt-in by name).
@@ -309,7 +320,7 @@ export function createWixToolkit(options) {
309
320
  biLogger.updateDefaults({ _uuid: '' });
310
321
  panorama.transaction(toolName).start({
311
322
  toolInvocationId,
312
- params: JSON.stringify(mergedArgs)
323
+ params: serializeToolParamsForBi(mergedArgs)
313
324
  });
314
325
  }
315
326
  const startTime = performance.now();
@@ -327,7 +338,8 @@ export function createWixToolkit(options) {
327
338
  else {
328
339
  additionalFields = formatToolResultAdditionalFields(cbResult, {
329
340
  returnedRows: toolBiParams.returnedRows,
330
- originalLength: toolBiParams.originalLength
341
+ originalLength: toolBiParams.originalLength,
342
+ upload: toolBiParams.upload
331
343
  }, { name: clientName });
332
344
  }
333
345
  // Panorama: finish or report error
@@ -342,7 +354,7 @@ export function createWixToolkit(options) {
342
354
  context: {
343
355
  toolName,
344
356
  toolInvocationId,
345
- params: JSON.stringify(mergedArgs),
357
+ params: serializeToolParamsForBi(mergedArgs),
346
358
  error: JSON.stringify(cbResult, null, 2)
347
359
  }
348
360
  });
@@ -361,7 +373,7 @@ export function createWixToolkit(options) {
361
373
  context: {
362
374
  toolName,
363
375
  toolInvocationId,
364
- params: JSON.stringify(mergedArgs),
376
+ params: serializeToolParamsForBi(mergedArgs),
365
377
  error: errorBody
366
378
  }
367
379
  });
@@ -394,7 +406,7 @@ export function createWixToolkit(options) {
394
406
  errorBody,
395
407
  toolInvocationId,
396
408
  toolName,
397
- params: JSON.stringify(mergedArgs),
409
+ params: serializeToolParamsForBi(mergedArgs),
398
410
  origin: nodeEnv,
399
411
  sessionId,
400
412
  executionResult: toolSucceeded ? 'Success' : 'Error',
@@ -447,7 +459,8 @@ export function createWixToolkit(options) {
447
459
  const httpClient = new HttpClient();
448
460
  return ((await getDynamicContext(authStrategy, httpClient, defaults, {
449
461
  partnerContextEnabled: true,
450
- includeAccountContext: true
462
+ includeAccountContext: true,
463
+ includeCompanionApp: true
451
464
  })) || null);
452
465
  }
453
466
  catch {