@wix/mcp 1.0.5 → 1.0.6

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 (41) hide show
  1. package/bin.js +1 -1
  2. package/build/bin.d.ts +3 -3
  3. package/build/bin.js +657 -82
  4. package/build/chunk-YRLMZUQM.js +1834 -0
  5. package/build/index.d.ts +30 -6
  6. package/build/index.js +193 -6
  7. package/package.json +7 -4
  8. package/build/api-call/index.d.ts +0 -2
  9. package/build/api-call/index.js +0 -124
  10. package/build/cli-tools/cli.d.ts +0 -4
  11. package/build/cli-tools/cli.js +0 -338
  12. package/build/cli-tools/utils.d.ts +0 -2
  13. package/build/cli-tools/utils.js +0 -25
  14. package/build/docs/docs.d.ts +0 -4
  15. package/build/docs/docs.js +0 -448
  16. package/build/docs/long-content.d.ts +0 -1
  17. package/build/docs/long-content.js +0 -1
  18. package/build/docs/semanticSearch.d.ts +0 -10
  19. package/build/docs/semanticSearch.js +0 -108
  20. package/build/docs/semanticSearch.test.d.ts +0 -1
  21. package/build/docs/semanticSearch.test.js +0 -459
  22. package/build/interactive-command-tools/eventually.d.ts +0 -6
  23. package/build/interactive-command-tools/eventually.js +0 -15
  24. package/build/interactive-command-tools/handleStdout.d.ts +0 -13
  25. package/build/interactive-command-tools/handleStdout.js +0 -75
  26. package/build/interactive-command-tools/interactive-command-utils.d.ts +0 -7
  27. package/build/interactive-command-tools/interactive-command-utils.js +0 -75
  28. package/build/logger.d.ts +0 -10
  29. package/build/logger.js +0 -61
  30. package/build/resources/docs.d.ts +0 -2
  31. package/build/resources/docs.js +0 -45
  32. package/build/sentry.d.ts +0 -1
  33. package/build/sentry.js +0 -10
  34. package/build/support/index.d.ts +0 -2
  35. package/build/support/index.js +0 -32
  36. package/build/tool-utils.d.ts +0 -1
  37. package/build/tool-utils.js +0 -29
  38. package/build/tool-utils.spec.d.ts +0 -1
  39. package/build/tool-utils.spec.js +0 -119
  40. package/build/wix-mcp-server.d.ts +0 -13
  41. package/build/wix-mcp-server.js +0 -51
package/build/bin.js CHANGED
@@ -1,98 +1,673 @@
1
- import './sentry.js';
2
- import minimist from 'minimist';
3
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
- import { addDocsTools, VALID_DOCS_TOOLS } from './docs/docs.js';
5
- import { addCliTools, VALID_CLI_TOOLS } from './cli-tools/cli.js';
6
- import { logger, attachStdErrLogger, attachMcpServerLogger, attachFileLogger } from './logger.js';
7
- import { WixMcpServer } from './wix-mcp-server.js';
8
- import { addDocsResources } from './resources/docs.js';
9
- const PUBLIC_TOOLS = [...VALID_DOCS_TOOLS];
10
- const EXPERIMENTAL_TOOLS = ['WIX_API', 'CLI_COMMAND'];
11
- export const DEFAULT_TOOLS = [...VALID_DOCS_TOOLS];
12
- const parsedArgs = minimist(process.argv.slice(2));
13
- function parseExperimentalArg() {
14
- const experimentalArg = parsedArgs['experimental'];
15
- if (!experimentalArg)
16
- return [];
17
- return experimentalArg
18
- .split(',')
19
- .map((t) => t.trim())
20
- .filter((tool) => EXPERIMENTAL_TOOLS.includes(tool));
1
+ import {
2
+ VALID_DOCS_TOOLS,
3
+ WixMcpServer,
4
+ addDocsResources,
5
+ addDocsTools,
6
+ attachFileLogger,
7
+ attachMcpServerLogger,
8
+ attachStdErrLogger,
9
+ handleWixAPIResponse,
10
+ logger
11
+ } from "./chunk-YRLMZUQM.js";
12
+
13
+ // src/sentry.ts
14
+ import * as Sentry from "@sentry/node";
15
+ Sentry.init({
16
+ dsn: "https://583c5af58c664fd1977d638a693b0ada@sentry-next.wixpress.com/20924",
17
+ tracesSampleRate: 1,
18
+ initialScope: {
19
+ tags: {
20
+ fullArtifactId: "com.wixpress.spartans.wix-mcp"
21
+ }
22
+ }
23
+ });
24
+
25
+ // src/bin.ts
26
+ import minimist from "minimist";
27
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
28
+
29
+ // src/cli-tools/cli.ts
30
+ import { z } from "zod";
31
+
32
+ // src/cli-tools/utils.ts
33
+ import { existsSync, readFileSync } from "fs";
34
+ import { homedir } from "os";
35
+ import path from "path";
36
+ function getCliAuthTokenForSiteId(siteIdOrAccountsFileName) {
37
+ const apiKeyFileName = path.join(homedir(), `.wix/auth/api-key.json`);
38
+ const apiKeyFileExists = existsSync(apiKeyFileName);
39
+ if (apiKeyFileExists) {
40
+ const apiKeyData = JSON.parse(readFileSync(apiKeyFileName, "utf8"));
41
+ return apiKeyData.token || apiKeyData.accessToken;
42
+ }
43
+ const siteTokenFileName = path.join(
44
+ homedir(),
45
+ `.wix/auth/${siteIdOrAccountsFileName}.json`
46
+ );
47
+ const siteTokenFileExists = existsSync(siteTokenFileName);
48
+ if (siteTokenFileExists) {
49
+ const authData = JSON.parse(readFileSync(siteTokenFileName, "utf8"));
50
+ return authData.accessToken || authData.token;
51
+ }
52
+ throw new Error(
53
+ "No site token or api key found. You need to authenticate with Wix CLI first."
54
+ );
21
55
  }
22
- function parseToolsArg() {
23
- const toolsArg = parsedArgs['tools'];
24
- const experimentalTools = parseExperimentalArg();
25
- if (!toolsArg) {
26
- // When no tools specified, return both default and experimental tools
27
- return [...DEFAULT_TOOLS, ...experimentalTools];
56
+ function getSiteIdFromCliAppConfig(appPath) {
57
+ const appConfig = JSON.parse(
58
+ readFileSync(path.join(appPath, ".wix/app.config.json"), "utf8")
59
+ );
60
+ return appConfig.siteId;
61
+ }
62
+
63
+ // src/cli-tools/cli.ts
64
+ import { execa } from "execa";
65
+
66
+ // src/interactive-command-tools/handleStdout.ts
67
+ import stripAnsi from "strip-ansi";
68
+
69
+ // src/interactive-command-tools/eventually.ts
70
+ import waitForExpect from "wait-for-expect";
71
+ var defaultOptions = {
72
+ timeout: 1e4,
73
+ interval: 200
74
+ };
75
+ async function eventually(expectation, options) {
76
+ return new Promise((resolve, reject) => {
77
+ waitForExpect.default(
78
+ async () => {
79
+ const ret = await expectation();
80
+ resolve(ret);
81
+ },
82
+ options?.timeout ?? defaultOptions.timeout,
83
+ options?.interval ?? defaultOptions.interval
84
+ ).catch((error) => reject(error));
85
+ });
86
+ }
87
+
88
+ // src/interactive-command-tools/handleStdout.ts
89
+ function handleStdout(stdout) {
90
+ let checkStartIndex = 0;
91
+ const lines = [];
92
+ logger.log(`handleStdout: stdout: ${stdout}`);
93
+ stdout.on("data", (chunk) => {
94
+ logger.log(`handleStdout: chunk: ${chunk}`);
95
+ lines.push(...stripAnsi(chunk.toString()).split("\n"));
96
+ });
97
+ return {
98
+ async waitForText(match, { timeout = 2 * 60 * 1e3 } = {}) {
99
+ return eventually(
100
+ () => {
101
+ const matchedIndex = lines.findIndex((line, index) => {
102
+ if (index < checkStartIndex) {
103
+ return false;
104
+ }
105
+ if (typeof match === "string") {
106
+ return line.includes(match);
107
+ }
108
+ return line.match(match);
109
+ });
110
+ checkStartIndex = matchedIndex >= 0 ? matchedIndex + 1 : lines.length;
111
+ if (matchedIndex !== -1) {
112
+ return lines[matchedIndex];
113
+ }
114
+ const message = `Could not match text in output: ${match}`;
115
+ throw new Error(message);
116
+ },
117
+ { timeout }
118
+ );
119
+ },
120
+ async waitForAndCallback(matchesAndCallbacks, { timeout = 2 * 60 * 1e3 } = {}) {
121
+ let stopResolve;
122
+ const stopPromise = new Promise((resolve) => {
123
+ stopResolve = resolve;
124
+ });
125
+ const processedMatches = /* @__PURE__ */ new Set();
126
+ const waitPromise = eventually(
127
+ () => {
128
+ for (const { match, callback } of matchesAndCallbacks) {
129
+ if (processedMatches.has(match)) {
130
+ continue;
131
+ }
132
+ if (lines.some((line) => line.includes(match))) {
133
+ logger.log(`create-cli: found match ${match}`);
134
+ processedMatches.add(match);
135
+ callback(() => {
136
+ logger.log(`create-cli: stopping match loop`);
137
+ stopResolve();
138
+ });
139
+ } else {
140
+ }
141
+ }
142
+ if (processedMatches.size === matchesAndCallbacks.length) {
143
+ return true;
144
+ }
145
+ throw new Error(
146
+ `Could not find any of the remaining matches: ${matchesAndCallbacks.filter((m) => !processedMatches.has(m.match)).map((m) => m.match).join(", ")}`
147
+ );
148
+ },
149
+ { timeout }
150
+ );
151
+ return Promise.race([waitPromise, stopPromise]);
152
+ },
153
+ async getOutput() {
154
+ return lines.join("\n");
155
+ }
156
+ };
157
+ }
158
+
159
+ // src/interactive-command-tools/interactive-command-utils.ts
160
+ var ENTER = "\r";
161
+ var DOWN = "\x1B[B";
162
+ var mockInteractiveGenerateCommandTool = async ({
163
+ extensionType,
164
+ stdin,
165
+ stdout
166
+ }) => {
167
+ try {
168
+ logger.log("RunWixCliCommand: handle stdout");
169
+ const stdoutHandler = handleStdout(stdout);
170
+ logger.log("RunWixCliCommand: waiting for text");
171
+ await stdoutHandler.waitForText(
172
+ "What kind of extension would you like to generate?"
173
+ );
174
+ if (extensionType === "DASHBOARD_PAGE") {
175
+ } else if (extensionType === "BACKEND_EVENT") {
176
+ logger.log("RunWixCliCommand: writing DOWN 9 times");
177
+ for (let i = 0; i < 9; i++) {
178
+ stdin.write(DOWN);
179
+ await new Promise((resolve) => setTimeout(resolve, 10));
180
+ }
181
+ }
182
+ logger.log("RunWixCliCommand: writing ENTER 1");
183
+ stdin.write(ENTER);
184
+ if (extensionType === "DASHBOARD_PAGE") {
185
+ await stdoutHandler.waitForText("Page title");
186
+ logger.log("RunWixCliCommand: writing ENTER 2");
187
+ stdin.write(ENTER);
188
+ await stdoutHandler.waitForText("Enter the route for the new page");
189
+ logger.log("RunWixCliCommand: writing ENTER 3");
190
+ stdin.write(ENTER);
191
+ } else if (extensionType === "BACKEND_EVENT") {
192
+ await stdoutHandler.waitForText("Event folder");
193
+ logger.log("RunWixCliCommand: writing ENTER 2");
194
+ stdin.write(ENTER);
195
+ logger.log("RunWixCliCommand: waiting for text");
196
+ try {
197
+ await stdoutHandler.waitForText(
198
+ "Would you like to install dependencies now?",
199
+ { timeout: 1e3 }
200
+ );
201
+ logger.log("RunWixCliCommand: writing ENTER 3");
202
+ stdin.write(ENTER);
203
+ } catch (error) {
204
+ if (error instanceof Error && error.message.includes("Could not match text in output")) {
205
+ logger.log(
206
+ "RunWixCliCommand: dependencies are already installed, skipping install"
207
+ );
208
+ logger.log(await stdoutHandler.getOutput());
209
+ } else {
210
+ throw error;
211
+ }
212
+ }
213
+ }
214
+ logger.log("RunWixCliCommand: waiting for success message");
215
+ try {
216
+ await stdoutHandler.waitForText("Successfully", { timeout: 1e3 });
217
+ logger.log("RunWixCliCommand: success message found");
218
+ } catch (error) {
219
+ if (error instanceof Error && error.message.includes("Could not match text in output")) {
220
+ logger.log("RunWixCliCommand: success message not found, skipping");
221
+ } else {
222
+ throw error;
223
+ }
28
224
  }
29
- const requestedTools = toolsArg.split(',').map((t) => t.trim());
30
- const tools = [
31
- // Include valid non-experimental tools
32
- ...requestedTools.filter((tool) => PUBLIC_TOOLS.includes(tool)),
33
- // Include enabled experimental tools
34
- ...experimentalTools
35
- ];
36
- // Warn about enabled experimental tools
37
- tools.forEach((tool) => {
38
- if (EXPERIMENTAL_TOOLS.includes(tool)) {
39
- logger.log(`Warning: ${tool} is an experimental tool and may have limited functionality or breaking changes`);
225
+ return stdoutHandler.getOutput();
226
+ } catch (error) {
227
+ logger.error("RunWixCliCommand: error", error);
228
+ throw error;
229
+ }
230
+ };
231
+
232
+ // src/cli-tools/cli.ts
233
+ var VALID_CLI_TOOLS = [
234
+ "WIX_API",
235
+ "CLI_COMMAND",
236
+ "CLI_COMMAND_INTERACTIVE_MODE"
237
+ ];
238
+ function addCliTools(server2, allowedTools = [
239
+ "WIX_API",
240
+ "CLI_COMMAND",
241
+ "CLI_COMMAND_INTERACTIVE_MODE"
242
+ ], isWixOne2 = false) {
243
+ if (allowedTools.includes("WIX_API")) {
244
+ server2.tool(
245
+ "CallWixAPI",
246
+ "Call Wix apis on an app. Use this to create, read, update, and delete data and other Wix entities in your Wix app.",
247
+ {
248
+ appPath: z.string().describe(
249
+ "The dir path to the wix backoffice cli app to call the api on behalf of. should have {appPath}/.wix/app.config.json file with a siteId field. if passed, siteId is not required"
250
+ ).optional(),
251
+ // should we have appPath or siteId here? (appPath encapsulates this more since we can get the siteId from the appPath then perform the call)
252
+ siteId: z.string().describe(
253
+ "The siteId of the wix backoffice cli app to call the api on behalf of. You can find the siteId in the {appPath}/.wix/app.config.json file. You can pass any other siteId if you want to call the api on behalf of a different site. If passed, appPath is not required. if not passed, the appPath must be provided."
254
+ ).optional(),
255
+ url: z.string().describe(
256
+ "The url of the api to call - usually you get this from the Wix REST docs or from the conversation context"
257
+ ),
258
+ method: z.string().describe(
259
+ "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)"
260
+ ),
261
+ body: z.string().optional().describe(
262
+ "A string representing of a valid JSON object to describe the body of the request"
263
+ )
264
+ },
265
+ async ({ method, url, body, appPath, siteId }) => {
266
+ logger.log(
267
+ `Calling Wix API: ${appPath} ${siteId} ${method} ${url}, body: ${JSON.stringify(
268
+ body
269
+ )}`
270
+ );
271
+ if (!siteId && !appPath) {
272
+ return {
273
+ content: [
274
+ {
275
+ type: "text",
276
+ text: "Either appPath or siteId must be provided"
277
+ }
278
+ ]
279
+ };
280
+ }
281
+ let siteIdToUse = siteId;
282
+ if (!siteIdToUse && appPath) {
283
+ siteIdToUse = getSiteIdFromCliAppConfig(appPath);
284
+ }
285
+ if (!siteIdToUse) {
286
+ return {
287
+ content: [
288
+ {
289
+ type: "text",
290
+ text: "Either appPath or siteId must be provided"
291
+ }
292
+ ]
293
+ };
294
+ }
295
+ logger.log(`Site ID for Wix API call: ${siteIdToUse}`);
296
+ const authorization = getCliAuthTokenForSiteId(siteIdToUse);
297
+ if (!authorization) {
298
+ return {
299
+ content: [
300
+ {
301
+ type: "text",
302
+ text: "Failed to get authorization token. Please check your siteId and appPath"
303
+ }
304
+ ]
305
+ };
40
306
  }
41
- });
42
- return tools;
307
+ try {
308
+ const response = await fetch(url, {
309
+ method,
310
+ headers: {
311
+ Authorization: authorization,
312
+ "wix-site-id": siteIdToUse,
313
+ ...body ? { "Content-Type": "application/json" } : {}
314
+ },
315
+ body
316
+ });
317
+ const responseData = await handleWixAPIResponse(response);
318
+ return {
319
+ content: [
320
+ {
321
+ type: "text",
322
+ text: `Wix API call successful: ${JSON.stringify(responseData)}`
323
+ }
324
+ ]
325
+ };
326
+ } catch (error) {
327
+ logger.error(`Failed to call Wix API: ${error}`);
328
+ throw new Error(`Failed to call Wix API: ${error}`);
329
+ }
330
+ }
331
+ );
332
+ }
333
+ if (allowedTools.includes("CLI_COMMAND_INTERACTIVE_MODE")) {
334
+ server2.tool(
335
+ "RunWixCliCommandInteractiveMode",
336
+ `Executes Wix CLI commands for Wix app development and management.
337
+ Use this tool to run commands like 'wix app generate' (adds new extensions), 'wix app build' (builds your app), 'wix app preview' (creates shareable preview), 'wix app release' (releases a new version of your app), and more.
338
+
339
+ IMPORTANT: Before using this tool, check if the command is mapped in package.json scripts:
340
+ * Use this tool for npm/yarn scripts that map to Wix CLI commands as well.
341
+ * Do not use this tool for starting the local development server.
342
+
343
+ Before using this tool, you MUST search the Wix documentation for the command you want to run.
344
+
345
+ DO NOT USE THIS TOOL FOR ANY OTHER PURPOSE. IT IS ONLY FOR WIX CLI COMMANDS.`,
346
+ {
347
+ appPath: z.string().describe("The full path to the Wix CLI app to run the command on"),
348
+ extensionType: z.enum(["DASHBOARD_PAGE", "BACKEND_EVENT"]).optional().describe(
349
+ "The type of extension to generate. You MUST provide this for commands that generate extensions."
350
+ ),
351
+ searchedDocs: z.boolean().describe(
352
+ "Whether you have already searched the Wix documentation for the command you want to run."
353
+ ),
354
+ command: z.string().min(1, "Command cannot be empty").max(1e3, "Command is too long").describe(
355
+ "The Wix CLI command to execute (e.g. 'wix app generate', 'wix app build', 'wix app preview', 'wix app release', etc.), or a npm/yarn script that maps to a Wix CLI command (e.g. 'npm run generate', 'yarn build', etc.)."
356
+ )
357
+ },
358
+ async ({ command, appPath, extensionType }) => {
359
+ command = command.replace("wix app generate", "npm run generate");
360
+ if (command.includes("generate") && !extensionType) {
361
+ return {
362
+ content: [
363
+ {
364
+ type: "text",
365
+ text: "Error: You must provide an extension type for the 'generate' command."
366
+ }
367
+ ],
368
+ isError: true
369
+ };
370
+ }
371
+ logger.log(
372
+ `RunWixCliCommand: command: ${command}, appPath: ${appPath}, extensionType: ${extensionType}`
373
+ );
374
+ try {
375
+ logger.log(`Executing Wix CLI command: ${command}`);
376
+ const commandParts = command.split(" ");
377
+ const commandName = commandParts[0];
378
+ const commandArgs = commandParts.slice(1);
379
+ const subprocess = execa(commandName, commandArgs, {
380
+ cwd: appPath,
381
+ extendEnv: true,
382
+ env: {
383
+ ...process.env,
384
+ PATH: process.env.PATH,
385
+ WIX_CLI_TEST_OVERRIDES: JSON.stringify({
386
+ inkDebug: true
387
+ })
388
+ },
389
+ timeout: 5 * 60 * 1e3,
390
+ // 5 minute timeout
391
+ maxBuffer: 10 * 1024 * 1024
392
+ // 10MB output limit
393
+ });
394
+ logger.log(`RunWixCliCommand: pid: ${subprocess.pid}`);
395
+ if (!subprocess.pid) {
396
+ let spawnError;
397
+ if (!spawnError) {
398
+ await new Promise((resolve) => {
399
+ subprocess.on("error", (err) => {
400
+ spawnError = err;
401
+ resolve({ spawnError });
402
+ });
403
+ });
404
+ }
405
+ return {
406
+ content: [
407
+ {
408
+ type: "text",
409
+ text: `Failed to start the Wix CLI command process. This usually indicates a problem with the command or the environment. Are you sure Wix CLI is installed globally?
410
+
411
+ Command: ${command}
412
+
413
+ ${spawnError}`
414
+ }
415
+ ]
416
+ };
417
+ }
418
+ const { stdin, stdout, stderr } = subprocess;
419
+ if (extensionType) {
420
+ const output = await mockInteractiveGenerateCommandTool({
421
+ extensionType,
422
+ stdin,
423
+ stdout
424
+ });
425
+ logger.log(`RunWixCliCommand: output: ${output}`);
426
+ return {
427
+ content: [{ type: "text", text: output }]
428
+ };
429
+ }
430
+ const stringifyStdout = JSON.stringify(stdout);
431
+ const stringifyStderr = JSON.stringify(stderr);
432
+ return {
433
+ content: [
434
+ { type: "text", text: stringifyStdout },
435
+ ...stringifyStderr ? [{ type: "text", text: `Error: ${stringifyStderr}` }] : []
436
+ ]
437
+ };
438
+ } catch (error) {
439
+ logger.error(`Error executing Wix CLI command: ${error}`);
440
+ return {
441
+ content: [{ type: "text", text: `Error: ${error}` }],
442
+ isError: true
443
+ };
444
+ }
445
+ }
446
+ );
447
+ }
448
+ if (allowedTools.includes("CLI_COMMAND")) {
449
+ server2.tool(
450
+ "RunWixCliCommand",
451
+ `Executes Wix CLI commands for Wix app development and management.
452
+ Use this tool to run commands like 'wix app generate' (adds new extensions), 'wix app build' (builds your app), 'wix app preview' (creates shareable preview), 'wix app release' (releases a new version of your app), and more.
453
+
454
+ IMPORTANT: Before using this tool, check if the command is mapped in package.json scripts:
455
+ * Use this tool for npm/yarn scripts that map to Wix CLI commands as well.
456
+ * Do not use this tool for starting the local development server.
457
+
458
+ Before using this tool, you MUST search the Wix documentation for the command you want to run.
459
+
460
+ DO NOT USE THIS TOOL FOR ANY OTHER PURPOSE. IT IS ONLY FOR WIX CLI COMMANDS.`,
461
+ {
462
+ appPath: z.string().describe("The full path to the Wix CLI app to run the command on."),
463
+ extensionType: z.enum([
464
+ "dashboard-page",
465
+ "dashboard-plugin",
466
+ "dashboard-menu-plugin",
467
+ "dashboard-modal",
468
+ "web-method",
469
+ "api-route",
470
+ "event",
471
+ "service-plugin"
472
+ ]).optional().describe(
473
+ "The type of extension to generate. You MUST provide this for commands that generate extensions."
474
+ ),
475
+ extensionName: z.string().optional().describe(
476
+ "The name of the extension to generate, e.g. My Dashboard Page. You MUST provide this for commands that generate extensions."
477
+ ),
478
+ searchedDocs: z.boolean().describe(
479
+ "Whether you have already searched the Wix documentation for the command you want to run."
480
+ ),
481
+ command: z.string().min(1, "Command cannot be empty").max(1e3, "Command is too long").describe(
482
+ "The Wix CLI command to execute (e.g. 'wix app generate', 'wix app build', 'wix app preview', 'wix app release', etc.), or a script that maps to a Wix CLI command (e.g. 'npm run generate', 'yarn generate', etc.)."
483
+ )
484
+ },
485
+ async ({ command, appPath, extensionType, extensionName }) => {
486
+ logger.log(
487
+ `RunWixCliCommand: command: ${command}, appPath: ${appPath}, extensionType: ${extensionType}, extensionName: ${extensionName}`
488
+ );
489
+ let commandName = "";
490
+ let commandArgs = [];
491
+ if (command.includes("generate")) {
492
+ if (!extensionType) {
493
+ return {
494
+ content: [
495
+ {
496
+ type: "text",
497
+ text: "Error: You must provide an extension type for the 'generate' command."
498
+ }
499
+ ],
500
+ isError: true
501
+ };
502
+ }
503
+ if (!extensionName) {
504
+ return {
505
+ content: [
506
+ {
507
+ type: "text",
508
+ text: "Error: You must provide an extension name for the 'generate' command."
509
+ }
510
+ ],
511
+ isError: true
512
+ };
513
+ }
514
+ commandName = "npx";
515
+ commandArgs = [
516
+ isWixOne2 ? "wix-one" : "wix",
517
+ "app",
518
+ "generate",
519
+ "-t",
520
+ extensionType,
521
+ "-n",
522
+ extensionName,
523
+ "--json"
524
+ ];
525
+ } else {
526
+ const commandParts = command.split(" ");
527
+ commandName = commandParts[0];
528
+ commandArgs = commandParts.slice(1);
529
+ }
530
+ if (isWixOne2 && commandName === "wix") {
531
+ commandName = "wix-one";
532
+ }
533
+ try {
534
+ logger.log(
535
+ `Executing Wix CLI command: ${commandName} ${commandArgs.join(" ")}`
536
+ );
537
+ const { stdout, stderr, exitCode } = await execa(
538
+ commandName,
539
+ commandArgs,
540
+ {
541
+ cwd: appPath,
542
+ extendEnv: true,
543
+ env: {
544
+ ...process.env
545
+ },
546
+ timeout: 5 * 60 * 1e3,
547
+ // 5 minute timeout
548
+ maxBuffer: 10 * 1024 * 1024
549
+ // 10MB output limit
550
+ }
551
+ );
552
+ if (exitCode !== 0) {
553
+ return {
554
+ content: [{ type: "text", text: `Error: ${stderr}` }],
555
+ isError: true
556
+ };
557
+ }
558
+ logger.log(`RunWixCliCommand: stdout: ${stdout}`);
559
+ logger.log(`RunWixCliCommand: stderr: ${stderr}`);
560
+ return {
561
+ content: [
562
+ { type: "text", text: stdout },
563
+ ...stderr ? [{ type: "text", text: `Error: ${stderr}` }] : []
564
+ ]
565
+ };
566
+ } catch (error) {
567
+ logger.error(`Error executing Wix CLI command: ${error}`);
568
+ return {
569
+ content: [{ type: "text", text: `Error: ${error}` }],
570
+ isError: true
571
+ };
572
+ }
573
+ }
574
+ );
575
+ }
43
576
  }
44
- const loggerType = parsedArgs['logger'] || 'mcp';
45
- if (loggerType === 'file') {
46
- attachFileLogger();
577
+
578
+ // src/bin.ts
579
+ var PUBLIC_TOOLS = [...VALID_DOCS_TOOLS];
580
+ var EXPERIMENTAL_TOOLS = ["WIX_API", "CLI_COMMAND"];
581
+ var DEFAULT_TOOLS = [...VALID_DOCS_TOOLS];
582
+ var parsedArgs = minimist(process.argv.slice(2));
583
+ function parseExperimentalArg() {
584
+ const experimentalArg = parsedArgs["experimental"];
585
+ if (!experimentalArg) return [];
586
+ return experimentalArg.split(",").map((t) => t.trim()).filter(
587
+ (tool) => EXPERIMENTAL_TOOLS.includes(tool)
588
+ );
47
589
  }
48
- else {
49
- // Initially we log to stderr, because MCP server is not connected yet
50
- // When the server is connected, we attach the MCP server logger
51
- attachStdErrLogger();
590
+ function parseToolsArg() {
591
+ const toolsArg = parsedArgs["tools"];
592
+ const experimentalTools = parseExperimentalArg();
593
+ if (!toolsArg) {
594
+ return [...DEFAULT_TOOLS, ...experimentalTools];
595
+ }
596
+ const requestedTools = toolsArg.split(",").map((t) => t.trim());
597
+ const tools = [
598
+ // Include valid non-experimental tools
599
+ ...requestedTools.filter(
600
+ (tool) => PUBLIC_TOOLS.includes(tool)
601
+ ),
602
+ // Include enabled experimental tools
603
+ ...experimentalTools
604
+ ];
605
+ tools.forEach((tool) => {
606
+ if (EXPERIMENTAL_TOOLS.includes(tool)) {
607
+ logger.log(
608
+ `Warning: ${tool} is an experimental tool and may have limited functionality or breaking changes`
609
+ );
610
+ }
611
+ });
612
+ return tools;
613
+ }
614
+ var loggerType = parsedArgs["logger"] || "mcp";
615
+ if (loggerType === "file") {
616
+ attachFileLogger();
617
+ } else {
618
+ attachStdErrLogger();
52
619
  }
53
- logger.log('--------------------------------');
54
- logger.log('starting WIX MCP server');
55
- logger.log('--------------------------------');
56
- const server = new WixMcpServer({
57
- name: 'wix-mcp-server',
58
- version: '1.0.0'
59
- }, {
620
+ logger.log("--------------------------------");
621
+ logger.log("starting WIX MCP server");
622
+ logger.log("--------------------------------");
623
+ var server = new WixMcpServer(
624
+ {
625
+ name: "wix-mcp-server",
626
+ version: "1.0.0"
627
+ },
628
+ {
60
629
  capabilities: {
61
- tools: {},
62
- prompts: {},
63
- logging: {},
64
- resources: {}
630
+ tools: {},
631
+ prompts: {},
632
+ logging: {},
633
+ resources: {}
65
634
  }
66
- });
67
- const activeTools = parseToolsArg();
68
- logger.log('Active tools:', activeTools);
69
- const docsTools = activeTools.filter((tool) => VALID_DOCS_TOOLS.includes(tool));
635
+ }
636
+ );
637
+ var activeTools = parseToolsArg();
638
+ logger.log("Active tools:", activeTools);
639
+ var docsTools = activeTools.filter(
640
+ (tool) => VALID_DOCS_TOOLS.includes(tool)
641
+ );
70
642
  if (docsTools.length > 0) {
71
- logger.log('Adding docs tools:', docsTools);
72
- addDocsTools(server, docsTools);
643
+ logger.log("Adding docs tools:", docsTools);
644
+ addDocsTools(server, docsTools);
73
645
  }
74
- const isWixOne = parsedArgs['cli'] === 'wix-one';
75
- const cliTools = activeTools.filter((tool) => VALID_CLI_TOOLS.includes(tool));
646
+ var isWixOne = parsedArgs["cli"] === "wix-one";
647
+ var cliTools = activeTools.filter(
648
+ (tool) => VALID_CLI_TOOLS.includes(tool)
649
+ );
76
650
  if (cliTools.length > 0) {
77
- logger.log('Adding cli tools:', cliTools, 'isWixOne:', isWixOne);
78
- addCliTools(server, cliTools, isWixOne);
651
+ logger.log("Adding cli tools:", cliTools, "isWixOne:", isWixOne);
652
+ addCliTools(server, cliTools, isWixOne);
79
653
  }
80
654
  try {
81
- const portals = parsedArgs['portals']?.split(',') || [];
82
- if (portals.length > 0) {
83
- logger.log('Adding docs resources for portals:', portals);
84
- await addDocsResources(server, portals);
85
- }
86
- }
87
- catch (error) {
88
- logger.error('Error adding docs resources:', error);
655
+ const portals = parsedArgs["portals"]?.split(",") || [];
656
+ if (portals.length > 0) {
657
+ logger.log("Adding docs resources for portals:", portals);
658
+ await addDocsResources(server, portals);
659
+ }
660
+ } catch (error) {
661
+ logger.error("Error adding docs resources:", error);
89
662
  }
90
- logger.log('Starting server');
91
- const transport = new StdioServerTransport();
92
- logger.log('Connecting to transport');
663
+ logger.log("Starting server");
664
+ var transport = new StdioServerTransport();
665
+ logger.log("Connecting to transport");
93
666
  await server.connect(transport);
94
- logger.log('Transport connected');
95
- if (loggerType === 'mcp') {
96
- // From now on, we log to the MCP server
97
- attachMcpServerLogger(server);
667
+ logger.log("Transport connected");
668
+ if (loggerType === "mcp") {
669
+ attachMcpServerLogger(server);
98
670
  }
671
+ export {
672
+ DEFAULT_TOOLS
673
+ };