Giving WordPress hands that AI can actually use
Deep Trivedi · WordCamp / Meetup
Giving WordPress hands that AI can actually use
By the end of this hour, you'll see a capability registered once in WordPress and called live by an AI.
Show of hands: who has wired an LLM to WordPress with custom REST glue?
Keep this short. Name yourself. Set the expectation that slides are visual anchors — you'll talk over them. Footer strip is intentional: Abilities shipped in 6.9, extended in 7.0, proposed expansion in 7.1.
Start with why LLMs feel brilliant and useless on a live site.
Brilliant reasoning. Zero situational awareness.
The problem

LLMs hallucinate today's stock price; they can write a plan to update your site but can't click the button.
A bigger model doesn't fix this — it's an access problem, not an IQ problem.
"Intelligence without access is a very expensive encyclopedia."
"So we bolt on integrations… and it gets ugly."
3 models × 3 tools = 9 brittle integrations
Integration tax
3 models × 3 tools = 9 brittle integrations
Every model↔tool pair = bespoke connector. WordPress updates its API → rewrite in 3 places. Fragile glue code, permanent maintenance debt.
"What if each side implemented ONE standard and N×M collapsed to N+M?"
Open standard — write the connector once
Standard
USB-C didn't change what devices do — it standardized the connection.
MCP did NOT work with ChatGPT on day one; OpenAI joined 4 months later.
"How many cables did USB-C kill in your bag?"
Host · Client · Server — Tools / Resources / Prompts
Architecture
Host (brain) · Client (translator, 1:1) · Server (driver) — Tools = DO · Resources = READ · Prompts = templates
One client per server (1:1). The LLM never touches your DB — the server is the security boundary.
"Everything is a tool" — resources are context to READ, tools are actions to DO, prompts are user-invoked slash-command templates.
initialize → capabilities → tools/list → tools/call → result
Lifecycle
initialize → capabilities → tools/list → tools/call → result
Two layers: data layer = JSON-RPC 2.0; transport = stdio (local) or Streamable HTTP (remote).
Most MCP bugs are protocolVersion mismatches — use npx @modelcontextprotocol/inspector to watch raw JSON-RPC.
"So what does this look like ON WordPress?"
Automattic/wordpress-mcp — now deprecated → mcp-adapter
WordPress MCP
Endpoints /wp/v2/wpmcp (stdio proxy) and /wp/v2/wpmcp/streamable. Granular CRUD toggles in admin.
"Draft this year's sales report from my WooCommerce orders" — AI reads orders under WordPress permissions.
It proved the demand… and exposed the cracks.
"Here's where it hurt."
Tool bloat, auth complexity, no native registry
Cracks
Apideck production data: GitHub+Slack+Sentry ≈ 143k of 200k tokens burned on tool definitions before the user says a word. Clients are mitigating (Cursor caps at 40 tools; Anthropic's tool-search cuts ~85%).
No shared way for plugins to declare "here's what I can do." Everyone reinvented "get a post."
"The protocol wasn't the problem. WordPress was missing a layer BELOW the protocol."
Protocol ≠ capability registry
The pivot
Protocol ≠ capability registry

MCP answers "HOW does an AI talk to a system?" It never answers "WHAT can this WordPress site do?" That's the Abilities API.
Register once → reachable from PHP, REST, JS, WP-CLI, and any MCP client. If MCP is ever replaced, you swap the adapter — your business logic survives.
"Let's meet the star of the talk."
Shipped in WordPress 6.9 — not a 7.0-only feature
Version correction
"Who thought this was a 7.0 feature? It's 6.9 — you may already have it in production."
Registry = WP_Abilities_Registry singleton; each ability = WP_Ability; each belongs to one category.
How many are on 6.9+ already?
Never claim Abilities is "a 7.0 feature." 7.0 added the client-side JS API, Abilities Explorer, and WP AI Client.
Named capability + schemas + permissions + callback
Anatomy
wp_register_ability( 'site-stats/get-post-count', [
'label' => 'Get Post Count',
'description' => 'The AI READS this to decide when to call',
'category' => 'site-stats',
'input_schema' => [ /* JSON Schema */ ],
'output_schema' => [ /* JSON Schema */ ],
'execute_callback' => fn( $input ) => [ 'count' => 42 ],
'permission_callback' => fn() => current_user_can( 'edit_posts' ),
'meta' => [
'show_in_rest' => true,
'mcp' => [ 'public' => true ],
'annotations' => [ 'readonly' => true, 'destructive' => false ],
],
] );Name = namespace/ability-name. The description is NOT cosmetic — it's the AI's tool-selection signal; write it like docs.
The destructive annotation defaults to TRUE — set it explicitly.
Schema validation = JSON Schema Draft-4 subset.
Three-step pipeline
Pipeline
Three-step pipeline
Registering on the wrong hook → _doing_it_wrong() + silent failure. Categories hook fires FIRST; hook name is wp_abilities_api_init (with the wp_ prefix — old blog posts got this wrong).
Picked from annotations: readonly→GET, default→POST, destructive→DELETE.
Input validation runs BEFORE the permission check.
wp_before_execute_ability / wp_after_execute_ability.
Abilities become MCP tools — without tool bloat
AI bridge
The adapter ships helper tools (discover-abilities, get-ability-info, execute-ability) so agents pull schemas on demand instead of ingesting everything — this is the direct answer to slide 8's tool bloat.
Custom servers via mcp_adapter_init + create_server().
Protocol dies → swap adapter, keep abilities.
Four lock layers
Security
Never __return_true on destructive abilities.
MCP clients act as logged-in WP users: treat them as attack surface.
Durable layer: build on Abilities, not MCP plugins
Practices
core/read-settings / read-content / read-users behind a show_in_abilities flag — drew maintainer pushback; state it as "proposed, contested" not "shipping."
Build on Abilities, not directly on any MCP plugin — that's the durable layer.
Cue card — run on Local WP yourself
Cue card
Keep this slide up the whole demo. Fallback: pre-recorded video if Wi-Fi dies.
Keep this slide up the whole demo. Fallback: pre-recorded video if Wi-Fi dies.
Pre-generate the application password + client config.
site-stats-ability plugincurl /wp-json/wp-abilities/v1/abilities…/site-stats/get-post-count/runQuestions welcome
Thank the audience. Open the floor for questions.