@wix/mcp 1.0.83 → 1.0.84

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.
@@ -19494,7 +19494,16 @@ ${skillsContent}`
19494
19494
  ] : await Promise.all(
19495
19495
  baseDocs.filter((doc) => doc.url === RECIPES_INDEX_URL).map(fetchDoc)
19496
19496
  );
19497
- const contents = [...baseContents, ...recipesContents];
19497
+ const recipeNotes = !skillsContent?.includes("Dashboard Navigation") ? [] : [
19498
+ await fetchDoc({
19499
+ action: "text",
19500
+ title: "Recipe Notes",
19501
+ content: dedent_default`
19502
+ - **Navigation recipes** (the *Dashboard Navigation* family) build direct manage.wix.com URLs. If your environment provides dedicated navigation tools, use those to perform the actual navigation — opening a recipe-built URL forces a full page refresh. Use the recipe URLs for composing a link to hand the user, or for navigating when no dedicated tool exists.
19503
+ `
19504
+ })
19505
+ ];
19506
+ const contents = [...baseContents, ...recipesContents, ...recipeNotes];
19498
19507
  const dynamicContext = await dynamicContextPromise;
19499
19508
  const parts = [
19500
19509
  ...contents.filter(
@@ -217,7 +217,23 @@ export async function addGetToKnowTools({ server, disableTools = [], toolDescrip
217
217
  : await Promise.all(baseDocs
218
218
  .filter((doc) => doc.url === RECIPES_INDEX_URL)
219
219
  .map(fetchDoc));
220
- const contents = [...baseContents, ...recipesContents];
220
+ // Cross-recipe steering that applies to a family of recipes rather than
221
+ // any single article; rendered right after the index. Gated on the note's
222
+ // target family actually appearing in the rendered index — this also
223
+ // covers a failed/custom index (no recipes → no notes) and tag-filtered
224
+ // visitor indexes, which carry no Dashboard Navigation recipes.
225
+ const recipeNotes = !skillsContent?.includes('Dashboard Navigation')
226
+ ? []
227
+ : [
228
+ await fetchDoc({
229
+ action: 'text',
230
+ title: 'Recipe Notes',
231
+ content: dedent `
232
+ - **Navigation recipes** (the *Dashboard Navigation* family) build direct manage.wix.com URLs. If your environment provides dedicated navigation tools, use those to perform the actual navigation — opening a recipe-built URL forces a full page refresh. Use the recipe URLs for composing a link to hand the user, or for navigating when no dedicated tool exists.
233
+ `
234
+ })
235
+ ];
236
+ const contents = [...baseContents, ...recipesContents, ...recipeNotes];
221
237
  const dynamicContext = await dynamicContextPromise;
222
238
  const parts = [
223
239
  ...contents
@@ -11,6 +11,8 @@ const NON_LATIN_LETTER = /(?![\p{Script=Latin}])\p{L}/u;
11
11
  function isSearchableSiteName(siteName) {
12
12
  return (!DEFAULT_SITE_NAME.test(siteName.trim()) && !NON_LATIN_LETTER.test(siteName));
13
13
  }
14
+ // Domain search rejects longer queries.
15
+ const MAX_QUERY_LENGTH = 100;
14
16
  async function fetchSiteDisplayName(siteAuthorization, siteId) {
15
17
  const response = await fetch(`${WIX_APIS_BASE_URL}/site-properties/v4/properties`, {
16
18
  headers: {
@@ -41,7 +43,7 @@ export function addSuggestedDomainTool(server, authStrategy) {
41
43
  query: z
42
44
  .string()
43
45
  .optional()
44
- .describe("Free-text keywords, business idea, or brand concept to base suggestions on. Use the user's own words."),
46
+ .describe("A few keywords, a business idea, or a brand name to base suggestions on, up to 100 characters. Use the user's own words."),
45
47
  siteId: z
46
48
  .string()
47
49
  .optional()
@@ -49,7 +51,7 @@ export function addSuggestedDomainTool(server, authStrategy) {
49
51
  tlds: z
50
52
  .array(z.string())
51
53
  .optional()
52
- .describe('Filter by specific TLDs (e.g. ["com", "net"]). Do not include the dot.'),
54
+ .describe('Optional. Include only when the user asks for specific TLDs. Filter by specific TLDs (e.g. ["com", "net"]). Do not include the dot.'),
53
55
  limit: z
54
56
  .number()
55
57
  .optional()
@@ -128,7 +130,9 @@ export function addSuggestedDomainTool(server, authStrategy) {
128
130
  }
129
131
  }
130
132
  }
131
- const params = new URLSearchParams({ query: resolvedQuery });
133
+ const params = new URLSearchParams({
134
+ query: resolvedQuery.slice(0, MAX_QUERY_LENGTH)
135
+ });
132
136
  if (limit) {
133
137
  params.set('paging.limit', String(limit));
134
138
  }
@@ -137,14 +141,21 @@ export function addSuggestedDomainTool(server, authStrategy) {
137
141
  params.append('tlds', tld);
138
142
  }
139
143
  }
140
- const response = await fetch(`${WIX_APIS_BASE_URL}/domain-search/v2/suggest-domains?${params}`, {
144
+ const suggestDomains = () => fetch(`${WIX_APIS_BASE_URL}/domain-search/v2/suggest-domains?${params}`, {
141
145
  method: 'GET',
142
146
  headers: {
143
147
  Accept: 'application/json'
144
148
  }
145
149
  });
150
+ let response = await suggestDomains();
151
+ let errorText = response.ok ? '' : await response.text();
152
+ // Domain search sells only some TLDs and rejects the whole request for one it doesn't.
153
+ if (errorText.includes('TLD_NOT_SUPPORTED') && params.has('tlds')) {
154
+ params.delete('tlds');
155
+ response = await suggestDomains();
156
+ errorText = response.ok ? '' : await response.text();
157
+ }
146
158
  if (!response.ok) {
147
- const errorText = await response.text();
148
159
  throw new Error(`Domain suggestions API returned ${response.status}: ${errorText}`);
149
160
  }
150
161
  const data = (await response.json());
@@ -3,6 +3,8 @@ import { WixMcpServer } from '../wix-mcp-server.js';
3
3
  export interface WixelSessionToolOptions {
4
4
  conductorOverride?: string;
5
5
  supportsWidgets?: () => boolean;
6
+ /** Shared by the session tools of one server; created by addWixelSessionTools. */
7
+ liveCards?: LiveCardRegistry;
6
8
  }
7
9
  type WixelAssetEntity = {
8
10
  id?: string;
@@ -30,11 +32,52 @@ export type WixelDeck = {
30
32
  };
31
33
  export declare function collectDecks(projectAssets: WixelAssetEntity[], deckIds: Set<string>): Map<string, WixelDeck>;
32
34
  export declare function extractAssetIds(text: string): string[];
35
+ /**
36
+ * Live result cards, per Wixel session handle: the turns a card was rendered
37
+ * for (and when), the asset ids / media URLs those cards display, and the
38
+ * last turn send_wixel_message opened. The model does not reliably obey "do
39
+ * not poll" once a live card is up, so the tools enforce it: list_wixel_events
40
+ * refuses while a card is active, get_wixel_asset_result refuses to render
41
+ * the same result a second time, and get_wixel_pending_question stays quiet
42
+ * for a question the card already shows.
43
+ *
44
+ * One registry per server instance (like list_wixel_events' cursor memory),
45
+ * so sessions never see each other's records. In-memory like that memory
46
+ * too: a Durable Object wake-up starts empty, and the intercepts simply
47
+ * don't apply until the next send.
48
+ */
49
+ type LiveCardRecord = {
50
+ /** Turn id → when its live card was rendered. */
51
+ turns: Map<string, number>;
52
+ /** Turns whose card reached done/failed — the agent may poll again. */
53
+ finishedTurns: Set<string>;
54
+ shownAssets: Set<string>;
55
+ lastSentTurn: string | null;
56
+ };
57
+ export type LiveCardRegistry = ReturnType<typeof createLiveCardRegistry>;
58
+ export declare function createLiveCardRegistry(): {
59
+ get: (handle: string) => LiveCardRecord | undefined;
60
+ forHandle: (handle: string) => LiveCardRecord;
61
+ isActive: (handle: string, params: {
62
+ authHeaders: Record<string, string>;
63
+ conductorOverride?: string;
64
+ metaSiteId: string;
65
+ }) => Promise<boolean>;
66
+ };
33
67
  export declare function addGetWixelPendingQuestionTool(server: WixMcpServer, authStrategy: McpAuthenticationStrategy, options?: WixelSessionToolOptions): void;
34
68
  export declare function addStartWixelSessionTool(server: WixMcpServer, authStrategy: McpAuthenticationStrategy, options?: WixelSessionToolOptions): void;
35
69
  export declare function addSendWixelMessageTool(server: WixMcpServer, authStrategy: McpAuthenticationStrategy, options?: WixelSessionToolOptions): void;
36
70
  export declare function addListWixelEventsTool(server: WixMcpServer, authStrategy: McpAuthenticationStrategy, options?: WixelSessionToolOptions): void;
37
71
  export declare function addGetWixelStylePresetsTool(server: WixMcpServer, authStrategy: McpAuthenticationStrategy, options?: WixelSessionToolOptions): void;
72
+ export type WixelTurnStatus = 'generating' | 'question' | 'done' | 'failed';
73
+ export declare function addGetWixelTurnResultTool(server: WixMcpServer, authStrategy: McpAuthenticationStrategy, options?: WixelSessionToolOptions): void;
74
+ export type WixelResultAssetEntry = {
75
+ id: string;
76
+ kind: 'image' | 'video' | 'slides' | 'document';
77
+ name: string | null;
78
+ url: string;
79
+ slideUrls?: string[];
80
+ };
38
81
  export declare function addGetWixelAssetResultTool(server: WixMcpServer, authStrategy: McpAuthenticationStrategy, options?: WixelSessionToolOptions): void;
39
82
  export declare function addWixelSessionTools(server: WixMcpServer, authStrategy: McpAuthenticationStrategy, options?: WixelSessionToolOptions): void;
40
83
  export {};