PluginProbe
Elementor Website Builder – more than just a page builder / 4.1.0-beta2
Elementor Website Builder – more than just a page builder v4.1.0-beta2
4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 All 457 releases
← All changes | modules/mcp/module.php +48 -198 4.3.4 → 4.1.0-beta2 View file →
@@ -2,20 +2,10 @@
2 2
3 3 namespace Elementor\Modules\Mcp;
4 4
5 5 use Elementor\Core\Base\Module as BaseModule;
6 -use Elementor\Core\Utils\Promotions\Filtered_Promotions_Manager;
7 -use Elementor\MCP\Composer\Admin\McpSettingsController;
8 -use Elementor\MCP\Composer\Admin\Page as Mcp_Admin_Page;
9 -use Elementor\MCP\Composer\Mcp\Registry as Shared_Registry;
10 -use Elementor\Modules\EditorOne\Classes\Menu_Data_Provider;
11 -use Elementor\Modules\Mcp\Abilities\Abstract_Ability;
12 -use Elementor\Modules\Mcp\AdminMenuItems\Editor_One_Mcp_Menu;
13 -use Elementor\Modules\Mcp\Preview\Public_Preview_Handler;
14 -use Elementor\Modules\Mcp\Registry\Ability_Registry;
15 -use Elementor\Modules\Mcp\RestApi\Mcp_Proxy_REST_API;
16 -use Elementor\Modules\Mcp\Utils\Editor_Sync_State;
17 -use Elementor\Utils;
6 +use Elementor\Plugin;
7 +use Elementor\Core\Experiments\Manager as ExperimentsManager;
18 8 use WP\MCP\Core\McpAdapter;
19 9
20 10 if ( ! defined( 'ABSPATH' ) ) {
21 11 exit;
@@ -21,144 +11,44 @@
21 11 exit;
22 12 }
23 13
24 14 class Module extends BaseModule {
15 + const EXPERIMENT_NAME = 'e_wp_abilities_api';
25 16
26 - const ANALYTICS_REGISTRAR_HANDLE = 'elementor-mcp-analytics-registrar';
27 - const PROMOTION_REGISTRAR_HANDLE = 'elementor-mcp-promotion-registrar';
28 - const MCP_PROMOTION_UPGRADE_URL = 'https://go.elementor.com/go-pro-mcp-connector-page-upgrade/';
29 - const MCP_PROMOTION_ALLOWED_DOMAIN = 'elementor.com';
30 -
31 - private Ability_Registry $registry;
32 -
33 17 public function get_name() {
34 18 return 'mcp';
35 19 }
36 20
37 - public function enqueue_analytics_registrar(): void {
38 - wp_enqueue_script(
39 - self::ANALYTICS_REGISTRAR_HANDLE,
40 - $this->get_js_assets_url( 'mcp-analytics-registrar' ),
41 - [ 'elementor-common', Mcp_Admin_Page::SCRIPT_HANDLE ],
42 - ELEMENTOR_VERSION,
43 - true
44 - );
45 - }
46 -
47 - public function enqueue_promotion_registrar(): void {
48 - if ( ! $this->should_enqueue_mcp_admin_promotion() ) {
49 - return;
50 - }
51 -
52 - wp_enqueue_script(
53 - self::PROMOTION_REGISTRAR_HANDLE,
54 - $this->get_js_assets_url( 'mcp-promotion-registrar' ),
55 - [
56 - 'elementor-common',
57 - Mcp_Admin_Page::SCRIPT_HANDLE,
58 - 'react',
59 - 'react-dom',
60 - 'wp-i18n',
61 - ],
62 - ELEMENTOR_VERSION,
63 - true
64 - );
65 -
66 - wp_localize_script(
67 - self::PROMOTION_REGISTRAR_HANDLE,
68 - 'elementorMcpPromotionConfig',
69 - [
70 - 'upgradeUrl' => $this->get_promotion_upgrade_url(),
71 - ]
72 - );
73 -
74 - wp_set_script_translations( self::PROMOTION_REGISTRAR_HANDLE, 'elementor' );
75 - }
76 -
77 - private function should_enqueue_mcp_admin_promotion(): bool {
78 - if ( ! current_user_can( 'manage_options' ) ) {
79 - return false;
80 - }
81 -
82 - if ( ! class_exists( Utils::class ) ) {
83 - return false;
84 - }
85 -
86 - if ( Utils::has_pro() && Utils::is_license_active() ) {
87 - return false;
88 - }
89 -
90 - return true;
91 - }
92 -
93 - private function get_promotion_upgrade_url(): string {
94 - $promotion_data = Filtered_Promotions_Manager::get_filtered_promotion_data(
95 - [ 'upgrade_url' => self::MCP_PROMOTION_UPGRADE_URL ],
96 - 'elementor/mcp/custom_promotion',
97 - 'upgrade_url'
98 - );
99 -
100 - $upgrade_url = $promotion_data['upgrade_url'] ?? '';
101 -
102 - return $this->is_allowed_promotion_url( $upgrade_url )
103 - ? $upgrade_url
104 - : self::MCP_PROMOTION_UPGRADE_URL;
105 - }
106 -
107 - private function is_allowed_promotion_url( $url ): bool {
108 - if ( ! is_string( $url ) ) {
109 - return false;
110 - }
111 -
112 - $host = wp_parse_url( $url, PHP_URL_HOST );
113 -
114 - if ( ! is_string( $host ) ) {
115 - return false;
116 - }
117 -
118 - $host = strtolower( $host );
119 -
120 - return self::MCP_PROMOTION_ALLOWED_DOMAIN === $host
121 - || str_ends_with( $host, '.' . self::MCP_PROMOTION_ALLOWED_DOMAIN );
122 - }
123 -
124 21 public static function is_active() {
125 22 return class_exists( McpAdapter::class ) &&
126 23 function_exists( 'wp_register_ability' ) &&
127 - class_exists( Shared_Registry::class );
24 + Plugin::instance()->experiments->is_feature_active( self::EXPERIMENT_NAME );
128 25 }
129 26
130 - public static function is_site_mcp_exposure_enabled(): bool {
131 - return McpSettingsController::is_enabled();
27 + public static function get_experimental_data() {
28 + return [
29 + 'name' => self::EXPERIMENT_NAME,
30 + 'title' => __( 'Elementor MCP WP Abilities API', 'elementor' ),
31 + 'description' => __( 'Enable Elementor MCP WP Abilities API. Requirements: 1. WordPress 7.0 or higher. 2. Create an application password for your agent user. 3. Add to your MCP config: {url: "https://<your-site-url>/wp-json/elementor/mcp", headers: {Authorization: "Basic <base64(user:application-password)>"}}', 'elementor' ),
32 + 'hidden' => true,
33 + 'default' => ExperimentsManager::STATE_INACTIVE,
34 + ];
132 35 }
133 36
134 37 public function __construct() {
135 38 parent::__construct();
136 39
137 - $this->registry = self::build_core_registry();
138 -
139 - ( new Mcp_Proxy_REST_API( $this->registry ) )->register_hooks();
140 - ( new Public_Preview_Handler() )->register();
141 - ( new Editor_Sync_State() )->register_hooks();
142 -
143 - if ( ! self::is_active() ) {
40 + if ( ! $this->is_active() ) {
144 41 return;
145 42 }
146 43
147 - add_action( 'init', [ $this, 'register_shared_registry_slugs' ], 5 );
148 - add_action( 'elementor/editor-one/menu/register', [ $this, 'register_editor_one_menu' ], Editor_One_Mcp_Menu::REGISTER_PRIORITY_AFTER_SUBMISSIONS );
44 + McpAdapter::instance();
149 45
150 46 add_action( 'wp_abilities_api_categories_init', [ $this, 'register_ability_category' ] );
151 -
152 - if ( self::is_site_mcp_exposure_enabled() ) {
153 - add_action( 'wp_abilities_api_init', [ $this, 'register_abilities' ] );
154 - }
47 + add_action( 'wp_abilities_api_init', [ $this, 'register_abilities' ] );
48 + add_action( 'mcp_adapter_init', [ $this, 'register_server' ] );
155 49 }
156 50
157 - public function registry(): Ability_Registry {
158 - return $this->registry;
159 - }
160 -
161 51 public function register_ability_category() {
162 52 if ( ! function_exists( 'wp_register_ability_category' ) ) {
163 53 return;
164 54 }
@@ -176,84 +66,44 @@
176 66 if ( ! function_exists( 'wp_register_ability' ) ) {
177 67 return;
178 68 }
179 69
180 - foreach ( $this->registry->all() as $ability ) {
181 - $ability->register();
182 - }
70 + ( new Abilities\List_Pages_Ability() )->register();
71 + ( new Abilities\Get_Structure_Ability() )->register();
72 + ( new Abilities\Update_Settings_Ability() )->register();
73 + ( new Abilities\Create_Page_Ability() )->register();
74 + ( new Abilities\Get_Globals_Ability() )->register();
183 75 }
184 76
185 - public function register_shared_registry_slugs(): void {
186 - $shared = Shared_Registry::instance();
77 + public function register_server( $adapter ) {
78 + if ( ! $adapter instanceof McpAdapter ) {
79 + return;
80 + }
187 81
188 - $shared->register_tools( $this->collect_server_ids( $this->registry->tools() ) );
189 - $shared->register_resources( $this->collect_server_ids( $this->registry->resources() ) );
190 - }
191 -
192 - public function register_editor_one_menu( Menu_Data_Provider $menu_data_provider ): void {
193 - $menu_data_provider->register_menu(
194 - new Editor_One_Mcp_Menu(),
195 - [ 'preserve_label_casing' => true ]
82 + $result = $adapter->create_server(
83 + 'elementor-mcp-server',
84 + 'elementor',
85 + 'mcp',
86 + 'Elementor MCP',
87 + 'Read and modify Elementor Editor abilities.',
88 + 'v1.0.0',
89 + [ \WP\MCP\Transport\HttpTransport::class ],
90 + \WP\MCP\Infrastructure\ErrorHandling\ErrorLogMcpErrorHandler::class,
91 + \WP\MCP\Infrastructure\Observability\NullMcpObservabilityHandler::class,
92 + [
93 + 'elementor/list-pages',
94 + 'elementor/get-page-structure',
95 + 'elementor/update-page-settings',
96 + 'elementor/create-page',
97 + 'elementor/get-globals',
98 + ],
99 + [],
100 + []
196 101 );
197 - }
198 102
199 - public static function build_core_registry(): Ability_Registry {
200 - $registry = new Ability_Registry();
201 -
202 - foreach ( self::get_core_abilities( $registry ) as $ability ) {
203 - $registry->add( $ability );
103 + if ( is_wp_error( $result ) ) {
104 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
105 + error_log( sprintf( '[Elementor MCP] Server registration failed: %s', $result->get_error_message() ) );
106 + return;
204 107 }
205 -
206 - return $registry;
207 - }
208 -
209 - /** @return Abstract_Ability[] */
210 - private static function get_core_abilities( Ability_Registry $registry ): array {
211 - $abilities = [
212 - new Abilities\Get_Structure_Ability(),
213 - new Abilities\Update_Settings_Ability(),
214 - new Abilities\Create_Page_Ability(),
215 - new Abilities\Create_Preview_Link_Ability(),
216 - new Abilities\Publish_Document_Ability(),
217 - new Abilities\Style_Best_Practices_Ability(),
218 - new Abilities\Wordpress_Best_Practices_Ability(),
219 - new Abilities\Manage_Variable_Ability(),
220 - new Abilities\Manage_Classes_Ability(),
221 - new Abilities\Manage_Default_Styles_Ability(),
222 - new Abilities\Get_Default_Styles_Ability(),
223 - new Abilities\Reorder_Classes_Ability(),
224 - new Abilities\Manage_Variable_Guide_Ability(),
225 - new Abilities\Get_Widget_Schema_Ability(),
226 - new Abilities\List_Widget_Schemas_Ability(),
227 - new Abilities\List_Dynamic_Tags_Ability(),
228 - new Abilities\Build_Composition_Ability(),
229 - new Abilities\Manage_Elements_Ability(),
230 - new Abilities\Global_Classes_Resource_Ability(),
231 - new Abilities\List_Assets_Ability(),
232 - new Abilities\Global_Variables_Resource_Ability(),
233 - new Abilities\Interactions_Schema_Resource_Ability(),
234 - new Abilities\List_Resources_Ability( $registry ),
235 - new Abilities\Read_Resource_Ability( $registry ),
236 - new Abilities\List_Components_Ability(),
237 - new Abilities\Manage_Component_Ability(),
238 - new Abilities\List_Posts_Ability(),
239 - ];
240 -
241 - return $abilities;
242 - }
243 -
244 - /**
245 - * @param Abstract_Ability[] $abilities
246 - * @return string[]
247 - */
248 - private function collect_server_ids( array $abilities ): array {
249 - $ids = [];
250 -
251 - foreach ( $abilities as $ability ) {
252 - if ( $ability->is_exposed_on_server() ) {
253 - $ids[] = $ability->get_id();
254 - }
255 - }
256 -
257 - return $ids;
258 108 }
259 109 }