Back to Tips & Tricks

Connect Claude Code to WordPress MCP with the Official MCP Adapter

BoostMyCroco TeamPublished on
Abstract illustration of a code editor linked to a WordPress site through a glowing connector, representing MCP Adapter

To connect Claude Code to WordPress over MCP, install the official MCP Adapter plugin (version 0.7.1) from the WordPress.org directory. Then point Claude Code, Cursor or VS Code at the default server at /wp-json/mcp/mcp-adapter-default-server. On a local site, the client runs WP-CLI over STDIO. On a live site, it goes through the @automattic/mcp-wordpress-remote proxy with an Application Password.

The AI reaches your site's abilities through three built-in tools. To give it something of your own to call, register an ability with wp_register_ability() and mark it public.

What MCP Adapter is (and isn't)

MCP Adapter is the server and transport layer between WordPress and MCP clients. It takes abilities registered with the Abilities API, in core since WordPress 6.9, and makes them callable from Claude Code, Claude Desktop, Cursor, VS Code and other MCP clients. It has no AI features, no MCP client and no chat UI of its own. If your site exposes no abilities, the AI has nothing to call.

Current facts for version 0.7.1, released 15 October 2026:

  • Requires WordPress 6.9 or higher and PHP 7.4 or higher. Tested up to WordPress 7.1.3.
  • Supports MCP revisions 2025-11-25 and 2026-07-28. Clients that ask for 2025-06-18 or 2024-11-05 still connect and are served with the 2025-11-25 schema.
  • The standalone Abilities API plugin has not been supported since 0.6.0. Use the API in core instead.
  • The plugin is still experimental and pre-1.0. MCP stays out of core because the spec is still changing, and the 2026-07-28 revision was a major breaking update.

The WordPress Core AI team released it as a canonical plugin on WordPress.org on 7 October 2026. If you follow Claude Code news, see also our piece on the Claude Code source code leak.

Install the official plugin

Install the plugin from the WordPress.org directory, not from a GitHub ZIP or a copy bundled inside another plugin.

  1. In WP Admin, go to Plugins > Add New.
  2. Search for "MCP Adapter".
  3. Click Install Now, then Activate.

Or install it with WP-CLI:

wp plugin install mcp-adapter --activate

Installed an earlier build from the GitHub releases page? Delete it first, then install from the directory so updates arrive through the normal dashboard.

Version 0.7.0 deprecated using the adapter as a bundled library. If a theme or plugin still ships its own copy, you will see a duplicate-copy notice. See Troubleshooting below.

How the default server works

Once the plugin is active, it registers a default MCP server at https://your-site.com/wp-json/mcp/mcp-adapter-default-server. That server offers three tools:

  • mcp-adapter/discover-abilities lists the public abilities on the site.
  • mcp-adapter/get-ability-info returns one ability's description and its input and output schemas.
  • mcp-adapter/execute-ability runs an ability with the arguments the AI built from that schema.

Your own abilities are not registered one by one in tools/list. A client that lists tools sees these three and nothing else, and that is by design. The AI calls discover, then get info, then execute.

Note the naming difference. In MCP tool calls the names use hyphens (mcp-adapter-discover-abilities), while ability names use a slash.

Want an ability to appear as its own direct tool? Create a custom server on the mcp_adapter_init hook with $adapter->create_server() and list the ability explicitly. Abilities without any public flag can only be reached this way.

Every request runs as a WordPress user. The default transport check is is_user_logged_in(), and each ability's own permission callback runs against that user. The user you connect with decides what the AI can do.

Option A: local site over STDIO

On a local site, the client can launch WP-CLI directly and talk to it over STDIO. No HTTP and no password are involved.

First, check the server from your terminal, inside the WordPress folder:

wp mcp-adapter list

echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | wp mcp-adapter serve --user=mcp-editor --server=mcp-adapter-default-server

echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"mcp-adapter-discover-abilities","arguments":{}}}' | wp mcp-adapter serve --user=mcp-editor --server=mcp-adapter-default-server

Replace mcp-editor with the login of a real user on the site. Here is what each command should return:

  • wp mcp-adapter list shows the registered servers.
  • The tools/list call returns the three tools above.
  • The discovery call returns the public abilities as JSON.

Next, add this to your client's MCP server configuration. Where the config lives depends on the client, so check its documentation.

{
  "mcpServers": {
    "wordpress-default": {
      "command": "wp",
      "args": [
        "--path=/path/to/your/wordpress/site",
        "mcp-adapter",
        "serve",
        "--server=mcp-adapter-default-server",
        "--user=mcp-editor"
      ]
    }
  }
}

Set --path to your WordPress root folder. The wp command must be on the PATH the client sees. If it isn't, use the full path to the WP-CLI binary.

Restart the client or reload its MCP servers. Then ask "Which WordPress abilities can you use?" It should call the discovery tool and list them.

Option B: live site over HTTP

For a site on a server, the client talks to @automattic/mcp-wordpress-remote. This is a small proxy that runs on your machine through npx, so Node.js must be installed. It turns the client's STDIO traffic into authenticated HTTP calls to the default server.

  1. Create a dedicated user in Users > Add New, for example mcp-editor. Give it the lowest role that still passes the permission checks of the abilities you need. Author or Editor covers most content work. Never use Administrator.
  2. Edit that user, scroll to Application Passwords, enter a name such as "Claude Code", and click Add New Application Password.
  3. Copy the generated password. WordPress shows it only once.
  4. Add the config below to your client with your HTTPS URL, the username and the Application Password.
{
  "mcpServers": {
    "wordpress-live": {
      "command": "npx",
      "args": ["-y", "@automattic/mcp-wordpress-remote@latest"],
      "env": {
        "WP_API_URL": "https://example.com/wp-json/mcp/mcp-adapter-default-server",
        "LOG_FILE": "/path/to/mcp-wordpress-remote.log",
        "WP_API_USERNAME": "mcp-editor",
        "WP_API_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
      }
    }
  }
}

LOG_FILE is where the proxy writes its log, which helps when a connection fails. Keep this config out of Git, because it contains a live credential. To cut off access, revoke the Application Password on the user's profile.

Add your own read-only ability

Now give the AI something useful and safe to call. We'll register bmc/list-recent-posts, a read-only ability that returns the latest published items of any public post type. Custom post types created with JetEngine are ordinary post types, so a JetEngine CPT slug works too.

Don't copy the example in the adapter's GitHub README onto a live site. It lets the caller choose the post status, including draft or private, while only checking the read capability, which every Subscriber has. Any logged-in user could then pull drafts and private posts through MCP.

Our version hard-codes post_status to publish. The read check then matches the data, because the ability returns nothing that isn't already public.

Keep these rules in mind:

  • Register on wp_abilities_api_init, not on init.
  • Use a namespaced name with a slash, like bmc/list-recent-posts.
  • Setting meta.public to true exposes the ability, including on the default MCP server.
  • meta.mcp.public overrides that for MCP only. false hides a public ability from MCP, and true exposes an otherwise private ability to MCP only. We set both so you can see the shape.
  • On WordPress 6.9 and 7.0, meta.public covers MCP but not the REST API, which still needs meta.show_in_rest set to true. From 7.1, core applies meta.public to REST as well.
  • Return plain arrays that match output_schema.

Create the file wp-content/mu-plugins/bmc-mcp-abilities.php and paste the code below. Create the mu-plugins folder first if it doesn't exist. Must-use plugins load automatically, so there is nothing to activate.

Code

<?php
/**
 * Plugin Name: BMC MCP Abilities
 * Description: Read-only MCP ability that lists recent published posts of a public post type.
 * Version: 1.0.0
 * Requires at least: 6.9
 * Requires PHP: 7.4
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

add_action( 'wp_abilities_api_init', 'bmc_register_mcp_abilities' );

/**
 * Register the bmc/list-recent-posts ability.
 */
function bmc_register_mcp_abilities() {
    if ( ! function_exists( 'wp_register_ability' ) ) {
        return;
    }

    wp_register_ability(
        'bmc/list-recent-posts',
        array(
            'label'               => __( 'List recent posts', 'bmc' ),
            'description'         => __( 'Returns the most recent published items of a public post type: ID, title, date and link. Never returns drafts, private posts or post content.', 'bmc' ),
            'category'            => 'site',
            'input_schema'        => array(
                'type'                 => 'object',
                'properties'           => array(
                    'post_type' => array(
                        'type'        => 'string',
                        'description' => 'Public post type slug, for example post, page or a JetEngine CPT slug.',
                        'default'     => 'post',
                    ),
                    'number'    => array(
                        'type'        => 'integer',
                        'description' => 'How many items to return.',
                        'minimum'     => 1,
                        'maximum'     => 20,
                        'default'     => 5,
                    ),
                ),
                'additionalProperties' => false,
            ),
            'output_schema'       => array(
                'type'  => 'array',
                'items' => array(
                    'type'       => 'object',
                    'properties' => array(
                        'ID'    => array( 'type' => 'integer' ),
                        'title' => array( 'type' => 'string' ),
                        'date'  => array( 'type' => 'string' ),
                        'link'  => array( 'type' => 'string' ),
                    ),
                    'required'   => array( 'ID', 'title', 'date', 'link' ),
                ),
            ),
            'execute_callback'    => 'bmc_list_recent_posts',
            // Safe with 'read' only because the query below is hard-coded to published posts.
            'permission_callback' => function () {
                return current_user_can( 'read' );
            },
            'meta'                => array(
                'public' => true,                      // Exposed to clients, including the default MCP server.
                'mcp'    => array( 'public' => true ), // MCP-only override; false would hide it from MCP.
                // On WordPress 6.9 and 7.0, REST API access also needs:
                // 'show_in_rest' => true,
            ),
        )
    );
}

/**
 * Execute callback: returns plain arrays that match output_schema.
 *
 * @param array $input Input sent by the client.
 * @return array|WP_Error
 */
function bmc_list_recent_posts( $input = array() ) {
    $input     = is_array( $input ) ? $input : array();
    $post_type = isset( $input['post_type'] ) ? sanitize_key( $input['post_type'] ) : 'post';
    $number    = isset( $input['number'] ) ? absint( $input['number'] ) : 5;
    $number    = max( 1, min( 20, $number ) );

    if ( ! post_type_exists( $post_type ) || ! get_post_type_object( $post_type )->public ) {
        return new WP_Error( 'bmc_invalid_post_type', __( 'Unknown or non-public post type.', 'bmc' ) );
    }

    $posts = get_posts(
        array(
            'post_type'      => $post_type,
            'post_status'    => 'publish', // Never let the caller choose the status.
            'has_password'   => false,     // Skip password-protected posts.
            'posts_per_page' => $number,
            'orderby'        => 'date',
            'order'          => 'DESC',
            'no_found_rows'  => true,
        )
    );

    $items = array();
    foreach ( $posts as $post ) {
        $items[] = array(
            'ID'    => (int) $post->ID,
            'title' => wp_strip_all_tags( get_the_title( $post ) ),
            'date'  => (string) get_post_time( 'c', true, $post ),
            'link'  => esc_url_raw( (string) get_permalink( $post ) ),
        );
    }

    return $items;
}

How the ability works and how to test it

  • Input: post_type is cleaned with sanitize_key(). number is clamped to 1-20 in PHP, even if a client ignores the schema.
  • Post type check: post_type_exists() and the public flag from get_post_type_object() stop the AI from reading non-public types such as navigation menu items.
  • Query: get_posts() runs with post_status fixed to publish, and has_password set to false skips password-protected posts.
  • Output: each item has only an ID, a title, an ISO 8601 date in GMT and a permalink. Post content and raw WP_Post objects never leave the site.
  • Permission: if you later add drafts, raise the check to match the data, for example edit_others_posts for other people's drafts.

Test it

  1. Run the discovery command from Option A again. bmc/list-recent-posts should now appear in the result.
  2. In your MCP client, ask: "Use the WordPress tools to show the 5 most recent published items of type post." Replace post with any public post type slug that exists on your site, such as your JetEngine CPT slug. The AI calls discovery, reads the ability info, and builds the execute-ability call itself. You should get back IDs, titles, dates and links.
  3. Ask for a post type that doesn't exist, or a non-public one. You should get the "Unknown or non-public post type" error instead of data.

Troubleshooting

  • My ability doesn't show in tools/list. Expected on the default server. The AI goes through discover, get info and execute. For a direct tool, list the ability in a custom server.
  • ability_not_found when calling your own ability. Since 0.7.1, abilities that are not exposed through MCP return the same error as unknown names. Check these in order:
    • meta.public is true.
    • meta.mcp.public is not false.
    • The permission callback passes for the connected user.
    • The file sits directly in mu-plugins, not in a subfolder. WordPress does not auto-load subfolders there.
  • Admin notice about a duplicate MCP Adapter copy. A theme or plugin bundles its own copy. Keep the WordPress.org plugin and ask the author to drop the bundled one. Defining WP_MCP_AUTOLOAD as false hides the notice, but this is not recommended.
  • Connection errors right after updating. Version 0.7.1 caps stored session data at 4 KiB, and affected clients need to reconnect once. On multisite, the 0.6.0 update also required one reconnect. Restart the MCP server in your client.
  • A tool, resource or prompt disappeared after 0.7.0. Malformed fields are no longer repaired, so the component is rejected. Check the debug log for a _doing_it_wrong entry with the schema error path and fix the source. Then confirm with wp mcp-adapter list --protocol=2026-07-28.
  • Fatal error mentioning WP_CLI on normal page loads. This was a 0.6.0 bug, fixed in 0.6.1. Update the plugin.
  • The ability works over MCP but not over the REST API. On WordPress 6.9 and 7.0, add 'show_in_rest' => true to meta.
  • Claude.ai web connector says "Your account was authorized, but no MCP server was found at the provided URL". This is reported in GitHub issue #361, opened 1 October 2026. It is still open with no maintainer reply. Use a config-file client instead, such as Claude Code, Claude Desktop, Cursor or VS Code, with the STDIO or proxy setup above.

Security checklist

  • Exposure is opt-in. Only mark an ability public if its output is something the connected user may see anyway.
  • Connect with a dedicated, least-privilege user and its own Application Password. Revoke the password when the project ends.
  • Use HTTPS for remote connections. Outside local environments, WordPress only offers Application Passwords on HTTPS sites.
  • Don't run wp mcp-adapter serve --user=admin on a production server. STDIO acts as whatever user you pass, with no password check in between.
  • The plugin is pre-1.0 and experimental, and 0.7.0 shipped breaking changes. Read the release notes before each update.

If you want custom abilities for your JetEngine data, or an MCP setup built and locked down for you, post a request on BoostMyCroco.

Frequently Asked Questions

Does the WordPress MCP Adapter work with Claude.ai web custom connectors?
Not reliably right now. A connection error with the Claude.ai web connector is reported in GitHub issue #361, which is still open without a maintainer reply. Use Claude Code, Claude Desktop, Cursor or VS Code with the STDIO or proxy configuration instead.
Is it safe to let Claude Code access my live WordPress site?
It can be, if you limit what it can reach. Abilities are only exposed when marked public, and each one still runs its permission check as the connected WordPress user. Connect with a dedicated low-privilege account over HTTPS, and remember that the plugin is still pre-1.0.
Do I need Node.js to use MCP Adapter?
Only for remote sites. The HTTP setup runs the @automattic/mcp-wordpress-remote proxy through npx, which needs Node.js on your computer. A local site connected over STDIO only needs WP-CLI.
Can the AI edit posts or JetEngine data once it is connected?
Only if an ability that edits data is exposed and the connected user has the right capabilities. MCP Adapter adds no abilities of its own. The example ability in this guide is read-only and returns published items only, including JetEngine custom post types.
What happened to the Automattic wordpress-mcp plugin?
The Automattic/wordpress-mcp repository is archived and read-only. The maintained option is the MCP Adapter plugin from WordPress/mcp-adapter, now available in the WordPress.org Plugin Directory.

Sources

  1. WordPress MCP Adapter 0.7.0 launches on the WordPress Plugin Directory (make.wordpress.org)
  2. Releases · WordPress/mcp-adapter · GitHub (github.com)
  3. WordPress MCP Adapter 0.7 Review (2026): Setup, Security, Verdict (instawp.com)

Related tips