The MemberPress AI Foundation MCP server returns structured errors when a request fails authentication, exceeds a rate limit, lacks scope or capability, or arrives while destructive writes are paused. Each error carries a code an AI client or developer can match on.
This reference catalogs the error codes the MCP server produces, shows what triggers each one, and explains how to resolve it. A troubleshooting section covers the failure modes that surface most often during initial setup.
Error Response Shape
The server returns errors at two layers, and they have different shapes. Matching on the correct field is essential for reliable error handling.
Transport-layer errors are rejected before JSON-RPC processing — authentication failures and unmounted routes. They use the WordPress REST error shape, with a string code and an HTTP status under data.status:
{
"code": "auth_required",
"message": "Authorization header required.",
"data": { "status": 401 }
}
Tool-layer errors occur after authentication, during tool dispatch — the safety layer and capability gates. They use the JSON-RPC 2.0 error shape, where code is the generic JSON-RPC value -32603 and the stable, matchable identifier is data.mp_error_code:
{
"code": -32603,
"message": "Destructive writes are paused by an administrator. Try again later or contact the site owner.",
"data": { "mp_error_code": "WRITES_PAUSED" },
"request_id": "req_011Cc7Bhv5NZnRMgQ9Bg2JBo"
}
Match on
data.mp_error_code, notcode. Every tool-layer error returns the same-32603; onlymp_error_codedistinguishes them. Therequest_idis unique per call — useful for support, never for matching.
Error Categories at a Glance
| Catégorie | Identifier | Layer |
|---|---|---|
| Authentification | auth_required and token errors | Transport (data.status: 401) |
| Route disabled or permalinks | rest_no_route | Transport (data.status: 404) |
| Scope and capability | SCOPE_INSUFFICIENT, CAPABILITY_INSUFFICIENT | Tool (-32603 + mp_error_code) |
| Safety layer | WRITES_PAUSED, CONFIRMATION_INVALID | Tool (-32603 + mp_error_code) |
| Rate limiting | RATE_LIMITED, public, registration | Mixed — see Rate Limit Errors |
| Validation | validation_error | Tool (-32603 + mp_error_code) |
| Resource and state | user_not_found, duplicate_username, already_refunded, le *_not_found family | Tool (-32603 + mp_error_code) |
| Credits | insufficient_credits, credits_unavailable | Not reachable through MCP tools — see below |
Erreurs d'authentification
The server validates credentials on every request. All main MCP routes require a Bearer token or Basic authentication.
A request with no Authorization header is rejected at the transport layer:
{
"code": "auth_required",
"message": "Authorization header required.",
"data": { "status": 401 }
}
| Déclencheur | Code | Message |
|---|---|---|
| No credentials | auth_required | “Authorization header required.” |
| Malformed header (not Bearer or Basic) | auth_required | “Bearer or Basic auth required.” |
| Expired token | token_expired | “Token has expired.” |
| Revoked or nonexistent token | auth_required | “Invalid or revoked token.” |
An expired token returns a distinct code. A revoked token and a token that never existed are deliberately indistinguishable — the token lookup filters revoked rows out, so the response does not disclose whether a given token ever existed.
401 responses on the MCP route carry a WWW-Authenticate header with the exact value Bearer realm="mcp", resource_metadata="<resource-metadata URL>", and the header is exposed via CORS. The OAuth endpoints deliberately omit it.
Resolution: generate a new token from the wizard, or reconnect the client to run the OAuth flow again. Confirm the token was not revoked on the MCP Connected Clients tabulation.
Scope and Capability Errors
Two distinct gates reject a tool call after authentication succeeds. Both surface as tool-layer errors.
Scope gate. Every tool declares a required scope. The server matches it against the token's granted scopes before dispatch. A read-only connection calling memberpress_create_member fails this gate.
Capability gate. Every write tool also declares the WordPress capability it requires — for example create_users, edit_users, delete_usersou manage_options. The server enforces the capability of the token's owner before dispatch. A full-scope token owned by a user without create_users still cannot create members.
The gates run in order — scope first — and return distinct codes:
| Gate | mp_error_code | Message |
|---|---|---|
| Champ d'application | SCOPE_INSUFFICIENT | Required scope "%s" is not granted on this token. |
| Capacité | CAPABILITY_INSUFFICIENT | Insufficient capability for this tool. The user must have "%s". |
Both use the tool-layer envelope — -32603 with the stable identifier in data.mp_error_code:
{
"code": -32603,
"message": "Insufficient capability for this tool. The user must have \"create_users\".",
"data": { "mp_error_code": "CAPABILITY_INSUFFICIENT" },
"request_id": "req_..."
}
Resolution:
- Scope failures: the connection needs a broader grant. Revoke it and issue a new connection with the required write scopes. The access ceiling must be at Full Access for new connections to receive write scopes;
- Capability failures: the WordPress user behind the token lacks the required role capability. Connect as a user with the capability, or grant it to the user.
Safety Layer Errors
The agent safety measures produce their own tool-layer errors. The Agent Safety Measures Reference explains the measures; this section catalogs their refusals.
WRITES_PAUSED
The kill switch pauses every destructive write. While active, the server refuses the destructive tools with WRITES_PAUSED — regardless of the connection's scopes and even when the call carries a valid confirmation token.
The refusal fires at the first, non-committing call: a destructive tool's *preview* is blocked, not only its execution. The kill switch gates the entire destructive write path, so a paused state cannot even produce a confirmation token. Read tools continue to work.
{
"code": -32603,
"message": "Destructive writes are paused by an administrator. Try again later or contact the site owner.",
"data": { "mp_error_code": "WRITES_PAUSED" },
"request_id": "req_011Cc7Bhv5NZnRMgQ9Bg2JBo"
}
Resolution: an administrator turns the kill switch off from the MCP Connected Clients tab. The pause is a deliberate administrative action; confirm why it was activated before resuming writes.
CONFIRMATION_INVALID
Destructive tools require a two-call flow: the first call returns a preview plus a single-use confirmation token; the second call passes the token in the confirmer paramètre. Three distinct causes return the same CONFIRMATION_INVALID erreur — the message does not disambiguate which occurred:
| Cause | Detail |
|---|---|
| Token expired | The token is older than its 60-second window |
| Token already used | Tokens are single-use |
| Arguments changed | The token binds to the exact tool, arguments, and user |
{
"code": -32603,
"message": "Confirmation token is invalid, expired, or arguments have changed. Call the tool without `confirm` to receive a fresh preview and token.",
"data": { "mp_error_code": "CONFIRMATION_INVALID" },
"request_id": "req_011Cc7AK3jF4SA4VLs3qsmBD"
}
Resolution: call the tool again without confirmer to obtain a fresh preview and token, then confirm within 60 seconds using identical arguments. Because one code covers three causes, a troubleshooting client should re-run the preview rather than try to diagnose which protection fired.
The collapse is deliberate. A bare pass/fail response does not disclose whether a given token ever existed, and the recovery is identical in every case: re-run the preview.
The response's error.data carries a reason field alongside the unchanged top-level code, with two values: expired_or_used (the token was not found — expired, already consumed, and never-issued deliberately stay collapsed) and arguments_changed (the token was valid, but the request drifted from what was previewed — re-run the preview and confirm the new token).
Rate Limit Errors
Independent rate limits protect the server, and the response shape differs by endpoint — the authenticated MCP endpoint does not return 429 at all.
| Surface | Limite | Réponse |
|---|---|---|
| Authenticated MCP endpoint | 120 requests per minute per token (default; configurable 1–1000) — set on the MCP Settings tab, where rate limiting can also be disabled entirely | JSON-RPC error at HTTP 200 — code -32029, mp_error_code: RATE_LIMITED |
| Public MCP endpoint | 60 requests per minute per IP (fixed) | HTTP 429 avec Retry-After: 60 |
OAuth /enregistrer | 60 registrations per hour per IP | HTTP 429 avec Retry-After: 3600 |
The authenticated endpoint's limit surfaces inside the JSON-RPC envelope, not as an HTTP error:
{"jsonrpc":"2.0","id":1,"error":{"code":-32029,"message":"Rate limit exceeded.","data":{"mp_error_code":"RATE_LIMITED"}}}
The public endpoint returns a plain JSON-RPC error body with its 429:
{"jsonrpc":"2.0","error":{"code":-32000,"message":"Rate limit exceeded. Please try again in a minute."}}
The registration endpoint returns an OAuth-style body with its 429:
{"error":"too_many_requests","error_description":"Too many client registrations from this IP. Please try again in an hour."}
Resolution: wait for the window to reset. For the authenticated endpoint, match on mp_error_code: RATE_LIMITED — a 200 status does not mean success — and back off at least one minute. Respect Retry-After where sent. For sustained legitimate volume, batch requests or reduce polling frequency.
Validation Errors
Validation failures are tool-layer errors: -32603 avec mp_error_code: validation_error. Les message itself explains the problem — it names the rejected value and, where a vocabulary applies, lists the accepted values. For example, creating a webhook with an unknown event returns:
Unknown events: member-added. Known events: transaction-completed, ...
Write tools validate argument vocabularies against their schemas, and legacy values are rejected with the accepted enumeration. Coupon tools are the documented example: mode_discount accepts standard ou first-paymentet type de réduction accepts percent ou dollar. The legacy values premier, touset flat are rejected.
Resolution: fix the input as the message describes — or read the tool's inputSchema en tools/list — then resend with canonical values. Do not retry the same arguments.
Resource and State Errors
Beyond validation, tools return caller-facing codes when a request is well-formed but cannot apply to the site's current state. These follow the same tool-layer envelope (-32603 + mp_error_code), and their messages state the reason directly:
| Code | Déclencheur |
|---|---|
user_not_found | The referenced member or user does not exist |
*_not_found family | The referenced resource (transaction, subscription, webhook, and so on) does not exist |
duplicate_username | Member creation with a username already in use |
already_refunded | A refund attempted on a transaction already refunded |
memberpress_not_active | The MemberPress plugin is not active |
Resolution: these are state conditions, not transient failures — verify the referenced resource (or the site state) and correct the request. Retrying unchanged cannot succeed.
Genuinely internal failures — store_failed, delete_failed, db_error — remain generic by design, so storage-layer detail does not leak to clients. A client receiving one of these can only retry later or report the failure to the site administrator.
Credit Errors — Not Reachable Through MCP
Preview calls route failures through the same allow-list as live execution and carry the same mp_error_code — a tool cannot leak in its preview an internal error that live execution would mask.
The server's error allow-list includes two credit-related codes: insufficient_credits et credits_unavailable. No MCP tool consumes AI Credits, and the MCP server calls no credit method. The codes exist so downstream services can pass credit errors through the JSON-RPC response; no MCP tool call path produces them.
A client working through the MCP tools never encounters these codes. Credit balances affect Mastermind-powered generation features (for example, Course Copilot), not MCP tool calls.
Troubleshooting Setup Failures
Failure modes that surface during initial connection, in the order users typically hit them:
- The authenticated MCP endpoint returns
404: permalinks are set to Plain. The REST API requires Post name or richer permalinks; - The public MCP endpoint returns
404(rest_no_route): the public catalog is disabled. When off, the route is not mounted, so any request returnsrest_no_route— the endpoint's existence is not revealed. Enable the catalog on the MCP Settings tabulation ; - The endpoint returns
401(auth_required) in a browser: expected behavior. The401confirms the endpoint is live; the browser carries no Authorization header; - Claude Desktop shows the connector but no tools: the OAuth approval did not complete, or the connection was revoked. Open the connector and reconnect;
step=start_errorduring Claude Desktop connection: OAuth registration is rate-limited to 60 attempts per hour per IP. Wait for the window to reset and retry;- A third-party client cannot register via OAuth (
invalid_redirect_uri): the dynamic registration endpoint accepts only allowlisted redirect URIs (the known AI clients). A client whose redirect URI is not on the allowlist is rejected at/enregistrer; - An expected tool is missing from
tools/list: the tool belongs to an inactive add-on. Add-on tools register only while their add-on is active. Calling an unregistered tool returns the standard JSON-RPC unknown-method error; - Write checkboxes missing from the wizard: the access ceiling is set to Read Only. The wizard hides write scopes and displays a notice. Raise the ceiling on the MCP Settings tabulation ;
- A destructive tool returns a preview instead of executing: expected behavior. Destructive tools require the two-call confirmation flow. Pass the returned token in the
confirmerparameter within 60 seconds.
Error Handling Guidance
- Match on
data.mp_error_codefor tool-layer errors, and oncodeplusdata.statusfor transport-layer errors. Never match on the bare-32603; auth_required/401: re-authenticate. Do not retry with the same credentials; repeated failures trigger the brute-force lockout;SCOPE_INSUFFICIENT/CAPABILITY_INSUFFICIENT: do not retry. The connection needs a broader scope grant, or the user behind the token needs the missing WordPress capability — a retry cannot succeed;WRITES_PAUSED: do not retry automatically. An administrator paused destructive writes deliberately; surface the state to the user;validation_error: fix the input as the message describes, then resend. Do not retry the same arguments — the same input produces the same rejection;CONFIRMATION_INVALID: restart the two-call flow from the preview call. One code covers three causes, so re-run the preview rather than diagnosing which fired. Never cache confirmation tokens;- Rate limits: back off. The authenticated endpoint signals
RATE_LIMITEDinside an HTTP200; the public and registration endpoints return429avecRetry-After. RespectRetry-Afterwhere sent; otherwise wait at least one minute.
Related Documentation
- MemberPress AI Foundation Overview and Setup Guide — installation, prerequisites, and post-install checks;
- Connecting AI Clients to MemberPress – Developer Reference — authentication methods and per-client configuration;
- MemberPress AI Foundation MCP Tools Reference — per-tool scopes, capabilities, and schemas;
- MemberPress AI Foundation Agent Safety Measures — the four measures behind the safety-layer errors.