@wix/mcp 1.0.16 → 1.0.18

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 (48) hide show
  1. package/build/bin-standalone.js +12691 -12854
  2. package/build/bin-standalone.js.map +4 -4
  3. package/build/cjs/index.cjs +290 -226
  4. package/build/cjs/index.cjs.map +4 -4
  5. package/build/dts/api-call/index.d.ts +1 -1
  6. package/build/dts/api-call/index.d.ts.map +1 -1
  7. package/build/dts/api-call/index.js +161 -128
  8. package/build/dts/api-call/index.js.map +1 -1
  9. package/build/dts/api-call/validation.d.ts +8 -0
  10. package/build/dts/api-call/validation.d.ts.map +1 -0
  11. package/build/dts/api-call/validation.js +31 -0
  12. package/build/dts/api-call/validation.js.map +1 -0
  13. package/build/dts/api-call/validation.test.d.ts +2 -0
  14. package/build/dts/api-call/validation.test.d.ts.map +1 -0
  15. package/build/dts/api-call/validation.test.js +42 -0
  16. package/build/dts/api-call/validation.test.js.map +1 -0
  17. package/build/dts/bin.d.ts.map +1 -1
  18. package/build/dts/bin.js +22 -0
  19. package/build/dts/bin.js.map +1 -1
  20. package/build/dts/cli-tools/cli.d.ts +1 -1
  21. package/build/dts/cli-tools/cli.d.ts.map +1 -1
  22. package/build/dts/cli-tools/cli.js +2 -223
  23. package/build/dts/cli-tools/cli.js.map +1 -1
  24. package/build/dts/docs/docs.d.ts.map +1 -1
  25. package/build/dts/docs/docs.js +4 -2
  26. package/build/dts/docs/docs.js.map +1 -1
  27. package/build/dts/docs/fetch-article.d.ts.map +1 -1
  28. package/build/dts/docs/fetch-article.js +11 -0
  29. package/build/dts/docs/fetch-article.js.map +1 -1
  30. package/build/dts/docs/fetch-article.test.d.ts +2 -0
  31. package/build/dts/docs/fetch-article.test.d.ts.map +1 -0
  32. package/build/dts/docs/fetch-article.test.js +12 -0
  33. package/build/dts/docs/fetch-article.test.js.map +1 -0
  34. package/build/dts/infra/panorama.d.ts +2 -0
  35. package/build/dts/infra/panorama.d.ts.map +1 -1
  36. package/build/dts/infra/panorama.js +1 -0
  37. package/build/dts/infra/panorama.js.map +1 -1
  38. package/build/dts/wix-mcp-server.d.ts +3 -0
  39. package/build/dts/wix-mcp-server.d.ts.map +1 -1
  40. package/build/dts/wix-mcp-server.js +9 -2
  41. package/build/dts/wix-mcp-server.js.map +1 -1
  42. package/build/esm/index.js +258 -188
  43. package/build/esm/index.js.map +3 -3
  44. package/package.json +4 -4
  45. package/build/dts/cli-tools/utils.d.ts +0 -3
  46. package/build/dts/cli-tools/utils.d.ts.map +0 -1
  47. package/build/dts/cli-tools/utils.js +0 -26
  48. package/build/dts/cli-tools/utils.js.map +0 -1
@@ -3713,9 +3713,9 @@ __export(tslib_es6_exports, {
3713
3713
  __asyncValues: () => __asyncValues,
3714
3714
  __await: () => __await,
3715
3715
  __awaiter: () => __awaiter,
3716
- __classPrivateFieldGet: () => __classPrivateFieldGet2,
3716
+ __classPrivateFieldGet: () => __classPrivateFieldGet,
3717
3717
  __classPrivateFieldIn: () => __classPrivateFieldIn,
3718
- __classPrivateFieldSet: () => __classPrivateFieldSet2,
3718
+ __classPrivateFieldSet: () => __classPrivateFieldSet,
3719
3719
  __createBinding: () => __createBinding,
3720
3720
  __decorate: () => __decorate,
3721
3721
  __disposeResources: () => __disposeResources,
@@ -4064,12 +4064,12 @@ function __importStar(mod) {
4064
4064
  function __importDefault(mod) {
4065
4065
  return mod && mod.__esModule ? mod : { default: mod };
4066
4066
  }
4067
- function __classPrivateFieldGet2(receiver, state, kind, f) {
4067
+ function __classPrivateFieldGet(receiver, state, kind, f) {
4068
4068
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4069
4069
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4070
4070
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
4071
4071
  }
4072
- function __classPrivateFieldSet2(receiver, state, value, kind, f) {
4072
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
4073
4073
  if (kind === "m") throw new TypeError("Private method is not writable");
4074
4074
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4075
4075
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
@@ -4218,8 +4218,8 @@ var init_tslib_es6 = __esm({
4218
4218
  __makeTemplateObject,
4219
4219
  __importStar,
4220
4220
  __importDefault,
4221
- __classPrivateFieldGet: __classPrivateFieldGet2,
4222
- __classPrivateFieldSet: __classPrivateFieldSet2,
4221
+ __classPrivateFieldGet,
4222
+ __classPrivateFieldSet,
4223
4223
  __classPrivateFieldIn,
4224
4224
  __addDisposableResource,
4225
4225
  __disposeResources,
@@ -5492,7 +5492,7 @@ var require_common = __commonJS({
5492
5492
  createDebug.namespaces = namespaces;
5493
5493
  createDebug.names = [];
5494
5494
  createDebug.skips = [];
5495
- const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(" ", ",").split(",").filter(Boolean);
5495
+ const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(/\s+/g, ",").split(",").filter(Boolean);
5496
5496
  for (const ns of split) {
5497
5497
  if (ns[0] === "-") {
5498
5498
  createDebug.skips.push(ns.slice(1));
@@ -5710,7 +5710,7 @@ var require_browser = __commonJS({
5710
5710
  function load() {
5711
5711
  let r;
5712
5712
  try {
5713
- r = exports2.storage.getItem("debug");
5713
+ r = exports2.storage.getItem("debug") || exports2.storage.getItem("DEBUG");
5714
5714
  } catch (error) {
5715
5715
  }
5716
5716
  if (!r && typeof process !== "undefined" && "env" in process) {
@@ -5736,15 +5736,16 @@ var require_browser = __commonJS({
5736
5736
  }
5737
5737
  });
5738
5738
 
5739
- // ../../node_modules/has-flag/index.js
5739
+ // ../../node_modules/supports-color/node_modules/has-flag/index.js
5740
5740
  var require_has_flag = __commonJS({
5741
- "../../node_modules/has-flag/index.js"(exports2, module2) {
5741
+ "../../node_modules/supports-color/node_modules/has-flag/index.js"(exports2, module2) {
5742
5742
  "use strict";
5743
- module2.exports = (flag, argv = process.argv) => {
5743
+ module2.exports = (flag, argv) => {
5744
+ argv = argv || process.argv;
5744
5745
  const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
5745
- const position = argv.indexOf(prefix + flag);
5746
- const terminatorPosition = argv.indexOf("--");
5747
- return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
5746
+ const pos = argv.indexOf(prefix + flag);
5747
+ const terminatorPos = argv.indexOf("--");
5748
+ return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
5748
5749
  };
5749
5750
  }
5750
5751
  });
@@ -5754,23 +5755,16 @@ var require_supports_color = __commonJS({
5754
5755
  "../../node_modules/supports-color/index.js"(exports2, module2) {
5755
5756
  "use strict";
5756
5757
  var os = require("os");
5757
- var tty = require("tty");
5758
5758
  var hasFlag = require_has_flag();
5759
- var { env } = process;
5759
+ var env = process.env;
5760
5760
  var forceColor;
5761
- if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
5762
- forceColor = 0;
5761
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false")) {
5762
+ forceColor = false;
5763
5763
  } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
5764
- forceColor = 1;
5764
+ forceColor = true;
5765
5765
  }
5766
5766
  if ("FORCE_COLOR" in env) {
5767
- if (env.FORCE_COLOR === "true") {
5768
- forceColor = 1;
5769
- } else if (env.FORCE_COLOR === "false") {
5770
- forceColor = 0;
5771
- } else {
5772
- forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
5773
- }
5767
+ forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0;
5774
5768
  }
5775
5769
  function translateLevel(level) {
5776
5770
  if (level === 0) {
@@ -5783,8 +5777,8 @@ var require_supports_color = __commonJS({
5783
5777
  has16m: level >= 3
5784
5778
  };
5785
5779
  }
5786
- function supportsColor(haveStream, streamIsTTY) {
5787
- if (forceColor === 0) {
5780
+ function supportsColor(stream) {
5781
+ if (forceColor === false) {
5788
5782
  return 0;
5789
5783
  }
5790
5784
  if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
@@ -5793,22 +5787,19 @@ var require_supports_color = __commonJS({
5793
5787
  if (hasFlag("color=256")) {
5794
5788
  return 2;
5795
5789
  }
5796
- if (haveStream && !streamIsTTY && forceColor === void 0) {
5790
+ if (stream && !stream.isTTY && forceColor !== true) {
5797
5791
  return 0;
5798
5792
  }
5799
- const min = forceColor || 0;
5800
- if (env.TERM === "dumb") {
5801
- return min;
5802
- }
5793
+ const min = forceColor ? 1 : 0;
5803
5794
  if (process.platform === "win32") {
5804
5795
  const osRelease = os.release().split(".");
5805
- if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
5796
+ if (Number(process.versions.node.split(".")[0]) >= 8 && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
5806
5797
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
5807
5798
  }
5808
5799
  return 1;
5809
5800
  }
5810
5801
  if ("CI" in env) {
5811
- if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
5802
+ if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
5812
5803
  return 1;
5813
5804
  }
5814
5805
  return min;
@@ -5837,16 +5828,19 @@ var require_supports_color = __commonJS({
5837
5828
  if ("COLORTERM" in env) {
5838
5829
  return 1;
5839
5830
  }
5831
+ if (env.TERM === "dumb") {
5832
+ return min;
5833
+ }
5840
5834
  return min;
5841
5835
  }
5842
5836
  function getSupportLevel(stream) {
5843
- const level = supportsColor(stream, stream && stream.isTTY);
5837
+ const level = supportsColor(stream);
5844
5838
  return translateLevel(level);
5845
5839
  }
5846
5840
  module2.exports = {
5847
5841
  supportsColor: getSupportLevel,
5848
- stdout: translateLevel(supportsColor(true, tty.isatty(1))),
5849
- stderr: translateLevel(supportsColor(true, tty.isatty(2)))
5842
+ stdout: getSupportLevel(process.stdout),
5843
+ stderr: getSupportLevel(process.stderr)
5850
5844
  };
5851
5845
  }
5852
5846
  });
@@ -12529,12 +12523,16 @@ var require_error3 = __commonJS({
12529
12523
  ];
12530
12524
  var HttpError = class _HttpError extends Error {
12531
12525
  constructor(error) {
12526
+ var _a;
12532
12527
  super(error.message);
12533
12528
  this.isWixHttpError = true;
12534
12529
  Object.setPrototypeOf(this, _HttpError.prototype);
12535
12530
  exports2.axiosErrorFields.forEach((key) => {
12536
12531
  this[key] = error[key];
12537
12532
  });
12533
+ if ((_a = this.response) === null || _a === void 0 ? void 0 : _a.headers) {
12534
+ this.response.requestId = (0, headers_1.requestIdOrEmptyString)(this.response);
12535
+ }
12538
12536
  }
12539
12537
  get requestId() {
12540
12538
  return (0, headers_1.requestIdOrEmptyString)(this.response);
@@ -16762,19 +16760,6 @@ var errorUtil;
16762
16760
  })(errorUtil || (errorUtil = {}));
16763
16761
 
16764
16762
  // ../../node_modules/zod/dist/esm/v3/types.js
16765
- var __classPrivateFieldGet = function(receiver, state, kind, f) {
16766
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
16767
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
16768
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
16769
- };
16770
- var __classPrivateFieldSet = function(receiver, state, value, kind, f) {
16771
- if (kind === "m") throw new TypeError("Private method is not writable");
16772
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
16773
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
16774
- return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
16775
- };
16776
- var _ZodEnum_cache;
16777
- var _ZodNativeEnum_cache;
16778
16763
  var ParseInputLazyPath = class {
16779
16764
  constructor(parent, value, path2, key) {
16780
16765
  this._cachedPath = [];
@@ -19599,10 +19584,6 @@ function createZodEnum(values, params) {
19599
19584
  });
19600
19585
  }
19601
19586
  var ZodEnum = class _ZodEnum extends ZodType {
19602
- constructor() {
19603
- super(...arguments);
19604
- _ZodEnum_cache.set(this, void 0);
19605
- }
19606
19587
  _parse(input) {
19607
19588
  if (typeof input.data !== "string") {
19608
19589
  const ctx = this._getOrReturnCtx(input);
@@ -19614,10 +19595,10 @@ var ZodEnum = class _ZodEnum extends ZodType {
19614
19595
  });
19615
19596
  return INVALID;
19616
19597
  }
19617
- if (!__classPrivateFieldGet(this, _ZodEnum_cache, "f")) {
19618
- __classPrivateFieldSet(this, _ZodEnum_cache, new Set(this._def.values), "f");
19598
+ if (!this._cache) {
19599
+ this._cache = new Set(this._def.values);
19619
19600
  }
19620
- if (!__classPrivateFieldGet(this, _ZodEnum_cache, "f").has(input.data)) {
19601
+ if (!this._cache.has(input.data)) {
19621
19602
  const ctx = this._getOrReturnCtx(input);
19622
19603
  const expectedValues = this._def.values;
19623
19604
  addIssueToContext(ctx, {
@@ -19666,13 +19647,8 @@ var ZodEnum = class _ZodEnum extends ZodType {
19666
19647
  });
19667
19648
  }
19668
19649
  };
19669
- _ZodEnum_cache = /* @__PURE__ */ new WeakMap();
19670
19650
  ZodEnum.create = createZodEnum;
19671
19651
  var ZodNativeEnum = class extends ZodType {
19672
- constructor() {
19673
- super(...arguments);
19674
- _ZodNativeEnum_cache.set(this, void 0);
19675
- }
19676
19652
  _parse(input) {
19677
19653
  const nativeEnumValues = util.getValidEnumValues(this._def.values);
19678
19654
  const ctx = this._getOrReturnCtx(input);
@@ -19685,10 +19661,10 @@ var ZodNativeEnum = class extends ZodType {
19685
19661
  });
19686
19662
  return INVALID;
19687
19663
  }
19688
- if (!__classPrivateFieldGet(this, _ZodNativeEnum_cache, "f")) {
19689
- __classPrivateFieldSet(this, _ZodNativeEnum_cache, new Set(util.getValidEnumValues(this._def.values)), "f");
19664
+ if (!this._cache) {
19665
+ this._cache = new Set(util.getValidEnumValues(this._def.values));
19690
19666
  }
19691
- if (!__classPrivateFieldGet(this, _ZodNativeEnum_cache, "f").has(input.data)) {
19667
+ if (!this._cache.has(input.data)) {
19692
19668
  const expectedValues = util.objectValues(nativeEnumValues);
19693
19669
  addIssueToContext(ctx, {
19694
19670
  received: ctx.data,
@@ -19703,7 +19679,6 @@ var ZodNativeEnum = class extends ZodType {
19703
19679
  return this._def.values;
19704
19680
  }
19705
19681
  };
19706
- _ZodNativeEnum_cache = /* @__PURE__ */ new WeakMap();
19707
19682
  ZodNativeEnum.create = (values, params) => {
19708
19683
  return new ZodNativeEnum({
19709
19684
  values,
@@ -19844,7 +19819,7 @@ var ZodEffects = class extends ZodType {
19844
19819
  parent: ctx
19845
19820
  });
19846
19821
  if (!isValid(base))
19847
- return base;
19822
+ return INVALID;
19848
19823
  const result = effect.transform(base.value, checkCtx);
19849
19824
  if (result instanceof Promise) {
19850
19825
  throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
@@ -19853,7 +19828,7 @@ var ZodEffects = class extends ZodType {
19853
19828
  } else {
19854
19829
  return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => {
19855
19830
  if (!isValid(base))
19856
- return base;
19831
+ return INVALID;
19857
19832
  return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
19858
19833
  status: status.value,
19859
19834
  value: result
@@ -21266,7 +21241,7 @@ var Protocol = class {
21266
21241
  request(request, resultSchema, options) {
21267
21242
  const { relatedRequestId, resumptionToken, onresumptiontoken } = options !== null && options !== void 0 ? options : {};
21268
21243
  return new Promise((resolve, reject) => {
21269
- var _a, _b, _c, _d, _e;
21244
+ var _a, _b, _c, _d, _e, _f;
21270
21245
  if (!this._transport) {
21271
21246
  reject(new Error("Not connected"));
21272
21247
  return;
@@ -21285,7 +21260,10 @@ var Protocol = class {
21285
21260
  this._progressHandlers.set(messageId, options.onprogress);
21286
21261
  jsonrpcRequest.params = {
21287
21262
  ...request.params,
21288
- _meta: { progressToken: messageId }
21263
+ _meta: {
21264
+ ...((_c = request.params) === null || _c === void 0 ? void 0 : _c._meta) || {},
21265
+ progressToken: messageId
21266
+ }
21289
21267
  };
21290
21268
  }
21291
21269
  const cancel = (reason) => {
@@ -21318,13 +21296,13 @@ var Protocol = class {
21318
21296
  reject(error);
21319
21297
  }
21320
21298
  });
21321
- (_c = options === null || options === void 0 ? void 0 : options.signal) === null || _c === void 0 ? void 0 : _c.addEventListener("abort", () => {
21299
+ (_d = options === null || options === void 0 ? void 0 : options.signal) === null || _d === void 0 ? void 0 : _d.addEventListener("abort", () => {
21322
21300
  var _a2;
21323
21301
  cancel((_a2 = options === null || options === void 0 ? void 0 : options.signal) === null || _a2 === void 0 ? void 0 : _a2.reason);
21324
21302
  });
21325
- const timeout = (_d = options === null || options === void 0 ? void 0 : options.timeout) !== null && _d !== void 0 ? _d : DEFAULT_REQUEST_TIMEOUT_MSEC;
21303
+ const timeout = (_e = options === null || options === void 0 ? void 0 : options.timeout) !== null && _e !== void 0 ? _e : DEFAULT_REQUEST_TIMEOUT_MSEC;
21326
21304
  const timeoutHandler = () => cancel(new McpError(ErrorCode.RequestTimeout, "Request timed out", { timeout }));
21327
- this._setupTimeout(messageId, timeout, options === null || options === void 0 ? void 0 : options.maxTotalTimeout, timeoutHandler, (_e = options === null || options === void 0 ? void 0 : options.resetTimeoutOnProgress) !== null && _e !== void 0 ? _e : false);
21305
+ this._setupTimeout(messageId, timeout, options === null || options === void 0 ? void 0 : options.maxTotalTimeout, timeoutHandler, (_f = options === null || options === void 0 ? void 0 : options.resetTimeoutOnProgress) !== null && _f !== void 0 ? _f : false);
21328
21306
  this._transport.send(jsonrpcRequest, { relatedRequestId, resumptionToken, onresumptiontoken }).catch((error) => {
21329
21307
  this._cleanupTimeout(messageId);
21330
21308
  reject(error);
@@ -22981,6 +22959,9 @@ var McpServer = class {
22981
22959
  return;
22982
22960
  }
22983
22961
  this.server.assertCanSetRequestHandler(CompleteRequestSchema.shape.method.value);
22962
+ this.server.registerCapabilities({
22963
+ completions: {}
22964
+ });
22984
22965
  this.server.setRequestHandler(CompleteRequestSchema, async (request) => {
22985
22966
  switch (request.params.ref.type) {
22986
22967
  case "ref/prompt":
@@ -23053,8 +23034,9 @@ var McpServer = class {
23053
23034
  const result = await template.resourceTemplate.listCallback(extra);
23054
23035
  for (const resource of result.resources) {
23055
23036
  templateResources.push({
23056
- ...resource,
23057
- ...template.metadata
23037
+ ...template.metadata,
23038
+ // the defined resource metadata should override the template metadata if present
23039
+ ...resource
23058
23040
  });
23059
23041
  }
23060
23042
  }
@@ -23413,6 +23395,7 @@ var createPanoramaClient = (opts) => {
23413
23395
  },
23414
23396
  data: {
23415
23397
  environment: opts.environment,
23398
+ serverInfo: opts.serverInfo,
23416
23399
  runtime: {
23417
23400
  packageVersion: packageJson.version,
23418
23401
  versions: process.versions,
@@ -23473,12 +23456,9 @@ var logger2 = createNullLogger();
23473
23456
 
23474
23457
  // src/wix-mcp-server.ts
23475
23458
  var WixMcpServer = class extends McpServer {
23476
- biLogger;
23477
- nodeEnv;
23478
- sessionId;
23479
- getUserId;
23480
23459
  constructor(serverInfo, options, nodeEnv) {
23481
23460
  super(serverInfo, options);
23461
+ this.serverInfo = serverInfo;
23482
23462
  this.sessionId = v4_default();
23483
23463
  this.nodeEnv = getEnvironment(nodeEnv);
23484
23464
  this.biLogger = createBiLogger({
@@ -23486,9 +23466,17 @@ var WixMcpServer = class extends McpServer {
23486
23466
  });
23487
23467
  logger2.log(`WixMcpServer created with sessionId: ${this.sessionId}`);
23488
23468
  }
23469
+ biLogger;
23470
+ nodeEnv;
23471
+ sessionId;
23472
+ getUserId;
23473
+ getClientName;
23489
23474
  setUserIdGetter(getUserId) {
23490
23475
  this.getUserId = getUserId;
23491
23476
  }
23477
+ setClientNameGetter(getClientName) {
23478
+ this.getClientName = getClientName;
23479
+ }
23492
23480
  tool(...args) {
23493
23481
  const cbIndex = args.findIndex((arg) => typeof arg === "function");
23494
23482
  if (cbIndex !== -1) {
@@ -23503,7 +23491,8 @@ var WixMcpServer = class extends McpServer {
23503
23491
  environment: this.nodeEnv,
23504
23492
  sessionId: this.sessionId,
23505
23493
  componentId: toolName,
23506
- uuid: this.getUserId?.()
23494
+ uuid: this.getUserId?.(),
23495
+ serverInfo: this.serverInfo
23507
23496
  });
23508
23497
  const toolInvocationId = v4_default();
23509
23498
  const httpClient = new import_http_client.HttpClient({
@@ -23562,7 +23551,7 @@ var WixMcpServer = class extends McpServer {
23562
23551
  }
23563
23552
  this.biLogger.report(
23564
23553
  (0, import_v2.wixMcpRequestSrc39Evid1607)({
23565
- clientName,
23554
+ clientName: this.getClientName?.() || clientName,
23566
23555
  duration,
23567
23556
  errorBody,
23568
23557
  toolInvocationId,
@@ -23728,6 +23717,18 @@ async function fetchArticleContentFromDigor(httpClient, articleUrl, mode, stripH
23728
23717
  }
23729
23718
  async function fetchArticleContent(httpClient, articleUrl, mode, stripHeader = false) {
23730
23719
  if (mode === "raw") {
23720
+ let parsedUrl;
23721
+ try {
23722
+ parsedUrl = new URL(articleUrl);
23723
+ } catch {
23724
+ throw new Error(`Invalid URL format: ${articleUrl}`);
23725
+ }
23726
+ const hostname = parsedUrl.hostname.replace("www.", "");
23727
+ if (hostname !== "dev.wix.com") {
23728
+ throw new Error(
23729
+ `Unsupported URL domain: ${hostname}. Article URL must be from dev.wix.com`
23730
+ );
23731
+ }
23731
23732
  const { data: doc } = await httpClient.get(articleUrl);
23732
23733
  return doc;
23733
23734
  }
@@ -24219,7 +24220,7 @@ var addDocsTools = (server, allowedTools = [
24219
24220
  getToKnowWixEnabled ? WixREADME_DEPENDENT_DESCRIPTION : ""
24220
24221
  ].join("\n"),
24221
24222
  {
24222
- articleUrl: external_exports.string().describe(
24223
+ articleUrl: external_exports.string().url().describe(
24223
24224
  "The URL of the docs article or method article to fetch. Should be something like https://dev.wix.com/docs/.../.../..."
24224
24225
  )
24225
24226
  },
@@ -24256,7 +24257,7 @@ var addDocsTools = (server, allowedTools = [
24256
24257
  content: [
24257
24258
  {
24258
24259
  type: "text",
24259
- text: "Could not fetch article content, you should try completing the task without it."
24260
+ text: `Could not fetch article content: "${error.message}". You should try completing the task without it.`
24260
24261
  }
24261
24262
  ]
24262
24263
  };
@@ -24270,7 +24271,7 @@ var addDocsTools = (server, allowedTools = [
24270
24271
  "This will give you the entire request/response schema with all the fields and their descriptions."
24271
24272
  ].join("\n"),
24272
24273
  {
24273
- articleUrl: external_exports.string().describe(
24274
+ articleUrl: external_exports.string().url().describe(
24274
24275
  "The URL of the documentation to fetch. Should be something like https://dev.wix.com/docs/.../.../..."
24275
24276
  )
24276
24277
  },
@@ -24300,7 +24301,7 @@ var addDocsTools = (server, allowedTools = [
24300
24301
  content: [
24301
24302
  {
24302
24303
  type: "text",
24303
- text: "Could not fetch method schema, you should try completing the task without it."
24304
+ text: `Could not fetch method schema: "${error.message}". You should try completing the task without it.`
24304
24305
  }
24305
24306
  ]
24306
24307
  };
@@ -24347,164 +24348,227 @@ var handleWixAPIResponse = async (response) => {
24347
24348
  return responseData;
24348
24349
  };
24349
24350
 
24351
+ // src/api-call/validation.ts
24352
+ function isApiUrlAllowed(url) {
24353
+ let parsedUrl;
24354
+ try {
24355
+ parsedUrl = new URL(url);
24356
+ } catch {
24357
+ return {
24358
+ isAllowed: false,
24359
+ error: `Invalid URL format: ${url}`
24360
+ };
24361
+ }
24362
+ const ALLOWED_HOSTNAMES = [
24363
+ "wix.com",
24364
+ "dev.wix.com",
24365
+ "manage.wix.com",
24366
+ "editor.wix.com",
24367
+ "wixapis.com"
24368
+ ];
24369
+ const hostname = parsedUrl.hostname.replace("www.", "");
24370
+ const isAllowedHostname = ALLOWED_HOSTNAMES.some(
24371
+ (domain) => hostname === domain
24372
+ );
24373
+ if (!isAllowedHostname) {
24374
+ return {
24375
+ isAllowed: false,
24376
+ error: `Unsupported URL domain: ${hostname}. URL must be from one of the allowed domains: ${ALLOWED_HOSTNAMES.join(", ")}`
24377
+ };
24378
+ }
24379
+ return {
24380
+ isAllowed: true
24381
+ };
24382
+ }
24383
+
24350
24384
  // src/api-call/index.ts
24351
- function addApiCallTool(server, strategy) {
24352
- server.tool(
24353
- "CallWixSiteAPI",
24354
- [
24355
- "Call Wix apis on a business or site. Use this to create, read, update, and delete data and other Wix entities in your Wix site,",
24356
- `You should ALWAYS check the rest docs - "SearchWixRESTDocumentation" for the specific API you want to call, don't just call it without knowing what it does, CHECK THE DOCS`,
24357
- "Error Handling:",
24358
- 'If the error is related to missing installed app or "WDE0110: Wix Code not enabled", you should install the missing app by using ReadFullDocsArticle tool to fetch the article - https://dev.wix.com/docs/kb-only/MCP_REST_RECIPES_KB_ID/TRAIN_wix.devcenter.apps.installer.v1.AppsInstallerService.InstallApp',
24359
- "**Note:** there is no need to check if an app is installed/ Wix Code enabled in advance, just call the API and handle the error if it occurs, the API error message will state it clearly.",
24360
- "For any other error, use your default error handling mechanism"
24361
- ].join("\n"),
24362
- {
24363
- siteId: external_exports.string().describe("The id of the site selected using site selection tool"),
24364
- url: external_exports.string().describe(
24365
- "The url of the api to call - ALWAYS get the information from the Wix REST docs or from the conversation context, the URL MUST BE ABSOLUTE URL"
24366
- ),
24367
- method: external_exports.string().describe(
24368
- "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)"
24369
- ),
24370
- body: external_exports.string().optional().describe(
24371
- "A string representing of a valid JSON object to describe the body of the request"
24372
- )
24373
- },
24374
- async ({ url, body, method, siteId }, { httpClient }) => {
24375
- logger2.log(
24376
- `Calling Wix Site API: ${siteId} ${url}, body: ${JSON.stringify(body)}`
24377
- );
24378
- try {
24379
- const response = await httpClient.request({
24380
- url,
24381
- method,
24382
- headers: {
24383
- ...await strategy.getSiteAuthHeaders(siteId),
24384
- ...body ? { "Content-Type": "application/json" } : {}
24385
- },
24386
- data: method === "GET" ? void 0 : body
24387
- });
24388
- const responseData = await handleWixAPIResponse(response);
24389
- return {
24390
- content: [
24391
- {
24392
- type: "text",
24393
- text: `Wix Site API call successful: ${JSON.stringify(responseData)}`
24394
- }
24395
- ]
24396
- };
24397
- } catch (error) {
24398
- logger2.error(`Failed to call Wix Site API: ${error}`);
24399
- const response = error.response;
24400
- if (!response) {
24401
- throw new Error(`Failed to call Wix Site API: ${error}`);
24385
+ function addApiCallTool(server, strategy, allowedTools = ["CallWixSiteAPI", "ListWixSites", "ManageWixSite"]) {
24386
+ if (allowedTools.includes("CallWixSiteAPI")) {
24387
+ server.tool(
24388
+ "CallWixSiteAPI",
24389
+ [
24390
+ "Call Wix apis on a business or site. Use this to create, read, update, and delete data and other Wix entities in your Wix site,",
24391
+ `You should ALWAYS check the rest docs - "SearchWixRESTDocumentation" for the specific API you want to call, don't just call it without knowing what it does, CHECK THE DOCS`,
24392
+ "Error Handling:",
24393
+ 'If the error is related to missing installed app or "WDE0110: Wix Code not enabled", you should install the missing app by using ReadFullDocsArticle tool to fetch the article - https://dev.wix.com/docs/kb-only/MCP_REST_RECIPES_KB_ID/TRAIN_wix.devcenter.apps.installer.v1.AppsInstallerService.InstallApp',
24394
+ "**Note:** there is no need to check if an app is installed/ Wix Code enabled in advance, just call the API and handle the error if it occurs, the API error message will state it clearly.",
24395
+ "For any other error, use your default error handling mechanism"
24396
+ ].join("\n"),
24397
+ {
24398
+ siteId: external_exports.string().describe("The id of the site selected using site selection tool"),
24399
+ url: external_exports.string().url().describe(
24400
+ "The url of the api to call - ALWAYS get the information from the Wix REST docs or from the conversation context, the URL MUST BE ABSOLUTE URL"
24401
+ ),
24402
+ method: external_exports.string().describe(
24403
+ "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)"
24404
+ ),
24405
+ body: external_exports.string().optional().describe(
24406
+ "A string representing of a valid JSON object to describe the body of the request"
24407
+ )
24408
+ },
24409
+ async ({ url, body, method, siteId }, { httpClient }) => {
24410
+ logger2.log(
24411
+ `Calling Wix Site API: ${siteId} ${url}, body: ${JSON.stringify(body)}`
24412
+ );
24413
+ const { isAllowed, error: urlError } = isApiUrlAllowed(url);
24414
+ if (!isAllowed) {
24415
+ return {
24416
+ content: [
24417
+ {
24418
+ isError: true,
24419
+ type: "text",
24420
+ text: `Error validating URL: ${urlError}`
24421
+ }
24422
+ ]
24423
+ };
24402
24424
  }
24403
- return handleWixAPIResponse(response);
24404
- }
24405
- }
24406
- );
24407
- server.tool(
24408
- "ListWixSites",
24409
- "List Wix sites for the current user, by default it will return all sites, but you can filter by name",
24410
- {
24411
- nameSearch: external_exports.string().optional().describe(
24412
- "optional filer by name, if not provided all sites will be returned"
24413
- ),
24414
- // Hack for Cursor ignoring tools with no params (when nameSearch is optional)
24415
- alwaysTrue: external_exports.boolean().describe("Always pass true to this parameter")
24416
- },
24417
- async ({ nameSearch }, { httpClient }) => {
24418
- const sitesRes = await httpClient.post(
24419
- "https://www.wixapis.com/site-list/v2/sites/query",
24420
- {
24421
- query: {
24422
- cursorPaging: { limit: 21 },
24423
- filter: {
24424
- ...nameSearch ? {
24425
- name: nameSearch
24426
- } : {},
24427
- namespace: {
24428
- $in: ["WIX", "DASHBOARD_FIRST", "ANYWHERE", "HEADLESS"]
24425
+ try {
24426
+ const response = await httpClient.request({
24427
+ url,
24428
+ method,
24429
+ headers: {
24430
+ ...await strategy.getSiteAuthHeaders(siteId),
24431
+ ...body ? { "Content-Type": "application/json" } : {}
24432
+ },
24433
+ data: method === "GET" ? void 0 : body
24434
+ });
24435
+ const responseData = await handleWixAPIResponse(response);
24436
+ return {
24437
+ content: [
24438
+ {
24439
+ type: "text",
24440
+ text: `Wix Site API call successful: ${JSON.stringify(responseData)}`
24429
24441
  }
24430
- }
24431
- }
24432
- },
24433
- {
24434
- headers: {
24435
- ...await strategy.getAccountAuthHeaders(),
24436
- "Content-Type": "application/json",
24437
- Accept: "application/json, text/plain, */*"
24442
+ ]
24443
+ };
24444
+ } catch (error) {
24445
+ logger2.error(`Failed to call Wix Site API: ${error}`);
24446
+ const response = error.response;
24447
+ if (!response) {
24448
+ throw new Error(`Failed to call Wix Site API: ${error}`);
24438
24449
  }
24450
+ return handleWixAPIResponse(response);
24439
24451
  }
24440
- );
24441
- const result = sitesRes.data.sites?.map(({ id, displayName }) => ({
24442
- id,
24443
- name: displayName
24444
- })) ?? [];
24445
- return {
24446
- content: [
24452
+ }
24453
+ );
24454
+ }
24455
+ if (allowedTools.includes("ListWixSites")) {
24456
+ server.tool(
24457
+ "ListWixSites",
24458
+ "List Wix sites for the current user, by default it will return all sites, but you can filter by name",
24459
+ {
24460
+ nameSearch: external_exports.string().optional().describe(
24461
+ "optional filer by name, if not provided all sites will be returned"
24462
+ ),
24463
+ // Hack for Cursor ignoring tools with no params (when nameSearch is optional)
24464
+ alwaysTrue: external_exports.boolean().describe("Always pass true to this parameter")
24465
+ },
24466
+ async ({ nameSearch }, { httpClient }) => {
24467
+ const sitesRes = await httpClient.post(
24468
+ "https://www.wixapis.com/site-list/v2/sites/query",
24447
24469
  {
24448
- type: "text",
24449
- text: JSON.stringify(result)
24470
+ query: {
24471
+ cursorPaging: { limit: 21 },
24472
+ filter: {
24473
+ ...nameSearch ? {
24474
+ name: nameSearch
24475
+ } : {},
24476
+ namespace: {
24477
+ $in: ["WIX", "DASHBOARD_FIRST", "ANYWHERE", "HEADLESS"]
24478
+ }
24479
+ }
24480
+ }
24450
24481
  },
24451
24482
  {
24452
- type: "text",
24453
- text: "if there is more than one site returned, the user should pick one from a list, list the sites (only name) for the user and ask them to pick one,If more than 20 are found you should list all 20 and suggest to search by the name of the site they are looking for"
24483
+ headers: {
24484
+ ...await strategy.getAccountAuthHeaders(),
24485
+ "Content-Type": "application/json",
24486
+ Accept: "application/json, text/plain, */*"
24487
+ }
24454
24488
  }
24455
- ]
24456
- };
24457
- }
24458
- );
24459
- server.tool(
24460
- "ManageWixSite",
24461
- `Use account level API in order to create a site, update a site and publish site.
24462
- ALWAYS use "SearchWixRESTDocumentation" to search for the API you should invoke, NEVER GUESS THE SITE API URL
24463
- You should ALWAYS check the rest docs - "SearchWixRESTDocumentation" for the specific API you want to call, don't just call it without knowing what it does, CHECK THE DOCS`,
24464
- {
24465
- url: external_exports.string().describe(
24466
- "The url of the api to call - ALWAYS get the information from the Wix REST docs DONT GUESS IT, the URL MUST BE ABSOLUTE URL"
24467
- ),
24468
- method: external_exports.string().describe(
24469
- "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)"
24470
- ),
24471
- body: external_exports.string().optional().describe(
24472
- "A string representing of a valid JSON object to describe the body of the request"
24473
- )
24474
- },
24475
- async ({ url, body, method }, { httpClient }) => {
24476
- logger2.log(
24477
- `Calling Wix Account level API: ${url}, body: ${JSON.stringify(body)}`
24478
- );
24479
- try {
24480
- const response = await httpClient.request({
24481
- url,
24482
- method,
24483
- headers: {
24484
- ...await strategy.getAccountAuthHeaders(),
24485
- ...body ? { "Content-Type": "application/json" } : {}
24486
- },
24487
- data: method === "GET" ? void 0 : body
24488
- });
24489
- const responseData = await handleWixAPIResponse(response);
24489
+ );
24490
+ const result = sitesRes.data.sites?.map(({ id, displayName }) => ({
24491
+ id,
24492
+ name: displayName
24493
+ })) ?? [];
24490
24494
  return {
24491
24495
  content: [
24492
24496
  {
24493
24497
  type: "text",
24494
- text: `Wix Account API call successful: ${JSON.stringify(responseData)}`
24498
+ text: JSON.stringify(result)
24499
+ },
24500
+ {
24501
+ type: "text",
24502
+ text: "if there is more than one site returned, the user should pick one from a list, list the sites (only name) for the user and ask them to pick one,If more than 20 are found you should list all 20 and suggest to search by the name of the site they are looking for"
24495
24503
  }
24496
24504
  ]
24497
24505
  };
24498
- } catch (error) {
24499
- logger2.error(`Failed to call Wix Account API: ${error}`);
24500
- const response = error.response;
24501
- if (!response) {
24502
- throw new Error(`Failed to call Wix Account API: ${error}`);
24506
+ }
24507
+ );
24508
+ }
24509
+ if (allowedTools.includes("ManageWixSite")) {
24510
+ server.tool(
24511
+ "ManageWixSite",
24512
+ `Use account level API in order to create a site, update a site and publish site.
24513
+ ALWAYS use "SearchWixRESTDocumentation" to search for the API you should invoke, NEVER GUESS THE SITE API URL
24514
+ You should ALWAYS check the rest docs - "SearchWixRESTDocumentation" for the specific API you want to call, don't just call it without knowing what it does, CHECK THE DOCS`,
24515
+ {
24516
+ url: external_exports.string().url().describe(
24517
+ "The url of the api to call - ALWAYS get the information from the Wix REST docs DONT GUESS IT, the URL MUST BE ABSOLUTE URL"
24518
+ ),
24519
+ method: external_exports.string().describe(
24520
+ "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)"
24521
+ ),
24522
+ body: external_exports.string().optional().describe(
24523
+ "A string representing of a valid JSON object to describe the body of the request"
24524
+ )
24525
+ },
24526
+ async ({ url, body, method }, { httpClient }) => {
24527
+ logger2.log(
24528
+ `Calling Wix Account level API: ${url}, body: ${JSON.stringify(body)}`
24529
+ );
24530
+ const { isAllowed, error: urlError } = isApiUrlAllowed(url);
24531
+ if (!isAllowed) {
24532
+ return {
24533
+ content: [
24534
+ {
24535
+ isError: true,
24536
+ type: "text",
24537
+ text: `Error validating URL: ${urlError}`
24538
+ }
24539
+ ]
24540
+ };
24541
+ }
24542
+ try {
24543
+ const response = await httpClient.request({
24544
+ url,
24545
+ method,
24546
+ headers: {
24547
+ ...await strategy.getAccountAuthHeaders(),
24548
+ ...body ? { "Content-Type": "application/json" } : {}
24549
+ },
24550
+ data: method === "GET" ? void 0 : body
24551
+ });
24552
+ const responseData = await handleWixAPIResponse(response);
24553
+ return {
24554
+ content: [
24555
+ {
24556
+ type: "text",
24557
+ text: `Wix Account API call successful: ${JSON.stringify(responseData)}`
24558
+ }
24559
+ ]
24560
+ };
24561
+ } catch (error) {
24562
+ logger2.error(`Failed to call Wix Account API: ${error}`);
24563
+ const response = error.response;
24564
+ if (!response) {
24565
+ throw new Error(`Failed to call Wix Account API: ${error}`);
24566
+ }
24567
+ return handleWixAPIResponse(response);
24503
24568
  }
24504
- return handleWixAPIResponse(response);
24505
24569
  }
24506
- }
24507
- );
24570
+ );
24571
+ }
24508
24572
  }
24509
24573
 
24510
24574
  // src/resources/docs.ts