An ability is a named PHP function registered with WordPress core. It has a schema, permission annotations, and a category. This page explains the lifecycle — from registration by a plugin developer to execution by an AI agent.
Registration
Abilities are registered inside the wp_abilities_api_init action hook. This is the only hook where wp_register_ability() works — calling it elsewhere silently fails.
add_action('wp_abilities_api_init', function () {
wp_register_ability('content/list', [
'title' => 'List Content',
'description' => 'List posts with filtering and pagination.',
'category' => 'content',
'callback' => 'my_content_list_handler',
'input_schema' => [
'type' => 'object',
'properties' => [
'post_type' => ['type' => 'string'],
'per_page' => ['type' => 'integer'],
'page' => ['type' => 'integer'],
],
],
'meta' => [
'annotations' => [
'readonly' => true,
],
],
]);
});
The name follows a two-segment format: category/action. Examples: content/list, site-health/status, fluent-crm/create-contact. WordPress core supports 2-4 segments.
Annotations
Each ability declares its behavioral characteristics through annotations in the meta.annotations field:
| Annotation | Meaning | HTTP Method |
|---|---|---|
readonly: true | Does not modify any data. Safe to call repeatedly. | GET |
destructive: true | Deletes or irreversibly modifies data. | DELETE (if idempotent) |
idempotent: true | Calling it twice with the same input produces the same result. | PUT/DELETE |
| (none of the above) | Creates or modifies data, not idempotent. | POST |
Annotations are how AI agents decide what’s safe to call without confirmation. A readonly ability can be called freely during diagnostics. A destructive ability should prompt the user before execution.
Discovery
AI agents discover abilities by calling mcp-adapter/discover-abilities. The response includes every registered ability with its name, description, category, annotations, and whether it requires input. Agents use this to build their available tool list.
For detailed information about a specific ability — including its full input schema — use mcp-adapter/get-ability-info with the ability name.
Execution
When an agent calls an ability through the MCP bridge, the execution chain is:
1. Agent calls ability by name with JSON input
2. Bridge routes to Adapter via HTTPS
3. Adapter validates input against registered schema
→ If invalid: returns error + expected schema
4. Adapter checks user capabilities
→ If unauthorized: returns permission error
5. Adapter calls the PHP callback with validated input
6. Callback returns structured data
7. Response flows back: Adapter → Bridge → Agent
Schema Gotchas
Empty properties. For abilities with no input parameters, omit the properties key entirely. Using (object) array() fails the WordPress validator silently.
Array types must include items. If a property type is array, the schema must include 'items' => array('type' => '...'). Missing items causes silent validation failure.
Hook timing. wp_register_ability() only works inside wp_abilities_api_init. Calling it on init, plugins_loaded, or anywhere else does nothing — no error, no registration.