A writing agent that needs to leave an article draft does not need the keys to publish it, edit someone else’s post, delete content, or change site settings. Giving it an administrator account makes the tool easy to connect, but turns every mistake, compromised token, or misunderstood request into a site-wide permission problem.
WordPress now has building blocks for narrower integrations: user capabilities, the Abilities API, the AI Client, and the MCP Adapter. They do different jobs. The goal is not to persuade a model to behave safely. It is to give the authenticated account and the server-side action only the authority required for the task.
This is a documentation-based design pattern, reviewed October 8, 2026. ACLTracks did not install or test a plugin, connect an agent, or run security experiments. The example below is a proposed implementation, not a tested security guarantee.
Start with the job, not the role
“Use WordPress” is too broad a permission request. Turn it into one operation: accept a title and article body, create one post in draft status, return its ID and edit link. If the agent does not need to find old content, do not expose a search tool. If it does not need to revise posts, do not expose an update tool. The narrow interface reduces both accidental actions and the amount of site data an agent can reach.
A WordPress administrator can manage plugins, settings, users, and site behavior. A content agent that only writes drafts has no reason to inherit those capabilities. WordPress checks capabilities for its own REST routes too, but an application password authenticates as a WordPress user. It does not turn that account into a token scoped to one URL or one agent action. The REST API authentication guide describes application passwords; the capability reference explains how WordPress checks a user’s authority.
Use a dedicated, non-administrator integration account with a deliberately small role. Keep the credential out of prompts, source control, and logs. If it is exposed, the account’s remaining capabilities define the damage it can do.
Four parts of the WordPress AI stack, four different jobs
The Abilities API, available in WordPress 6.9 and later, gives a site a standard registry of named operations. An ability declares a description, input and output schemas, a callback, and a permission callback. Its schema tells a client what shape of data to send; the permission check decides whether the current WordPress user may invoke the operation.
The WordPress AI Client, included in WordPress 7.0, is a provider-neutral PHP interface for sending prompts to a configured AI service. It can help a plugin generate draft copy. It does not authenticate an external agent or grant permission to publish. Provider credentials and WordPress user credentials are separate concerns.
The MCP Adapter maps selected WordPress abilities to MCP tools that compatible clients can discover and call. It is an adapter layer, not an AI model and not a substitute for the ability’s permission check. The current adapter documentation describes an HTTP endpoint and a WP-CLI STDIO route. The adapter is distributed separately; installing WordPress does not by itself mean an MCP server is active.
Those layers fit together, but they are not interchangeable. An agent instruction describes the intended workflow. Authentication identifies the account. WordPress capabilities and server-side permission callbacks authorize each operation. A public MCP flag controls which abilities the adapter exposes to MCP clients. Exposure says an operation is available to ask for; it does not say every authenticated user is allowed to run it.
A proposed draft-only workflow
For an outside agent using MCP, the publisher could register one ability such as editorial/create-draft. Give it a narrow input schema containing only a title and article content. The callback would set the author to the authenticated integration user and set post_status to draft itself. The client would not supply a status, author ID, existing post ID, arbitrary metadata, or a list of site options.
| Layer | Draft-only design | What it does not do |
|---|---|---|
| WordPress user and role | Dedicated account with read and a custom capability such as create_agent_drafts. | Does not make an application password endpoint-specific. |
| Ability permission check | Require current_user_can('create_agent_drafts') before the callback runs. | Does not filter or validate article meaning by itself. |
| Application callback | Validate and bound title/body; force draft status and current-user ownership; create only, with no edit, delete, or settings action. | Does not make a prompt trustworthy or prevent duplicates unless the logic handles retries. |
| MCP exposure | Expose only this ability, using MCP-specific visibility or an MCP server configured for the intended tools. | Does not grant authorization. Permission checks still apply at execution. |
| Agent instructions | Tell the model to prepare drafts, cite supplied sources, and ask a person to review before publication. | Does not stop an agent from attempting another available operation. |
In a default MCP server, the adapter’s discovery and execution tools provide a route to abilities that have been exposed. Mark only the intended ability for MCP access, or use a custom server that selects the tool set deliberately. Keep REST exposure separate: an ability’s show_in_rest setting controls its REST API visibility, while MCP exposure is configured through the adapter’s metadata. Do not mark a broad set of site abilities public just to make one draft tool discoverable.
The MCP HTTP transport also authenticates a WordPress user. In the adapter’s current documentation, transport access has its own capability gate, separate from the selected ability’s permission callback. A dedicated role may need the transport’s minimum read capability, but that does not require granting post editing or administration. Check the adapter version and server configuration you deploy; transport and exposure settings are part of the actual security boundary.
Where each restriction has to hold
WordPress roles and capabilities set the account’s general authority. Core REST endpoints check the user’s capabilities before allowing post creation, updates, deletion, or privileged settings access. The Posts REST reference documents the fields and operations available through the posts endpoint. Give the integration account no publish, delete, settings, plugin, or user-management capabilities. Avoid broad built-in roles simply because their names sound editorial.
Custom application logic defines what the one draft operation means. Check a custom capability in the ability’s permission callback. Force the status to draft in the server callback rather than accepting a client-provided status. Assign ownership from the current user. Do not accept arbitrary IDs that could turn a create request into an update to somebody else’s content.
API permissions apply at more than one boundary. The REST API authenticates the account and checks the relevant route’s capability. The Abilities API checks an ability’s own permission callback on execution, including through its REST endpoints when those are enabled. The MCP Adapter applies transport access checks and then delegates the selected ability call through that same authorization path. Keep the account’s ordinary WordPress capabilities narrow as well, because the MCP tool is not necessarily its only authenticated route.
Agent instructions set expectations, not access. “Never publish” is useful operating guidance. It is not a server check. If publication is unauthorized, omit a publish ability and make the WordPress account incapable of publishing through the standard API too.
Validate inputs, ownership, and retries
JSON schemas can reject inputs with the wrong shape before execution, and the Abilities API reports failures through WordPress errors. That is useful structure, not complete validation. The callback still needs sensible length limits, allowed fields, safe handling for markup, and clear behavior when an input is missing or malformed. Treat generated text as untrusted content. Return only the new draft’s ID, status, and edit URL, not unrelated user records, private posts, or internal configuration.
Make ownership explicit. A create-only callback should use the authenticated integration account as post author and should not accept a caller-selected author. If editorial review needs to pass a draft to an editor, use an intentional human workflow for that handoff. Do not quietly add a general “edit any post” tool to solve it.
Plan for retries. A timeout can leave a client uncertain whether a draft was created, and another call can create a duplicate. MCP annotations can describe an operation’s behavior to clients, but they do not make callback side effects idempotent. If duplicates matter, accept a request key or stable source identifier, record it server-side, and return the existing draft when the same operation is retried. Log the operation and its result without logging credentials or full private content. Return useful, bounded errors rather than raw stack traces.
Use the narrowest useful interface
For plugin developers, the practical design is a capability per meaningful action, an ability schema for that action, a permission callback that checks the authenticated user, and a callback that limits the possible side effect. Add MCP exposure only when an external client needs it. The July WordPress plugin tutorial shows how abilities, the AI Client, and MCP can be composed; the safety comes from the permissions and callback you define, not from composing more components.
For an independent publisher, begin with a local or staging implementation and inspect the account’s effective capabilities and exposed tools before connecting a production site. Start with a draft-only ability and a human review step. Keep a way to revoke the integration credential. Expand the tool set only when a real workflow requires another operation.
The point is to give the agent a useful handle, not the admin keys. A clear prompt can help it use that handle well. A dedicated WordPress identity, capability checks, carefully exposed abilities, and a constrained callback determine what the handle can actually move.
Sources and implementation references
- Build your first AI-Powered WordPress plugin
- From Abilities to AI Agents: Introducing the WordPress MCP Adapter
- Abilities API handbook
- Abilities REST API endpoints and permissions
- REST API authentication and Application Passwords
- current_user_can() reference
- WordPress MCP Adapter source and documentation
