wp-media/mcp-oauth

MCP OAuth layer for the WordPress MCP Adapter

Maintainers

Package info

github.com/wp-media/mcp-oauth

pkg:composer/wp-media/mcp-oauth

Transparency log

Statistics

Installs: 31

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 5

v1.0 2026-07-15 21:06 UTC

This package is auto-updated.

Last update: 2026-07-17 15:03:53 UTC


README

OAuth 2.1 + Client ID Metadata Document (CIMD) authentication layer for the wordpress/mcp-adapter package.

This library is designed to be embedded, via Composer, into one or more WordPress plugins. It centralizes OAuth endpoint routing, .well-known discovery documents, JWT-based MCP transport authentication, and MCP server registration behind a single wiring point so that multiple consuming plugins never register duplicate rewrite rules or duplicate MCP servers.

Installation

composer require wp-media/mcp-oauth

Usage

Boot the library from your plugin's main file. Calling it on plugins_loaded is recommended; the hard requirement is that it runs no later than rest_api_init priority 15 (when the MCP adapter registers its servers):

add_action( 'plugins_loaded', static function () {
	\WPMedia\MCP\OAuth\Bootstrap::instance();
} );

Bootstrap::instance() is a singleton: if more than one plugin on the same site calls it, only the first call wires the library (rewrite rules, OAuth endpoint routing, discovery documents, and MCP server registration); every later call returns the same instance and binds nothing further.

The OAuth server is disabled by default. Enable it with:

add_filter( 'wpmedia_mcp_oauth_server_enabled', '__return_true' );

When disabled, all /oauth/* endpoints and /.well-known/oauth-* discovery documents return 404, and the MCP OAuth transport server is not registered.

Trusted CIMD publishers

Only clients whose Client ID Metadata Document matches a known, trusted publisher can complete the authorization flow. Claude is bundled as a trusted publisher by default. Add your own via:

add_filter( 'wpmedia_mcp_oauth_trusted_publishers', function ( array $publishers ) {
	$publishers['my-client'] = [
		'client_ids' => [ 'https://example.com/oauth/client-metadata' ],
		'host'       => 'example.com',
	];

	return $publishers;
} );

Rewrite rules

Rewrite rules are flushed lazily and automatically the first time init runs after installing or upgrading the library (tracked by an internal version flag), so no activation hook is required. If your plugin flips the wpmedia_mcp_oauth_server_enabled filter at runtime (e.g. from a settings screen), call Bootstrap::schedule_rewrite_flush() afterwards so the rules are re-flushed on the next request.

Architecture

  • Bootstrap — the single entry point. Hand-wires the object graph and binds every WordPress hook directly (add_action/add_filter).
  • Auth\Router — dispatches /oauth/{authorize,authorize-callback,token,consent,revoke} to their respective endpoint handlers.
  • Auth\Discovery\Endpoints — serves the /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server RFC discovery documents.
  • Transport\ServerRegistrar — registers the MCP OAuth server (and, when needed, the shared mcp-adapter abilities) with wordpress/mcp-adapter.
  • Context — the single is_enabled() gate consulted everywhere.
  • Views\Render — generic view renderer. Loads a named template and executes it with $data in scope; used by Auth\AuthorizeCallback for the consent screen.

Logging

MCP structured logging lives in McpLogger (inc/Logging/), the single choke-point for all [MCP] log lines. All log output — including security/audit lines such as refresh-token-reuse detection — is gated on both WP_DEBUG and WP_DEBUG_LOG being enabled, matching WordPress core's own behaviour of only redirecting error_log() output to wp-content/debug.log when WP_DEBUG is true.

Operational note: because audit logging shares this same gate, operators who need audit-trail visibility in production must enable both constants (not just WP_DEBUG_LOG). Understand that doing so also enables verbose WP debug logging generally.

Testing

composer run-tests        # unit + integration
composer test-unit
composer test-integration
composer phpcs
composer phpstan

License

GPL-2.0-or-later