Connect with OAuth and PKCE
OAuth is the preferred way to connect a client. A compatible client sets it up almost entirely on its own; your part is approving the request as the right WordPress user.
What the client does
- Calls the MCP endpoint and receives
401with aWWW-Authenticateheader pointing at the protected resource metadata. - Reads that metadata, which names this site as its authorization server.
- Reads the authorization server metadata, which lists the registration, authorization and token endpoints.
- Registers itself dynamically, receiving a client ID.
- Opens the authorization endpoint in a browser.
- Exchanges the returned code for tokens.
Steps 1 to 4 and 6 need nothing from you. Step 5 does.
What you do
The authorization endpoint requires you to be logged in to WordPress. If you are not, it redirects you to the login screen first.
You then see a consent screen naming the client and the scopes it is asking for. Approving issues an authorization code; declining returns access_denied to the client and nothing is granted.
Log in as the user whose capabilities the assistant should inherit. This is the decision that matters. Approving while logged in as an administrator gives the assistant administrator reach. See The authorization endpoint.
PKCE is mandatory
The server requires PKCE with the S256 method. A request without a code challenge, or using any other method, is rejected with invalid_pkce.
PKCE means the client generates a secret verifier, sends only its hash when starting the flow, and proves possession of the original when exchanging the code. An intercepted authorization code is useless without the verifier.
There is no client secret. The token endpoint uses token_endpoint_auth_method: none, which is correct for public clients and is why PKCE is not optional here.
Token lifetimes
| Token | Lifetime |
|---|---|
| Authorization code | 10 minutes, single use |
| Access token | 1 hour |
| Refresh token | 30 days |
The client refreshes silently, so a working connection keeps working for up to thirty days of activity without you doing anything. After that it repeats the authorization step.
Authorization codes are consumed on use — replaying one fails.
Tokens are bound
Each token is bound to:
- the client it was issued to;
- the site, by blog ID;
- the resource, meaning this site's MCP endpoint;
- the user who approved it;
- the scopes approved.
A token from one site does not work on another, and a refresh request whose resource does not match is refused. Tokens are stored hashed, never in plain text.
Scopes
The client asks for scopes; you see them on the consent screen. Eight exist, in read and write pairs across four areas. Approve the narrowest set that lets the work happen — see OAuth scopes.
Scopes alone do not grant anything. The acting user's capabilities and the write gates still apply.
Revoking
Reset OAuth in the MCP settings panel revokes every client, code and token for the site at once. Connected assistants stop working immediately and must repeat authorization.
There is no per-client revoke button in the panel; the reset is all-or-nothing. Bear that in mind when several assistants are connected.
When it fails
| Symptom | Cause |
|---|---|
| The flow never starts | Pretty permalinks are not configured, so the OAuth URLs 404 |
| Authorization completes, calls still 401 | The Authorization header is being stripped upstream |
invalid_resource |
The client's server URL does not match the endpoint exactly |
invalid_pkce |
The client did not send an S256 challenge |
invalid_client |
The registration was lost, often after a Reset OAuth |
invalid_grant |
The code expired, was replayed, or the redirect URI differs |
oauth_disabled |
Enable OAuth is off in the settings |
| Rate limited during setup | Registration and token requests allow 5 attempts per minute |
Run the diagnostics in the MCP settings panel; it reports explicitly whether the Authorization header arrived.
Next
Connect a client walks through the whole setup, then make your first read request.