@elementor/editor-canvas 3.33.0-271 → 3.33.0-272

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
@@ -1,6 +1,7 @@
1
1
  // src/init.tsx
2
2
  import { injectIntoLogic, injectIntoTop } from "@elementor/editor";
3
3
  import { init as initInteractionsRepository } from "@elementor/editor-interactions";
4
+ import { getMCPByDomain } from "@elementor/editor-mcp";
4
5
 
5
6
  // src/components/classes-rename.tsx
6
7
  import { useEffect } from "react";
@@ -1111,11 +1112,11 @@ function getVal2(val) {
1111
1112
  var transformOriginTransformer = createTransformer((value) => {
1112
1113
  const x = getVal2(value.x);
1113
1114
  const y = getVal2(value.y);
1114
- const z = getVal2(value.z);
1115
- if (x === DEFAULT_XY && y === DEFAULT_XY && z === DEFAULT_Z) {
1115
+ const z3 = getVal2(value.z);
1116
+ if (x === DEFAULT_XY && y === DEFAULT_XY && z3 === DEFAULT_Z) {
1116
1117
  return null;
1117
1118
  }
1118
- return `${x} ${y} ${z}`;
1119
+ return `${x} ${y} ${z3}`;
1119
1120
  });
1120
1121
 
1121
1122
  // src/transformers/styles/transform-rotate-transformer.ts
@@ -1457,6 +1458,740 @@ function initLegacyViews() {
1457
1458
  });
1458
1459
  }
1459
1460
 
1461
+ // src/mcp/resources/widgets-schema-resource.ts
1462
+ import { getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
1463
+ import { ResourceTemplate } from "@elementor/editor-mcp";
1464
+ import {
1465
+ Schema
1466
+ } from "@elementor/editor-props";
1467
+ import { getStylesSchema as getStylesSchema2 } from "@elementor/editor-styles";
1468
+ var WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
1469
+ var STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
1470
+ var initWidgetsSchemaResource = (reg) => {
1471
+ const { mcpServer } = reg;
1472
+ mcpServer.resource(
1473
+ "styles-schema",
1474
+ new ResourceTemplate(STYLE_SCHEMA_URI, {
1475
+ list: () => {
1476
+ const categories = [...Object.keys(getStylesSchema2()), "custom_css"];
1477
+ return {
1478
+ resources: categories.map((category) => ({
1479
+ uri: `elementor://styles/schema/${category}`,
1480
+ name: "Style schema for " + category
1481
+ }))
1482
+ };
1483
+ }
1484
+ }),
1485
+ {
1486
+ description: "Common styles schema for the specified category"
1487
+ },
1488
+ async (uri, variables) => {
1489
+ const category = typeof variables.category === "string" ? variables.category : variables.category?.[0];
1490
+ if (category === "custom_css") {
1491
+ return {
1492
+ contents: [
1493
+ {
1494
+ uri: uri.toString(),
1495
+ text: "Free style inline CSS string of properties and their values. Applicable for a single element, only the properties and values are accepted."
1496
+ }
1497
+ ]
1498
+ };
1499
+ }
1500
+ const stylesSchema = getStylesSchema2()[category];
1501
+ if (!stylesSchema) {
1502
+ throw new Error(`No styles schema found for category: ${category}`);
1503
+ }
1504
+ const cleanedupPropSchema = cleanupPropType(stylesSchema);
1505
+ const asJson = Schema.propTypeToJsonSchema(cleanedupPropSchema);
1506
+ return {
1507
+ contents: [
1508
+ {
1509
+ uri: uri.toString(),
1510
+ text: JSON.stringify(asJson)
1511
+ }
1512
+ ]
1513
+ };
1514
+ }
1515
+ );
1516
+ mcpServer.resource(
1517
+ "widget-schema-by-type",
1518
+ new ResourceTemplate(WIDGET_SCHEMA_URI, {
1519
+ list: () => {
1520
+ const cache = getWidgetsCache2() || {};
1521
+ const availableWidgets = Object.keys(cache || {}).filter(
1522
+ (widgetType) => cache[widgetType]?.atomic_props_schema
1523
+ );
1524
+ return {
1525
+ resources: availableWidgets.map((widgetType) => ({
1526
+ uri: `elementor://widgets/schema/${widgetType}`,
1527
+ name: "Widget schema for " + widgetType
1528
+ }))
1529
+ };
1530
+ }
1531
+ }),
1532
+ {
1533
+ description: "PropType schema for the specified widget type"
1534
+ },
1535
+ async (uri, variables) => {
1536
+ const widgetType = typeof variables.widgetType === "string" ? variables.widgetType : variables.widgetType?.[0];
1537
+ const propSchema = getWidgetsCache2()?.[widgetType]?.atomic_props_schema;
1538
+ if (!propSchema) {
1539
+ throw new Error(`No prop schema found for element type: ${widgetType}`);
1540
+ }
1541
+ const cleanedupPropSchema = cleanupPropSchema(propSchema);
1542
+ const asJson = Object.fromEntries(
1543
+ Object.entries(cleanedupPropSchema).map(([key, propType]) => [
1544
+ key,
1545
+ Schema.propTypeToJsonSchema(propType)
1546
+ ])
1547
+ );
1548
+ delete asJson.classes;
1549
+ delete asJson._cssid;
1550
+ delete asJson.attributes;
1551
+ return {
1552
+ contents: [
1553
+ {
1554
+ uri: uri.toString(),
1555
+ text: JSON.stringify(asJson)
1556
+ }
1557
+ ]
1558
+ };
1559
+ }
1560
+ );
1561
+ };
1562
+ function cleanupPropSchema(propSchema) {
1563
+ const result = {};
1564
+ Object.keys(propSchema).forEach((propName) => {
1565
+ result[propName] = cleanupPropType(propSchema[propName]);
1566
+ });
1567
+ return result;
1568
+ }
1569
+ function cleanupPropType(propType) {
1570
+ const result = {};
1571
+ Object.keys(propType).forEach((property) => {
1572
+ switch (property) {
1573
+ case "key":
1574
+ case "kind":
1575
+ result[property] = propType[property];
1576
+ break;
1577
+ case "meta":
1578
+ case "settings":
1579
+ {
1580
+ if (Object.keys(propType[property] || {}).length > 0) {
1581
+ result[property] = propType[property];
1582
+ }
1583
+ }
1584
+ break;
1585
+ }
1586
+ });
1587
+ if (result.kind === "plain") {
1588
+ Object.defineProperty(result, "kind", { value: "string" });
1589
+ } else if (result.kind === "array") {
1590
+ result.item_prop_type = cleanupPropType(propType.item_prop_type);
1591
+ } else if (result.kind === "object") {
1592
+ const shape = propType.shape;
1593
+ const cleanedShape = cleanupPropSchema(shape);
1594
+ result.shape = cleanedShape;
1595
+ } else if (result.kind === "union") {
1596
+ const propTypes = propType.prop_types;
1597
+ const cleanedPropTypes = {};
1598
+ Object.keys(propTypes).forEach((key) => {
1599
+ cleanedPropTypes[key] = cleanupPropType(propTypes[key]);
1600
+ });
1601
+ result.prop_types = cleanedPropTypes;
1602
+ }
1603
+ return result;
1604
+ }
1605
+
1606
+ // src/mcp/tools/build-composition/tool.ts
1607
+ import {
1608
+ createElement as createElement5,
1609
+ deleteElement,
1610
+ generateElementId,
1611
+ getContainer,
1612
+ getWidgetsCache as getWidgetsCache4
1613
+ } from "@elementor/editor-elements";
1614
+
1615
+ // src/mcp/utils/do-update-element-property.ts
1616
+ import {
1617
+ createElementStyle,
1618
+ getElementStyles,
1619
+ getWidgetsCache as getWidgetsCache3,
1620
+ updateElementSettings,
1621
+ updateElementStyle
1622
+ } from "@elementor/editor-elements";
1623
+ import { getPropSchemaFromCache, Schema as Schema2 } from "@elementor/editor-props";
1624
+ import { getStylesSchema as getStylesSchema3 } from "@elementor/editor-styles";
1625
+ function resolvePropValue(value, forceKey) {
1626
+ return Schema2.adjustLlmPropValueSchema(value, forceKey);
1627
+ }
1628
+ var doUpdateElementProperty = (params) => {
1629
+ const { elementId, propertyName, propertyValue, elementType } = params;
1630
+ if (propertyName === "_styles") {
1631
+ const elementStyles = getElementStyles(elementId) || {};
1632
+ const propertyMapValue = propertyValue;
1633
+ const styleSchema = getStylesSchema3();
1634
+ const transformedStyleValues = Object.fromEntries(
1635
+ Object.entries(propertyMapValue).map(([key, val]) => {
1636
+ if (key === "custom_css") {
1637
+ return [key, val];
1638
+ }
1639
+ const { key: propKey, kind } = styleSchema?.[key] || {};
1640
+ if (!propKey && kind !== "union") {
1641
+ throw new Error(`_styles property ${key} is not supported.`);
1642
+ }
1643
+ return [key, resolvePropValue(val, propKey)];
1644
+ })
1645
+ );
1646
+ let customCss;
1647
+ Object.keys(propertyMapValue).forEach((stylePropName) => {
1648
+ const propertyRawSchema = styleSchema[stylePropName];
1649
+ if (stylePropName === "custom_css") {
1650
+ customCss = {
1651
+ raw: btoa(propertyMapValue[stylePropName])
1652
+ };
1653
+ return;
1654
+ }
1655
+ const isSupported = !!propertyRawSchema;
1656
+ if (!isSupported) {
1657
+ throw new Error(`_styles property ${stylePropName} is not supported.`);
1658
+ }
1659
+ if (propertyRawSchema.kind === "plain") {
1660
+ if (typeof propertyMapValue[stylePropName] !== "object") {
1661
+ const propUtil = getPropSchemaFromCache(propertyRawSchema.key);
1662
+ if (propUtil) {
1663
+ const plainValue = propUtil.create(propertyMapValue[stylePropName]);
1664
+ propertyMapValue[stylePropName] = plainValue;
1665
+ }
1666
+ }
1667
+ }
1668
+ });
1669
+ const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
1670
+ if (!localStyle) {
1671
+ createElementStyle({
1672
+ elementId,
1673
+ custom_css: customCss,
1674
+ classesProp: "classes",
1675
+ label: "local",
1676
+ meta: {
1677
+ breakpoint: "desktop",
1678
+ state: null
1679
+ },
1680
+ props: {
1681
+ ...transformedStyleValues
1682
+ }
1683
+ });
1684
+ } else {
1685
+ updateElementStyle({
1686
+ elementId,
1687
+ styleId: localStyle.id,
1688
+ meta: {
1689
+ breakpoint: "desktop",
1690
+ state: null
1691
+ },
1692
+ props: {
1693
+ ...transformedStyleValues
1694
+ }
1695
+ });
1696
+ }
1697
+ return;
1698
+ }
1699
+ const elementPropSchema = getWidgetsCache3()?.[elementType]?.atomic_props_schema;
1700
+ if (!elementPropSchema) {
1701
+ throw new Error(`No prop schema found for element type: ${elementType}`);
1702
+ }
1703
+ if (!elementPropSchema[propertyName]) {
1704
+ const propertyNames = Object.keys(elementPropSchema);
1705
+ throw new Error(
1706
+ `Property "${propertyName}" does not exist on element type "${elementType}". Available properties are: ${propertyNames.join(
1707
+ ", "
1708
+ )}`
1709
+ );
1710
+ }
1711
+ const value = resolvePropValue(propertyValue);
1712
+ updateElementSettings({
1713
+ id: elementId,
1714
+ props: {
1715
+ [propertyName]: value
1716
+ },
1717
+ withHistory: false
1718
+ });
1719
+ };
1720
+
1721
+ // src/mcp/tools/build-composition/prompt.ts
1722
+ import { toolPrompts } from "@elementor/editor-mcp";
1723
+ var CUSTOM_CSS_URI = STYLE_SCHEMA_URI.replace("{category}", "custom_css");
1724
+ var generatePrompt = () => {
1725
+ const buildCompositionsToolPrompt = toolPrompts("build-compositions");
1726
+ buildCompositionsToolPrompt.description(`
1727
+ Build entire elementor widget comositions representing complex structures of nested elements.
1728
+
1729
+ # When to use this tool
1730
+ Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
1731
+ Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
1732
+
1733
+ # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
1734
+ 1. [${WIDGET_SCHEMA_URI}]
1735
+ Required to understand which widgets are available, and what are their configuration schemas.
1736
+ Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
1737
+ 2. [${CUSTOM_CSS_URI}]
1738
+ Required to understand the styles schema for the widgets. All widgets share the same styles schema.
1739
+ USE ONLY THE "custom_css" CATEGORY FROM THE STYLES SCHEMA FOR STYLING THE ELEMENTS with this tool.
1740
+ 3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
1741
+
1742
+ # Instructions
1743
+ 1. Understand the user requirements carefully.
1744
+ 2. Build a valid XML structure using only the allowed custom tags provided. For example, if you
1745
+ use the "e-button" element, it would be represented as <e-button></e-button> in the XML structure.
1746
+ 3. Plan the configuration for each element according to the user requirements, using the configuration schema provided for each custom tag.
1747
+ Every widget type has it's own configuration schema, retreivable from the resource [${WIDGET_SCHEMA_URI}].
1748
+ PropValues must follow the exact PropType schema provided in the resource.
1749
+ 4. For every element, provide a "configuration-id" attribute. For example:
1750
+ \`<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading2"></e-heading></e-flexbox>\`
1751
+ In the elementConfig property, provide the actual configuration object for each configuration-id used in the XML structure.
1752
+ In the stylesConfig property, provide the actual styles configuration object for each configuration-id used in the XML structure.
1753
+ For easy execution, USE ONLY "custom_css" category from the styles schema resource to apply styles.
1754
+ 5. Ensure the XML structure is valid and parsable.
1755
+ 6. Do not add any attribute nodes, classes, id's, and no text nodes allowed, for inline styles prefer USE the [${CUSTOM_CSS_URI}] resource for custom_css.
1756
+ 7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-div-block" and "e-flexbox".
1757
+ 8. Make sure that non-container elements do NOT have any nested elements.
1758
+ 9. Unsless the user specifically requires structure only, BE EXPRESSIVE AND VISUALLY CREATIVE AS POSSIBLE IN APPLYING STYLE CONFIGURATION.
1759
+ In the case of doubt, prefer adding more styles to make the composition visually appealing.
1760
+
1761
+ # Additional Guidelines
1762
+ - Most users expect the structure to be well designed and visually appealing.
1763
+ - Use layout properties, ensure "white space" design approach is followed, and make sure the composition is visually balanced.
1764
+ - Use appropriate spacing, alignment, and sizing to create a harmonious layout.
1765
+ - Consider the visual hierarchy of elements to guide the user's attention effectively.
1766
+ - You are encouraged to use colors, typography, and other style properties to enhance the visual appeal, as long as they are part of the configuration schema for the elements used.
1767
+ - Always aim for a clean and professional look that aligns with modern design principles.
1768
+ - When you are required to create placeholder texts, use texts that have a length that fits the goal. When long texts are required, use longer placeholder texts. When the user specifies exact texts, use the exact texts.
1769
+ - Image size does not affect the actual size on the screen, only which quality to use. If you use images, specifically add _styles PropValues to define the image sizes.
1770
+
1771
+ # CONSTRAINTS
1772
+ When a tool execution fails, retry up to 10 more times, read the error message carefully, and adjust the XML structure or the configurations accordingly.
1773
+ If a "$$type" is missing, update the invalid object, if the XML has parsing errors, fix it, etc. and RETRY.
1774
+ VALIDATE the XML structure before delivering it as the final result.
1775
+ VALIDATE the JSON structure used in the "configuration" attributes for each element before delivering the final result. The configuration must MATCH the PropValue schemas.
1776
+ NO LINKS ALLOWED. Never apply links to elements, even if they appear in the PropType schema.
1777
+ elementConfig values must align with the widget's PropType schema, available at the resource [${WIDGET_SCHEMA_URI}].
1778
+ stylesConfig values must align with the common styles PropType schema, available at the resource [${STYLE_SCHEMA_URI}].
1779
+
1780
+ # Parameters
1781
+ All parameters are MANDATORY.
1782
+ - xmlStructure
1783
+ - elementConfig
1784
+ - stylesConfig
1785
+
1786
+ If unsure about the configuration of a specific property, read the schema resources carefully.
1787
+
1788
+
1789
+ `);
1790
+ buildCompositionsToolPrompt.example(`
1791
+ A Heading and a button inside a flexbox
1792
+ {
1793
+ xmlStructure: "<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading1"></e-heading><e-button configuration-id="button1"></e-button></e-flexbox>"
1794
+ elementConfig: {
1795
+ "flex1": {
1796
+ "tag": {
1797
+ "$$type": "string",
1798
+ "value": "section"
1799
+ },
1800
+ },
1801
+ styleConfig: {
1802
+ "heading1": {
1803
+ "custom_css": "font-size: 24px; color: #333;"
1804
+ }
1805
+ },
1806
+ }
1807
+ `);
1808
+ buildCompositionsToolPrompt.parameter(
1809
+ "xmlStructure",
1810
+ `**MANDATORY** A valid XML structure representing the composition to be built, using custom elementor tags, styling and configuration PropValues.`
1811
+ );
1812
+ buildCompositionsToolPrompt.parameter(
1813
+ "elementConfig",
1814
+ `**MANDATORY** A record mapping configuration IDs to their corresponding configuration objects, defining the PropValues for each element created.`
1815
+ );
1816
+ buildCompositionsToolPrompt.parameter(
1817
+ "styleConfig",
1818
+ `**MANDATORY** A record mapping style PropTypes to their corresponding style configuration objects, defining the PropValues for styles to be applied to elements.`
1819
+ );
1820
+ buildCompositionsToolPrompt.instruction(
1821
+ `You will be provided the XML structure with element IDs. These IDs represent the actual elementor widgets created on the page/post.
1822
+ You should use these IDs as reference for further configuration, styling or changing elements later on.`
1823
+ );
1824
+ buildCompositionsToolPrompt.instruction(
1825
+ `If you have global styles/classes available in the project, you should prefer using them over inline styles, and you are welcome to execute relevant tools AFTER this tool execution, to apply global classes to the created elements.`
1826
+ );
1827
+ return buildCompositionsToolPrompt.prompt();
1828
+ };
1829
+
1830
+ // src/mcp/tools/build-composition/schema.ts
1831
+ import { z } from "@elementor/schema";
1832
+ var inputSchema = {
1833
+ xmlStructure: z.string().describe("The XML structure representing the composition to be built"),
1834
+ elementConfig: z.record(
1835
+ z.string().describe("The configuration id"),
1836
+ z.record(z.string().describe("property name"), z.any().describe("The PropValue for the property"))
1837
+ ).describe("A record mapping element IDs to their configuration objects. REQUIRED"),
1838
+ stylesConfig: z.record(
1839
+ z.string().describe("The configuration id"),
1840
+ z.record(
1841
+ z.string().describe("_styles property name"),
1842
+ z.any().describe("The PropValue for the style property. MANDATORY")
1843
+ )
1844
+ ).describe("A record mapping element IDs to their styles configuration objects.").default({})
1845
+ };
1846
+ var outputSchema = {
1847
+ errors: z.string().describe("Error message if the composition building failed").optional(),
1848
+ xmlStructure: z.string().describe("The built XML structure as a string").optional(),
1849
+ llmInstructions: z.string().describe("Instructions used to further actions for you").optional()
1850
+ };
1851
+
1852
+ // src/mcp/tools/build-composition/tool.ts
1853
+ var initBuildCompositionsTool = (reg) => {
1854
+ const { addTool } = reg;
1855
+ addTool({
1856
+ name: "build-compositions",
1857
+ description: generatePrompt(),
1858
+ schema: inputSchema,
1859
+ outputSchema,
1860
+ handler: async (params) => {
1861
+ let xml = null;
1862
+ const { xmlStructure, elementConfig, stylesConfig } = params;
1863
+ const errors = [];
1864
+ const softErrors = [];
1865
+ const widgetsCache = getWidgetsCache4() || {};
1866
+ const documentContainer = getContainer("document");
1867
+ const rootContainer = createElement5({
1868
+ containerId: documentContainer.id,
1869
+ model: {
1870
+ elType: "container",
1871
+ id: generateElementId()
1872
+ },
1873
+ options: { useHistory: false }
1874
+ });
1875
+ try {
1876
+ const parser = new DOMParser();
1877
+ xml = parser.parseFromString(xmlStructure, "application/xml");
1878
+ const errorNode = xml.querySelector("parsererror");
1879
+ if (errorNode) {
1880
+ throw new Error("Failed to parse XML structure: " + errorNode.textContent);
1881
+ }
1882
+ const children = Array.from(xml.children);
1883
+ const iterate = (node, containerElement) => {
1884
+ const elementTag = node.tagName;
1885
+ if (!widgetsCache[elementTag]) {
1886
+ errors.push(new Error(`Unknown widget type: ${elementTag}`));
1887
+ }
1888
+ const isContainer = elementTag === "e-flexbox" || elementTag === "e-div-block";
1889
+ const newElement = isContainer ? createElement5({
1890
+ containerId: containerElement.id,
1891
+ model: {
1892
+ elType: elementTag,
1893
+ id: generateElementId()
1894
+ },
1895
+ options: { useHistory: false }
1896
+ }) : createElement5({
1897
+ containerId: containerElement.id,
1898
+ model: {
1899
+ elType: "widget",
1900
+ widgetType: elementTag,
1901
+ id: generateElementId()
1902
+ },
1903
+ options: { useHistory: false }
1904
+ });
1905
+ node.setAttribute("id", newElement.id);
1906
+ const configId = node.getAttribute("configuration-id") || "";
1907
+ try {
1908
+ const configObject = elementConfig[configId] || {};
1909
+ const styleObject = stylesConfig[configId] || {};
1910
+ configObject._styles = styleObject;
1911
+ for (const [propertyName, propertyValue] of Object.entries(configObject)) {
1912
+ const widgetSchema = widgetsCache[elementTag];
1913
+ if (!widgetSchema?.atomic_props_schema?.[propertyName] && propertyName !== "_styles") {
1914
+ softErrors.push(
1915
+ new Error(
1916
+ `Property "${propertyName}" does not exist on element type "${elementTag}".`
1917
+ )
1918
+ );
1919
+ continue;
1920
+ }
1921
+ try {
1922
+ doUpdateElementProperty({
1923
+ elementId: newElement.id,
1924
+ propertyName,
1925
+ propertyValue,
1926
+ elementType: elementTag
1927
+ });
1928
+ } catch (error) {
1929
+ softErrors.push(error);
1930
+ }
1931
+ }
1932
+ if (isContainer) {
1933
+ for (const child of node.children) {
1934
+ iterate(child, newElement);
1935
+ }
1936
+ } else {
1937
+ node.innerHTML = "";
1938
+ node.removeAttribute("configuration");
1939
+ }
1940
+ } finally {
1941
+ }
1942
+ };
1943
+ for (const childNode of children) {
1944
+ iterate(childNode, rootContainer);
1945
+ try {
1946
+ } catch (error) {
1947
+ errors.push(error);
1948
+ }
1949
+ }
1950
+ } catch (error) {
1951
+ errors.push(error);
1952
+ }
1953
+ if (errors.length) {
1954
+ deleteElement({
1955
+ elementId: rootContainer.id,
1956
+ options: { useHistory: false }
1957
+ });
1958
+ }
1959
+ if (errors.length > 0) {
1960
+ const errorText = `Failed to build composition with the following errors:
1961
+
1962
+
1963
+ ${errors.map((e) => typeof e === "string" ? e : e.message).join("\n\n")}
1964
+ "Missing $$type" errors indicate that the configuration objects are invalid. Try again and apply **ALL** object entries with correct $$type.
1965
+ Now that you have these errors, fix them and try again. Errors regarding configuration objects, please check again the PropType schemas`;
1966
+ throw new Error(errorText);
1967
+ }
1968
+ if (!xml) {
1969
+ throw new Error("XML structure is null after parsing.");
1970
+ }
1971
+ return {
1972
+ xmlStructure: new XMLSerializer().serializeToString(xml),
1973
+ llmInstructions: (softErrors.length ? `The composition was built successfully, but there were some issues with the provided configurations:
1974
+
1975
+ ${softErrors.map((e) => `- ${e.message}`).join("\n")}
1976
+
1977
+ Please use confiugure-element tool to fix these issues. Now that you have information about these issues, use the configure-element tool to fix them!` : "") + `
1978
+ Next Steps:
1979
+ - Use "apply-global-class" tool as there may be global styles ready to be applied to elements.
1980
+ - Use "configure-element" tool to further configure elements as needed, including styles.
1981
+ `
1982
+ };
1983
+ }
1984
+ });
1985
+ };
1986
+
1987
+ // src/mcp/tools/configure-element/prompt.ts
1988
+ var configureElementToolPrompt = `Configure an existing element on the page.
1989
+
1990
+ # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
1991
+ 1. [${WIDGET_SCHEMA_URI}]
1992
+ Required to understand which widgets are available, and what are their configuration schemas.
1993
+ Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
1994
+ 2. [${STYLE_SCHEMA_URI}]
1995
+ Required to understand the styles schema for the widgets. All widgets share the same styles schema, grouped by categories.
1996
+ Use this resource to understand which style properties are available for each element, and how to structure the "_styles" configuration property.
1997
+
1998
+ Before using this tool, check the definitions of the elements PropTypes at the resource "widget-schema-by-type" at editor-canvas__elementor://widgets/schema/{widgetType}
1999
+ All widgets share a common _style property for styling, which uses the common styles schema.
2000
+ Retreive and check the common styles schema at the resource list "styles-schema" at editor-canvas__elementor://styles/schema/{category}
2001
+
2002
+ Unless specifically noted, attempt to use the _style property "custom_css" for any styling, read the resource editor-canvas__elementor://styles/schema/custom_css for more information.
2003
+
2004
+ # Parameters
2005
+ - propertiesToChange: An object containing the properties to change, with their new values. MANDATORY
2006
+ - elementId: The ID of the element to configure. MANDATORY
2007
+ - elementType: The type of the element to configure (i.e. e-heading, e-button). MANDATORY
2008
+
2009
+ # When to use this tool
2010
+ When a user requires to change anything in an element, such as updating text, colors, sizes, or other configurable properties.
2011
+ This tool handles elements of type "widget".
2012
+ This tool handles styling elements, using the _styles property in the configuration.
2013
+
2014
+ The element's schema must be known before using this tool.
2015
+
2016
+ Attached resource link describing how PropType schema should be parsed as PropValue for this tool.
2017
+
2018
+ Read carefully the PropType Schema of the element and it's styles, then apply correct PropValue according to the schema.
2019
+
2020
+ PropValue structure:
2021
+ {
2022
+ "$$type": string, // MANDATORY as defined in the PropType schema under the "key" property
2023
+ value: unknown // The value according to the PropType schema for kinds of "array", use array with PropValues items inside. For "object", read the shape property of the PropType schema. For "plain", use strings.
2024
+ }
2025
+
2026
+ <IMPORTANT>
2027
+ ALWAYS MAKE SURE you have the PropType schemas for the element you are configuring, and the common-styles schema for styling. If you are not sure, retreive the schema from the resources mentioned above.
2028
+ </IMPORTANT>
2029
+
2030
+ You can use multiple property changes at once by providing multiple entries in the propertiesToChange object, including _style alongside non-style props.
2031
+ Some properties are nested, use the root property name, then objects with nested values inside, as the complete schema suggests.
2032
+ Nested properties, such as for the _styles, should include a "_styles" property with object containing the definitions to change.
2033
+
2034
+ Make sure you have the "widget-schema-by-type" resource available to retreive the PropType schema for the element type you are configuring.
2035
+
2036
+ # How to configure elements
2037
+ We use a dedicated PropType Schema for configuring elements, including styles. When you configure an element, you must use the EXACT PropType Value as defined in the schema.
2038
+ For _styles, use the style schema provided, as it also uses the PropType format.
2039
+ For all non-primitive types, provide the key property as defined in the schema as $$type in the generated objecct, as it is MANDATORY for parsing.
2040
+
2041
+ Use the EXACT "PROP-TYPE" Schema given, and ALWAYS include the "key" property from the original configuration for every property you are changing.
2042
+
2043
+ # Example
2044
+ \`\`\`json
2045
+ {
2046
+ propertiesToChange: {
2047
+ title: {
2048
+ $$type: 'string',
2049
+ value: 'New Title Text'
2050
+ },
2051
+ border: {
2052
+ $$type: 'boolean',
2053
+ value: false
2054
+ },
2055
+ _styles: {
2056
+ 'line-height': {
2057
+ $$type: 'size',
2058
+ value: {
2059
+ size: {
2060
+ $$type: 'number',
2061
+ value: 20
2062
+ },
2063
+ unit: {
2064
+ $$type: 'string',
2065
+ value: 'px'
2066
+ }
2067
+ }
2068
+ }
2069
+ }
2070
+ }
2071
+ };
2072
+ \`\`\`
2073
+
2074
+ <IMPORTANT>
2075
+ The $$type property is MANDATORY for every value, it is required to parse the value and apply application-level effects.
2076
+ </IMPORTANT>
2077
+ `;
2078
+
2079
+ // src/mcp/tools/configure-element/schema.ts
2080
+ import { z as z2 } from "@elementor/schema";
2081
+ var inputSchema2 = {
2082
+ propertiesToChange: z2.record(
2083
+ z2.string().describe(
2084
+ "The property name. If nested property, provide the root property name, and the object delta only."
2085
+ ),
2086
+ z2.any().describe("The property's value")
2087
+ ).describe("An object record containing property names and their new values to be set on the element").optional(),
2088
+ elementType: z2.string().describe("The type of the element to retreive the schema"),
2089
+ elementId: z2.string().describe("The unique id of the element to configure")
2090
+ };
2091
+ var outputSchema2 = {
2092
+ success: z2.boolean().describe(
2093
+ "Whether the configuration change was successful, only if propertyName and propertyValue are provided"
2094
+ )
2095
+ };
2096
+
2097
+ // src/mcp/tools/configure-element/tool.ts
2098
+ var initConfigureElementTool = (reg) => {
2099
+ const { addTool } = reg;
2100
+ addTool({
2101
+ name: "configure-element",
2102
+ description: configureElementToolPrompt,
2103
+ schema: inputSchema2,
2104
+ outputSchema: outputSchema2,
2105
+ handler: ({ elementId, propertiesToChange, elementType }) => {
2106
+ if (!propertiesToChange) {
2107
+ throw new Error(
2108
+ "propertiesToChange is required to configure an element. Now that you have this information, ensure you have the schema and try again."
2109
+ );
2110
+ }
2111
+ const toUpdate = Object.entries(propertiesToChange);
2112
+ for (const [propertyName, propertyValue] of toUpdate) {
2113
+ if (!propertyName && !elementId && !elementType) {
2114
+ throw new Error(
2115
+ "propertyName, elementId, elementType are required to configure an element. If you want to retreive the schema, use the get-element-configuration-schema tool."
2116
+ );
2117
+ }
2118
+ try {
2119
+ doUpdateElementProperty({
2120
+ elementId,
2121
+ elementType,
2122
+ propertyName,
2123
+ propertyValue
2124
+ });
2125
+ } catch (error) {
2126
+ const errorMessage = createUpdateErrorMessage({
2127
+ propertyName,
2128
+ elementId,
2129
+ elementType,
2130
+ error
2131
+ });
2132
+ throw new Error(errorMessage);
2133
+ }
2134
+ }
2135
+ return {
2136
+ success: true
2137
+ };
2138
+ }
2139
+ });
2140
+ };
2141
+ function createUpdateErrorMessage(opts) {
2142
+ const { propertyName, elementId, elementType, error } = opts;
2143
+ return `Failed to update property "${propertyName}" on element "${elementId}": ${error.message}.
2144
+ Check the element's PropType schema at the resource [${WIDGET_SCHEMA_URI.replace(
2145
+ "{widgetType}",
2146
+ elementType
2147
+ )}] for type "${elementType}" to ensure the property exists and the value matches the expected PropType.
2148
+ Now that you have this information, ensure you have the schema and try again.`;
2149
+ }
2150
+
2151
+ // src/mcp/canvas-mcp.ts
2152
+ var initCanvasMcp = (reg) => {
2153
+ const { setMCPDescription } = reg;
2154
+ setMCPDescription(
2155
+ 'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
2156
+ );
2157
+ initWidgetsSchemaResource(reg);
2158
+ initBuildCompositionsTool(reg);
2159
+ initConfigureElementTool(reg);
2160
+ };
2161
+
2162
+ // src/mcp/mcp-description.ts
2163
+ var mcpDescription = `Canvas MCP - Working with widgets and styles: how to use the PropType schemas and generate PropValue structures
2164
+
2165
+ # Elementor's PropValue configuration system
2166
+
2167
+ Every widget in Elementor has a set of properties that can be configured. These properties are defined using a strict schema, which specifies the type and structure of each property's value.
2168
+ All values are wrapped in a special structure called a "PropValue", which includes data and additional information about the type of the value.
2169
+
2170
+ To correctly configure a widget's properties, you must follow the PropType schema defined for that widget. This schema outlines the expected structure and types for each property, ensuring that the values you provide are valid and can be properly interpreted by Elementor.
2171
+ Every widget has it's own PropType schema, retreivable from the resource [${WIDGET_SCHEMA_URI}].
2172
+ ALL WIDGETS share a common _styles property with a uniform styles schema, retreivable from the resource [${STYLE_SCHEMA_URI}].
2173
+ The style schema is grouped by categories, such as "typography", "background", "border", etc.
2174
+
2175
+ All array types that can receive union types, are typed as mixed array, which means that each item in the array can be of any of the allowed types defined in the PropType schema.
2176
+ Example: the "background" can have a background-overlay property, which can contain multiple overlays, such as color, gradient, image, etc. Each item in the array must follow the PropType schema for each overlay type.
2177
+ All _style properties are OPTIONAL. When a _style is defined, we MERGE the values with existing styles, so only the properties you define will be changed, and the rest will remain as is.
2178
+
2179
+ When applicable for styles, use the "custom_css" property for free-form CSS styling. This property accepts a string of CSS rules that will be applied directly to the element.
2180
+ The css string must follow standard CSS syntax, with properties and values separated by semicolons, no selectors, or nesting rules allowed.
2181
+
2182
+ Additionaly, some PropTypes have metadata information (meta property) that can help in understaind the PropType usage, such as description or other useful information.
2183
+
2184
+ # Note about null values
2185
+ If a PropValue's value is null, omit the entire PropValue object.
2186
+
2187
+ Example of "image" PropValue structure:
2188
+
2189
+ PropValue structure:
2190
+ {$$type:'image',value:{src:{$$type:'image-src',value:{url:{$$type:'url',value:'https://example.com/image.jpg'}}},size:{$$type:'string',value:'full'}}}
2191
+
2192
+ Example of
2193
+ `;
2194
+
1460
2195
  // src/prevent-link-in-link-commands.ts
1461
2196
  import {
1462
2197
  getAnchoredAncestorId,
@@ -1553,17 +2288,17 @@ import {
1553
2288
 
1554
2289
  // src/style-commands/undoable-actions/paste-element-style.ts
1555
2290
  import {
1556
- createElementStyle,
2291
+ createElementStyle as createElementStyle2,
1557
2292
  deleteElementStyle,
1558
- getElementStyles,
1559
- updateElementStyle
2293
+ getElementStyles as getElementStyles2,
2294
+ updateElementStyle as updateElementStyle2
1560
2295
  } from "@elementor/editor-elements";
1561
2296
  import { ELEMENTS_STYLES_RESERVED_LABEL } from "@elementor/editor-styles-repository";
1562
2297
  import { undoable } from "@elementor/editor-v1-adapters";
1563
2298
  import { __ as __3 } from "@wordpress/i18n";
1564
2299
 
1565
2300
  // src/style-commands/utils.ts
1566
- import { getElementLabel, getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
2301
+ import { getElementLabel, getWidgetsCache as getWidgetsCache5 } from "@elementor/editor-elements";
1567
2302
  import { CLASSES_PROP_KEY } from "@elementor/editor-props";
1568
2303
  import { __ as __2 } from "@wordpress/i18n";
1569
2304
  function hasAtomicWidgets(args) {
@@ -1588,7 +2323,7 @@ function getClassesProp(container) {
1588
2323
  }
1589
2324
  function getContainerSchema(container) {
1590
2325
  const type = container?.model.get("widgetType") || container?.model.get("elType");
1591
- const widgetsCache = getWidgetsCache2();
2326
+ const widgetsCache = getWidgetsCache5();
1592
2327
  const elementType = widgetsCache?.[type];
1593
2328
  return elementType?.atomic_props_schema ?? null;
1594
2329
  }
@@ -1614,7 +2349,7 @@ var undoablePasteElementStyle = () => undoable(
1614
2349
  if (!classesProp) {
1615
2350
  return null;
1616
2351
  }
1617
- const originalStyles = getElementStyles(container.id);
2352
+ const originalStyles = getElementStyles2(container.id);
1618
2353
  const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
1619
2354
  const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
1620
2355
  const revertData = {
@@ -1623,7 +2358,7 @@ var undoablePasteElementStyle = () => undoable(
1623
2358
  };
1624
2359
  if (styleId) {
1625
2360
  newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
1626
- updateElementStyle({
2361
+ updateElementStyle2({
1627
2362
  elementId,
1628
2363
  styleId,
1629
2364
  meta,
@@ -1634,7 +2369,7 @@ var undoablePasteElementStyle = () => undoable(
1634
2369
  } else {
1635
2370
  const [firstVariant] = newStyle.variants;
1636
2371
  const additionalVariants = newStyle.variants.slice(1);
1637
- revertData.styleId = createElementStyle({
2372
+ revertData.styleId = createElementStyle2({
1638
2373
  elementId,
1639
2374
  classesProp,
1640
2375
  label: ELEMENTS_STYLES_RESERVED_LABEL,
@@ -1661,7 +2396,7 @@ var undoablePasteElementStyle = () => undoable(
1661
2396
  }
1662
2397
  const [firstVariant] = revertData.originalStyle.variants;
1663
2398
  const additionalVariants = revertData.originalStyle.variants.slice(1);
1664
- createElementStyle({
2399
+ createElementStyle2({
1665
2400
  elementId: container.id,
1666
2401
  classesProp,
1667
2402
  label: ELEMENTS_STYLES_RESERVED_LABEL,
@@ -1717,7 +2452,7 @@ import {
1717
2452
  } from "@elementor/editor-v1-adapters";
1718
2453
 
1719
2454
  // src/style-commands/undoable-actions/reset-element-style.ts
1720
- import { createElementStyle as createElementStyle2, deleteElementStyle as deleteElementStyle2, getElementStyles as getElementStyles2 } from "@elementor/editor-elements";
2455
+ import { createElementStyle as createElementStyle3, deleteElementStyle as deleteElementStyle2, getElementStyles as getElementStyles3 } from "@elementor/editor-elements";
1721
2456
  import { ELEMENTS_STYLES_RESERVED_LABEL as ELEMENTS_STYLES_RESERVED_LABEL2 } from "@elementor/editor-styles-repository";
1722
2457
  import { undoable as undoable2 } from "@elementor/editor-v1-adapters";
1723
2458
  import { __ as __4 } from "@wordpress/i18n";
@@ -1726,7 +2461,7 @@ var undoableResetElementStyle = () => undoable2(
1726
2461
  do: ({ containers }) => {
1727
2462
  return containers.map((container) => {
1728
2463
  const elementId = container.model.get("id");
1729
- const containerStyles = getElementStyles2(elementId);
2464
+ const containerStyles = getElementStyles3(elementId);
1730
2465
  Object.keys(containerStyles ?? {}).forEach(
1731
2466
  (styleId) => deleteElementStyle2(elementId, styleId)
1732
2467
  );
@@ -1744,7 +2479,7 @@ var undoableResetElementStyle = () => undoable2(
1744
2479
  Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
1745
2480
  const [firstVariant] = style.variants;
1746
2481
  const additionalVariants = style.variants.slice(1);
1747
- createElementStyle2({
2482
+ createElementStyle3({
1748
2483
  elementId,
1749
2484
  classesProp,
1750
2485
  styleId,
@@ -1813,6 +2548,11 @@ function init() {
1813
2548
  id: "classes-rename",
1814
2549
  component: ClassesRename
1815
2550
  });
2551
+ initCanvasMcp(
2552
+ getMCPByDomain("canvas", {
2553
+ instructions: mcpDescription
2554
+ })
2555
+ );
1816
2556
  }
1817
2557
 
1818
2558
  // src/sync/drag-element-from-panel.ts