MemberPress AI Foundation enforces four safety measures on Model Context Protocol (MCP) write operations. These measures protect a site from unintended or unauthorized changes when an AI client connects through the MCP server. They operate together. A single write call can pass through scope checks, preview defaults, a confirmation gate, and the kill switch before it changes data.
This reference explains each measure, what it protects against, and how the MCP server enforces it. Two measures act when an AI client calls a tool: confirmation tokens and dry-run defaults. One measure governs what scope vocabulary a connection token carries: granular scopes. One measure lets an administrator halt every destructive write instantly: the kill switch.
How the Safety Layer Works
The four measures map to four distinct questions about a write operation:
| Maßnahme | Name | The question it answers |
|---|---|---|
| A | Confirmation tokens | What may a token DO when a destructive tool runs? |
| B | Dry-run defaults | What mode does a write tool default to when called? |
| C | Granular scopes | What scope vocabulary does a connection token carry? |
| D | Kill switch | Can an administrator halt every destructive write at once? |
Measures A, B, and D act at tool-call time. The MCP server evaluates them inside Server::handle_tool_call on every write request. Measure C acts in two places. At tool-call time, the server matches a tool's required scope against the token's granted scopes. At token-issuance time, the default access ceiling caps what scopes a new connection receives.
All four measures live in the MemberPressAI\MCP namespace and run server-side. An AI client cannot bypass them by crafting a request differently, because enforcement happens after the request reaches the server, not in the client.
Measure A — Confirmation Tokens
Confirmation tokens protect destructive operations with a mandatory two-call flow. A destructive tool cannot run on a single call. The first call returns a preview plus a single-use token; the second call must include that token to execute.
One narrow exemption applies: reversible actions skip the gate. memberpress_manage_subscription mit Aktion: "Fortsetzen" und memberpress_manage_sub_account mit Aktion: "Hinzufügen" undo rather than destroy, and execute without a token. A single shared allowlist drives the exemption on both the MCP endpoint and the WordPress Abilities surface, so the two gates cannot drift apart. Every other destructive call requires the token.
Six tools are destructive and require this flow:
| Werkzeug | What it does |
|---|---|
memberpress_delete_member | Deletes a member |
memberpress_refund_transaction | Refunds a transaction |
memberpress_delete_webhook | Deletes a webhook |
memberpress_reset_course_progress | Resets a learner's course progress |
memberpress_manage_sub_account | Manages a corporate sub-account |
memberpress_manage_subscription | Manages a subscription |
How the Two-Call Flow Works
- The AI client calls the destructive tool with its arguments. The server returns a preview of the effect plus a confirmation token.
- The AI client calls the same tool again with the same arguments plus a
bestätigen.parameter set to the token value. The server verifies the token and executes the operation.
The token carries three protections. It expires after 60 seconds (the TTL constant in ConfirmationTokens). It is single-use — the server consumes it on the executing call. The server binds it to the exact combination of tool name, arguments, and user ID. A token issued for one operation cannot authorize a different one.
The design rationale, from the development team: “just passing a boolean isn't strong enough consent for an action you can't undo.” A confirmation token proves the caller saw the specific preview for the specific operation before committing to it.
The First-Call Response
The first call returns a preview of the effect, a single-use Bestätigungs-Token, and the token's remaining lifetime. The following is the response from a memberpress_refund_transaction preview call:
{
"preview": {
"dry_run": true,
"action": "refund_transaction",
"preview": {
"transaction_id": 432,
"amount": "100.00",
"total": "100.00",
"user_id": "<user-id>",
"product_id": 2332,
"subscription_listing_may_show_inactive": true,
"subscription_listing_note": "If this was the latest transaction backing the subscription, the WP admin Subscriptions list will show the subscription as \"Active: No\" — that column is derived from the latest transaction's status, not the subscription record itself. The subscription record is unchanged unless you chose to cancel the subscription as part of this refund."
}
},
"confirmation_token": "ct_<token>",
"expires_in": 60,
"next_step": "Call memberpress_refund_transaction again with the same arguments plus confirm: \"ct_<token>\" to execute."
}
The token arrives in Bestätigungs-Token. Die expires_in field gives the remaining lifetime in seconds. The next_step field states exactly how to execute. The inner preview.preview object describes the operation's effect; its fields vary by tool. The subscription_listing_* fields shown here are refund-specific — the Tools Reference and Errors documents cover refund response detail.
When a Token Is Invalid
A token that has expired, has already been used, or is presented with changed arguments fails with a single error. The server does not distinguish the three causes:
{
"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_<id>"
}
Match on data.mp_error_code (CONFIRMATION_INVALID), not the generic JSON-RPC -32603 code. The recovery path is always the same: call the tool again without bestätigen. to receive a fresh preview and a new token.
Measure B — Dry-Run Defaults
Write tools default to preview. A write tool does not change data unless the caller explicitly opts in to execute. This protects against an AI client running a mutation it only intended to inspect.
Write tools fall into two shapes:
Non-destructive writes (9 tools) carry an ausführen parameter. The tool previews by default and returns a preview payload without persisting. Passing ausführen: true runs the operation live. These tools include memberpress_create_member, memberpress_update_member, memberpress_create_coupon, memberpress_create_subscriptionund memberpress_create_webhookund andere.
Destructive writes (6 tools) carry neither ausführen nor a legacy dry-run parameter. They preview by default and require the Measure A confirmation token flow to execute. The two-call gate is their only execute mechanism.
This split means a reader can tell a tool's risk level from its parameters. A tool with ausführen is reversible; a tool with no ausführen and a confirmation requirement is destructive.
The Non-Destructive Preview Shape
A non-destructive write tool called without ausführen: true returns a flat preview payload. The following is the response from a memberpress_create_member preview call:
{
"dry_run": true,
"action": "create_member",
"preview": {
"email": "mcp-preview-test@example.com",
"username": "mcppreviewtest",
"first_name": "MCP",
"last_name": "PreviewTest"
},
"validation": "passed"
}
This envelope is flat: dry_run, Aktion, Vorschauund validation sit at the top level, and there is no confirmation token. It differs from a destructive preview, where the Vorschau object is nested one level deeper (preview.preview) and a Bestätigungs-Token is present. The validation field reports whether the previewed input would pass validation on execute.
Measure C — Granular Scopes
Connection tokens carry specific scopes rather than blanket access. A token scoped to read members cannot write billing data. This limits the blast radius of any single connection to exactly the operations its scopes permit.
Scope Vocabulary
The MCP server defines the following scopes in ScopeMatcher:
| Umfang | Zuschüsse |
|---|---|
lesen | Read access to all data through read tools |
write:content | Write access to content: access rules and coupons |
Schreibe: Mitglieder | Write access to members |
Schreiben: Rechnungsstellung | Write access to billing: subscription management and transaction refunds |
write:imports | Write access to member imports |
Schreiben: Webhooks | Write access to webhooks and email reminders |
Schreiben: Kurse | Write access to course operations |
vollständig | All write scopes (satisfies any specific schreiben:* requirement) |
Die lesen scope is implicit on every token. The server matches a tool's required scope against the token's granted scopes before dispatch through Server::current_token_has_scope.
Scope alone is not the only gate. Each write tool also declares the WordPress capability it requires (for example, Benutzer anlegen oder Benutzer bearbeiten), and the server enforces that capability before dispatch. A token with vollständig scope still cannot create users if the token owner lacks the Benutzer anlegen capability. The two gates return distinct errors, and the scope gate runs first: a missing scope fails with SCOPE_INSUFFICIENT; a missing capability fails with FÄHIGKEIT_UNZUREICHEND.
Default Access Ceiling
The default access ceiling caps the scopes the server can issue to a new connection. An administrator sets it through the “Maximum access level for new connections” setting on the MCP Settings tab. The ceiling determines the maximum scope any new token carries, regardless of what the connecting client requests.
The setting has two options: Read Only und Full Access.
When set to Read Only, the wizard hides the write-scope checkboxes entirely — they are not shown greyed out — and the server caps every new connection at read scope. The wizard's Access step shows only the always-granted read scope, with this notice:
Site administrator has set the maximum access level to Read Only. New connections cannot be issued write scopes until this is raised in MCP Settings.
When set to Full Access, the wizard's Access step shows the write-scope checkboxes, pre-checked, and the administrator unchecks any a connection does not need. A new connection then receives write scopes up to what the connecting user's WordPress capabilities allow.
The ceiling enforces server-side at four token-issuance paths. A hand-crafted request cannot bypass the wizard interface to request a wider scope:
- Wizard token creation;
- OAuth
/authorize; - OAuth
/tokenexchange; - Dynamic client registration (RFC 7591).
The ceiling is an extension of the scope vocabulary, not a separate mechanism. It exists only because Measure C defines the scopes it caps.
Measure D — Kill Switch
The kill switch lets an administrator halt every destructive write instantly. When active, the server refuses every destructive tool call and returns the WRITES_PAUSED error, regardless of the calling token's scopes or any valid confirmation token.
An administrator toggles the switch from the MCP Connected Clients admin page. The control is a Pause all writes button. While destructive writes are active, the page shows this status:
Destructive writes are active — Pauses refunds, cancellations, deletions, and bulk imports for every connected client. Read tools keep working.
The setting persists across regular settings saves, so a routine settings update does not silently turn it off. The server records admin.writes_paused und admin.writes_resumed events to the audit log when the switch changes state.
The kill switch is the broadest measure. Measures A, B, and C constrain individual operations; the kill switch overrides all of them for destructive calls in a single action. It is the appropriate response when an administrator suspects a connection is behaving unexpectedly and wants to stop all destructive activity before investigating.
The WRITES_PAUSED Response
While the kill switch is active, every destructive tool call fails with this response, regardless of the calling token's scopes or any valid confirmation token:
{
"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_<id>"
}
The switch gates the entire destructive-write path: even the first (preview) call of a destructive tool returns WRITES_PAUSED, so the confirmation flow cannot begin. As with all tool errors, match on data.mp_error_code (WRITES_PAUSED), not the generic -32603.
Related Capabilities
The WordPress Abilities Surface
On WordPress 6.9 and later, AI Foundation also registers tools through the WordPress Abilities API, exposed via the WordPress.org MCP Adapter. This is a second programmatic surface that reaches the same underlying operations as the MCP endpoint, with three mechanical differences:
- Preview control. Write operations on the Abilities surface expose a
dry_runparameter: they preview by default, and the caller passesdry_run: falseto run live — where the MCP endpoint usesausführen: trueinstead; - Write gate. Write access through the Abilities surface is gated on the
mpai_use_mcp_writecapability; - Coverage. The surface registers the core tool families; add-on tool surfaces are exposed via MCP only.
The safety model carries over: the surface enforces the same per-tool WordPress capability requirements, destructive operations require the same confirmation-token flow (including the same reversible-action exemption), and the kill switch pauses destructive Abilities writes just as it pauses MCP writes. Reaching the operations through a different protocol does not relax the gates.
Activity Log
The Activity Log records MCP tool events for audit and troubleshooting. It lives on the MCP Connected Clients tab and lists each event with four columns: Zeit, Client, Werkzeugund Ergebnis. Die Ergebnis column shows the stored outcome code for each call — Erfolg, Fehler, confirmation_required, confirmation_invalid, confirmation_race_lost, scope_insufficient, capability_insufficient, writes_paused, and a small family of preview/encoding failure codes.
The log makes the destructive confirmation flow auditable: a destructive tool's preview call logs confirmation_required, and its execution logs Erfolg — the two calls are distinguishable. A non-destructive tool's preview and live execution both log Erfolg; call arguments are deliberately never logged, so the log does not record whether ausführen was passed. How long entries are kept is governed by the Log Retention setting on the MCP Settings tab (default 30 Tage).
A Note on AI Client Behavior
Some MCP clients automatically complete the two-call confirmation flow without surfacing the confirmation step to the user. A client may show a preview and then issue the second call internally, so the operation appears to run in one step. This is client-side workflow behavior, not a gap in the safety layer. The server still enforces the two-call requirement, and the client supplies a valid token on the second call.
To observe the confirmation gate directly, use a tool that issues each call explicitly, such as Postman or curl. A client that abstracts the flow hides the two calls, but the server still requires both.
Zugehörige Dokumentation
- MemberPress AI Foundation – Überblick und Einrichtungsanleitung — what AI Foundation is, how to install it, and how to connect AI clients;
- MemberPress AI Foundation MCP-Tools – Referenz — the full tool catalog, including which tools are destructive and what scope each requires;
- MemberPress AI Foundation MCP Errors and Troubleshooting — the complete error catalog, including
WRITES_PAUSEDundFÄHIGKEIT_UNZUREICHEND; - Connecting AI Clients to MemberPress — how the server issues connections and assigns scopes during setup.