__( 'Setup required', 'acrossai-mcp-manager' ), 'description' => self::message(), 'category' => 'acrossai-mcp', 'meta' => array( 'mcp' => array( // NOT public: this must never surface through // discover-abilities. It reaches a client only by being // placed in a specific server's tool list (SEC-002). 'public' => false, 'type' => 'tool', ), ), 'input_schema' => array( 'type' => 'object', 'properties' => array(), 'additionalProperties' => false, 'default' => array(), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'message' => array( 'type' => 'string', 'description' => __( 'What the site administrator must do before this server can offer any tools.', 'acrossai-mcp-manager' ), ), ), ), 'execute_callback' => static function (): array { return array( 'message' => self::message() ); }, // Same bar as listing the server's tools. This discloses only a // public plugin name, and carries no privilege of its own. 'permission_callback' => static function (): bool { return is_user_logged_in(); }, ) ); } /** * The operator-facing sentence, used as BOTH the tool description and its * return value so the message lands whether a client reads the list or * calls the tool. * * Translatable like every other string in the plugin (clarification Q3). An * AI client on a localised site receives it in that site's language; * hardcoding English would leave the only untranslated string in the * plugin, which a future contributor would "fix" without knowing why. * * Discloses the add-on's public name only — no paths, versions, or site * configuration. * * @since 0.1.0 * @return string */ public static function message(): string { return __( 'This MCP server requires the AcrossAI Abilities Manager plugin to be installed and activated. No tools are available until then. Ask the site administrator to install it from the AcrossAI Add-ons page, or to change this server\'s type.', 'acrossai-mcp-manager' ); } /** * Register the ability category this plugin owns. * * Loader-wired to `wp_abilities_api_categories_init` per A1. Must run before * `register()` assigns an ability to it; WP fires the categories hook ahead * of `wp_abilities_api_init`, so the ordering is the platform's, not ours. * * Guarded on the function existing so a site without the Abilities API * degrades silently rather than fataling (§V: optional integrations). * * @since 0.1.0 * @return void */ public static function register_category(): void { if ( ! function_exists( 'wp_register_ability_category' ) ) { return; } wp_register_ability_category( self::CATEGORY, array( 'label' => __( 'AcrossAI MCP', 'acrossai-mcp-manager' ), 'description' => __( 'Diagnostic entries owned by the AcrossAI MCP Manager plugin.', 'acrossai-mcp-manager' ), ) ); } }