Skip to content

wp_register_ability returns NULL when called from plugin during wp_abilities_api_init #135

@gelakhubutia

Description

@gelakhubutia

Description

When trying to register a custom ability from a WordPress plugin using the recommended wp_abilities_api_init hook, wp_register_ability consistently returns NULL even when called correctly during the action.

Environment

  • WordPress 6.9.1 (Abilities API built into core)
  • MCP Adapter plugin v0.4.1 (installed via Composer with Jetpack autoloader)
  • WooCommerce 10.5.2
  • PHP 8.x, shared hosting (cPanel)

Steps to Reproduce

  1. Install wordpress/mcp-adapter via Composer in wp-content/plugins/
  2. Create a plugin with the following code:
add_action( 'wp_abilities_api_init', function() {
    $result = wp_register_ability( 'my-plugin/my-ability', [
        'label'       => 'My Ability',
        'description' => 'Test ability',
        'input_schema' => [ 'type' => 'object', 'properties' => [] ],
        'execute_callback' => function( $input ) { return [ 'success' => true ]; },
        'permission_callback' => function() { return current_user_can( 'manage_options' ); },
        'meta' => [ 'show_in_rest' => true ],
    ]);
    error_log( 'Result: ' . ( $result ? get_class( $result ) : 'NULL' ) );
}, 5 );

add_action( 'plugins_loaded', function() {
    if ( class_exists( 'WP\MCP\Core\McpAdapter' ) ) {
        \WP\MCP\Core\McpAdapter::instance();
    }
}, 1 );
  1. Run wp eval 'var_dump(array_keys(wp_get_abilities()));'

Expected Behavior

my-plugin/my-ability should appear in the abilities list.

Actual Behavior

wp_register_ability returns NULL. The hook fires correctly (doing_action('wp_abilities_api_init') returns true), but the registration silently fails.

Debug Findings

  • doing_action('wp_abilities_api_init') returns YES inside the callback ✅
  • wp_register_ability is loaded from wp-includes/abilities-api.php (core) ✅
  • McpAdapter::instance() successfully initializes ✅
  • WooCommerce is also hooked into wp_abilities_api_init and its abilities register fine
  • The registry appears to already be initialized before our plugin's callback runs, possibly due to WooCommerce triggering WP_Abilities_Registry::get_instance() first

Question

Is there a timing conflict between WooCommerce's bundled abilities-api vendor copy and WordPress core's native implementation in 6.9? Is there a recommended way to register abilities from a plugin when WooCommerce is also present?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions