30 days free. No credit card. Full access from the moment you connect your site.

Start free trial

v0.1.8 — F034 MCP client subsystem refactor

🧩 What's new

Feature 034 — MCP client subsystem refactor: self-describing subclasses + canonical filter-aware enumeration.

Every concrete MCP client class in includes/MCPClients/ now declares its own display metadata via six new methods on AbstractMCPClient — no more stranded metadata in the Renderer's private const. Enumeration collapses to a single canonical entry point that companion plugins can extend cleanly.

The six new methods on AbstractMCPClient

All backwards-compatible defaults — existing third-party subclasses that only implement the three original abstract methods (get_client_slug, get_client_name, get_config_snippet) continue to work unchanged:

MethodDefaultPurpose
get_icon(): string''Emoji / short display marker for sub-nav
get_description(): string''One-line translated description
get_config_file(): string''Config file path hint (untranslated)
get_top_level_key(): string''JSON/TOML top-level key (untranslated)
get_instructions(): string''Translated setup instructions
get_priority(): int100Sub-nav slot preference (WP-idiomatic; lower runs earlier)

Canonical enumeration

The eight built-in clients migrate their metadata verbatim from the (now-deleted) MCPClientsBlock::CLIENT_META const, with priorities 10, 20, 30, ..., 80 preserving byte-identical pre-refactor sub-nav order.

Enumeration collapses to AbstractMCPClient::get_all_registered_clients() — a single canonical entry point mirroring ConnectorProfileRegistry::get_profiles() (F021 pattern) line-for-line:

  1. Fires acrossai_mcp_client_classes filter with DEFAULT_CLIENT_CLASSES seed
  2. Validates each contributed FQN (is_string + class_exists + is_subclass_of → silent skip per SEC-013-008)
  3. Validates each subclass's slug against /[a-z0-9-]{1,64}/ (bad slug → _doing_it_wrong under WP_DEBUG + skip)
  4. Dedups by slug (duplicate → _doing_it_wrong under WP_DEBUG + later-wins)
  5. Sorts by (priority ASC, slug ASC)

The pre-F034 glob-based AbstractMCPClient::get_all_clients() (which ignored the filter) is deleted. MCPClientsBlock::render_body() shrinks from 32 lines to 6.

Third-party companion plugins

Add a new MCP client to the sub-nav in three steps:

namespace MyCompanyPlugin\MCPClients;
use AcrossAI_MCP_Manager\Includes\MCPClients\AbstractMCPClient;

class ZedClient extends AbstractMCPClient {
    public function get_client_slug(): string { return 'zed'; }
    public function get_client_name(): string { return __( 'Zed Editor', 'my-plugin' ); }
    public function get_config_snippet( string $server_url, string $auth_token ): array { /* ... */ }

    public function get_icon(): string { return '⚡'; }
    public function get_description(): string { return __( 'Zed collaborative AI editor', 'my-plugin' ); }
    public function get_config_file(): string { return '~/.config/zed/settings.json'; }
    public function get_top_level_key(): string { return 'mcpServers'; }
    public function get_instructions(): string { return __( '...', 'my-plugin' ); }
    public function get_priority(): int { return 45; } // Between GitHubCopilot (40) and Codex (50)
}
add_filter( 'acrossai_mcp_client_classes', function ( array $fqns ): array {
    $fqns[] = \MyCompanyPlugin\MCPClients\ZedClient::class;
    return $fqns;
} );

The client appears in the server-edit → Clients tab sub-nav with the declared metadata in the declared position. Full walkthrough at specs/034-mcp-client-metadata-refactor/quickstart.md on the branch.

No breaking changes

  • Zero admin-visible behaviour change (byte-identical sub-nav render for the eight built-in clients).
  • Existing acrossai_mcp_client_classes filter contract preserved verbatim.
  • Existing third-party subclasses that only implement the three original abstract methods continue to work — the six new methods all default to safe empty values.
  • No database schema changes, no admin UI changes, no REST route changes.

Safe to upgrade in place.

Test coverage

  • mcpclients PHPUnit suite: 86 tests / 181 assertions (up from 74/119 pre-F034)
  • Three new test files:
    • GetAllRegisteredClientsTest.php — enumeration + validation + filter + priority sort
    • ConcreteClientMetadataTest.php — data-provider parameterized over all 8 built-ins × 6 metadata fields
    • MCPClientsBlockRenderTest.php — DOM byte-identity + hostile third-party subclass XSS regression (fake subclass returning <script>alert(1)</script> verified to render escaped, not raw)

Durable memory captured

  • D35 / DEC-F034-SELF-CONTAINED-SUBSYSTEM-CONTRACT — the architectural pattern: any subsystem with an abstract base + filter-based subclass contribution + per-subclass display metadata MUST declare metadata on the abstract (never as a private const on a Renderer) AND MUST expose enumeration via ONE canonical static method.
  • A18 — scoped carve-out from A12 for tests/bootstrap.php in-memory WP function stubs pattern that lets pure-PHP suites cover code that fires WP hooks without a full WP bootstrap.

Follow-up work

  • F036 (planned) — public discovery API ConnectionMethodRegistry under public/Discovery/ for a planned BuddyBoss add-on. Depends on F034 (this release) as a hard prerequisite. Engineering brief at docs/planings-tasks/036-connection-method-discovery-api.md.

References

  • Feature PR: #48 (merged as 9c3876f)
  • Release PR: #49 (merged as 31709ff)
  • Spec-kit docs: specs/034-mcp-client-metadata-refactor/
  • Sibling pattern reference: includes/Connectors/AbstractConnectorProfile.php + includes/Connectors/ConnectorProfileRegistry.php (F021)

Keep reading