WP Manifestindependent plugin directory
manifest / ai / mcp-abilities

MCP Abilities

A WordPress plugin that registers content management abilities for MCP clients via the WordPress Abilities API.

by Ian Svoboda · github.com/iansvo/mcp-abilities · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/iansvo/mcp-abilities/archive/refs/heads/main.zip

A WordPress plugin that registers content management abilities for MCP clients via the WordPress Abilities API. Use it directly or as a starting point for your own abilities plugin.

Requires WordPress 6.9+ and the MCP Adapter plugin.

Installation

  1. Download or clone this repository into wp-content/plugins/:
    cd wp-content/plugins/
    git clone https://github.com/iansvo/mcp-abilities.git
  2. Activate the plugin in wp-admin or via WP-CLI:
    wp plugin activate mcp-abilities
  3. Make sure the MCP Adapter plugin is also installed and active.

Included Abilities

Ability Description Required Cap Type
mcp-abilities/site-info Site name, URL, WP version, theme, timezone read Read
mcp-abilities/list-posts List posts with filtering and pagination read Read
mcp-abilities/get-post Get a single post by ID with content and meta read Read
mcp-abilities/create-post Create a new post or page edit_posts Write
mcp-abilities/update-post Update an existing post by ID edit_posts Write
mcp-abilities/delete-post Trash or permanently delete a post delete_posts Write

MCP User Setup

Create a dedicated WordPress user for your MCP client rather than using your admin account. This gives you scoped capabilities, a clear audit trail in post revisions, and easy revocation.

The unfiltered_html Problem

WordPress applies wp_kses_post to content saved by users who lack the unfiltered_html capability. This corrupts code blocks containing HTML, PHP, or JSX — tags get stripped and block comment attributes get mangled.

Contributor and Author roles don't have unfiltered_html. Editor and Administrator roles do, but they grant far more capabilities than an MCP agent needs.

This plugin deliberately does not run wp_kses_post on post content in its callbacks. Instead, it lets wp_insert_post and wp_update_post handle sanitization internally — these functions respect the unfiltered_html capability. If your MCP user has the capability, content is preserved. If not, WordPress core still sanitizes safely.

Custom MCP Agent Role (mu-plugin)

Drop this file in wp-content/mu-plugins/mcp-agent-role.php to create a role with content management capabilities and unfiltered_html:

<?php
/**
 * Plugin Name: MCP Agent Role
 * Description: Creates a custom role for MCP AI agents with content management caps + unfiltered_html.
 */

add_action( 'init', function () {
    $version = 1;

    if ( (int) get_option( 'mcp_agent_role_version' ) === $version ) {
        return;
    }

    remove_role( 'mcp_agent' );

    add_role(
        'mcp_agent',
        'MCP Agent',
        array(
            // Read.
            'read'                   => true,

            // Posts.
            'edit_posts'             => true,
            'edit_others_posts'      => true,
            'edit_published_posts'   => true,
            'publish_posts'          => true,
            'delete_posts'           => true,
            'delete_others_posts'    => true,
            'delete_published_posts' => true,

            // Pages.
            'edit_pages'             => true,
            'edit_others_pages'      => true,
            'edit_published_pages'   => true,
            'publish_pages'          => true,
            'delete_pages'           => true,
            'delete_others_pages'    => true,
            'delete_published_pages' => true,

            // Media.
            'upload_files'           => true,

            // Critical for code blocks.
            'unfiltered_html'        => true,
        )
    );

    update_option( 'mcp_agent_role_version', $version );
});

After adding the mu-plugin:

  1. Create a new user in wp-admin with the MCP Agent role
  2. Generate an Application Password for that user (Users > Edit User > Application Passwords)

Security Considerations

  • unfiltered_html allows saving arbitrary HTML. This is acceptable for a controlled AI agent authenticated via application password, but understand the tradeoff.
  • Multisite: unfiltered_html is restricted to Super Admins by default and cannot be granted to custom roles through add_role alone.
  • Least privilege: This role intentionally excludes manage_options, activate_plugins, and other administrative capabilities. Add them only if you need them.
  • Role versioning: Bump the $version number in the mu-plugin if you change the capabilities list — the role will be recreated on the next page load.

Extending With Additional Abilities

This plugin focuses on content management. You can register additional abilities for plugin management, options, users, or anything else. Here's a quick example for listing plugins:

add_action( 'wp_abilities_api_init', function () {
    wp_register_ability(
        'my-plugin/list-plugins',
        array(
            'category'    => 'mcp-abilities',
            'label'       => 'List Plugins',
            'description' => 'List installed plugins with their status.',
            'output_schema' => array(
                'type'       => 'object',
                'properties' => array(
                    'plugins' => array( 'type' => 'array' ),
                ),
            ),
            'permission_callback' => function () {
                return current_user_can( 'activate_plugins' );
            },
            'execute_callback' => function () {
                if ( ! function_exists( 'get_plugins' ) ) {
                    require_once ABSPATH . 'wp-admin/includes/plugin.php';
                }

                $all_plugins    = get_plugins();
                $active_plugins = get_option( 'active_plugins', array() );

                $plugins = array();
                foreach ( $all_plugins as $file => $data ) {
                    $plugins[] = array(
                        'file'    => $file,
                        'name'    => $data['Name'],
                        'version' => $data['Version'],
                        'active'  => in_array( $file, $active_plugins, true ),
                    );
                }

                return array( 'plugins' => $plugins );
            },
            'meta' => array(
                'show_in_rest' => true,
                'mcp'          => array( 'public' => true ),
            ),
        )
    );
});

License

GPL-2.0-or-later. See LICENSE for details.