Skip to content

Add extensibility hook for custom Ability Table columns #203

@raftaar1191

Description

@raftaar1191

Summary

Add a filter hook to allow developers to extend the Ability_Table class in the Abilities Explorer, enabling custom columns without modifying core plugin files.

Problem Statement

Currently, there's no way for third-party plugins to add custom columns to the Abilities Explorer table. This limits extensibility for developers who want to display additional metadata or custom information about abilities.

Use Case: At WordCamp Kolhapur 2026, we want to display which abilities support MCP (Model Context Protocol) directly in the table view, but there's no clean way to achieve this without modifying core files.

Proposed Solution

Add a filter hook in the Abilities Explorer admin page that allows replacing or extending the table class:

// In the admin page file where the table is instantiated
$table_class = apply_filters( 'ai_abilities_explorer_table_class', Ability_Table::class );
$table = new $table_class();

Additionally, ensure that meta data is available at the top level of formatted abilities (not just in raw_data):

// In Ability_Handler::format_single_ability()
return array(
    'slug'          => $name,
    'name'          => $ability->get_label(),
    'description'   => $ability->get_description(),
    'provider'      => self::detect_provider( $name, $meta ),
    'input_schema'  => $ability->get_input_schema(),
    'output_schema' => $ability->get_output_schema(),
    'meta'          => $meta,  // Add this line
    'raw_data'      => array(
        // ...existing code...
    ),
);

Example Implementation

Here's how a developer would extend the table in their plugin:

<?php
namespace WordCamp_Kolhapur_2026;

use WordPress\AI\Experiments\Abilities_Explorer\Ability_Table as Base_Ability_Table;

class Extended_Ability_Table extends Base_Ability_Table {
    
    public function get_columns(): array {
        $columns = parent::get_columns();
        
        // Insert MCP Support before Actions
        $actions = $columns['actions'];
        unset( $columns['actions'] );
        $columns['mcp_support'] = __( 'MCP Support', 'wordcamp-kolhapur-2026' );
        $columns['actions'] = $actions;
        
        return $columns;
    }
    
    public function get_sortable_columns(): array {
        $sortable = parent::get_sortable_columns();
        $sortable['mcp_support'] = array( 'mcp_support', false );
        return $sortable;
    }
    
    public function column_mcp_support( $item ): string {
        $has_mcp = isset( $item['meta']['mcp']['public'] ) 
            && true === $item['meta']['mcp']['public'];
        
        if ( $has_mcp ) {
            return '<span style="color: #00a32a; font-weight: 600;">✓ Yes</span>';
        }
        return '<span style="color: #d63638;">✗ No</span>';
    }
    
    public function prepare_items(): void {
        parent::prepare_items();
        
        // Handle custom column sorting
        $orderby = isset( $_REQUEST['orderby'] ) 
            ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) 
            : '';
        
        if ( 'mcp_support' === $orderby && ! empty( $this->items ) ) {
            $order = isset( $_REQUEST['order'] ) 
                ? sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) 
                : 'asc';
            
            usort(
                $this->items,
                static function ( $a, $b ) use ( $order ) {
                    $a_has_mcp = isset( $a['meta']['mcp']['public'] ) 
                        && true === $a['meta']['mcp']['public'];
                    $b_has_mcp = isset( $b['meta']['mcp']['public'] ) 
                        && true === $b['meta']['mcp']['public'];
                    
                    $result = $a_has_mcp <=> $b_has_mcp;
                    return 'asc' === $order ? $result : -$result;
                }
            );
        }
    }
}

// Hook in the custom table class
add_filter(
    'ai_abilities_explorer_table_class',
    function ( $class_name ) {
        return Extended_Ability_Table::class;
    }
);

Benefits

  1. Extensibility: Plugins can add custom columns without forking or modifying core files
  2. Clean Architecture: Follows WordPress plugin development best practices
  3. Maintainability: Changes in the AI plugin won't break third-party extensions
  4. Flexibility: Each plugin can independently add its own columns
  5. Real-world Use Case: MCP support indicator helps developers quickly identify compatible abilities

Additional Use Cases

Beyond MCP support, this extensibility would enable:

  • Performance metrics: Display execution time or resource usage
  • Usage statistics: Show how often an ability is invoked
  • Custom metadata: Display plugin-specific information
  • Integration status: Show connection status with external services
  • Deprecation warnings: Highlight abilities scheduled for removal

Visual Example

Current table:

Name          | Slug                    | Provider | Actions
Get Posts     | wordpress/get-posts     | Core     | View | Test
Create Draft  | my-plugin/create-draft  | Plugin   | View | Test

With MCP Support column:

Name          | Slug                    | Provider | MCP Support | Actions
Get Posts     | wordpress/get-posts     | Core     | ✓ Yes       | View | Test
Create Draft  | my-plugin/create-draft  | Plugin   | ✗ No        | View | Test

Implementation Checklist

  • Add ai_abilities_explorer_table_class filter in admin page
  • Ensure meta is available in formatted ability data (top-level, not just in raw_data)
  • Document the filter in code comments
  • Add example to developer documentation
  • Consider adding action hooks as an alternative: do_action( 'ai_abilities_explorer_column_{$column_name}', $item )

Related Files

  • includes/Experiments/Abilities_Explorer/Ability_Table.php
  • includes/Experiments/Abilities_Explorer/Ability_Handler.php
  • Admin page file that instantiates the table

Context

This request comes from WordCamp Kolhapur 2026 where we're building integrations with the WordPress Abilities API and MCP. We want to showcase extensibility patterns that other developers can follow.

Reference repository: https://github.com/raftaar1191/wordcamp-kolhapur-2026

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status

    Backlog

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions