@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.
- package/README.md +2 -2
- package/build/bin-standalone.js +1457 -332
- package/build/cjs/index.cjs +3379 -1333
- package/build/cjs/toolkit.cjs +2158 -373
- package/build/dts/api-call/headless-release.d.ts +56 -0
- package/build/dts/api-call/headless-release.js +135 -0
- package/build/dts/api-call/index.d.ts +9 -1
- package/build/dts/api-call/index.js +36 -8
- package/build/dts/api-call/site-files.d.ts +14 -0
- package/build/dts/api-call/site-files.js +106 -10
- package/build/dts/api-call/upload-headless-website-files.d.ts +117 -5
- package/build/dts/api-call/upload-headless-website-files.js +565 -20
- package/build/dts/api-call/upload-image-tool.d.ts +2 -0
- package/build/dts/api-call/upload-image-tool.js +8 -4
- package/build/dts/bin.d.ts +1 -1
- package/build/dts/bin.js +3 -1
- package/build/dts/code-mode/attachments.d.ts +9 -6
- package/build/dts/code-mode/attachments.js +23 -16
- package/build/dts/code-mode/index.d.ts +6 -1
- package/build/dts/code-mode/index.js +32 -12
- package/build/dts/code-mode/truncate-response.js +5 -1
- package/build/dts/config/default-config.d.ts +35 -5
- package/build/dts/config/default-config.js +339 -182
- package/build/dts/config/file-params.d.ts +22 -0
- package/build/dts/config/file-params.js +24 -0
- package/build/dts/config/param-descriptions.d.ts +14 -2
- package/build/dts/config/param-descriptions.js +33 -14
- package/build/dts/constants.d.ts +1 -0
- package/build/dts/constants.js +1 -0
- package/build/dts/docs/docs.d.ts +12 -1
- package/build/dts/docs/docs.js +274 -43
- package/build/dts/docs/fetch-article.d.ts +21 -0
- package/build/dts/docs/fetch-article.js +66 -4
- package/build/dts/docs/get-to-know.d.ts +7 -2
- package/build/dts/docs/get-to-know.js +36 -14
- package/build/dts/docs/guessed-url.d.ts +41 -0
- package/build/dts/docs/guessed-url.js +185 -0
- package/build/dts/docs/mintlify-docs.d.ts +121 -0
- package/build/dts/docs/mintlify-docs.js +391 -0
- package/build/dts/docs/semanticSearch.d.ts +2 -1
- package/build/dts/docs/semanticSearch.js +14 -7
- package/build/dts/docs/start-deploy-website.d.ts +7 -6
- package/build/dts/docs/start-deploy-website.js +13 -8
- package/build/dts/docs/start-headless-build.d.ts +8 -10
- package/build/dts/docs/start-headless-build.js +14 -28
- package/build/dts/index.d.ts +2 -2
- package/build/dts/index.js +2 -2
- package/build/dts/infra/redact-personal-data.d.ts +4 -0
- package/build/dts/infra/redact-personal-data.js +148 -0
- package/build/dts/site-widget-tools/constants.d.ts +50 -2
- package/build/dts/site-widget-tools/constants.js +65 -8
- package/build/dts/site-widget-tools/index.d.ts +1 -0
- package/build/dts/site-widget-tools/index.js +1 -0
- package/build/dts/site-widget-tools/pick-images-tool/index.d.ts +14 -0
- package/build/dts/site-widget-tools/pick-images-tool/index.js +138 -0
- package/build/dts/site-widget-tools/pull-site-creation-job-tool/index.js +1 -1
- package/build/dts/site-widget-tools/search-site-templates-tool/index.js +25 -2
- package/build/dts/site-widget-tools/site-builder-tool/index.js +35 -3
- package/build/dts/site-widget-tools/site-creation-tool/index.d.ts +7 -1
- package/build/dts/site-widget-tools/site-creation-tool/index.js +22 -51
- package/build/dts/site-widget-tools/suggested-domain-tool/index.js +26 -12
- package/build/dts/support/index.d.ts +4 -0
- package/build/dts/support/index.js +13 -7
- package/build/dts/tool-utils.d.ts +8 -1
- package/build/dts/tool-utils.js +26 -2
- package/build/dts/toolkit-entry.d.cts +15 -10
- package/build/dts/toolkit-entry.d.ts +15 -10
- package/build/dts/toolkit.d.ts +2 -2
- package/build/dts/toolkit.js +21 -8
- package/build/dts/wix-mcp-server.d.ts +10 -1
- package/build/dts/wix-mcp-server.js +25 -7
- package/build/dts/wixel/constants.d.ts +8 -1
- package/build/dts/wixel/constants.js +8 -1
- package/build/dts/wixel/index.d.ts +1 -1
- package/build/dts/wixel/index.js +2 -2
- package/build/dts/wixel/wixel-a2a-client.d.ts +83 -0
- package/build/dts/wixel/wixel-a2a-client.js +166 -0
- package/build/dts/wixel/wixel-bi.d.ts +2 -1
- package/build/dts/wixel/wixel-bi.js +2 -1
- package/build/dts/wixel/{external-agent-api.d.ts → wixel-session-entries.d.ts} +11 -33
- package/build/dts/wixel/{external-agent-api.js → wixel-session-entries.js} +33 -54
- package/build/dts/wixel/wixel-session-tools.d.ts +21 -26
- package/build/dts/wixel/wixel-session-tools.js +494 -599
- package/build/esm/index.js +3422 -1388
- package/build/esm/toolkit.js +2158 -373
- 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
|
-
|
|
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
|
-
/**
|
|
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,
|
|
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
|
-
/**
|
|
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': '
|
|
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('
|
|
62
|
-
|
|
49
|
+
.describe('A few keywords describing the site.'),
|
|
50
|
+
sitePrompt: z
|
|
63
51
|
.string()
|
|
64
52
|
.optional()
|
|
65
|
-
.describe(
|
|
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}]
|
|
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
|
|
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
|
|
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
|
-
|
|
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: [
|
|
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(
|
|
15
|
+
if (disableTools.includes(REPORT_ISSUE_TOOL_NAME) ||
|
|
16
|
+
disableTools.includes(LEGACY_REPORT_ISSUE_TOOL_NAME)) {
|
|
12
17
|
return;
|
|
13
18
|
}
|
|
14
|
-
server.tool(
|
|
15
|
-
|
|
16
|
-
|
|
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(`[
|
|
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: '
|
|
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
|
|
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;
|
package/build/dts/tool-utils.js
CHANGED
|
@@ -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)
|
|
262
|
-
* SearchWixAPISpec (default:
|
|
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)
|
|
262
|
-
* SearchWixAPISpec (default:
|
|
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
|
package/build/dts/toolkit.d.ts
CHANGED
|
@@ -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)
|
|
111
|
-
* SearchWixAPISpec (default:
|
|
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;
|
package/build/dts/toolkit.js
CHANGED
|
@@ -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:
|
|
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:
|
|
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:
|
|
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:
|
|
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 {
|