admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('gosmtp_ajax'),
'endpoint_url' => trailingslashit(home_url()) . ltrim(self::$ABILITIES_ENDPOINT, '/'),
'i18n' => [
'installing' => esc_html__('Installing...', 'gosmtp'),
'activating' => esc_html__('Activating...', 'gosmtp'),
'updating' => esc_html__('Updating...', 'gosmtp'),
'generating' => esc_html__('Generating...', 'gosmtp'),
'testing' => esc_html__('Testing...', 'gosmtp'),
'genErrTitle' => esc_html__('Could not generate the password.', 'gosmtp'),
'testOkPrefix' => esc_html__('Success:', 'gosmtp'),
'testFailPrefix'=> esc_html__('Failed:', 'gosmtp'),
],
]);
// Status probes (kept cheap; safe to run on each render).
$abilities_api_available = function_exists('wp_register_ability');
$adapter_active = is_plugin_active('mcp-adapter/mcp-adapter.php');
$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();
$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 = esc_html__('your-application-password', 'gosmtp');
$user_placeholder = $username ? $username : esc_html__('', 'gosmtp');
$adapter_installed_version = $adapter_installed ? self::get_installed_mcp_adapter_version() : '';
$adapter_latest_version = '';
$adapter_update_available = false;
if($adapter_installed && $adapter_installed_version){
$release = self::get_mcp_adapter_release();
if(!empty($release['version']) && version_compare($release['version'], $adapter_installed_version, '>')){
$adapter_latest_version = $release['version'];
$adapter_update_available = true;
}
}
?>
esc_html__('Abilities', 'gosmtp'), 'state' => $abilities_api_available ? 'done' : 'todo'],
['label' => esc_html__('MCP Adapter', 'gosmtp'),'state' => $adapter_active ? 'done' : 'todo'],
['label' => esc_html__('Password', 'gosmtp'), 'state' => $has_app_password ? 'done' : 'todo'],
['label' => esc_html__('Test', 'gosmtp'), 'state' => !empty($test_status['ok']) ? 'done' : 'todo'],
];
foreach($step_states as $idx => $st){
echo '
';
echo '' . ($st === 'done' ? '✓' : esc_html((string)($idx + 1))) . ' ';
echo '' . esc_html($chips[$idx]['label']) . ' ';
echo '
';
}
?>
' . sprintf(esc_html__('Next up: %s', 'gosmtp'), '
' . esc_html($next_step) . ' ') . '';
}else{
echo '
' . esc_html__('All steps complete. Your AI client can now connect.', 'gosmtp') . '
';
}
?>
' . esc_html__('GoSMTP exposes the abilities listed below. They are picked up automatically by any installed MCP adapter and surfaced to AI clients as tools.', 'gosmtp') . '';
echo wp_kses_post(self::render_abilities_list());
}else{
echo '
' . esc_html__('The WordPress Abilities API ships in WordPress 6.9+. GoSMTP 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.', 'gosmtp') . '
';
}
?>
' . esc_html__('The MCP Adapter plugin is installed and active. Your site now exposes an MCP server that AI clients can connect to.', 'gosmtp') . '';
if($adapter_update_available){
echo '
' . sprintf(esc_html__('A newer version of the MCP Adapter is available (installed: %1$s, latest: %2$s).', 'gosmtp'), '' . esc_html($adapter_installed_version) . ' ', '' . esc_html($adapter_latest_version) . ' ') . '
';
echo '
' . esc_html__('Update MCP Adapter', 'gosmtp') . ' ';
}
}elseif($adapter_installed){
echo '
' . esc_html__('The MCP Adapter is installed but not active. Activate it to enable the MCP server.', 'gosmtp') . '
';
echo '
' . esc_html__('Activate MCP Adapter', 'gosmtp') . ' ';
}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. GoSMTP requires the MCP Adapter to expose its abilities to AI clients.', 'gosmtp') . '
';
echo '
' . esc_html__('Install MCP Adapter', 'gosmtp') . ' ';
}
?>
' . esc_html(($test_ok ? __('Success: ', 'gosmtp') : __('Failed: ', 'gosmtp')) . $test_message) . '
';
}else{
echo '
';
}
?>
' . wp_json_encode([
'siteUrl' => $site_url,
'mcpServerUrl' => $mcp_server_url,
'endpointUrl' => $endpoint_url,
'username' => $username,
'passwordHolder' => $app_pass_placeholder,
'userPlaceholder'=> $user_placeholder,
'serverName' => 'gosmtp-site',
'adapterActive' => $adapter_active,
'hasAppPassword' => $has_app_password,
'i18n' => [
'copy' => esc_html__('Copy snippet', 'gosmtp'),
'copied' => esc_html__('Copied!', 'gosmtp'),
'installing' => esc_html__('Installing...', 'gosmtp'),
'activating' => esc_html__('Activating...', 'gosmtp'),
'updating' => esc_html__('Updating...', 'gosmtp'),
'generating' => esc_html__('Generating...', 'gosmtp'),
'testing' => esc_html__('Testing...', 'gosmtp'),
'genErrTitle' => esc_html__('Could not generate the password.', 'gosmtp'),
'testOkPrefix' => esc_html__('Success:', 'gosmtp'),
'testFailPrefix'=> esc_html__('Failed:', 'gosmtp'),
],
]) . '';
// Segmented tab bar
$clients = [
'claude-desktop' => ['label' => esc_html__('Claude Desktop', 'gosmtp'), 'icon' => 'C'],
'claude-code' => ['label' => esc_html__('Claude Code CLI', 'gosmtp'), 'icon' => '>_'],
'cursor' => ['label' => esc_html__('Cursor', 'gosmtp'), 'icon' => 'Cu'],
'vscode' => ['label' => esc_html__('VS Code', 'gosmtp'), 'icon' => 'VS'],
'antigravity' => ['label' => esc_html__('Antigravity', 'gosmtp'), 'icon' => 'AG'],
'opencode' => ['label' => esc_html__('OpenCode', 'gosmtp'), 'icon' => 'OC'],
'gemini-cli' => ['label' => esc_html__('Gemini CLI', 'siteseo-pro'), 'icon' => 'G', 'deprecated' => true],
];
echo '
';
$first = true;
foreach($clients as $id => $data){
$badge = '';
if(!empty($data['deprecated'])){
$badge = ' ' . esc_html__('Deprecated', 'gosmtp') . ' ';
}
echo '' . esc_html($data['label']) . wp_kses_post($badge) . ' ';
$first = false;
}
?>
' . esc_html__('No GoSMTP abilities are currently exposed. Activate the MCP Adapter to surface them.', 'gosmtp') . '
';
}
$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']) . ' ';
}
if(!empty($ability['pro'])){
$html .= '' . esc_html__('Pro', 'gosmtp') . ' ';
}
$html .= ' ';
}
$html .= ' ';
$html .= '
';
}
$html .= '
';
return $html;
}
/**
* The catalogue of GoSMTP abilities exposed to MCP clients. Mirrors the
* abilities registered in main/abilitiesregister.php (Free) and
* main/abilitiesregister.php in Pro. The Pro section is only merged when
* the GoSMTP Pro plugin is installed and active.
*
* @return array
*/
static function get_registered_abilities(){
$free = [
esc_html__('Settings', 'gosmtp') => [
[
'label' => esc_html__('Get GoSMTP Settings', 'gosmtp'),
'description' => esc_html__('Returns global from email/name, force flags, return path and logging toggles. Credentials are never exposed.', 'gosmtp'),
],
],
esc_html__('Mailer', 'gosmtp') => [
[
'label' => esc_html__('List Configured Mailers', 'gosmtp'),
'description' => esc_html__('Lists configured SMTP connections with their nickname, mailer type and backup connection.', 'gosmtp'),
],
],
esc_html__('Test', 'gosmtp') => [
[
'label' => esc_html__('Send a Test Email', 'gosmtp'),
'description' => esc_html__('Sends a test email through the configured mailer and reports the result.', 'gosmtp'),
],
],
];
// Allow GoSMTP Pro to register additional abilities.
return apply_filters('gosmtp_registered_abilities', $free);
}
/**
* Scan installed plugins for the MCP Adapter (folder prefix: mcp-adapter/).
*
* @return string
*/
static function get_installed_mcp_adapter_file(){
if(!function_exists('get_plugins')){
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$all_plugins = get_plugins();
$target_file = 'mcp-adapter/mcp-adapter.php';
if(isset($all_plugins[ $target_file ])){
return $target_file;
}
return '';
}
/**
* Read the installed MCP Adapter version from the plugin headers.
*
* @return string Empty string when the adapter is not installed.
*/
static function get_installed_mcp_adapter_version(){
$file = self::get_installed_mcp_adapter_file();
if('' === $file){
return '';
}
if(!function_exists('get_plugins')){
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$all_plugins = get_plugins();
if(!isset($all_plugins[ $file ]['Version'])){
return '';
}
return (string)$all_plugins[ $file ]['Version'];
}
/**
* Does the current user already have an MCP app password created by GoSMTP?
*
* @return bool
*/
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;
}
/**
* Read the saved test-connection status for the current user.
*
* @return array
*/
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'] : '',
];
}
/**
* Persist the test-connection status for the current user.
*
* @param bool $ok
* @param string $message
* @return void
*/
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,
]);
}
// Fetch the latest MCP Adapter release info from GitHub (cached 1 day).
static function get_mcp_adapter_release(){
$cached = get_transient(\GOSMTP\Abilities::$MCP_ADAPTER_RELEASE_CACHE);
if(false !== $cached && is_array($cached)){
return $cached;
}
$response = wp_remote_get(\GOSMTP\Abilities::$MCP_ADAPTER_RELEASE_URL, [
'timeout' => 10,
'headers' => ['Accept' => 'application/vnd.github+json'],
]);
if(is_wp_error($response) || 200 !== wp_remote_retrieve_response_code($response)){
return [];
}
$body = json_decode(wp_remote_retrieve_body($response), true);
if(!is_array($body) || empty($body['tag_name']) || empty($body['assets'][0]['browser_download_url'])){
return [];
}
$payload = [
'version' => ltrim((string)$body['tag_name'], 'v'),
'download_url' => esc_url_raw($body['assets'][0]['browser_download_url']),
];
set_transient(\GOSMTP\Abilities::$MCP_ADAPTER_RELEASE_CACHE, $payload, DAY_IN_SECONDS);
return $payload;
}
}