wp_register_ability( string $name,  $args ): WP_Ability|null

Registers a new ability using the Abilities API. It requires three steps:

Description

  1. Hook into the wp_abilities_api_init action.
  2. Call wp_register_ability() with a namespaced name and configuration.
  3. Provide execute and permission callbacks.

Example:

function my_plugin_register_abilities(): void {
    wp_register_ability(
        'my-plugin/analyze-text',
        array(
            'label'               => __( 'Analyze Text', 'my-plugin' ),
            'description'         => __( 'Performs sentiment analysis on provided text.', 'my-plugin' ),
            'category'            => 'text-processing',
            'input_schema'        => array(
                'type'        => 'string',
                'description' => __( 'The text to be analyzed.', 'my-plugin' ),
                'minLength'   => 10,
                'required'    => true,
            ),
            'output_schema'       => array(
                'type'        => 'string',
                'enum'        => array( 'positive', 'negative', 'neutral' ),
                'description' => __( 'The sentiment result: positive, negative, or neutral.', 'my-plugin' ),
                'required'    => true,
            ),
            'execute_callback'    => 'my_plugin_analyze_text',
            'permission_callback' => 'my_plugin_can_analyze_text',
            'meta'                => array(
                'annotations' => array(
                    'readonly' => true,
                ),
                'public'      => true,
            ),
        )
    );
}
add_action( 'wp_abilities_api_init', 'my_plugin_register_abilities' );

Naming Conventions

Ability names must follow these rules:

  • Include a namespace prefix (e.g., my-plugin/my-ability).
  • Use only lowercase alphanumeric characters, dashes, and forward slashes.
  • Use descriptive, action-oriented names (e.g., process-payment, generate-report).

Categories

Abilities must be organized into categories. Ability categories provide better discoverability and must be registered before the abilities that reference them:

function my_plugin_register_categories(): void {
    wp_register_ability_category(
        'text-processing',
        array(
            'label'       => __( 'Text Processing', 'my-plugin' ),
            'description' => __( 'Abilities for analyzing and transforming text.', 'my-plugin' ),
        )
    );
}
add_action( 'wp_abilities_api_categories_init', 'my_plugin_register_categories' );

Input and Output Schemas

Schemas define the expected structure, type, and constraints for ability inputs and outputs using JSON Schema syntax. They serve two critical purposes: automatic validation of data passed to and returned from abilities, and self-documenting API contracts for developers.

WordPress implements a validator based on a subset of the JSON Schema Version 4 specification (https://json-schema.org/specification-links.html#draft-4).
For details on supported JSON Schema properties and syntax, see the related WordPress REST API Schema documentation: https://developer.wordpress.org/rest-api/extending-the-rest-api/schema/#json-schema-basics

Defining schemas is mandatory when there is a value to pass or return.
They ensure data integrity, improve developer experience, and enable better documentation:

'input_schema' => array(
    'type'        => 'string',
    'description' => __( 'The text to be analyzed.', 'my-plugin' ),
    'minLength'   => 10,
    'required'    => true,
),
'output_schema'       => array(
    'type'        => 'string',
    'enum'        => array( 'positive', 'negative', 'neutral' ),
    'description' => __( 'The sentiment result: positive, negative, or neutral.', 'my-plugin' ),
    'required'    => true,
),

Callbacks

Execute Callback

The execute callback performs the ability’s core functionality. It receives optional input data and returns either a result or WP_Error on failure.

function my_plugin_analyze_text( string $input ): string|WP_Error {
    $score = My_Plugin::perform_sentiment_analysis( $input );
    if ( is_wp_error( $score ) ) {
        return $score;
    }
    return My_Plugin::interpret_sentiment_score( $score );
}

Permission Callback

The permission callback determines whether the ability can be executed.
It receives the same input as the execute callback and must return a boolean or WP_Error. Common use cases include checking user capabilities, validating API keys, or verifying system state:

function my_plugin_can_analyze_text( string $input ): bool|WP_Error {
    return current_user_can( 'edit_posts' );
}

Client Exposure

Set the high-level public flag to make an ability available to clients such as the REST API, MCP, or AI agents:

'meta' => array(
    'public' => true,
),

The public flag seeds the default for each per-channel flag. For the REST API it seeds show_in_rest, which lets the ability be invoked via HTTP requests. Set a per-channel flag directly to override that default. For example, keep a public ability out of the REST API:

'meta' => array(
    'public'       => true,
    'show_in_rest' => false,
),

See also

Parameters

$namestringrequired
The name of the ability. Must be a namespaced string containing a prefix, e.g., my-plugin/my-ability. Can only contain lowercase alphanumeric characters, dashes, and forward slashes.
mixed> $args { An associative array of arguments for configuring the ability.
@type string $label Required. The human-readable label for the ability.
@type string $description Required. A detailed description of what the ability does and when it should be used.
@type string $category Required. The ability category slug this ability belongs to.
The ability category must be registered via wp_register_ability_category() before registering the ability.
@type callable $execute_callback Required. A callback function to execute when the ability is invoked.
Receives optional mixed input data and must return either a result value (any type) or a WP_Error object on failure.
@type callable $permission_callback Required. A callback function to check permissions before execution.
Receives optional mixed input data (same as execute_callback) and must return true/false for simple checks, or WP_Error for detailed error responses.
@type array<string, mixed> $input_schema Optional. JSON Schema definition for validating the ability’s input.
Must be a valid JSON Schema object defining the structure and constraints for input data. Used for automatic validation and API documentation.
@type array<string, mixed> $output_schema Optional. JSON Schema definition for the ability’s output.
Describes the structure of successful return values from execute_callback. Used for documentation and validation.
@type array<string, mixed> $meta { Optional. Additional metadata for the ability.
@type array<string, bool|null> $annotations { Optional. Semantic annotations describing the ability’s behavioral characteristics.
These annotations are hints for tooling and documentation.
@type bool|null $readonly Optional. If true, the ability does not modify its environment.
@type bool|null $destructive Optional. If true, the ability may perform destructive updates to its environment.
If false, the ability performs only additive updates.
@type bool|null $idempotent Optional. If true, calling the ability repeatedly with the same arguments will have no additional effect on its environment.
} @type bool $public Optional. Whether the ability is meant to be available to clients such as the REST API, MCP, or AI agents. Seeds the default for per-channel flags like $show_in_rest.
Defaults to false.
@type bool $show_in_rest Optional. Whether to expose this ability in the REST API.
When true, the ability can be invoked via HTTP requests.
Default is the value of $public when set, false otherwise.
} @type string $ability_class Optional. Fully-qualified custom class name to instantiate instead of the default WP_Ability class. The custom class must extend WP_Ability. Useful for advanced customization of ability behavior.
}

Return

WP_Ability|null The registered ability instance on success, null on failure.

Source

function wp_register_ability( string $name, array $args ): ?WP_Ability {
	if ( ! doing_action( 'wp_abilities_api_init' ) ) {
		_doing_it_wrong(
			__FUNCTION__,
			sprintf(
				/* translators: 1: wp_abilities_api_init, 2: string value of the ability name. */
				__( 'Abilities must be registered on the %1$s action. The ability %2$s was not registered.' ),
				'<code>wp_abilities_api_init</code>',
				'<code>' . esc_html( $name ) . '</code>'
			),
			'6.9.0'
		);
		return null;
	}

	$registry = WP_Abilities_Registry::get_instance();
	if ( null === $registry ) {
		return null;
	}

	return $registry->register( $name, $args );
}

Changelog

VersionDescription
6.9.0Introduced.

User Contributed Notes

  1. Skip to note 2 content

    I recently started playing with the WordPress Abilities API and tried to connect it with Claude Desktop using the MCP Adapter.

    I made a small plugin just for testing. It has two abilities: one to get published notes from my website, and another one to create new notes as drafts.

    It was interesting to see how Claude can interact with WordPress through these abilities, without giving it full access to the website.

    One thing I learned is that permissions are really important, especially when allowing AI to create or change content. I also think keeping AI-generated content as drafts is a good idea, so we can review it before publishing.

    Still learning about this API, but I think it opens some interesting possibilities for WordPress developers.

You must log in before being able to contribute a note or feedback.