@wix/mcp 1.0.16 → 1.0.17

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 +12687 -12854
  2. package/build/bin-standalone.js.map +4 -4
  3. package/build/cjs/index.cjs +286 -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 +6 -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 +254 -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
  });
@@ -16762,19 +16756,6 @@ var errorUtil;
16762
16756
  })(errorUtil || (errorUtil = {}));
16763
16757
 
16764
16758
  // ../../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
16759
  var ParseInputLazyPath = class {
16779
16760
  constructor(parent, value, path2, key) {
16780
16761
  this._cachedPath = [];
@@ -19599,10 +19580,6 @@ function createZodEnum(values, params) {
19599
19580
  });
19600
19581
  }
19601
19582
  var ZodEnum = class _ZodEnum extends ZodType {
19602
- constructor() {
19603
- super(...arguments);
19604
- _ZodEnum_cache.set(this, void 0);
19605
- }
19606
19583
  _parse(input) {
19607
19584
  if (typeof input.data !== "string") {
19608
19585
  const ctx = this._getOrReturnCtx(input);
@@ -19614,10 +19591,10 @@ var ZodEnum = class _ZodEnum extends ZodType {
19614
19591
  });
19615
19592
  return INVALID;
19616
19593
  }
19617
- if (!__classPrivateFieldGet(this, _ZodEnum_cache, "f")) {
19618
- __classPrivateFieldSet(this, _ZodEnum_cache, new Set(this._def.values), "f");
19594
+ if (!this._cache) {
19595
+ this._cache = new Set(this._def.values);
19619
19596
  }
19620
- if (!__classPrivateFieldGet(this, _ZodEnum_cache, "f").has(input.data)) {
19597
+ if (!this._cache.has(input.data)) {
19621
19598
  const ctx = this._getOrReturnCtx(input);
19622
19599
  const expectedValues = this._def.values;
19623
19600
  addIssueToContext(ctx, {
@@ -19666,13 +19643,8 @@ var ZodEnum = class _ZodEnum extends ZodType {
19666
19643
  });
19667
19644
  }
19668
19645
  };
19669
- _ZodEnum_cache = /* @__PURE__ */ new WeakMap();
19670
19646
  ZodEnum.create = createZodEnum;
19671
19647
  var ZodNativeEnum = class extends ZodType {
19672
- constructor() {
19673
- super(...arguments);
19674
- _ZodNativeEnum_cache.set(this, void 0);
19675
- }
19676
19648
  _parse(input) {
19677
19649
  const nativeEnumValues = util.getValidEnumValues(this._def.values);
19678
19650
  const ctx = this._getOrReturnCtx(input);
@@ -19685,10 +19657,10 @@ var ZodNativeEnum = class extends ZodType {
19685
19657
  });
19686
19658
  return INVALID;
19687
19659
  }
19688
- if (!__classPrivateFieldGet(this, _ZodNativeEnum_cache, "f")) {
19689
- __classPrivateFieldSet(this, _ZodNativeEnum_cache, new Set(util.getValidEnumValues(this._def.values)), "f");
19660
+ if (!this._cache) {
19661
+ this._cache = new Set(util.getValidEnumValues(this._def.values));
19690
19662
  }
19691
- if (!__classPrivateFieldGet(this, _ZodNativeEnum_cache, "f").has(input.data)) {
19663
+ if (!this._cache.has(input.data)) {
19692
19664
  const expectedValues = util.objectValues(nativeEnumValues);
19693
19665
  addIssueToContext(ctx, {
19694
19666
  received: ctx.data,
@@ -19703,7 +19675,6 @@ var ZodNativeEnum = class extends ZodType {
19703
19675
  return this._def.values;
19704
19676
  }
19705
19677
  };
19706
- _ZodNativeEnum_cache = /* @__PURE__ */ new WeakMap();
19707
19678
  ZodNativeEnum.create = (values, params) => {
19708
19679
  return new ZodNativeEnum({
19709
19680
  values,
@@ -19844,7 +19815,7 @@ var ZodEffects = class extends ZodType {
19844
19815
  parent: ctx
19845
19816
  });
19846
19817
  if (!isValid(base))
19847
- return base;
19818
+ return INVALID;
19848
19819
  const result = effect.transform(base.value, checkCtx);
19849
19820
  if (result instanceof Promise) {
19850
19821
  throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
@@ -19853,7 +19824,7 @@ var ZodEffects = class extends ZodType {
19853
19824
  } else {
19854
19825
  return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => {
19855
19826
  if (!isValid(base))
19856
- return base;
19827
+ return INVALID;
19857
19828
  return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
19858
19829
  status: status.value,
19859
19830
  value: result
@@ -21266,7 +21237,7 @@ var Protocol = class {
21266
21237
  request(request, resultSchema, options) {
21267
21238
  const { relatedRequestId, resumptionToken, onresumptiontoken } = options !== null && options !== void 0 ? options : {};
21268
21239
  return new Promise((resolve, reject) => {
21269
- var _a, _b, _c, _d, _e;
21240
+ var _a, _b, _c, _d, _e, _f;
21270
21241
  if (!this._transport) {
21271
21242
  reject(new Error("Not connected"));
21272
21243
  return;
@@ -21285,7 +21256,10 @@ var Protocol = class {
21285
21256
  this._progressHandlers.set(messageId, options.onprogress);
21286
21257
  jsonrpcRequest.params = {
21287
21258
  ...request.params,
21288
- _meta: { progressToken: messageId }
21259
+ _meta: {
21260
+ ...((_c = request.params) === null || _c === void 0 ? void 0 : _c._meta) || {},
21261
+ progressToken: messageId
21262
+ }
21289
21263
  };
21290
21264
  }
21291
21265
  const cancel = (reason) => {
@@ -21318,13 +21292,13 @@ var Protocol = class {
21318
21292
  reject(error);
21319
21293
  }
21320
21294
  });
21321
- (_c = options === null || options === void 0 ? void 0 : options.signal) === null || _c === void 0 ? void 0 : _c.addEventListener("abort", () => {
21295
+ (_d = options === null || options === void 0 ? void 0 : options.signal) === null || _d === void 0 ? void 0 : _d.addEventListener("abort", () => {
21322
21296
  var _a2;
21323
21297
  cancel((_a2 = options === null || options === void 0 ? void 0 : options.signal) === null || _a2 === void 0 ? void 0 : _a2.reason);
21324
21298
  });
21325
- const timeout = (_d = options === null || options === void 0 ? void 0 : options.timeout) !== null && _d !== void 0 ? _d : DEFAULT_REQUEST_TIMEOUT_MSEC;
21299
+ const timeout = (_e = options === null || options === void 0 ? void 0 : options.timeout) !== null && _e !== void 0 ? _e : DEFAULT_REQUEST_TIMEOUT_MSEC;
21326
21300
  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);
21301
+ 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
21302
  this._transport.send(jsonrpcRequest, { relatedRequestId, resumptionToken, onresumptiontoken }).catch((error) => {
21329
21303
  this._cleanupTimeout(messageId);
21330
21304
  reject(error);
@@ -22981,6 +22955,9 @@ var McpServer = class {
22981
22955
  return;
22982
22956
  }
22983
22957
  this.server.assertCanSetRequestHandler(CompleteRequestSchema.shape.method.value);
22958
+ this.server.registerCapabilities({
22959
+ completions: {}
22960
+ });
22984
22961
  this.server.setRequestHandler(CompleteRequestSchema, async (request) => {
22985
22962
  switch (request.params.ref.type) {
22986
22963
  case "ref/prompt":
@@ -23053,8 +23030,9 @@ var McpServer = class {
23053
23030
  const result = await template.resourceTemplate.listCallback(extra);
23054
23031
  for (const resource of result.resources) {
23055
23032
  templateResources.push({
23056
- ...resource,
23057
- ...template.metadata
23033
+ ...template.metadata,
23034
+ // the defined resource metadata should override the template metadata if present
23035
+ ...resource
23058
23036
  });
23059
23037
  }
23060
23038
  }
@@ -23413,6 +23391,7 @@ var createPanoramaClient = (opts) => {
23413
23391
  },
23414
23392
  data: {
23415
23393
  environment: opts.environment,
23394
+ serverInfo: opts.serverInfo,
23416
23395
  runtime: {
23417
23396
  packageVersion: packageJson.version,
23418
23397
  versions: process.versions,
@@ -23473,12 +23452,9 @@ var logger2 = createNullLogger();
23473
23452
 
23474
23453
  // src/wix-mcp-server.ts
23475
23454
  var WixMcpServer = class extends McpServer {
23476
- biLogger;
23477
- nodeEnv;
23478
- sessionId;
23479
- getUserId;
23480
23455
  constructor(serverInfo, options, nodeEnv) {
23481
23456
  super(serverInfo, options);
23457
+ this.serverInfo = serverInfo;
23482
23458
  this.sessionId = v4_default();
23483
23459
  this.nodeEnv = getEnvironment(nodeEnv);
23484
23460
  this.biLogger = createBiLogger({
@@ -23486,9 +23462,17 @@ var WixMcpServer = class extends McpServer {
23486
23462
  });
23487
23463
  logger2.log(`WixMcpServer created with sessionId: ${this.sessionId}`);
23488
23464
  }
23465
+ biLogger;
23466
+ nodeEnv;
23467
+ sessionId;
23468
+ getUserId;
23469
+ getClientName;
23489
23470
  setUserIdGetter(getUserId) {
23490
23471
  this.getUserId = getUserId;
23491
23472
  }
23473
+ setClientNameGetter(getClientName) {
23474
+ this.getClientName = getClientName;
23475
+ }
23492
23476
  tool(...args) {
23493
23477
  const cbIndex = args.findIndex((arg) => typeof arg === "function");
23494
23478
  if (cbIndex !== -1) {
@@ -23503,7 +23487,8 @@ var WixMcpServer = class extends McpServer {
23503
23487
  environment: this.nodeEnv,
23504
23488
  sessionId: this.sessionId,
23505
23489
  componentId: toolName,
23506
- uuid: this.getUserId?.()
23490
+ uuid: this.getUserId?.(),
23491
+ serverInfo: this.serverInfo
23507
23492
  });
23508
23493
  const toolInvocationId = v4_default();
23509
23494
  const httpClient = new import_http_client.HttpClient({
@@ -23562,7 +23547,7 @@ var WixMcpServer = class extends McpServer {
23562
23547
  }
23563
23548
  this.biLogger.report(
23564
23549
  (0, import_v2.wixMcpRequestSrc39Evid1607)({
23565
- clientName,
23550
+ clientName: this.getClientName?.() || clientName,
23566
23551
  duration,
23567
23552
  errorBody,
23568
23553
  toolInvocationId,
@@ -23728,6 +23713,18 @@ async function fetchArticleContentFromDigor(httpClient, articleUrl, mode, stripH
23728
23713
  }
23729
23714
  async function fetchArticleContent(httpClient, articleUrl, mode, stripHeader = false) {
23730
23715
  if (mode === "raw") {
23716
+ let parsedUrl;
23717
+ try {
23718
+ parsedUrl = new URL(articleUrl);
23719
+ } catch {
23720
+ throw new Error(`Invalid URL format: ${articleUrl}`);
23721
+ }
23722
+ const hostname = parsedUrl.hostname.replace("www.", "");
23723
+ if (hostname !== "dev.wix.com") {
23724
+ throw new Error(
23725
+ `Unsupported URL domain: ${hostname}. Article URL must be from dev.wix.com`
23726
+ );
23727
+ }
23731
23728
  const { data: doc } = await httpClient.get(articleUrl);
23732
23729
  return doc;
23733
23730
  }
@@ -24219,7 +24216,7 @@ var addDocsTools = (server, allowedTools = [
24219
24216
  getToKnowWixEnabled ? WixREADME_DEPENDENT_DESCRIPTION : ""
24220
24217
  ].join("\n"),
24221
24218
  {
24222
- articleUrl: external_exports.string().describe(
24219
+ articleUrl: external_exports.string().url().startsWith("https://dev.wix.com/").describe(
24223
24220
  "The URL of the docs article or method article to fetch. Should be something like https://dev.wix.com/docs/.../.../..."
24224
24221
  )
24225
24222
  },
@@ -24256,7 +24253,7 @@ var addDocsTools = (server, allowedTools = [
24256
24253
  content: [
24257
24254
  {
24258
24255
  type: "text",
24259
- text: "Could not fetch article content, you should try completing the task without it."
24256
+ text: `Could not fetch article content: "${error.message}". You should try completing the task without it.`
24260
24257
  }
24261
24258
  ]
24262
24259
  };
@@ -24270,7 +24267,7 @@ var addDocsTools = (server, allowedTools = [
24270
24267
  "This will give you the entire request/response schema with all the fields and their descriptions."
24271
24268
  ].join("\n"),
24272
24269
  {
24273
- articleUrl: external_exports.string().describe(
24270
+ articleUrl: external_exports.string().url().startsWith("https://dev.wix.com/").describe(
24274
24271
  "The URL of the documentation to fetch. Should be something like https://dev.wix.com/docs/.../.../..."
24275
24272
  )
24276
24273
  },
@@ -24300,7 +24297,7 @@ var addDocsTools = (server, allowedTools = [
24300
24297
  content: [
24301
24298
  {
24302
24299
  type: "text",
24303
- text: "Could not fetch method schema, you should try completing the task without it."
24300
+ text: `Could not fetch method schema: "${error.message}". You should try completing the task without it.`
24304
24301
  }
24305
24302
  ]
24306
24303
  };
@@ -24347,164 +24344,227 @@ var handleWixAPIResponse = async (response) => {
24347
24344
  return responseData;
24348
24345
  };
24349
24346
 
24347
+ // src/api-call/validation.ts
24348
+ function isApiUrlAllowed(url) {
24349
+ let parsedUrl;
24350
+ try {
24351
+ parsedUrl = new URL(url);
24352
+ } catch {
24353
+ return {
24354
+ isAllowed: false,
24355
+ error: `Invalid URL format: ${url}`
24356
+ };
24357
+ }
24358
+ const ALLOWED_HOSTNAMES = [
24359
+ "wix.com",
24360
+ "dev.wix.com",
24361
+ "manage.wix.com",
24362
+ "editor.wix.com",
24363
+ "wixapis.com"
24364
+ ];
24365
+ const hostname = parsedUrl.hostname.replace("www.", "");
24366
+ const isAllowedHostname = ALLOWED_HOSTNAMES.some(
24367
+ (domain) => hostname === domain
24368
+ );
24369
+ if (!isAllowedHostname) {
24370
+ return {
24371
+ isAllowed: false,
24372
+ error: `Unsupported URL domain: ${hostname}. URL must be from one of the allowed domains: ${ALLOWED_HOSTNAMES.join(", ")}`
24373
+ };
24374
+ }
24375
+ return {
24376
+ isAllowed: true
24377
+ };
24378
+ }
24379
+
24350
24380
  // 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}`);
24381
+ function addApiCallTool(server, strategy, allowedTools = ["CallWixSiteAPI", "ListWixSites", "ManageWixSite"]) {
24382
+ if (allowedTools.includes("CallWixSiteAPI")) {
24383
+ server.tool(
24384
+ "CallWixSiteAPI",
24385
+ [
24386
+ "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,",
24387
+ `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`,
24388
+ "Error Handling:",
24389
+ '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',
24390
+ "**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.",
24391
+ "For any other error, use your default error handling mechanism"
24392
+ ].join("\n"),
24393
+ {
24394
+ siteId: external_exports.string().describe("The id of the site selected using site selection tool"),
24395
+ url: external_exports.string().url().describe(
24396
+ "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"
24397
+ ),
24398
+ method: external_exports.string().describe(
24399
+ "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)"
24400
+ ),
24401
+ body: external_exports.string().optional().describe(
24402
+ "A string representing of a valid JSON object to describe the body of the request"
24403
+ )
24404
+ },
24405
+ async ({ url, body, method, siteId }, { httpClient }) => {
24406
+ logger2.log(
24407
+ `Calling Wix Site API: ${siteId} ${url}, body: ${JSON.stringify(body)}`
24408
+ );
24409
+ const { isAllowed, error: urlError } = isApiUrlAllowed(url);
24410
+ if (!isAllowed) {
24411
+ return {
24412
+ content: [
24413
+ {
24414
+ isError: true,
24415
+ type: "text",
24416
+ text: `Error validating URL: ${urlError}`
24417
+ }
24418
+ ]
24419
+ };
24402
24420
  }
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"]
24421
+ try {
24422
+ const response = await httpClient.request({
24423
+ url,
24424
+ method,
24425
+ headers: {
24426
+ ...await strategy.getSiteAuthHeaders(siteId),
24427
+ ...body ? { "Content-Type": "application/json" } : {}
24428
+ },
24429
+ data: method === "GET" ? void 0 : body
24430
+ });
24431
+ const responseData = await handleWixAPIResponse(response);
24432
+ return {
24433
+ content: [
24434
+ {
24435
+ type: "text",
24436
+ text: `Wix Site API call successful: ${JSON.stringify(responseData)}`
24429
24437
  }
24430
- }
24431
- }
24432
- },
24433
- {
24434
- headers: {
24435
- ...await strategy.getAccountAuthHeaders(),
24436
- "Content-Type": "application/json",
24437
- Accept: "application/json, text/plain, */*"
24438
+ ]
24439
+ };
24440
+ } catch (error) {
24441
+ logger2.error(`Failed to call Wix Site API: ${error}`);
24442
+ const response = error.response;
24443
+ if (!response) {
24444
+ throw new Error(`Failed to call Wix Site API: ${error}`);
24438
24445
  }
24446
+ return handleWixAPIResponse(response);
24439
24447
  }
24440
- );
24441
- const result = sitesRes.data.sites?.map(({ id, displayName }) => ({
24442
- id,
24443
- name: displayName
24444
- })) ?? [];
24445
- return {
24446
- content: [
24448
+ }
24449
+ );
24450
+ }
24451
+ if (allowedTools.includes("ListWixSites")) {
24452
+ server.tool(
24453
+ "ListWixSites",
24454
+ "List Wix sites for the current user, by default it will return all sites, but you can filter by name",
24455
+ {
24456
+ nameSearch: external_exports.string().optional().describe(
24457
+ "optional filer by name, if not provided all sites will be returned"
24458
+ ),
24459
+ // Hack for Cursor ignoring tools with no params (when nameSearch is optional)
24460
+ alwaysTrue: external_exports.boolean().describe("Always pass true to this parameter")
24461
+ },
24462
+ async ({ nameSearch }, { httpClient }) => {
24463
+ const sitesRes = await httpClient.post(
24464
+ "https://www.wixapis.com/site-list/v2/sites/query",
24447
24465
  {
24448
- type: "text",
24449
- text: JSON.stringify(result)
24466
+ query: {
24467
+ cursorPaging: { limit: 21 },
24468
+ filter: {
24469
+ ...nameSearch ? {
24470
+ name: nameSearch
24471
+ } : {},
24472
+ namespace: {
24473
+ $in: ["WIX", "DASHBOARD_FIRST", "ANYWHERE", "HEADLESS"]
24474
+ }
24475
+ }
24476
+ }
24450
24477
  },
24451
24478
  {
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"
24479
+ headers: {
24480
+ ...await strategy.getAccountAuthHeaders(),
24481
+ "Content-Type": "application/json",
24482
+ Accept: "application/json, text/plain, */*"
24483
+ }
24454
24484
  }
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);
24485
+ );
24486
+ const result = sitesRes.data.sites?.map(({ id, displayName }) => ({
24487
+ id,
24488
+ name: displayName
24489
+ })) ?? [];
24490
24490
  return {
24491
24491
  content: [
24492
24492
  {
24493
24493
  type: "text",
24494
- text: `Wix Account API call successful: ${JSON.stringify(responseData)}`
24494
+ text: JSON.stringify(result)
24495
+ },
24496
+ {
24497
+ type: "text",
24498
+ 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
24499
  }
24496
24500
  ]
24497
24501
  };
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}`);
24502
+ }
24503
+ );
24504
+ }
24505
+ if (allowedTools.includes("ManageWixSite")) {
24506
+ server.tool(
24507
+ "ManageWixSite",
24508
+ `Use account level API in order to create a site, update a site and publish site.
24509
+ ALWAYS use "SearchWixRESTDocumentation" to search for the API you should invoke, NEVER GUESS THE SITE API URL
24510
+ 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`,
24511
+ {
24512
+ url: external_exports.string().url().describe(
24513
+ "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"
24514
+ ),
24515
+ method: external_exports.string().describe(
24516
+ "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)"
24517
+ ),
24518
+ body: external_exports.string().optional().describe(
24519
+ "A string representing of a valid JSON object to describe the body of the request"
24520
+ )
24521
+ },
24522
+ async ({ url, body, method }, { httpClient }) => {
24523
+ logger2.log(
24524
+ `Calling Wix Account level API: ${url}, body: ${JSON.stringify(body)}`
24525
+ );
24526
+ const { isAllowed, error: urlError } = isApiUrlAllowed(url);
24527
+ if (!isAllowed) {
24528
+ return {
24529
+ content: [
24530
+ {
24531
+ isError: true,
24532
+ type: "text",
24533
+ text: `Error validating URL: ${urlError}`
24534
+ }
24535
+ ]
24536
+ };
24537
+ }
24538
+ try {
24539
+ const response = await httpClient.request({
24540
+ url,
24541
+ method,
24542
+ headers: {
24543
+ ...await strategy.getAccountAuthHeaders(),
24544
+ ...body ? { "Content-Type": "application/json" } : {}
24545
+ },
24546
+ data: method === "GET" ? void 0 : body
24547
+ });
24548
+ const responseData = await handleWixAPIResponse(response);
24549
+ return {
24550
+ content: [
24551
+ {
24552
+ type: "text",
24553
+ text: `Wix Account API call successful: ${JSON.stringify(responseData)}`
24554
+ }
24555
+ ]
24556
+ };
24557
+ } catch (error) {
24558
+ logger2.error(`Failed to call Wix Account API: ${error}`);
24559
+ const response = error.response;
24560
+ if (!response) {
24561
+ throw new Error(`Failed to call Wix Account API: ${error}`);
24562
+ }
24563
+ return handleWixAPIResponse(response);
24503
24564
  }
24504
- return handleWixAPIResponse(response);
24505
24565
  }
24506
- }
24507
- );
24566
+ );
24567
+ }
24508
24568
  }
24509
24569
 
24510
24570
  // src/resources/docs.ts