' . __('Unauthorized', 'pagelayer') . '

'; return; } pagelayer_page_header(__('AI Agents Connection', 'pagelayer')); $abilities_api_available = function_exists('wp_register_ability'); $adapter_active = class_exists('\\WP\\MCP\\Core\\McpAdapter'); $adapter_installed = '' !== self::get_installed_mcp_adapter_file(); $has_app_password = self::current_user_has_mcp_app_password(); $test_status = self::get_test_connection_status(); $test_ok = !empty($test_status['ok']); $test_message = !empty($test_status['message']) ? $test_status['message'] : ''; $site_url = trailingslashit(rtrim(home_url(), '/')); $endpoint_url = $site_url . ltrim(self::$ABILITIES_ENDPOINT, '/'); $mcp_server_url = $site_url . ltrim(self::$MCP_SERVER_ENDPOINT, '/'); $username = function_exists('wp_get_current_user') ? wp_get_current_user()->user_login : ''; $app_pass_placeholder = __('your-application-password', 'pagelayer'); $user_placeholder = $username ?: __('', 'pagelayer'); $total_steps = 4; $done_count = 0; $next_step = ''; if(!$abilities_api_available){ $next_step = __('Abilities API registration', 'pagelayer'); }elseif(!$adapter_active){ $done_count++; $next_step = __('MCP Adapter installation', 'pagelayer'); }elseif(!$has_app_password){ $done_count += 2; $next_step = __('Application Password generation', 'pagelayer'); }elseif(!$test_ok){ $done_count += 3; $next_step = __('Connection test', 'pagelayer'); }else{ $done_count += 4; } $stepper_width = 0; if ($done_count > 1) { $stepper_width = ($done_count - 1) / 3 * 100; } $adapter_label = $adapter_active ? __('Active', 'pagelayer') : ($adapter_installed ? __('Inactive', 'pagelayer') : __('Not installed', 'pagelayer')); ?>

__('Abilities', 'pagelayer'), 'state' => $abilities_api_available ? 'done' : 'todo'], ['label' => __('MCP Adapter', 'pagelayer'),'state' => $adapter_active ? 'done' : 'todo'], ['label' => __('Password', 'pagelayer'), 'state' => $has_app_password ? 'done' : 'todo'], ['label' => __('Test', 'pagelayer'), 'state' => $test_ok ? 'done' : 'todo'], ]; foreach($chips as $idx => $chip){ echo '
'; echo '' . ($chip['state'] === 'done' ? '✓' : esc_html((string)($idx + 1))) . ''; echo '' . esc_html($chip['label']) . ''; echo '
'; } ?>
' . sprintf(__('Next up: %s', 'pagelayer'), '' . esc_html($next_step) . '') . '

'; }else{ echo '

' . __('All steps complete. Your AI client can now connect.', 'pagelayer') . '

'; } ?>
' . esc_html__('Pagelayer registers building and styling abilities. They are picked up automatically by any installed MCP adapter and surfaced to AI clients as tools.', 'pagelayer') . '

'; echo wp_kses_post( self::render_abilities_list() ); }else{ echo '

' . esc_html__('The WordPress Abilities API ships in WordPress 6.9+. Pagelayer can still work today — installing the MCP Adapter backfills the API so your AI client can connect immediately. Consider updating WordPress for native abilities support.', 'pagelayer') . '

'; } ?>
' . esc_html__('The MCP Adapter plugin is installed and active. Your site now exposes an MCP server that AI clients can connect to.', 'pagelayer') . '

'; }elseif($adapter_installed){ echo '

' . esc_html__('The MCP Adapter is installed but not active. Activate it to enable the MCP server.', 'pagelayer') . '

'; echo ''; }else{ echo '

' . esc_html__('Install the official WordPress MCP Adapter plugin with a single click. It bridges your site to any MCP-compatible AI client.', 'pagelayer') . '

'; echo ''; } ?>


							

    ' . esc_html__('No Pagelayer abilities are currently exposed. Activate the MCP Adapter to surface them.', 'pagelayer') . '

    '; } $html = '
    '; foreach($groups as $group => $items){ $html .= '
    '; $html .= '

    ' . esc_html($group) . '

    '; $html .= '
      '; foreach($items as $ability){ $html .= '
    • '; $html .= '' . esc_html($ability['label']) . ''; if(!empty($ability['description'])){ $html .= '' . esc_html($ability['description']) . ''; } $html .= '
    • '; } $html .= '
    '; $html .= '
    '; } $html .= '
    '; return $html; } static function get_registered_abilities(){ return [ __('Pages Management', 'pagelayer') => [ [ 'label' => __('Create Page', 'pagelayer'), 'description' => __('Creates a new WordPress page built with Pagelayer.', 'pagelayer'), ], [ 'label' => __('Update Page', 'pagelayer'), 'description' => __('Updates page title, builder data, and publish status.', 'pagelayer'), ], [ 'label' => __('Get / List / Delete Pages', 'pagelayer'), 'description' => __('Inspect, list, and delete Pagelayer pages.', 'pagelayer'), ], [ 'label' => __('Validate Page Layout', 'pagelayer'), 'description' => __('AI validation engine for widget compatibility, hierarchy, responsiveness, accessibility, and SEO.', 'pagelayer'), ], [ 'label' => __('Duplicate / Publish Page', 'pagelayer'), 'description' => __('Clone pages with fresh element IDs and publish drafts.', 'pagelayer'), ], ], __('Individual Posts Management', 'pagelayer') => [ [ 'label' => __('Create Post', 'pagelayer'), 'description' => __('Creates a new blog post built with Pagelayer, specifying categories, tags, excerpt, and featured image.', 'pagelayer'), ], [ 'label' => __('Update Post', 'pagelayer'), 'description' => __('Updates post layout, categories, tags, excerpt, and status.', 'pagelayer'), ], [ 'label' => __('Get / List / Delete Posts', 'pagelayer'), 'description' => __('Inspect, list, publish, duplicate, and delete blog posts.', 'pagelayer'), ], ], __('Widgets & Schemas', 'pagelayer') => [ [ 'label' => __('List Widgets', 'pagelayer'), 'description' => __('List all registered Pagelayer widgets, display names, categories, icons, and nesting rules.', 'pagelayer'), ], [ 'label' => __('Get Widget Schema & Examples', 'pagelayer'), 'description' => __('Retrieve control property schema and canonical pagelayer_data node examples.', 'pagelayer'), ], ], __('Theme Templates', 'pagelayer') => [ [ 'label' => __('Get / Create Theme Templates', 'pagelayer'), 'description' => __('Build header, footer, blog archive, single blog, search, 404, sidebar, popup, and WooCommerce templates.', 'pagelayer'), ], [ 'label' => __('Update / Delete Templates', 'pagelayer'), 'description' => __('Update or delete theme templates and display condition rules.', 'pagelayer'), ], ], __('Navigation Menus', 'pagelayer') => [ [ 'label' => __('Get / Create Menus', 'pagelayer'), 'description' => __('Build the WordPress nav menus that the Primary Menu widget renders in headers, including Mega Menu dropdowns and theme location assignment.', 'pagelayer'), ], ], __('Global Design System', 'pagelayer') => [ [ 'label' => __('Get Theme Settings & Styles', 'pagelayer'), 'description' => __('Retrieve theme options, global colors/fonts, content width, and WooCommerce status.', 'pagelayer'), ], [ 'label' => __('Presets & Catalogs', 'pagelayer'), 'description' => __('Get color palette presets, spacing scale presets, FontAwesome icon catalog, and font catalog.', 'pagelayer'), ], [ 'label' => __('Search Real Images', 'pagelayer'), 'description' => __('Search Pexels by keyword for real, topically relevant photos to use in place of placeholders (requires a Pexels API key, configured below).', 'pagelayer'), ], ], ]; } static function get_installed_mcp_adapter_file(){ if(!function_exists('get_plugins')){ require_once ABSPATH . 'wp-admin/includes/plugin.php'; } foreach(array_keys(get_plugins()) as $plugin_file){ if(0 === strpos($plugin_file, 'mcp-adapter/')){ return $plugin_file; } } return ''; } static function current_user_has_mcp_app_password(){ $user_id = get_current_user_id(); if(!$user_id || !class_exists('WP_Application_Passwords')){ return false; } foreach(\WP_Application_Passwords::get_user_application_passwords($user_id) as $app){ if(!empty($app['app_id']) && $app['app_id'] === self::$APP_PASSWORD_APP_ID){ return true; } } return false; } static function get_test_connection_status(){ $user_id = get_current_user_id(); if(!$user_id){ return ['ok' => false, 'message' => '']; } $stored = get_user_meta($user_id, self::$TEST_STATUS_META, true); if(!is_array($stored)){ return ['ok' => false, 'message' => '']; } return [ 'ok' => !empty($stored['ok']), 'message' => !empty($stored['message']) ? $stored['message'] : '', ]; } public static function save_test_connection_status($ok, $message){ $user_id = get_current_user_id(); if(!$user_id){ return; } update_user_meta($user_id, self::$TEST_STATUS_META, [ 'ok' => !empty($ok), 'message' => (string)$message, ]); } static $MCP_ADAPTER_DOWNLOAD_URL = 'https://github.com/WordPress/mcp-adapter/releases/latest/download/mcp-adapter.zip'; static $MCP_ADAPTER_GITHUB_API = 'https://api.github.com/repos/WordPress/mcp-adapter/releases/latest'; static function get_mcp_adapter_download_url(){ $response = wp_remote_get(self::$MCP_ADAPTER_GITHUB_API, array( 'headers' => array( 'Accept' => 'application/vnd.github+json', 'User-Agent' => 'Pagelayer/' . PAGELAYER_VERSION, ), 'timeout' => 30, )); if(is_wp_error($response)){ return self::$MCP_ADAPTER_DOWNLOAD_URL; } $body = wp_remote_retrieve_body($response); $data = json_decode($body, true); if(is_array($data) && !empty($data['assets'])){ foreach($data['assets'] as $asset){ if(!empty($asset['browser_download_url']) && false !== stripos($asset['name'], '.zip')){ return $asset['browser_download_url']; } } } return self::$MCP_ADAPTER_DOWNLOAD_URL; } }