The Abilities API in WordPress 7.0 let plugins describe what AI (and other callers) can do. WordPress 7.1 is the ops release for that API: filtering, a single public flag, execution lifecycle hooks, client-ready JSON Schema, and REST input that arrives already typed.
If you need the 7.0 primer first, start at the Abilities API hub. If you already registered abilities in 7.0, read this before you expose them to MCP or REST clients.
1. The unified public flag
In 7.0 you opted into REST with meta.show_in_rest. Every new client (MCP, WebMCP, a future agent adapter) would have needed its own flag. 7.1 adds meta.public as the general exposure intent.
Resolution for REST:
$show_in_rest = $meta['show_in_rest'] ?? $meta['public'] ?? false;
Channel-specific values win. Explicit false is kept (null-coalescing, not “empty means inherit”).
wp_register_ability( 'my-plugin/export-users', [
'label' => __( 'Export users', 'my-plugin' ),
'description' => __( 'Exports user data as CSV.', 'my-plugin' ),
'category' => 'data-export',
'execute_callback' => 'my_plugin_export_users',
'permission_callback' => function (): bool {
return current_user_can( 'export' );
},
'meta' => [
'public' => true, // REST + future clients inherit this
],
] ); Core abilities core/get-site-info, core/get-user-info, and core/get-environment-info now set meta.public instead of show_in_rest. REST behaviour is unchanged. The WordPress MCP Adapter will honour public in its next release. WP-CLI still lists every ability.
Existing 'show_in_rest' => true keeps working. Migrate to public => true when the ability is meant for multiple client types.
2. Filtering with wp_get_abilities()
Before 7.1, wp_get_abilities() always returned the full registry. Everyone rolled their own array_filter. Now it accepts $args:
$abilities = wp_get_abilities( [
'category' => 'data-export',
'namespace' => 'my-plugin',
'metadata' => [ 'public' => true ],
] );
Declarative filters combine with AND. Custom per-item callbacks and a final result callback are also supported. Two global filters wrap the pipeline:
wp_get_abilities_item_include— keep or drop one abilitywp_get_abilities_result— reshape the final list
The REST abilities list controller now uses wp_get_abilities() instead of filtering after a full fetch. PHP and REST share one pipeline. You can also request the raw registry when you truly need every ability unfiltered.
3. Execution lifecycle
7.1 adds wp_ability_invoked at the start of WP_Ability::execute() — before input normalization, validation, permission checks, and the wp_pre_execute_ability short-circuit.
add_action( 'wp_ability_invoked', function ( $ability_name, $input, $ability ) {
// Fires even when input is invalid or permission fails.
// Do not log $input blindly — it may contain secrets.
do_action( 'my_plugin_record_ability_invocation', [
'ability' => $ability_name,
'timestamp' => time(),
] );
}, 10, 3 ); That is the hook for telemetry, tracing, and invocation counts. It runs for invalid input, failed permissions, short-circuits, cached results, and approval-gated calls.
wp_before_execute_ability and wp_after_execute_ability now receive the WP_Ability instance as a final argument. Existing two-arg callbacks still work; bump $accepted_args to receive the object.
Custom validation beyond JSON Schema:
wp_ability_validate_inputwp_ability_validate_output
Each receives true|WP_Error $is_valid, the value, and the ability name. Return true or a WP_Error. Returning false becomes a generic error. REST-style validate_callback / sanitize_callback schema keywords are not run by the Abilities API — use these filters.
There is also wp_pre_execute_ability to short-circuit execution. See New execution lifecycle filters.
4. Client-ready schemas and core abilities
core/get-site-info, core/get-user-info, and core/get-environment-info now share schema conventions: every output property has a translatable Title Case title and a description. Clients (REST, MCP, AI) can present fields without hard-coding labels.
core/get-user-info adds first_name, last_name, nickname, description, user_url. roles is normalized with array_values() so JSON is always an array. Optional fields input requests a subset; unknown names fail with ability_invalid_input before the callback. core/get-environment-info supports the same fields pattern.
core/get-user-info is now on REST at /wp-json/wp-abilities/v1/abilities. JSON Schema is prepared for client compatibility — see JSON Schema preparation.
5. Typed input on REST run
GET and DELETE used to pass every query string as a string. "10" was not 10; "true" was not true; ids=1,2,3 was one string.
7.1 coerces run-request input to input_schema types after validation accepts the value, as the input argument’s sanitize_callback. Permission and execute callbacks both see native types:
GET /wp-json/wp-abilities/v1/abilities/my-plugin/list-items/run
?input[limit]=10&input[featured]=true&input[ids]=1,2,3
becomes limit => 10, featured => true, ids => [1, 2, 3]. Invalid input is not coerced; you still get ability_invalid_input.
| WordPress 7.0 strings | WordPress 7.1 schema types | |
|---|---|---|
| limit=10 | "10" | 10 (int) |
| featured=true | "true" | true (bool) |
| ids=1,2,3 | "1,2,3" | [1, 2, 3] |
| Invalid input | Callback saw junk | ability_invalid_input first |
Landmines
meta.public => true and skip permission_callback Always set permission_callback; public only controls discovery error_log( wp_json_encode( $input ) ) on wp_ability_invoked Log ability name + timestamp; redact or drop raw input Rely on validate_callback inside input_schema
Use wp_ability_validate_input / wp_ability_validate_output
Next: WordPress 7.1 Editor Changes — the always-iframed canvas and the block APIs around it.
Get the next one in your inbox. Practical tips, no fluff.
More tutorials
View all- WordPress
How to Prepare Your Plugin or Theme for WordPress 7.1
A WordPress 7.1 compatibility checklist: iframed editor, client-side media hooks, Abilities public flag, jQuery UI 1.14.2, plus features that did not ship (React 19, collaboration).
22 min
- WordPress
What's New in WordPress 7.1 for Developers
WordPress 7.1 field guide for developers: client-side media, Abilities API, always-iframed editor, SVG Icon API, global styles, and what to test before users upgrade.
18 min
- WordPress
Client-Side Media Processing in WordPress 7.1
WordPress 7.1 processes images in the browser with wasm-vips — compression, thumbnails, HEIC, AVIF, GIF-to-video — plus REST sideload, finalize, and plugin hook compatibility.
25 min