Context
The feature/mcp-oauth branch adds an MCP server at /wp-json/mcp/mcp-oauth-server with a full OAuth 2.1 flow. MCP clients such as Claude Code use two RFC-mandated discovery documents to start the handshake:
/.well-known/oauth-protected-resource (RFC 9728) — advertises the MCP resource
/.well-known/oauth-authorization-server (RFC 8414) — lists all OAuth endpoints
Both documents and the OAuth flow endpoints (/oauth/authorize, /oauth/token, etc.) are served via WordPress rewrite rules that are registered and flushed during plugin activation.
Bug & Workaround
Symptom: After deploying the plugin (or on a fresh activation), MCP clients report "couldn't reach the MCP server". Both /.well-known documents and /wp-json/mcp/mcp-oauth-server return HTTP 404.
Root cause (short version): The MCP OAuth subscribers that register and flush the rewrite rules are not wired into the activation routine, so WordPress never writes the new rules to the database on first activation.
Workaround: Go to Settings → Permalinks and click Save Changes (no modification needed). This triggers flush_rewrite_rules() and immediately makes all MCP endpoints reachable.
Acceptance criteria
- Activating WP Rocket on a clean site immediately makes
/.well-known/oauth-authorization-server return a valid RFC 8414 JSON document — no manual permalink flush required.
GET /wp-json/mcp/mcp-oauth-server (unauthenticated) returns HTTP 401 with a WWW-Authenticate: Bearer header (not 404).
- Connecting Claude Code to the MCP URL starts the OAuth flow without any manual setup step.
- Existing activation behaviour (htaccess, cache dirs, capabilities, preload, performance hints) is unaffected.
Additional information
Root cause 1 — MCP subscribers absent from the activation container
Activation::activate_plugin() (inc/Engine/Activation/Activation.php) builds its own isolated Container + Event_Manager with a fixed set of service providers. McpAuthServiceProvider and McpTransportServiceProvider are not included, so mcp_auth_subscriber and mcp_auth_discovery_subscriber are never added to the activation event manager. When do_action('rocket_activation') fires, Auth/Subscriber::on_activation() is never called — meaning SecretManager::ensure_secret() is skipped and flush_rewrite_rules() is never called for the MCP OAuth rules.
Proposed fix: Add both service providers and wire both subscribers into the activation event manager, following the existing pattern for performance_hints_warmup_subscriber:
// inc/Engine/Activation/Activation.php — after the existing addServiceProvider calls
$container->addServiceProvider( new McpAuthServiceProvider() );
$container->addServiceProvider( new McpTransportServiceProvider() );
$event_manager->add_subscriber( $container->get( 'mcp_auth_subscriber' ) );
$event_manager->add_subscriber( $container->get( 'mcp_auth_discovery_subscriber' ) );
Root cause 2 — McpAdapter::instance() fires mcp_adapter_init before subscribers are registered
In the original inc/main.php, McpAdapter::instance() is called at file-load time, before plugins_loaded fires:
// top of main.php — runs at plugin require time, before any WordPress hooks
if ( class_exists( McpAdapter::class ) ) {
McpAdapter::instance(); // fires do_action('mcp_adapter_init') immediately
}
// ...
add_action( 'plugins_loaded', 'rocket_init' ); // subscribers registered here — too late
mcp_transport_subscriber listens on mcp_adapter_init to instantiate OAuthHttpTransport and call register_rest_route(). Because the action fires before rocket_init() registers any subscribers, the REST route is never registered and every request to /wp-json/mcp/mcp-oauth-server returns 404.
Proposed fix: Move the McpAdapter::instance() call inside rocket_init(), after $wp_rocket->load(), so subscribers are hooked before the action fires:
// inc/main.php — inside rocket_init(), after $wp_rocket->load()
if ( class_exists( McpAdapter::class ) ) {
McpAdapter::instance();
}
Context
The
feature/mcp-oauthbranch adds an MCP server at/wp-json/mcp/mcp-oauth-serverwith a full OAuth 2.1 flow. MCP clients such as Claude Code use two RFC-mandated discovery documents to start the handshake:/.well-known/oauth-protected-resource(RFC 9728) — advertises the MCP resource/.well-known/oauth-authorization-server(RFC 8414) — lists all OAuth endpointsBoth documents and the OAuth flow endpoints (
/oauth/authorize,/oauth/token, etc.) are served via WordPress rewrite rules that are registered and flushed during plugin activation.Bug & Workaround
Symptom: After deploying the plugin (or on a fresh activation), MCP clients report "couldn't reach the MCP server". Both
/.well-knowndocuments and/wp-json/mcp/mcp-oauth-serverreturn HTTP 404.Root cause (short version): The MCP OAuth subscribers that register and flush the rewrite rules are not wired into the activation routine, so WordPress never writes the new rules to the database on first activation.
Workaround: Go to Settings → Permalinks and click Save Changes (no modification needed). This triggers
flush_rewrite_rules()and immediately makes all MCP endpoints reachable.Acceptance criteria
/.well-known/oauth-authorization-serverreturn a valid RFC 8414 JSON document — no manual permalink flush required.GET /wp-json/mcp/mcp-oauth-server(unauthenticated) returns HTTP 401 with aWWW-Authenticate: Bearerheader (not 404).Additional information
Root cause 1 — MCP subscribers absent from the activation container
Activation::activate_plugin()(inc/Engine/Activation/Activation.php) builds its own isolatedContainer+Event_Managerwith a fixed set of service providers.McpAuthServiceProviderandMcpTransportServiceProviderare not included, somcp_auth_subscriberandmcp_auth_discovery_subscriberare never added to the activation event manager. Whendo_action('rocket_activation')fires,Auth/Subscriber::on_activation()is never called — meaningSecretManager::ensure_secret()is skipped andflush_rewrite_rules()is never called for the MCP OAuth rules.Proposed fix: Add both service providers and wire both subscribers into the activation event manager, following the existing pattern for
performance_hints_warmup_subscriber:Root cause 2 —
McpAdapter::instance()firesmcp_adapter_initbefore subscribers are registeredIn the original
inc/main.php,McpAdapter::instance()is called at file-load time, beforeplugins_loadedfires:mcp_transport_subscriberlistens onmcp_adapter_initto instantiateOAuthHttpTransportand callregister_rest_route(). Because the action fires beforerocket_init()registers any subscribers, the REST route is never registered and every request to/wp-json/mcp/mcp-oauth-serverreturns 404.Proposed fix: Move the
McpAdapter::instance()call insiderocket_init(), after$wp_rocket->load(), so subscribers are hooked before the action fires: