=== AcrossAI MCP Manager === Contributors: raftaar1191 Tags: mcp, ai, claude, chatgpt, cursor Requires at least: 7.0 Requires PHP: 8.1 Tested up to: 7.0 Stable tag: 0.2.9 License: GPL-2.0-or-later License URI: https://www.gnu.org/licenses/gpl-2.0.html Connect WordPress to Claude, ChatGPT, Cursor, VS Code, Copilot, Gemini and any MCP-compatible AI client — with per-server access control. == Description == MCP Manager connects your WordPress site to any MCP-compatible AI client — Claude, ChatGPT, Cursor, VS Code, GitHub Copilot, Gemini, and more — so those clients can safely read, edit, and act on your site. Every headline section below links to the full documentation at [acrossai.co/doc-category/mcp-manager](https://acrossai.co/doc-category/mcp-manager/) — the docs are the source of truth and get updated first. Source and issues live at [github.com/acrossai-co/acrossai-mcp-manager](https://github.com/acrossai-co/acrossai-mcp-manager). = Key Features = * **Multiple MCP servers per site** — create, enable, disable, and configure independently. → [Docs](https://acrossai.co/docs/mcp-servers/) * **Multi-client connection guides** — copy-paste-ready configs for Claude Desktop, VS Code + Copilot, GitHub Copilot, ChatGPT, Cursor, Gemini CLI, and custom clients. → [Docs](https://acrossai.co/docs/mcp-connect-a-client/) * **CLI browser-approval flow** — let terminal users connect with one command; approval happens in a browser tab. → [Docs](https://acrossai.co/docs/mcp-cli-connections/) * **WP-CLI (STDIO) transport** — local clients can connect through a WP-CLI subprocess with no network credential transmission. → [Docs](https://acrossai.co/docs/mcp-wp-cli-stdio/) * **Application Passwords under the hood** — WordPress-native credentials, one-click generation, and revocation from the user profile page. → [Docs](https://acrossai.co/docs/mcp-application-passwords/) * **Per-server tool and ability curation** — pick exactly which WordPress abilities each MCP server exposes as callable tools. → [Docs](https://acrossai.co/docs/mcp-tools-and-abilities/) * **Per-server access control** — gate every MCP request by user, role, capability, or your own policy provider. → [Docs](https://acrossai.co/docs/mcp-access-control/) * **Frontend embeds** — shortcode + block to show your users how to connect their AI clients from your own site. → [Docs](https://acrossai.co/docs/mcp-embeds-shortcode-block/) = How It Works = 1. Install and activate the plugin ([step-by-step](https://acrossai.co/docs/mcp-install-and-activate/)) 2. Open **AcrossAI → MCP** in your WordPress admin 3. Pick your AI client tab (Claude, VS Code, ChatGPT, Cursor, Gemini, GitHub Copilot, or Custom) 4. Generate a new Application Password with one click 5. Copy the ready-made JSON config and paste it into your client 6. Restart your client — it now sees your site's abilities Longer walkthrough with screenshots: [Getting started → connect your first AI client](https://acrossai.co/docs/mcp-getting-started/). = Connection Types = MCP Manager ships with three connection styles out of the box, plus one optional paid add-on: * **MCP Client (npx bridge)** — the default. Paste a JSON config into Claude Desktop, VS Code, Cursor, etc. Uses `@automattic/mcp-wordpress-remote@latest` with a WordPress Application Password. → [Docs](https://acrossai.co/docs/mcp-connect-a-client/) * **CLI Connections (browser approval)** — one command in the terminal, one click in the browser, zero password copying. → [Docs](https://acrossai.co/docs/mcp-cli-connections/) * **WP-CLI (STDIO)** — local subprocess, no network credential transmission. Best for CI or local dev boxes. → [Docs](https://acrossai.co/docs/mcp-wp-cli-stdio/) * **AI Connectors (paid add-on)** — one-click Claude, ChatGPT, and Grok hosted-OAuth connectors. Requires the separate [AcrossAI AI Connectors plugin](https://acrossai.co/ai-connectors/) (14-day money-back). → [Docs](https://acrossai.co/docs/mcp-ai-connectors/) = Requirements = * WordPress 7.0 or higher * PHP 8.1 or higher * WordPress Application Passwords support (built-in since WP 5.6) == Installation == 1. Upload the plugin directory to `/wp-content/plugins/` 2. Activate the plugin through the 'Plugins' menu in WordPress 3. Navigate to Settings → MCP Manager to configure Or: 1. Go to Admin → Plugins → Add New 2. Search for "MCP Manager" 3. Click "Install Now" then "Activate" == Frequently Asked Questions == Full FAQ + troubleshooting lives at [acrossai.co/docs/mcp-faq-troubleshooting](https://acrossai.co/docs/mcp-faq-troubleshooting/). Quick answers below. = Are my credentials secure? = Yes. MCP Manager uses WordPress's native Application Passwords — each one is generated by WordPress, tied to your user, revocable from the profile page, and never stored in this plugin's own tables. Full detail: [Application passwords & security](https://acrossai.co/docs/mcp-application-passwords/). = Can I connect multiple AI clients to the same site? = Yes — generate a separate password (or CLI approval) per client. You can also run multiple MCP servers on the same site with different tool/ability sets and per-server access rules. See [MCP servers](https://acrossai.co/docs/mcp-servers/). = Which AI clients are supported? = Claude Desktop, ChatGPT, Cursor, VS Code (with Copilot), GitHub Copilot, Gemini CLI, and any custom MCP-compatible client. Adding a new client is a filter callback. See [Connecting an AI client](https://acrossai.co/docs/mcp-connect-a-client/). = Does it work on multisite? = Yes — each site in the network configures independently. = Do I need the paid AI Connectors add-on? = Only if you want the one-click hosted-OAuth flow for Claude, ChatGPT, or Grok. All other connection styles (MCP Client, CLI, WP-CLI STDIO) are free and shipped with this plugin. See [AI Connectors add-on](https://acrossai.co/ai-connectors/). == Support == * **Docs hub** — [acrossai.co/doc-category/mcp-manager](https://acrossai.co/doc-category/mcp-manager/) * **Troubleshooting & FAQ** — [acrossai.co/docs/mcp-faq-troubleshooting](https://acrossai.co/docs/mcp-faq-troubleshooting/) * **Source code + issue tracker** — [github.com/acrossai-co/acrossai-mcp-manager](https://github.com/acrossai-co/acrossai-mcp-manager) == Screenshots == 1. Settings page with client tabs for easy configuration 2. Copy-paste ready JSON configuration 3. One-click password generation 4. Per-provider configuration file locations and top-level keys == Changelog == = 0.2.9 = * **Dependencies — bump `acrossai-co/main-menu` `0.0.31` → `0.0.33`.** The upstream vendor renamed its "AI Connectors" baseline Add-ons entry to **AcrossAI Pro** in `0.0.32` — the shared Add-ons page (`admin.php?page=acrossai-addons`) and Dashboard card now advertise the renamed plugin (`acrossai-pro/acrossai-pro.php` install folder, `acrossai-pro` registry slug) instead of the former AI Connectors listing. `0.0.33` refreshed the AcrossAI Pro card copy — description now also mentions user access control across AcrossAI plugins — and points every AcrossAI Pro CTA (Add-ons card `more_url` / `learn_more_url`, Dashboard primary/secondary CTAs) at `https://acrossai.co/pricing/#pricing`. **No changes required in this plugin:** MCP Manager's `AddonsFilter::remove_self()` filters the `acrossai_addons` list by its own slug (`acrossai-mcp-manager`), so the vendor's baseline entry rename doesn't affect what shows on the Add-ons page here. The per-server-edit **Connectors/Integrations** tab still points at the separate `acrossai-ai-connectors` WordPress plugin (WP plugin folder slug, distinct from the vendor's addons-registry slug), so the promo card + CTA are unaffected. Transitive: `automattic/jetpack-autoloader` `v5.0.21` → `v5.0.23` (patch). * **Internal: `ACROSSAI_MCP_MANAGER_VERSION` constant + `Stable tag` bumped to `0.2.9` matching the plugin header.** = 0.2.8 = * **⚠️ Security — Behavior change — MCP `resources/read` and `prompts/get` requests are now gated by the per-server Access Control rule (F1 fix).** Prior to 0.2.8 the plugin only hooked the vendor's `mcp_adapter_pre_tool_call` filter. The two sibling pre-dispatch filters — `mcp_adapter_pre_resource_read` (`vendor/wordpress/mcp-adapter/includes/Handlers/Resources/ResourcesHandler.php:138`) and `mcp_adapter_pre_prompt_get` (`.../Prompts/PromptsHandler.php:157`) — had no subscriber. Combined with the Feature 042 transport layer intentionally deferring to F015 for rule-configured servers (returning the vendor `'read'` default so any authenticated user passes the transport gate, on the assumption that F015 would then enforce), any authenticated user could `POST {"method":"resources/read","params":{"uri":"…"}}` (or `{"method":"prompts/get"}`) against a server configured "Editors only" and the operator's rule was **never consulted**. 0.2.8 extracts the enforcement body of `gate_mcp_tool_call` into a shared private `apply_ac_gate()` helper and adds two sibling public callbacks — `gate_mcp_resource_read` + `gate_mcp_prompt_get` — wired adjacent to the existing tool-call filter in `Main::define_public_hooks()`. Deny path returns a `WP_Error` with a `gate` value of `mcp_resource_read` / `mcp_prompt_get` (previously always `mcp_tool_call`). Observability hooks are reused: `acrossai_mcp_access_control_denied` and `acrossai_mcp_access_control_missing_server` now fire from three MCP boundary sites — the `$context` arg discriminates and the `$subject` arg is polymorphic (tool name / resource URI / prompt name depending on which gate fired). New PHPUnit coverage at `tests/phpunit/Includes/AccessControl/McpDispatchGatesTest.php` — fail-open parity per gate, missing-server observability hook subject-arg carries URI/prompt name, three-context deny-hook contract, all three vendor filter registrations verified. * **Operator action if you were relying on the resource/prompt bypass**: audit any server that exposes MCP resources or prompts AND has a rule configured. Non-privileged users who previously succeeded on `resources/read` / `prompts/get` will now receive HTTP 403 with the same `acrossai_mcp_access_denied` error code the tool-call gate has emitted since 0.0.7. Broaden the rule in the **Access Control** tab if the previous fail-open was intended (unlikely — most operators wanted the rule to apply). * **⚠️ Security — Behavior change — F042 transport layer now fails CLOSED when the wpb-access-control vendor package is unavailable (F2 fix).** Prior to 0.2.8 both access-control gates failed OPEN under the same condition: `AcrossAI_MCP_Access_Control::gate_mcp_tool_call` returned `$args` (allow) when `class_exists( AccessControlManager::class )` was false; `TransportPermissionDefault::filter_default_capability` returned the vendor `'read'` default under the mirror condition (`class_exists( RuleQuery::class )`). Because both gates degraded in the same direction, a single dependency failure — composer breakage, autoloader race on `rest_api_init`, missed dependency after site clone, vendor package rename — collapsed the entire two-gate stack, letting every authenticated user reach every tool on every server. 0.2.8 inverts F042's missing-vendor branch to return `'manage_options'` instead. Paired with F015's fail-open on the same condition, the stack now degrades to **admin-only** rather than "wide open to every logged-in user" when the vendor library is missing. Class docblock on `TransportPermissionDefault` explicitly documents the intentional asymmetry — "F015 fails open + F042 fails closed = admin-only when the vendor breaks" — so the invariant survives future refactors. The `class_exists()` call is now behind a protected `has_access_control_library()` seam to enable direct test coverage (`tests/phpunit/Includes/AccessControl/TransportPermissionMissingVendorTest.php`). * **Operator action**: none in the healthy-vendor case (Composer install intact). If your deploy pipeline can produce a state where `vendor/wpboilerplate/access-control` is absent, non-admin MCP traffic will now receive 401 instead of full access. Restore the vendor package and MCP endpoints resume normal per-rule enforcement. * **Admin — Server list at `?page=acrossai_mcp_manager` redesigned for a tighter, more actionable layout.** Column changes: **removed** Slug (redundant with the Route/Route Namespace columns and the Name column's inline edit link), Route Namespace + Route **merged** into a single `Route` column displayed as `/` with duplicate slashes at the join collapsed, **removed** Version (still surfaced on the per-server-edit Overview tab). Final column order: `☐ | Name | Status | Registered From | Route | Actions`. **Actions column extended** — the existing Enable/Disable toggle is now bundled with 5 quick-access buttons: **Edit** (primary-styled) links to the server-edit page, and four per-tab quick-links (**Connectors**, **Access Control**, **Abilities**, **MCP Clients**) jump directly to the corresponding tab on the edit page. Quick-links render as subtle rounded pill-badges with a dashicon prefix (`dashicons-admin-plugins` / `dashicons-shield` / `dashicons-superhero-alt` / `dashicons-admin-users`) — lighter than full buttons but more scannable than plain text links. New `.acrossai-actions-cell` flex wrapper in `src/scss/backend.scss` keeps the button cluster wrapping cleanly on narrow viewports; Status + Registered From columns capped at 120px so the freed horizontal space flows to Route + Actions. Preserves the existing per-row nonce on the Enable/Disable toggle. No DB or REST changes. * **UI — AI Connectors tab renamed to "Connectors/Integrations".** The per-server-edit tab label at `?page=acrossai_mcp_manager&action=edit&server=&tab=ai-connectors` now reads **Connectors/Integrations** instead of "AI Connectors". Tab slug (`ai-connectors`) is intentionally unchanged so the last-wins tab-registration override from the `acrossai-ai-connectors` companion plugin keeps landing on the same placeholder — no companion-plugin coordination required. `AiConnectorEmbedTransport::label()` (a separate F037 embed transport) is left as-is; only the per-server-edit tab label is affected. * **Internal: `ACROSSAI_MCP_MANAGER_VERSION` constant + `Stable tag` bumped to `0.2.8` matching the plugin header.** = 0.2.7 = * **Docs — Fixes for the WordPress.org plugin import.** Trimmed the `Tags:` header from 8 tags to 5 (`mcp, ai, claude, chatgpt, cursor`) — WordPress.org silently drops any tag past the fifth; the surplus (`copilot`, `vscode`, `gemini`) never showed up in the plugin listing anyway. Condensed the changelog for versions prior to `0.2.0` into a single "Earlier versions" pointer to the GitHub Releases page so the full changelog stays under WordPress.org's 5,000-word cap (previously ~8,258 words → the older entries were truncated on import and never rendered on the plugin page). Same information, still discoverable — just hosted on GitHub instead of duplicated in `README.txt`. * **Internal: `ACROSSAI_MCP_MANAGER_VERSION` constant + `Stable tag` bumped to `0.2.7` matching the plugin header.** = 0.2.6 = * **Refactor — `ConnectionMethodRegistry::get_ai_connectors()` now sources its DTOs from a new WordPress filter `acrossai_mcp_manager_discovery_ai_connectors` instead of calling the companion plugin's `ConnectorProfileRegistry` class directly.** The paid companion (`acrossai-pro` 0.8.0+) hooks the new filter and returns the same DTO shape from its own registry — Discovery's `ai_connector` category behaves identically for end users. Removes a hardcoded FQN string (`\AcrossAI_AI_Connectors\Includes\Connectors\ConnectorProfileRegistry`) from the free plugin so future companion renames / restructures don't silently break Discovery. Fail-safe unchanged: with no companion active, the filter returns an empty array and the `ai_connector` category is omitted from Discovery — no fatal, no warning. * **Internal: `ACROSSAI_MCP_MANAGER_VERSION` constant + `Stable tag` bumped to `0.2.6` matching the plugin header.** = 0.2.5 = * **⚠️ Security — Behavior change — MCP endpoints default to administrators only when no Access Control rule is set (Feature 042).** Previously, an MCP server with no rule configured in its **Access Control** tab was fail-open at the tool-call layer — any authenticated user could reach the server's `/wp-json/{namespace}/{route}` endpoint. Starting with 0.2.5, a new runtime filter (`mcp_adapter_default_transport_permission_user_capability`, hooked by the new `\AcrossAI_MCP_Manager\Includes\AccessControl\TransportPermissionDefault` singleton) hard-blocks non-admins at the REST `permission_callback` stage whenever the wpb-access-control dropdown reads **"No user access added by admin"**. Together with the existing F015 `mcp_adapter_pre_tool_call` gate, this ships a **two-filter, per-server permission stack** (defense-in-depth): filter 1 hard-stops non-admin traffic on rules-less servers; filter 2 does precise per-rule enforcement on rule-configured servers. **Neither filter has any hardcoded server slug or "default server special case"** — both resolve the current server independently per request (filter 1 via URL route → `MCPServerQuery` lookup; filter 2 via `$server->get_server_id()`). Adding a server via **Add New Server** applies both filters automatically. **Zero DB writes** — the runtime filter approach replaced an earlier DB-row-seeding attempt (dropped via force-push on PR #71) that conflicted with the vendor UI's admin state model. Ships with a static info banner on the **Access Control** tab describing the default policy + how to broaden access via the vendor dropdown (Anyone / Authenticated users / role / user / capability). **26 PHPUnit tests** across 2 files at `tests/phpunit/Includes/AccessControl/` (`TransportPermissionDefaultTest` + `TransportPermissionRoleMatrixTest`) cover every filter-callback branch in isolation plus 6 user roles × 4 rule shapes × ≥4 servers per test end-to-end (including a 5×4 truth-table matrix proving per-server independence). * **Operator action if you were relying on the fail-open default**: open each MCP server's **Access Control** tab, set the "Who can access" dropdown to the intended rule (e.g. `WordPress role → Editor` or `Anyone` for the previous behavior), and Save. Rules-less servers are now admin-only until you configure them. * **UX — Cache-exclusion warning surfaces in the shared Notices submenu when the CLI (npm/npx) connection flow is enabled (Feature 041).** When **Settings → MCP → Allow CLI connections via npm / npx** (`acrossai_mcp_npm_login_enabled`) is ON, a persistent warning card now appears in the AcrossAI **Notices** submenu (and in the WP-native dismissible summary) instructing operators to exclude the CLI auth URL (`https:///acrossai-mcp-manager/`) from page caching. The URL carries per-request nonces + single-use auth codes; caching plugins that treat it as static content silently break the login flow. The existing inline banner in the settings section is preserved — this feature adds a second, higher-visibility surface that co-admins and future visitors see even if they never open the specific settings section. Notice id `acrossai_mcp_manager_cli_auth_cache_exclusion`, source `MCP Manager`, gated on the option value. Uses `FrontendAuth::get_base_url()` for the URL — any future change to the CLI landing route propagates automatically. * **Internal: `ACROSSAI_MCP_MANAGER_VERSION` constant + `Stable tag` bumped to `0.2.5` matching the plugin header.** = 0.2.4 = * **Dependencies — bump `wpboilerplate/wpb-access-control` `2.0.0` → `3.1.0`.** Two vendor changes surface in the per-server **Access Control** tab (`?tab=access-control`): (1) new **"Any logged-in user"** option in the *Who can access* dropdown — backed by the new `TYPE_AUTHENTICATED` sentinel in `AccessControlManager` (returns `true` iff `$user_id > 0`), and (2) the existing "Everyone (no restriction)" option is relabelled **"Public (no login required)"** — pure UI relabel, same underlying behavior (`TYPE_EVERYONE` unchanged, existing rules unaffected). v3.0.0 also removed the built-in `BuddyBossProfileTypeProvider` + `MemberPressMembershipProvider` (moved to a separate `acrossai/user-access-pro` add-on); this plugin never wired them into the *Who can access* dropdown, so removal has no visible effect here. Docblock at `includes/Main.php` refreshed to drop the stale BuddyBoss/MemberPress reference. No data migration required. * **Internal: `ACROSSAI_MCP_MANAGER_VERSION` constant + `Stable tag` bumped to `0.2.4` matching the plugin header.** = 0.2.3 = * **UX — In-context nudges to install the AcrossAI Abilities Manager add-on.** When the sibling `acrossai-abilities-manager` plugin is not active, the server-edit **Abilities** and **Tools** tabs (`?tab=abilities` / `?tab=tools`) now surface a small WordPress-native `notice-info` block above the picker with a link to the shared Add-ons page (`admin.php?page=acrossai-addons`). Without the add-on both pickers only list the three core abilities WordPress ships by default (`core/get-environment-info`, `core/get-site-info`, `core/get-user-info`); the add-on registers a rich library of built-in abilities that populate both surfaces. Detection is a plain `is_plugin_active()` check — same message + same link covers both "not installed" and "installed-but-off" states. Placed after the existing "Server is disabled" warning and before the `wp_get_abilities()` capability check, so the nudge is visible even when the abilities API itself is missing. * **UI — AcrossAI brand logo on the AI Connectors placeholder tab.** Replaces the hand-rolled interconnected-nodes SVG on the AI Connectors placeholder promo (`?tab=ai-connectors` when the `acrossai-ai-connectors` companion is missing / inactive) with the same brand SVG the vendor uses on the shared Add-ons page (`https://acrossai.co/wp-content/uploads/2026/07/acrossai-logo-2.svg`). New `LOGO_URL` class constant on `AIConnectorsPromoTab`; icon markup swapped from an inline `` inside a gradient tile to a plain `AcrossAI` tag; deleted the private `render_network_svg()` method (dead code). CSS: dropped `.acai-aic-promo__icon` (gradient background + colored SVG) in favor of `.acai-aic-promo__logo` (`height: 48px; max-width: 180px; object-fit: contain`) so the brand mark sits cleanly without a decorative background box. * **Refactor — Renamed the "MCP Tracker" tab to "Logs".** The per-server tab formerly reached at `?tab=mcp-tracker` is now `?tab=mcp-log`, and the tab-bar label reads **Logs** instead of **MCP Tracker**. Priority slot 80 preserved so the tab-bar ordering is unchanged. Class name `McpTrackerTab` kept (internal identifier) along with the body copy that identifies the third-party [MCP Tracker plugin on WordPress.org](https://wordpress.org/plugins/mcp-tracker/) (WPVMCPT) product name — those aren't the tab label, they're a specific product reference. Deep links to the old `?tab=mcp-tracker` fall through to Registry's "first surviving tab" default (Overview) rather than 404. Test fixture updated: five `'mcp-tracker'` occurrences in `RegistryTest.php` migrated to `'mcp-log'`. * **Docs — Rewrote `README.txt` as a lean docs-hub pointer.** The plugin's WordPress.org readme now defers to [acrossai.co/doc-category/mcp-manager](https://acrossai.co/doc-category/mcp-manager/) as the source of truth for every feature description — copy lives in one place instead of drifting between two. Description condensed to a two-line multi-client pitch; **Key Features** reshaped to reflect the current feature set (multiple servers per site, per-server tool/ability curation, per-server access control, frontend embeds, CLI + WP-CLI STDIO transports) with each bullet linking to its docs page; **How It Works** trimmed to the 6-step get-started path; new **Connection Types** section calls out the four supported paths (MCP Client, CLI Connections, WP-CLI STDIO, and the paid [AI Connectors add-on](https://acrossai.co/ai-connectors/)); **Requirements** bumped to WordPress 7.0+ / PHP 8.1+ (matches the plugin header — old readme had drifted to 5.9 / 7.4); FAQ trimmed from 7 questions to 5 with a new "Do I need the paid AI Connectors add-on?" entry; new **Support** section links to docs hub, FAQ page, and GitHub issue tracker. Header tags expanded (`chatgpt`, `cursor`, `gemini` added). Deleted the stale post-F040 **Experimental Direct Claude Connectors** section, the CLI-flow deep dive, and the Provider Configuration Paths list — those live in the docs now. * **Internal: `ACROSSAI_MCP_MANAGER_VERSION` constant + `Stable tag` bumped to `0.2.3` matching the plugin header.** = 0.2.2 = * **Notices — migrated persistent-condition banners to the cross-plugin `acrossai_notices` filter.** The "MCP adapter package missing" and "wpb-access-control library missing" warnings no longer render as inline `admin_notices` banners on every screen. They're pushed into the shared collection introduced in `acrossai-co/main-menu` 0.0.30, which surfaces them in two consolidated places: (1) a **Notices submenu** under the AcrossAI parent menu (with a count bubble; the page also stays reachable when the count is zero and renders an "All clear" empty state per the 0.0.31 fix) and (2) a **single WP-native dismissible summary** on every other admin page. Dismissal is now fingerprint-based (per-user meta `_acrossai_notices_summary_fp`) — adding, resolving, or renaming a notice re-shows the summary automatically. **Deletions**: `Notices::render_missing_adapter_notice`, `Notices::handle_adapter_notice_dismissal`, `ADAPTER_DISMISS_META_KEY`, `ADAPTER_DISMISS_NONCE_ACTION`, `AcrossAI_MCP_Access_Control::maybe_show_library_notice`, and the US4 dismiss-persistence handler in `src/js/backend.js` — all obsoleted by the shared summary. **Additions**: `Notices::register_shared_notices()` returns records with ids `acrossai_mcp_manager_adapter_missing` (type `error`) and `acrossai_mcp_manager_wpb_access_control_missing` (type `warning`), both scoped with `source: 'MCP Manager'`. One-shot action-result flashes (`?notice=`) stay on the standard `admin_notices` hook — page-scoped transient messages don't fit the shared collection model. * **UI — Redesigned the AI Connectors placeholder tab as a centered sales card.** When the `acrossai-ai-connectors` companion add-on is not installed or not active, the AI Connectors tab on the server-edit page (`?page=acrossai_mcp_manager&action=edit&server=&tab=ai-connectors`) now renders a vertically-centered polished card sourced from https://acrossai.co/ai-connectors/ — headline ("Connect WordPress to Claude, ChatGPT & Grok in one click"), supported-client pills (Claude · ChatGPT · Grok), four benefit bullets, a purple CTA ("Install add-on" / "Activate add-on" depending on companion state), a "Learn more" link, and a 14-day money-back trust line. State resolution unchanged — Registry's last-wins dedup at priority 35 still swaps the placeholder out for the companion's real `AIConnectorsTab` the moment the add-on activates. * **Dependencies: bump `acrossai-co/main-menu` `0.0.29` → `0.0.31`.** 0.0.30 shipped the shared `acrossai_notices` filter + Notices submenu + `SummaryNoticeEmitter`. 0.0.31 fixed a "Sorry, you are not allowed to access this page." error on direct visits to `admin.php?page=acrossai-notices` when the notice count was zero (page callback is now always wired; empty-state sidebar row is hidden via inline `