Download the PHP package wp-media/mcp-oauth without Composer

On this page you can find all versions of the php package wp-media/mcp-oauth. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package mcp-oauth

MCP OAuth

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

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):

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 enabled by default. Disable it with:

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

The trusted-publisher allowlist is a trust signal, not a gate. Any client presenting a valid Client ID Metadata Document may complete the authorization flow; the consent screen tells the user which tier the client is in — a client matching a trusted publisher gets a green "Verified publisher" badge, and every other client gets a prominent "not a verified publisher" warning above its display name so the user makes an informed choice. Claude is bundled as a trusted publisher by default. Add your own via:

A CIMD client_id URL must be an HTTPS URL served on the default port (443); URLs carrying an explicit port (e.g. https://example.com:8443/client-metadata) are rejected before any fetch. This lets the resolver pin the connection to a validated IP as an anti-DNS-rebinding (SSRF) safeguard.

Restoring the trusted-publisher hard gate

Unverified providers are allowed by default (wpmedia_mcp_oauth_allow_untrusted_providers defaults to true). Sites that want only verified publishers to authorize can restore the old hard-reject — unverified clients are then refused with a 400 before consent:

The filter must return a real boolean. A non-boolean return is reported via _doing_it_wrong() and discarded in favour of the default (true), so a misconfigured filter leaves untrusted providers allowed.

With the filter set to false, a client_id whose host is not on the allowlist is refused with "Unknown OAuth client." before any fetch — including when a record for it is already in the transient cache, since the host check runs before the cache read. A client_id on an allowlisted host that does not match the publisher's exact client_ids is refused with "This OAuth client is not a verified publisher."

CIMD fetch rate limit

Resolving an unknown client_id costs one outbound HTTPS fetch, so the resolver keeps a global budget of 30 fetches per minute. Only cache misses count against it — an already-resolved client_id is served from its transient and is always free. When the budget is exhausted, further cache-miss resolutions fail until the window resets. Raise (or lower) the ceiling with:

The budget is global rather than per host or per client, so it is deliberately coarse: a flood of unknown client_id URLs can delay a legitimate client whose cached document has just expired. Raise the limit on sites that serve many distinct MCP clients.

Because unverified providers are allowed by default, this shared budget is also reachable by anonymous callers: a burst of untrusted client_id URLs can briefly starve resolution of a trusted client whose cached document expires inside the same window. The window self-heals within 60 seconds of the last allowed fetch; per-tier counters are tracked as a follow-up.

Returning a value below 1 is a deliberate way to block every cache-miss fetch, which disables resolution of any new client_id; already-cached clients are unaffected, since cache hits never consult the budget.

Observability

Observability events are off by default: the MCP server is created with the mcp-adapter's NullMcpObservabilityHandler, so nothing is written on a normal request. The server registers on rest_api_init, so a verbose handler records at least one event per REST request, which floods debug.log on sites running with WP_DEBUG and WP_DEBUG_LOG enabled.

Opt in to this library's verbose handler (events logged under the [MCP][OBSERVABILITY] scope) with:

Any class implementing the adapter's McpObservabilityHandlerInterface is accepted; anything else falls back to the null handler. Errors are unaffected — they still go through ErrorLogMcpErrorHandler — and the TOKEN/VALIDATOR log scopes still trace the OAuth flow.

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

Hosting: .well-known conflicts

The two RFC discovery documents are served via a WordPress rewrite rule (^\.well-known/oauth-(protected-resource|authorization-server)$), registered at 'top' priority — the recommended pattern for competing with WordPress's own default rewrite rules.

On some hosts (OVH, cPanel/AutoSSL, Plesk, and most managed-WP hosts are common defaults), the web server itself provisions a physical .well-known/acme-challenge/ directory for Let's Encrypt auto-SSL, and scopes that provisioning to the entire .well-known/ path prefix — for example an Apache <Directory>/Alias block with AllowOverride None, or an Nginx location block matching the whole prefix rather than just acme-challenge/. Once that happens, sibling paths under .well-known/ — including our two discovery documents, which don't physically exist on disk — can 404 before Apache/Nginx ever hands the request to PHP. When that's the case, template_redirect never fires, and no WordPress-level code change can fix this: the interception happens in the web server, before WordPress's rewrite engine runs at all. This is a known, unsolved WordPress core gap (Trac #37201, wontfix).

This library never touches pre-existing content under .well-known/ (it has no static-file-write fallback — writing into a directory a host already manages is exactly what causes permission/ownership failures on other plugins, e.g. the WooCommerce Stripe gateway's abandoned attempt at the same thing). It also ships a Site Health self-check (Auth\Discovery\HealthCheck) that surfaces a "MCP OAuth discovery documents" test under Tools → Site Health → Status, which flags this exact failure mode with a recommended status when it detects the fingerprint of the confirmed bug (a bare 404 with no WordPress-originated response header). The discovery documents are an optional MCP feature, so this is deliberately kept below critical to avoid raising a red alert for a non-blocking misconfiguration. The only real fix is a server-config change, applied by whoever controls the host/vhost:

Apache

Add this to your vhost config, or to .htaccess in the site root (above WordPress's own # BEGIN WordPress block, so it is evaluated first) — it re-enables rewriting only for the two OAuth discovery paths, leaving acme-challenge/ and everything else under .well-known/ untouched:

If your host scopes .well-known/ with a <Directory>/Alias block that sets AllowOverride None, you will additionally need that block changed (or carved out) at the vhost level — a .htaccess rule alone cannot override it. Only your host or sysadmin can make that change.

Nginx

Nginx prioritizes an exact-match location = block over a broader prefix match (e.g. location ^~ /.well-known/), so adding these two exact-match blocks wins over a wider .well-known/ interception without touching it:

Caveats

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

License

GPL-2.0-or-later


All versions of mcp-oauth with dependencies

PHP Build Version
Package Version
Requires php Version >=7.4
wp-media/apply-filters-typed Version ^1.0
wordpress/mcp-adapter Version ^0.5
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package wp-media/mcp-oauth contains the following files

Loading the files please wait ...