WP Webhooks / Blog / AI integration
Article · AI integration

WordPress Abilities API: Expose Plugin Features to AI

What the WordPress Abilities API is, how wp_register_ability() works, and how to expose plugin features to AI agents and MCP clients safely.

8 min 2026-07-02
#ai#abilities-api#wordpress

TL;DR: The WordPress Abilities API is a central registry where plugins describe what they can do — a label, a JSON input schema, a permission callback, and an execute callback — under a namespaced id like my-plugin/create_webhook.

  • Register once, consume three ways: your own PHP, the REST surface under /wp-abilities/v1/, and MCP clients like Claude Code or Cursor via the MCP Adapter.
  • Hook wp_abilities_api_init and guard with function_exists('wp_register_ability') so the plugin still works on older WordPress.
  • Every invocation passes the ability's permission callback before its execute callback runs — AI access inherits your capability model.
  • The next major release of the Webhook Actions plugin publishes 17 webhook-building abilities this way; its in-admin Build with AI agent calls the same registry directly.

/ Overview

What is the WordPress Abilities API?

The Abilities API is WordPress core's standard way for plugins, themes, and core itself to describe distinct machine-callable capabilities in one central registry. An ability is a typed operation — "create a webhook", "list delivery logs" — bundled with a human-readable label and description, a JSON Schema for its input and output, an execute callback, and a permission callback. The canonical reference lives in the Abilities API handbook, and the API's development happens in the WordPress/abilities-api repository.

The motivation is AI. Agents are only as good as the operations they can call, and until now every plugin invented its own bridge: bespoke REST endpoints, admin-ajax handlers, prompt glue. The Abilities API replaces that with a discoverable catalog — an AI client can enumerate what a site can do, read each ability's schema, and invoke it with validated input, without knowing anything about the plugin's internals¹.

/ Registration

How does wp_register_ability() work?

You register each ability on the wp_abilities_api_init action with a namespaced name — vendor/ability — and a definition array. The function reference is on developer.wordpress.org; registration returns a WP_Ability instance. Group related abilities with wp_register_ability_category() so clients can present them as one toolset.

PHP — registering an ability (guarded for older WordPress)

// The Abilities API ships in newer WordPress cores — guard so the
// plugin still activates cleanly where it is absent.
if ( function_exists( 'wp_register_ability' ) ) {
    add_action( 'wp_abilities_api_init', function () {
        wp_register_ability_category( 'webhook-actions', [
            'label' => __( 'Webhook Actions', 'my-plugin' ),
        ] );

        wp_register_ability( 'my-plugin/create_webhook', [
            'label'               => 'Create webhook',
            'description'         => 'Create a new outbound webhook (created disabled).',
            'category'            => 'webhook-actions',
            'input_schema'        => [
                'type'       => 'object',
                'properties' => [
                    'name'         => [ 'type' => 'string' ],
                    'endpoint_url' => [ 'type' => 'string' ],
                ],
                'required'   => [ 'name', 'endpoint_url' ],
            ],
            'output_schema'       => [ 'type' => 'object' ],
            'execute_callback'    => fn( $input ) => $registry->execute( 'create_webhook', $input ),
            'permission_callback' => fn() => current_user_can( 'manage_options' ),
        ] );
    } );
}

/ Schemas

How do input schemas make abilities machine-callable?

The input schema is what turns a PHP callback into something a language model can call reliably. Models hallucinate parameter names and shapes; a JSON Schema pins the contract — property names, types, required fields, and enums — so the client can construct valid input and the site can validate it before the callback ever runs.

Enums are the underrated part. A property like conditions_evaluate_on declared as enum: ['original', 'transformed'] means the model cannot invent a third mode — the invalid call is rejected at the schema boundary, not deep inside your business logic. The same schema doubles as documentation: agents read the description strings to decide which ability fits the user's goal, so write them like one-line docs, not labels.

/ Permissions

How do permission callbacks gate AI access?

Every invocation — from PHP, REST, or an MCP client — passes the ability's permission_callback before the execute_callback runs. There is no separate "AI permission system" to design: abilities inherit WordPress's capability model, and an agent can never do more than the identity it authenticates as.

In practice you want more granularity than one capability check. The Webhook Actions plugin (in its upcoming major release) tags each ability with a scope — read for list/inspect operations, full for mutations — mirroring its REST API token scopes, and exposes the decision through a filter so site owners can open specific scopes to token-mediated MCP access without touching code. Destructive abilities additionally carry a requires_confirm flag in their meta: enabling or deleting a webhook always demands explicit user confirmation, and an HTTP probe demands it only when the probe method is unsafe.

How a plugin ability reaches AI clients through the WordPress Abilities APIA plugin registers each operation once with wp_register_ability under its own namespace. The Abilities API registry then exposes the same ability to three consumers: the plugin's own in-admin agent calling it directly in PHP, the REST surface under /wp-abilities/v1/, and the MCP Adapter that external AI clients such as Claude Code or Cursor connect to. Every path passes the ability's permission callback before its execute callback runs.

allowed

denied

Plugin ability definitions
label + input_schema + callbacks

wp_register_ability()
'my-plugin/create_webhook'

Abilities API registry

In-admin agent
direct PHP call

REST
/wp-abilities/v1/

MCP Adapter
Claude Code / Cursor

permission_callback

execute_callback runs

request rejected

FIG 01 — One ability registration, three consumers
Register an ability once and every consumer — your own admin UI, the REST surface, and any MCP client — gets the same typed, permission-gated operation. — the registration pattern

/ Discovery

How do external AI clients discover abilities?

Two surfaces come free with registration. The REST surface under /wp-abilities/v1/ lets any authenticated HTTP client list registered abilities, read their schemas, and run them. And the MCP Adapter exposes the same registry over the Model Context Protocol — the open standard AI tools use to connect to external systems — so Claude Code, Cursor, and other MCP clients can discover and invoke your site's toolset like any other MCP server².

This is the payoff of central registration: you write zero per-client integration code. The day a new MCP-speaking tool appears, it can already drive your plugin.

/ Case study

How does a real plugin register its toolset?

The upcoming Webhook Actions release publishes 17 abilities under the flowsystems-webhook-actions/* namespace: five read abilities (list triggers, list webhooks, inspect a webhook, read a captured trigger schema, read delivery logs) and twelve full-scope abilities (list credential names, create and update webhooks, set field mappings and conditions, assign credentials, run test dispatches, probe endpoints, build chains, enable and delete webhooks).

The instructive part is that the registration is purely additive. The plugin's own in-admin AI agent calls the internal registry directly in PHP, so Build with AI works on any supported WordPress version. When the Abilities API is present, a thin registrar class also publishes each definition with wp_register_ability() — same schemas, same callbacks, same permission gates. One toolset, defined once, consumed by the in-admin agent, the REST surface, and external MCP clients alike. (For how the agent side works, see the plan-first agent architecture.)

ConcernDIY AI bridge (custom endpoints + glue)Abilities API (Webhook Actions)
DiscoveryHand-written docs the model never seesMachine-readable registry with JSON Schemas
ValidationEach endpoint re-implements input checksSchema-validated input before the callback runs
PermissionsPer-endpoint checks you must rememberCentral permission callback + confirm meta per ability
New AI clientsOne custom integration per toolREST + MCP Adapter serve every client

/ Adoption

Should your plugin adopt the Abilities API now?

If your plugin has operations an agent could usefully drive — creating content, configuring integrations, querying state — yes, and the additive pattern makes it low-risk. Keep your internal API as the source of truth, register abilities as a thin layer over it, guard with function_exists(), and mark destructive operations with confirmation metadata. Your plugin loses nothing on older WordPress and gains a full AI surface on newer cores.

Two design rules from building this: keep ability granularity at the level of user intent (one ability per meaningful operation, not per database row), and never expose secrets through read abilities — list credential names, never values. If you already run a REST API, your ability scopes should mirror its token scopes so there is exactly one permission story to audit. For the REST-first view of the same toolset, see creating and managing webhooks over the REST API.

The Webhook Actions plugin will ship its full webhook toolset as WordPress Abilities in its next major release — so Claude Code, Cursor, or any MCP client can build and manage reliable, queued, retried webhook integrations on your site.

/Footnotes
¹ Abilities API handbook and background: developer.wordpress.org/apis/abilities-api/; development at github.com/WordPress/abilities-api.
² The Model Context Protocol was introduced by Anthropic as an open standard for connecting AI assistants to external systems: anthropic.com/news/model-context-protocol.
FAQ

Common questions always ask.

Don't see yours? Open an issue on GitHub or check the full reference in the API docs.

What is the WordPress Abilities API? +
It is a central WordPress registry where plugins, themes, and core describe machine-callable capabilities. Each ability bundles a namespaced id, a label and description, JSON input and output schemas, an execute callback, and a permission callback, so AI agents and other clients can discover and invoke plugin features in a standard, validated way.
How do I register an ability in WordPress? +
Hook the wp_abilities_api_init action and call wp_register_ability() with a namespaced name like my-plugin/create_webhook and a definition array: label, description, category, input_schema, output_schema, execute_callback, and permission_callback. Guard the registration with function_exists() so the plugin still works on WordPress versions without the API.
How do AI tools like Claude Code use WordPress abilities? +
Through two surfaces that come free with registration: the REST surface under /wp-abilities/v1/, and the MCP Adapter, which exposes the registry as a Model Context Protocol server. Any MCP client — Claude Code, Cursor, and others — can then list the site's abilities, read their schemas, and invoke them with validated input.
Is the Abilities API safe to expose on a production site? +
Yes, if you use its gates. Every invocation passes the ability's permission callback before the execute callback runs, so access inherits your capability model. Mark destructive abilities with confirmation metadata, scope read and write abilities separately, and never expose secret values through read abilities.
Does my plugin need the Abilities API to work with AI? +
No — and the best pattern treats it as additive. Keep an internal registry your own features call directly, then also publish each definition via wp_register_ability() when the API is present. The Webhook Actions plugin is built exactly this way: its upcoming in-admin Build with AI agent works on any supported WordPress, and MCP/REST access lights up automatically on newer cores.
Ready

Stop losing webhooks.
Start logging them.

$ wp plugin install flowsystems-webhook-actions --activate