@elementor/editor-canvas 4.1.0-801 → 4.1.0-803

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -45,12 +45,81 @@ var initBreakpointsResource = (reg) => {
45
45
  };
46
46
 
47
47
  // src/mcp/resources/widgets-schema-resource.ts
48
- import { getWidgetsCache } from "@elementor/editor-elements";
48
+ import { getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
49
49
  import { ResourceTemplate } from "@elementor/editor-mcp";
50
50
  import {
51
51
  Schema
52
52
  } from "@elementor/editor-props";
53
53
  import { getStylesSchema } from "@elementor/editor-styles";
54
+
55
+ // src/mcp/utils/element-data-util.ts
56
+ import { getWidgetsCache } from "@elementor/editor-elements";
57
+ function hasV3Controls(controls) {
58
+ return typeof controls === "object" && controls !== null && Object.keys(controls).length > 0;
59
+ }
60
+ function isWidgetAvailableForLLM(config) {
61
+ if (!config) {
62
+ return false;
63
+ }
64
+ if (config.meta?.llm_support === false) {
65
+ return false;
66
+ }
67
+ if (config.atomic_props_schema) {
68
+ return true;
69
+ }
70
+ return hasV3Controls(config.controls);
71
+ }
72
+ function getWidgetVersion(config) {
73
+ return config?.atomic_props_schema ? "v4" : "v3";
74
+ }
75
+ function getAvailableWidgets() {
76
+ const cache = getWidgetsCache() ?? {};
77
+ return Object.keys(cache).filter((widgetType) => isWidgetAvailableForLLM(cache[widgetType])).sort().map((widgetType) => {
78
+ const config = cache[widgetType];
79
+ const description = typeof config?.meta?.description === "string" ? config.meta.description : void 0;
80
+ return {
81
+ type: widgetType,
82
+ version: getWidgetVersion(config),
83
+ ...description && { description }
84
+ };
85
+ });
86
+ }
87
+
88
+ // src/mcp/resources/widgets-schema-resource.ts
89
+ var V3_LAYOUT_CONTROL_TYPES = /* @__PURE__ */ new Set(["section", "tab", "tabs"]);
90
+ function extractV3ControlsMetadata(controls) {
91
+ if (!hasV3Controls(controls)) {
92
+ return {};
93
+ }
94
+ const result = {};
95
+ for (const [controlKey, raw] of Object.entries(controls)) {
96
+ if (!raw || typeof raw !== "object") {
97
+ continue;
98
+ }
99
+ const control = raw;
100
+ const controlType = typeof control.type === "string" ? control.type : void 0;
101
+ if (controlType && V3_LAYOUT_CONTROL_TYPES.has(controlType)) {
102
+ continue;
103
+ }
104
+ const entry = {};
105
+ if (Object.prototype.hasOwnProperty.call(control, "default")) {
106
+ entry.default = control.default;
107
+ }
108
+ if (controlType) {
109
+ entry.type = controlType;
110
+ }
111
+ if (Object.prototype.hasOwnProperty.call(control, "options") && control.options !== void 0) {
112
+ const options = control.options;
113
+ if (options && typeof options === "object" && !Array.isArray(options)) {
114
+ entry.options = Object.keys(options);
115
+ } else {
116
+ entry.options = options;
117
+ }
118
+ }
119
+ result[controlKey] = entry;
120
+ }
121
+ return result;
122
+ }
54
123
  var WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
55
124
  var STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
56
125
  var BEST_PRACTICES_URI = "elementor://styles/best-practices";
@@ -98,7 +167,7 @@ Variables from the user context ARE NOT SUPPORTED AND WILL RESOLVE IN ERROR.
98
167
  }
99
168
  }),
100
169
  {
101
- description: "Common styles schema for the specified category"
170
+ description: "Common styles schema for the specified category (applicable for V4 elements only)"
102
171
  },
103
172
  async (uri, variables) => {
104
173
  const category = typeof variables.category === "string" ? variables.category : variables.category?.[0];
@@ -124,9 +193,9 @@ Variables from the user context ARE NOT SUPPORTED AND WILL RESOLVE IN ERROR.
124
193
  "widget-schema-by-type",
125
194
  new ResourceTemplate(WIDGET_SCHEMA_URI, {
126
195
  list: () => {
127
- const cache = getWidgetsCache() || {};
128
- const availableWidgets = Object.keys(cache || {}).filter(
129
- (widgetType) => cache[widgetType]?.atomic_props_schema && cache[widgetType].meta?.llm_support !== false
196
+ const cache = getWidgetsCache2() || {};
197
+ const availableWidgets = Object.keys(cache).filter(
198
+ (widgetType) => isWidgetAvailableForLLM(cache[widgetType])
130
199
  );
131
200
  return {
132
201
  resources: availableWidgets.map((widgetType) => ({
@@ -141,11 +210,31 @@ Variables from the user context ARE NOT SUPPORTED AND WILL RESOLVE IN ERROR.
141
210
  },
142
211
  async (uri, variables) => {
143
212
  const widgetType = typeof variables.widgetType === "string" ? variables.widgetType : variables.widgetType?.[0];
144
- const widgetData = getWidgetsCache()?.[widgetType];
145
- const propSchema = widgetData?.atomic_props_schema;
146
- if (!propSchema || !widgetData) {
213
+ const widgetData = getWidgetsCache2()?.[widgetType];
214
+ if (!widgetData) {
147
215
  throw new Error(`No prop schema found for element type: ${widgetType}`);
148
216
  }
217
+ const propSchema = widgetData.atomic_props_schema;
218
+ if (!propSchema) {
219
+ if (!hasV3Controls(widgetData.controls)) {
220
+ throw new Error(`No prop schema found for element type: ${widgetType}`);
221
+ }
222
+ const controlMetadata = extractV3ControlsMetadata(widgetData.controls);
223
+ return {
224
+ contents: [
225
+ {
226
+ uri: uri.toString(),
227
+ mimeType: "application/json",
228
+ text: JSON.stringify({
229
+ widget_version: "v3",
230
+ message: "This widget exists in the editor but has no atomic props schema (V4). Use control_metadata as non-authoritative hints from legacy controls.",
231
+ fields_note: "All settings are optional; there is no JSON schema for this widget type.",
232
+ properties: controlMetadata
233
+ })
234
+ }
235
+ ]
236
+ };
237
+ }
149
238
  const asJson = Object.fromEntries(
150
239
  Object.entries(propSchema).map(([key, propType]) => [
151
240
  key,
@@ -174,7 +263,7 @@ Variables from the user context ARE NOT SUPPORTED AND WILL RESOLVE IN ERROR.
174
263
  llmGuidance.default_styles = defaultStyles;
175
264
  }
176
265
  const allowedChildTypes = widgetData.allowed_child_types;
177
- const allWidgets = getWidgetsCache() || {};
266
+ const allWidgets = getWidgetsCache2() || {};
178
267
  const allowedParents = Object.entries(allWidgets).filter(([, parentConfig]) => parentConfig.allowed_child_types?.includes(widgetType)).map(([parentType]) => parentType);
179
268
  if (allowedChildTypes?.length || allowedParents.length) {
180
269
  llmGuidance.nesting = {
@@ -1876,7 +1965,7 @@ function initStyleTransformers() {
1876
1965
  }
1877
1966
 
1878
1967
  // src/legacy/init-legacy-views.ts
1879
- import { getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
1968
+ import { getWidgetsCache as getWidgetsCache3 } from "@elementor/editor-elements";
1880
1969
  import { __privateListenTo, v1ReadyEvent as v1ReadyEvent2 } from "@elementor/editor-v1-adapters";
1881
1970
 
1882
1971
  // src/renderers/create-dom-renderer.ts
@@ -3121,7 +3210,7 @@ function registerElementType(type, elementTypeGenerator) {
3121
3210
  }
3122
3211
  function initLegacyViews() {
3123
3212
  __privateListenTo(v1ReadyEvent2(), () => {
3124
- const widgetsCache = getWidgetsCache2() ?? {};
3213
+ const widgetsCache = getWidgetsCache3() ?? {};
3125
3214
  const legacyWindow = window;
3126
3215
  const renderer = createDomRenderer();
3127
3216
  registerProPromotionTypes(widgetsCache);
@@ -3207,7 +3296,67 @@ function initTabsModelExtensions() {
3207
3296
  registerModelExtensions("e-tab", tabModelExtensions);
3208
3297
  }
3209
3298
 
3299
+ // src/mcp/resources/available-widgets-resource.ts
3300
+ import { v1ReadyEvent as v1ReadyEvent3 } from "@elementor/editor-v1-adapters";
3301
+ var AVAILABLE_WIDGETS_URI = "elementor://context/available-widgets";
3302
+ var AVAILABLE_WIDGETS_URI_V4 = "elementor://context/available-widgets/v4";
3303
+ var initAvailableWidgetsResource = (reg) => {
3304
+ const { resource, sendResourceUpdated } = reg;
3305
+ const buildContents = (uri, filterFunction = () => true) => {
3306
+ const widgets = getAvailableWidgets().filter(filterFunction);
3307
+ return {
3308
+ contents: [
3309
+ {
3310
+ uri,
3311
+ mimeType: "application/json",
3312
+ text: JSON.stringify(widgets, null, 2)
3313
+ }
3314
+ ]
3315
+ };
3316
+ };
3317
+ const notifyResourcesUpdated = () => {
3318
+ sendResourceUpdated({
3319
+ uri: AVAILABLE_WIDGETS_URI,
3320
+ ...buildContents(AVAILABLE_WIDGETS_URI)
3321
+ });
3322
+ sendResourceUpdated({
3323
+ uri: AVAILABLE_WIDGETS_URI_V4,
3324
+ ...buildContents(AVAILABLE_WIDGETS_URI_V4, (w) => w.version === "v4")
3325
+ });
3326
+ };
3327
+ resource(
3328
+ "available-widgets-v4",
3329
+ AVAILABLE_WIDGETS_URI_V4,
3330
+ {
3331
+ description: "All registered v4 version widgets"
3332
+ },
3333
+ async () => buildContents(AVAILABLE_WIDGETS_URI_V4, (w) => w.version === "v4")
3334
+ );
3335
+ resource(
3336
+ "available-widgets",
3337
+ AVAILABLE_WIDGETS_URI,
3338
+ {
3339
+ description: "All registered widget types with v3/v4 version metadata and description."
3340
+ },
3341
+ async () => buildContents(AVAILABLE_WIDGETS_URI)
3342
+ );
3343
+ const eventName = v1ReadyEvent3().name;
3344
+ const onV1Ready = () => {
3345
+ const widgets = getAvailableWidgets();
3346
+ if (widgets.length === 0) {
3347
+ return;
3348
+ }
3349
+ window.removeEventListener(eventName, onV1Ready);
3350
+ notifyResourcesUpdated();
3351
+ };
3352
+ window.addEventListener(eventName, onV1Ready);
3353
+ onV1Ready();
3354
+ };
3355
+
3210
3356
  // src/mcp/resources/document-structure-resource.ts
3357
+ import {
3358
+ getWidgetsCache as getWidgetsCache4
3359
+ } from "@elementor/editor-elements";
3211
3360
  import { __privateListenTo as listenTo, commandEndEvent as commandEndEvent4 } from "@elementor/editor-v1-adapters";
3212
3361
  var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
3213
3362
  var initDocumentStructureResource = (reg) => {
@@ -3228,7 +3377,8 @@ var initDocumentStructureResource = (reg) => {
3228
3377
  commandEndEvent4("document/elements/move"),
3229
3378
  commandEndEvent4("document/elements/copy"),
3230
3379
  commandEndEvent4("document/elements/paste"),
3231
- commandEndEvent4("editor/documents/attach-preview")
3380
+ commandEndEvent4("editor/documents/attach-preview"),
3381
+ commandEndEvent4("editor/documents/switch")
3232
3382
  ],
3233
3383
  updateDocumentStructure
3234
3384
  );
@@ -3258,9 +3408,7 @@ function getDocumentStructure() {
3258
3408
  return { error: "No active document found" };
3259
3409
  }
3260
3410
  const containers = document2.container?.children || [];
3261
- const elements = containers.map(
3262
- (container) => extractElementData(container)
3263
- );
3411
+ const elements = containers.map((container) => extractElementData(container));
3264
3412
  return {
3265
3413
  documentId: document2.id,
3266
3414
  documentType: document2.config.type,
@@ -3268,6 +3416,16 @@ function getDocumentStructure() {
3268
3416
  elements: elements.filter((el) => el !== null)
3269
3417
  };
3270
3418
  }
3419
+ function resolveElementVersion(element) {
3420
+ if (element.model?.config?.atomic) {
3421
+ return "v4";
3422
+ }
3423
+ const widgetType = element.model?.attributes?.widgetType;
3424
+ if (widgetType && getWidgetsCache4()?.[widgetType]?.atomic_props_schema) {
3425
+ return "v4";
3426
+ }
3427
+ return "v3";
3428
+ }
3271
3429
  function extractElementData(element) {
3272
3430
  if (!element || !element.model) {
3273
3431
  return null;
@@ -3276,7 +3434,8 @@ function extractElementData(element) {
3276
3434
  const result = {
3277
3435
  id: model.id,
3278
3436
  elType: model.elType,
3279
- widgetType: model.widgetType || void 0
3437
+ widgetType: model.widgetType || void 0,
3438
+ version: resolveElementVersion(element)
3280
3439
  };
3281
3440
  const title = model.title || element.model?.editor_settings?.title;
3282
3441
  if (title) {
@@ -3288,28 +3447,346 @@ function extractElementData(element) {
3288
3447
  return result;
3289
3448
  }
3290
3449
 
3450
+ // src/mcp/resources/editor-state-resource.ts
3451
+ import { __privateListenTo as listenTo2, commandEndEvent as commandEndEvent5 } from "@elementor/editor-v1-adapters";
3452
+ var CURRENTLY_VIEWED_SCREEN = "The user is currently viewing the Elementor editor";
3453
+ var PAGE_CONTENT_CHARACTER_LIMIT = 500;
3454
+ var PREVIEW_TEXT_NODE_MIN_LENGTH = 2;
3455
+ var EDITOR_STATE_URI = "elementor://context/editor-state";
3456
+ var initEditorStateResource = (reg) => {
3457
+ const { resource, sendResourceUpdated } = reg;
3458
+ let lastSerializedState = "";
3459
+ const buildState = () => ({
3460
+ currentlyViewedScreen: CURRENTLY_VIEWED_SCREEN,
3461
+ pageContent: getPageContentFromPreview(),
3462
+ pageTitle: getPageTitle()
3463
+ });
3464
+ const notifyIfChanged = () => {
3465
+ const serialized = JSON.stringify(buildState());
3466
+ if (serialized === lastSerializedState) {
3467
+ return;
3468
+ }
3469
+ lastSerializedState = serialized;
3470
+ sendResourceUpdated({ uri: EDITOR_STATE_URI });
3471
+ };
3472
+ listenTo2(
3473
+ [commandEndEvent5("editor/documents/switch"), commandEndEvent5("editor/documents/attach-preview")],
3474
+ notifyIfChanged
3475
+ );
3476
+ lastSerializedState = JSON.stringify(buildState());
3477
+ resource(
3478
+ "editor-state",
3479
+ EDITOR_STATE_URI,
3480
+ {
3481
+ description: "Editor page title, preview text snapshot, and viewed screen label."
3482
+ },
3483
+ async () => {
3484
+ return {
3485
+ contents: [
3486
+ {
3487
+ uri: EDITOR_STATE_URI,
3488
+ text: JSON.stringify(buildState(), null, 2)
3489
+ }
3490
+ ]
3491
+ };
3492
+ }
3493
+ );
3494
+ };
3495
+ function getPageContentFromPreview() {
3496
+ try {
3497
+ const root = window.elementor?.$previewContents?.[0];
3498
+ if (!root) {
3499
+ return null;
3500
+ }
3501
+ const content = [];
3502
+ const clone = root.cloneNode(true);
3503
+ clone.querySelectorAll(".elementor-editor-element-settings, #elementor-add-new-section").forEach((el) => {
3504
+ el.remove();
3505
+ });
3506
+ const walk = (node, insideElementorElement = false) => {
3507
+ const isInside = node.classList?.contains("elementor-element") || insideElementorElement;
3508
+ if (node.nodeType === Node.TEXT_NODE && isInside) {
3509
+ const text2 = node.textContent?.trim().replace(/\s+/g, " ");
3510
+ if (text2 && text2.length > PREVIEW_TEXT_NODE_MIN_LENGTH) {
3511
+ content.push(text2);
3512
+ }
3513
+ } else {
3514
+ node.childNodes.forEach((child) => {
3515
+ walk(child, isInside);
3516
+ });
3517
+ }
3518
+ };
3519
+ walk(clone);
3520
+ const text = content.join(" ");
3521
+ if (text.length > PAGE_CONTENT_CHARACTER_LIMIT) {
3522
+ return text.slice(0, PAGE_CONTENT_CHARACTER_LIMIT) + "...";
3523
+ }
3524
+ return text;
3525
+ } catch {
3526
+ return null;
3527
+ }
3528
+ }
3529
+ function getPageTitle() {
3530
+ try {
3531
+ const extendedWindow = window;
3532
+ const currentDocument = extendedWindow.elementor?.documents?.getCurrent?.();
3533
+ const postTitle = currentDocument?.config?.settings?.post_title;
3534
+ if (postTitle) {
3535
+ return postTitle;
3536
+ }
3537
+ let title = document.title || "Page";
3538
+ title = title.split(/\s*[‹»|–—-]\s*/)[0];
3539
+ const trimmed = title.trim();
3540
+ return trimmed || "Page";
3541
+ } catch {
3542
+ return "Page";
3543
+ }
3544
+ }
3545
+
3546
+ // src/mcp/resources/general-context-resource.ts
3547
+ import { __privateListenTo as listenTo3, commandEndEvent as commandEndEvent6 } from "@elementor/editor-v1-adapters";
3548
+ var GENERAL_CONTEXT_URI = "elementor://context/general";
3549
+ var initGeneralContextResource = (reg) => {
3550
+ const { resource, sendResourceUpdated } = reg;
3551
+ let lastSerializedPayload = null;
3552
+ const getPageTitle2 = () => {
3553
+ const extendedWindow = window;
3554
+ const title = extendedWindow.elementor?.documents?.getCurrent?.()?.config?.settings?.post_title;
3555
+ if (!title?.trim()) {
3556
+ return null;
3557
+ }
3558
+ return title;
3559
+ };
3560
+ const buildPayload = () => {
3561
+ const extendedWindow = window;
3562
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
3563
+ const postParam = new URLSearchParams(location.search).get("post");
3564
+ const parsedPostId = postParam ? Number(postParam) : null;
3565
+ const postId = parsedPostId !== null && Number.isFinite(parsedPostId) ? parsedPostId : null;
3566
+ const pageTitle = getPageTitle2();
3567
+ const urlObject = new URL(window.location.href);
3568
+ const pageUrl = urlObject.pathname + urlObject.search;
3569
+ const pageName = pageTitle || "Elementor Editor";
3570
+ const plugins = extendedWindow.angieConfig?.plugins;
3571
+ return {
3572
+ timezone,
3573
+ postId,
3574
+ currentPage: {
3575
+ pageName,
3576
+ pageTitle,
3577
+ pageUrl
3578
+ },
3579
+ ...plugins && { plugins }
3580
+ };
3581
+ };
3582
+ const pushUpdateIfChanged = () => {
3583
+ const serialized = JSON.stringify(buildPayload());
3584
+ if (serialized === lastSerializedPayload) {
3585
+ return;
3586
+ }
3587
+ lastSerializedPayload = serialized;
3588
+ sendResourceUpdated({ uri: GENERAL_CONTEXT_URI });
3589
+ };
3590
+ resource(
3591
+ "general-context",
3592
+ GENERAL_CONTEXT_URI,
3593
+ {
3594
+ description: "General context: timezone, post id, and current page."
3595
+ },
3596
+ async () => {
3597
+ return {
3598
+ contents: [
3599
+ {
3600
+ uri: GENERAL_CONTEXT_URI,
3601
+ mimeType: "application/json",
3602
+ text: JSON.stringify(buildPayload(), null, 2)
3603
+ }
3604
+ ]
3605
+ };
3606
+ }
3607
+ );
3608
+ listenTo3(
3609
+ [
3610
+ commandEndEvent6("editor/documents/switch"),
3611
+ commandEndEvent6("editor/documents/attach-preview"),
3612
+ commandEndEvent6("document/elements/settings")
3613
+ ],
3614
+ pushUpdateIfChanged
3615
+ );
3616
+ pushUpdateIfChanged();
3617
+ };
3618
+
3619
+ // src/mcp/resources/selected-element-resource.ts
3620
+ import { getContainer as getContainer2, getSelectedElements, getWidgetsCache as getWidgetsCache5 } from "@elementor/editor-elements";
3621
+ import {
3622
+ __privateListenTo as listenTo4,
3623
+ commandEndEvent as commandEndEvent7
3624
+ } from "@elementor/editor-v1-adapters";
3625
+ var SELECTED_ELEMENT_URI = "elementor://context/selected-element";
3626
+ var initSelectedElementResource = (reg) => {
3627
+ const { resource, sendResourceUpdated } = reg;
3628
+ let currentPayloadText = null;
3629
+ const publishIfChanged = (payload) => {
3630
+ const nextText = JSON.stringify(payload);
3631
+ if (nextText !== currentPayloadText) {
3632
+ currentPayloadText = nextText;
3633
+ sendResourceUpdated({ uri: SELECTED_ELEMENT_URI });
3634
+ }
3635
+ };
3636
+ const onCommand = (e) => {
3637
+ if (e.type !== "command") {
3638
+ return;
3639
+ }
3640
+ const commandEvent = e;
3641
+ if (commandEvent.command === "document/elements/deselect-all") {
3642
+ publishIfChanged(createEmptySelectedElementPayload());
3643
+ return;
3644
+ }
3645
+ if (commandEvent.command !== "document/elements/select" && commandEvent.command !== "document/elements/settings") {
3646
+ return;
3647
+ }
3648
+ const { container } = commandEvent.args || {};
3649
+ if (container?.id) {
3650
+ publishIfChanged(buildPayloadFromContainer(container));
3651
+ return;
3652
+ }
3653
+ publishIfChanged(readSelectionFromEditor());
3654
+ };
3655
+ listenTo4(
3656
+ [
3657
+ commandEndEvent7("document/elements/select"),
3658
+ commandEndEvent7("document/elements/deselect-all"),
3659
+ commandEndEvent7("document/elements/settings")
3660
+ ],
3661
+ onCommand
3662
+ );
3663
+ publishIfChanged(readSelectionFromEditor());
3664
+ resource(
3665
+ "selected-element",
3666
+ SELECTED_ELEMENT_URI,
3667
+ {
3668
+ description: "Currently selected Elementor element context."
3669
+ },
3670
+ async () => {
3671
+ return {
3672
+ contents: [
3673
+ {
3674
+ uri: SELECTED_ELEMENT_URI,
3675
+ text: JSON.stringify(readSelectionFromEditor(), null, 2)
3676
+ }
3677
+ ]
3678
+ };
3679
+ }
3680
+ );
3681
+ };
3682
+ function createEmptySelectedElementPayload() {
3683
+ return {
3684
+ elementDisplayName: null,
3685
+ elementType: null,
3686
+ properties: null,
3687
+ selectedElementId: null,
3688
+ selectedParentId: null,
3689
+ version: null,
3690
+ widgetType: null
3691
+ };
3692
+ }
3693
+ function readSelectionFromEditor() {
3694
+ const elements = getSelectedElements();
3695
+ if (elements.length !== 1) {
3696
+ return createEmptySelectedElementPayload();
3697
+ }
3698
+ const container = getContainer2(elements[0].id);
3699
+ return buildPayloadFromContainer(container);
3700
+ }
3701
+ function buildPayloadFromContainer(container) {
3702
+ if (!container?.id) {
3703
+ return createEmptySelectedElementPayload();
3704
+ }
3705
+ const widgetType = container.model.get("widgetType") ?? null;
3706
+ const elementType = container.type ?? "widget";
3707
+ return {
3708
+ elementDisplayName: getElementDisplayName(container),
3709
+ elementType,
3710
+ properties: getElementProperties(container, widgetType),
3711
+ selectedElementId: container.id,
3712
+ selectedParentId: container.parent?.id ?? null,
3713
+ version: resolveElementVersion2(container, widgetType),
3714
+ widgetType
3715
+ };
3716
+ }
3717
+ function resolveElementVersion2(container, widgetType) {
3718
+ if (container.model?.config?.atomic) {
3719
+ return "v4";
3720
+ }
3721
+ if (widgetType && getWidgetsCache5()?.[widgetType]?.atomic_props_schema) {
3722
+ return "v4";
3723
+ }
3724
+ return "v3";
3725
+ }
3726
+ function getElementProperties(container, widgetType) {
3727
+ const settings = container.settings?.toJSON?.();
3728
+ if (!settings || typeof settings !== "object") {
3729
+ return null;
3730
+ }
3731
+ const widgetConfig = widgetType ? getWidgetsCache5()?.[widgetType] : null;
3732
+ const controls = widgetConfig?.controls;
3733
+ const filtered = {};
3734
+ for (const [key, value] of Object.entries(settings)) {
3735
+ if (value === void 0 || value === null || value === "") {
3736
+ continue;
3737
+ }
3738
+ const controlDefault = controls?.[key]?.default;
3739
+ if (controlDefault !== void 0 && JSON.stringify(value) === JSON.stringify(controlDefault)) {
3740
+ continue;
3741
+ }
3742
+ filtered[key] = value;
3743
+ }
3744
+ return Object.keys(filtered).length > 0 ? filtered : null;
3745
+ }
3746
+ function getElementDisplayName(container) {
3747
+ try {
3748
+ if (container.label) {
3749
+ return container.label;
3750
+ }
3751
+ const widgetType = container.model?.get?.("widgetType");
3752
+ if (widgetType) {
3753
+ const capitalizedType = widgetType.charAt(0).toUpperCase() + widgetType.slice(1);
3754
+ return capitalizedType.replace(/-/g, " ");
3755
+ }
3756
+ if (container.type === "container") {
3757
+ return "Container";
3758
+ }
3759
+ if (container.type === "section") {
3760
+ return "Section";
3761
+ }
3762
+ return `Element ${container.id}`;
3763
+ } catch {
3764
+ return `Element ${container.id}`;
3765
+ }
3766
+ }
3767
+
3291
3768
  // src/mcp/tools/build-composition/tool.ts
3292
3769
  import { getCurrentDocument } from "@elementor/editor-documents";
3293
3770
  import {
3294
3771
  createElement as createElement8,
3295
3772
  deleteElement,
3296
- getContainer as getContainer3,
3297
- getWidgetsCache as getWidgetsCache6
3773
+ getContainer as getContainer4,
3774
+ getWidgetsCache as getWidgetsCache9
3298
3775
  } from "@elementor/editor-elements";
3299
3776
 
3300
3777
  // src/composition-builder/composition-builder.ts
3301
3778
  import {
3302
3779
  createElement as createElement7,
3303
3780
  generateElementId,
3304
- getContainer as getContainer2,
3305
- getWidgetsCache as getWidgetsCache5
3781
+ getContainer as getContainer3,
3782
+ getWidgetsCache as getWidgetsCache8
3306
3783
  } from "@elementor/editor-elements";
3307
3784
 
3308
3785
  // src/mcp/utils/do-update-element-property.ts
3309
3786
  import {
3310
3787
  createElementStyle,
3311
3788
  getElementStyles,
3312
- getWidgetsCache as getWidgetsCache3,
3789
+ getWidgetsCache as getWidgetsCache6,
3313
3790
  updateElementSettings,
3314
3791
  updateElementStyle
3315
3792
  } from "@elementor/editor-elements";
@@ -3402,7 +3879,7 @@ var doUpdateElementProperty = (params) => {
3402
3879
  }
3403
3880
  return;
3404
3881
  }
3405
- const elementPropSchema = getWidgetsCache3()?.[elementType]?.atomic_props_schema;
3882
+ const elementPropSchema = getWidgetsCache6()?.[elementType]?.atomic_props_schema;
3406
3883
  if (!elementPropSchema) {
3407
3884
  throw new Error(`No prop schema found for element type: ${elementType}`);
3408
3885
  }
@@ -3426,7 +3903,7 @@ var doUpdateElementProperty = (params) => {
3426
3903
  };
3427
3904
 
3428
3905
  // src/mcp/utils/validate-input.ts
3429
- import { getWidgetsCache as getWidgetsCache4 } from "@elementor/editor-elements";
3906
+ import { getWidgetsCache as getWidgetsCache7 } from "@elementor/editor-elements";
3430
3907
  import { Schema as Schema3 } from "@elementor/editor-props";
3431
3908
  import { getStylesSchema as getStylesSchema4 } from "@elementor/editor-styles";
3432
3909
  var _widgetsSchema = null;
@@ -3434,7 +3911,7 @@ var validateInput = {
3434
3911
  get widgetsSchema() {
3435
3912
  if (!_widgetsSchema) {
3436
3913
  const schema2 = {};
3437
- const cache = getWidgetsCache4();
3914
+ const cache = getWidgetsCache7();
3438
3915
  if (!cache) {
3439
3916
  return {};
3440
3917
  }
@@ -3518,9 +3995,9 @@ var CompositionBuilder = class _CompositionBuilder {
3518
3995
  rootContainers = [];
3519
3996
  api = {
3520
3997
  createElement: createElement7,
3521
- getWidgetsCache: getWidgetsCache5,
3998
+ getWidgetsCache: getWidgetsCache8,
3522
3999
  generateElementId,
3523
- getContainer: getContainer2,
4000
+ getContainer: getContainer3,
3524
4001
  doUpdateElementProperty
3525
4002
  };
3526
4003
  xml;
@@ -3763,6 +4240,10 @@ var generatePrompt = () => {
3763
4240
  # RESOURCES (Read before use)
3764
4241
  - [elementor://global-classes] - Check FIRST for reusable classes
3765
4242
  - [elementor://global-variables] - ONLY use variables defined here
4243
+ - [${AVAILABLE_WIDGETS_URI}/v4]
4244
+
4245
+ # TOOL SUUPORT
4246
+ This tool support v4 elements only
3766
4247
 
3767
4248
  # WORKFLOW
3768
4249
  1. Check/create global classes via "create-global-class" tool
@@ -3944,24 +4425,26 @@ var initBuildCompositionsTool = (reg) => {
3944
4425
  { description: "Styles schema", uri: STYLE_SCHEMA_URI },
3945
4426
  { description: "Global Classes", uri: "elementor://global-classes" },
3946
4427
  { description: "Global Variables", uri: "elementor://global-variables" },
3947
- { description: "Styles best practices", uri: BEST_PRACTICES_URI }
4428
+ { description: "Styles best practices", uri: BEST_PRACTICES_URI },
4429
+ { description: "Available widgets for this tool", uri: AVAILABLE_WIDGETS_URI_V4 }
3948
4430
  ],
3949
4431
  outputSchema,
3950
4432
  modelPreferences: {
3951
4433
  hints: [{ name: "claude-sonnet-4-5" }]
3952
4434
  },
3953
4435
  handler: async (params) => {
4436
+ assertCompositionXmlUsesV4WidgetsOnly(params.xmlStructure);
3954
4437
  const { xmlStructure, elementConfig, stylesConfig, customCSS } = params;
3955
4438
  let generatedXML = "";
3956
4439
  const errors = [];
3957
4440
  const rootContainers = [];
3958
- const documentContainer = getContainer3("document");
4441
+ const documentContainer = getContainer4("document");
3959
4442
  const currentDocument = getCurrentDocument();
3960
4443
  const targetContainer = getCompositionTargetContainer(documentContainer, currentDocument?.type.value);
3961
4444
  try {
3962
4445
  const compositionBuilder = CompositionBuilder.fromXMLString(xmlStructure, {
3963
4446
  createElement: createElement8,
3964
- getWidgetsCache: getWidgetsCache6
4447
+ getWidgetsCache: getWidgetsCache9
3965
4448
  });
3966
4449
  compositionBuilder.setElementConfig(elementConfig);
3967
4450
  compositionBuilder.setStylesConfig(stylesConfig);
@@ -4038,6 +4521,31 @@ Remember: Global classes ensure design consistency and reusability. Don't skip a
4038
4521
  }
4039
4522
  });
4040
4523
  };
4524
+ function assertCompositionXmlUsesV4WidgetsOnly(xmlStructure) {
4525
+ const doc = new DOMParser().parseFromString(xmlStructure, "application/xml");
4526
+ if (doc.querySelector("parsererror")) {
4527
+ throw new Error("Failed to parse XML string: " + doc);
4528
+ }
4529
+ const widgetsCache = getWidgetsCache9() ?? {};
4530
+ for (const node of doc.querySelectorAll("*")) {
4531
+ const type = node.tagName;
4532
+ const widgetData = widgetsCache[type];
4533
+ if (!widgetData) {
4534
+ continue;
4535
+ }
4536
+ if (widgetData.elType !== "widget") {
4537
+ continue;
4538
+ }
4539
+ if (!widgetData.atomic_props_schema) {
4540
+ throw new Error(
4541
+ `This tool does not support V3 elements. Please use the elementor-v3-mcp tools instead for element type: ${type}`
4542
+ );
4543
+ }
4544
+ }
4545
+ }
4546
+
4547
+ // src/mcp/tools/configure-element/tool.ts
4548
+ import { getWidgetsCache as getWidgetsCache10 } from "@elementor/editor-elements";
4041
4549
 
4042
4550
  // src/mcp/tools/configure-element/prompt.ts
4043
4551
  var configureElementToolPrompt = `Configure an existing element on the page.
@@ -4177,6 +4685,17 @@ var initConfigureElementTool = (reg) => {
4177
4685
  speedPriority: 0.7
4178
4686
  },
4179
4687
  handler: ({ elementId, propertiesToChange, elementType, stylePropertiesToChange }) => {
4688
+ const widgetData = getWidgetsCache10()?.[elementType];
4689
+ if (!widgetData) {
4690
+ throw new Error(
4691
+ `Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
4692
+ );
4693
+ }
4694
+ if (!widgetData.atomic_props_schema) {
4695
+ throw new Error(
4696
+ `This tool does not support V3 elements. Please use the elementor-v3-mcp tools instead for element type: ${elementType}`
4697
+ );
4698
+ }
4180
4699
  const toUpdate = Object.entries(propertiesToChange);
4181
4700
  const { valid, errors } = validateInput.validatePropSchema(elementType, propertiesToChange);
4182
4701
  const { valid: stylesValid, errors: stylesErrors } = validateInput.validateStyles(
@@ -4258,7 +4777,7 @@ Check the styles schema at the resource [${STYLE_SCHEMA_URI.replace(
4258
4777
  }
4259
4778
 
4260
4779
  // src/mcp/tools/get-element-config/tool.ts
4261
- import { getContainer as getContainer4, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache7 } from "@elementor/editor-elements";
4780
+ import { getContainer as getContainer5, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache11 } from "@elementor/editor-elements";
4262
4781
  import { Schema as Schema4 } from "@elementor/editor-props";
4263
4782
  import { z as z3 } from "@elementor/schema";
4264
4783
  var schema = {
@@ -4297,12 +4816,24 @@ var initGetElementConfigTool = (reg) => {
4297
4816
  speedPriority: 0.9
4298
4817
  },
4299
4818
  handler: async ({ elementId }) => {
4300
- const element = getContainer4(elementId);
4819
+ const element = getContainer5(elementId);
4301
4820
  if (!element) {
4302
4821
  throw new Error(`Element with ID ${elementId} not found.`);
4303
4822
  }
4823
+ const elementType = element.model.get("widgetType") || element.model.get("elType") || "";
4824
+ const widgetData = getWidgetsCache11()?.[elementType];
4825
+ if (!widgetData) {
4826
+ throw new Error(
4827
+ `Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
4828
+ );
4829
+ }
4830
+ if (!widgetData.atomic_props_schema) {
4831
+ throw new Error(
4832
+ `This tool does not support V3 elements. Please use the elementor-v3-mcp tools instead for element type: ${elementType}`
4833
+ );
4834
+ }
4304
4835
  const elementRawSettings = element.settings;
4305
- const propSchema = getWidgetsCache7()?.[element.model.get("widgetType") || element.model.get("elType") || ""]?.atomic_props_schema;
4836
+ const propSchema = getWidgetsCache11()?.[elementType]?.atomic_props_schema;
4306
4837
  if (!elementRawSettings || !propSchema) {
4307
4838
  throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
4308
4839
  }
@@ -4354,7 +4885,11 @@ var initCanvasMcp = (reg) => {
4354
4885
  `
4355
4886
  );
4356
4887
  initWidgetsSchemaResource(reg);
4888
+ initAvailableWidgetsResource(reg);
4357
4889
  initDocumentStructureResource(reg);
4890
+ initSelectedElementResource(reg);
4891
+ initEditorStateResource(reg);
4892
+ initGeneralContextResource(reg);
4358
4893
  initBuildCompositionsTool(reg);
4359
4894
  initGetElementConfigTool(reg);
4360
4895
  initConfigureElementTool(reg);
@@ -4561,16 +5096,16 @@ function shouldBlock(sourceElements, targetElements) {
4561
5096
  }
4562
5097
 
4563
5098
  // src/style-commands/paste-style.ts
4564
- import { getContainer as getContainer5, getElementSetting, updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
5099
+ import { getContainer as getContainer6, getElementSetting, updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
4565
5100
  import { classesPropTypeUtil } from "@elementor/editor-props";
4566
5101
  import {
4567
- __privateListenTo as listenTo2,
5102
+ __privateListenTo as listenTo5,
4568
5103
  blockCommand as blockCommand4,
4569
5104
  commandStartEvent
4570
5105
  } from "@elementor/editor-v1-adapters";
4571
5106
 
4572
5107
  // src/utils/command-utils.ts
4573
- import { getElementLabel as getElementLabel2, getWidgetsCache as getWidgetsCache8 } from "@elementor/editor-elements";
5108
+ import { getElementLabel as getElementLabel2, getWidgetsCache as getWidgetsCache12 } from "@elementor/editor-elements";
4574
5109
  import { CLASSES_PROP_KEY } from "@elementor/editor-props";
4575
5110
  import { __ as __5 } from "@wordpress/i18n";
4576
5111
  function hasAtomicWidgets(args) {
@@ -4595,7 +5130,7 @@ function getClassesProp(container) {
4595
5130
  }
4596
5131
  function getContainerSchema(container) {
4597
5132
  const type = container?.model.get("widgetType") || container?.model.get("elType");
4598
- const widgetsCache = getWidgetsCache8();
5133
+ const widgetsCache = getWidgetsCache12();
4599
5134
  const elementType = widgetsCache?.[type];
4600
5135
  return elementType?.atomic_props_schema ?? null;
4601
5136
  }
@@ -4701,7 +5236,7 @@ function initPasteStyleCommand() {
4701
5236
  command: "document/elements/paste-style",
4702
5237
  condition: hasAtomicWidgets
4703
5238
  });
4704
- listenTo2(
5239
+ listenTo5(
4705
5240
  commandStartEvent("document/elements/paste-style"),
4706
5241
  (e) => pasteStyles(e.args, pasteElementStyleCommand)
4707
5242
  );
@@ -4714,7 +5249,7 @@ function pasteStyles(args, pasteLocalStyle) {
4714
5249
  }
4715
5250
  const clipboardElements = getClipboardElements(storageKey);
4716
5251
  const [clipboardElement] = clipboardElements ?? [];
4717
- const clipboardContainer = getContainer5(clipboardElement.id);
5252
+ const clipboardContainer = getContainer6(clipboardElement.id);
4718
5253
  if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
4719
5254
  return;
4720
5255
  }
@@ -4754,7 +5289,7 @@ function pasteClasses(containers, classes) {
4754
5289
 
4755
5290
  // src/style-commands/reset-style.ts
4756
5291
  import {
4757
- __privateListenTo as listenTo3,
5292
+ __privateListenTo as listenTo6,
4758
5293
  blockCommand as blockCommand5,
4759
5294
  commandStartEvent as commandStartEvent2
4760
5295
  } from "@elementor/editor-v1-adapters";
@@ -4812,7 +5347,7 @@ function initResetStyleCommand() {
4812
5347
  command: "document/elements/reset-style",
4813
5348
  condition: hasAtomicWidgets
4814
5349
  });
4815
- listenTo3(
5350
+ listenTo6(
4816
5351
  commandStartEvent2("document/elements/reset-style"),
4817
5352
  (e) => resetStyles(e.args, resetElementStyles)
4818
5353
  );