MCP Abilities Guard
Free plugin · GPLv2 · WordPress 6.9+
MCP Abilities Guard
Set every AI ability to always allow, require approval, or always reject — and see what each one actually did.
The problem
MCP plugins let an AI agent act on your site. Whichever one you use, the result is the same: a model connected in Claude, Cursor or Codex can create posts, edit content, change settings and delete things — and by default nothing stands between the model deciding and WordPress doing.
MCP Ability Guard puts a decision point in front of every ability. You do not need the ability’s author to have built any of this.
Three choices, for every ability
Always allow
It runs, and what it did is recorded — with an undo for core objects.
Require approval
It is held. Nothing changes until a person says yes, and the agent is told to wait rather than retry.
Always reject
It never runs. The agent is told to stop trying, and the attempt is recorded.
How it decides what an ability does
Most tools guess from an ability’s name, or trust whatever its author declared. Both are wrong often enough to matter — an ability called get_report can still send email. This plugin prefers evidence, strongest first.
- Watching it run. While an ability executes, the plugin records what it touches — posts, options, users, terms, comments, and writes to any plugin’s own tables. Seen reading and never writing, it earns read-only status.
- Reading its code. Before an ability has ever run, its callback is inspected for database writes, outbound requests and file changes. This catches a write on the first call rather than the second.
- Its declared annotation. Believed, but only provisionally. If an ability claims read-only and then writes, that claim is revoked on the spot.
- Its name. The weakest signal, used last, and never enough on its own to auto-allow.
Every row shows which of these produced its classification, so you always know whether you are reading a verified result or an assumption. When nothing can be determined, the plugin says unknown — and unknown is held, not allowed.
Some things are never auto-allowed
Sending mail, making outbound requests and writing files leave no trace in your database, cannot be observed afterwards, and cannot be undone by anything. A clean run history is not evidence that they are safe — so abilities that do these are held for approval however many times they have run without incident.
What it does
- Works with whichever MCP plugin you use
- Covers abilities from any plugin, with no cooperation from their authors
- Queues held calls for review, with sensitive values redacted
- Records every execution, with undo for posts, options, users, terms and comments
- Different rules per caller, so one agent can be trusted where another is not
- Multiple approvers, and optional expiry for unanswered requests
- Learning mode, to classify without holding anything
What it does not do
- It does not run an MCP server, transport or authentication
- It does not replace an ability’s own permission checks — those still run
- It does not govern MCP tools that were never registered as abilities. Those are outside its reach, and the Coverage screen names them rather than leaving you to assume you are covered
- It does not phone home, collect telemetry, or make any external request
Install it
- Install MCP Ability Guard and activate it.
- Go to Tools → Ability Guard.
- Leave Learning mode on at first. The plugin watches and classifies without holding anything, so you can see what your abilities really do before deciding.
- Turn learning mode off and set your rules. A reasonable start: always allow the reads, require approval for anything that writes, and always reject anything you never want an agent touching.
Requirements
- WordPress 6.9 or later — the Abilities API arrived in core in 6.9
- PHP 7.4 or later
- At least one plugin that registers abilities, and usually an MCP server plugin to expose them
Questions
Does it work with my MCP plugin?
It should. Rules attach to abilities as WordPress registers them, so it does not matter which plugin later exposes them. Tool calls are recognised by the MCP protocol’s own message shape rather than by any particular endpoint, so no per-plugin support is needed.
What is the difference between “require approval” and “always reject”?
Require approval holds the call and waits for a person. Always reject refuses it outright and tells the agent not to retry or attempt the same change another way. Use reject for things no agent should ever do, so you are not answering the same prompt repeatedly.
What happens to the agent while a request is held?
It is told the request is queued, that nothing has changed, and that it should not retry. It can look up the outcome later through an ability provided for that purpose. Agents told only “denied” tend to look for another route, which is why the wording matters.
Will it slow my site down?
It does nothing on front-end page loads. The work happens only while an ability is executing, which is an admin or API request.
Can it undo what an agent did?
Core objects — posts, pages, options, users, terms, comments — yes, provided nothing else has edited them since. Writes to a plugin’s own tables are recorded but not reversible. Email, outbound requests and file writes cannot be undone by anything, which is why abilities that do those are never auto-allowed.
Does it send data anywhere?
No. There is no external service, no telemetry and no account. Everything is stored in your own database.