Are you down with MCP?

To be honest, I didn’t get the big deal with MCP. A lot of use cases felt uninspiring. Why would I burn tokens asking an AI to paste a blog post or get basic information out of my website when I could probably do it faster myself? It felt like a cool concept without much real world impact. So I decided to try it out myself.

Now, after playing with the WordPress Abilities API and MCP Adaptor, I’m starting to see the light. This time I began with a very specific WordPress + WooCommerce workflow to see if I could make it faster with AI. And it didn’t disappoint.

The key here is not just an MCP’s ability to connect to an application and fetch or update data. That’s only half of it. The other half is that this connection is mediated through the natural language interface of an AI agent which brings its own capabilities to the workflow. You should have a need for both of these things working together.

Let’s dig into a concrete example.

For my wife’s bakery, I have a custom WordPress plugin that helps track the costs of separate ingredients and calculate a basic COGS value for each item she makes. Recipes are a basic custom post type, and ingredients are a taxonomy. Ingredients have a few meta fields- the cost of the ingredient and the amount in the package. When I assign the “flour” ingredient to the “bread” recipe, I say how many grams are in that recipe, and the plugin uses the ingredient info to tell me how much it’ll cost to make one batch. I can assign that cost to any products in Woo, and as she’s filling out orders, we can see the profit margin.

We were updating prices and adding new ingredients for some recipes and I was manually editing this information in the user interface- filling out fields, hitting save, etc. This was the first moment where I thought, couldn’t I just write- or better yet speak- these changes to an AI and have it update all the prices for me? Or could I tell an AI that she’s baking 20 loaves and ask it to check how much flour we’ll need on hand? All the data is there, and instead of designing and building more custom UI for all of this, more forms to click through, I could just use an MCP.

Putting the pieces together

Before I start, a few caveats

  1. This is still early days for MCP and for me trying to understand it.
  2. Don’t do this stuff on a production site!
  3. You need to install two plugins (or composer dependencies, if that’s your jam) because this functionality is not in core yet, Abilities API and MCP Adaptor. Then write your own stuff in a plugin.
  4. Jonathan Bossenger’s talk at WCUS is fantastic if you want to dig in further.

Now I’m going to give a very simplified overview (mostly to sharpen my own understanding), but know there’s much more below this surface level explanation.

Abilities API

An ability is a PHP function that takes input and provides output. It becomes a tool you can expose. In your plugin, you use wp_register_ability to create new tools. My ability was “create ingredient.” It took in the name of the ingredient and some data and created a new term. Example: “Add flour to my ingredients list. It’s $9.99 for 1000 grams.”

The Abilities API is a return to classic PHP and WordPress. If you’ve written custom WP REST API endpoints or WP CLI commands, it will feel familiar. You have access to all the same core WordPress functionality. You just have to make sure you specify the input/output schema and describe what it does in very natural language. Whereas REST endpoints include everything related to an object, abilities feel much more specific.

In the future, these same abilities could be exposed in different ways, like an AI agent inside the WordPress dashboard, a new protocol, or in the Command Palette. The ability is just a primitive for a common action, and updating a term could end up being an ability provided in core already and perhaps you’ll be able to hook in and modify the schema for your taxonomies instead of building the entire ability from scratch.

Expand to see an example ability
<?php   // Ability to create a new ingredient
add_action('abilities_api_init', function () {
    wp_register_ability('bc-recipe-calculator/create-ingredient', [
        'label' => 'Create Ingredient',
        'description' => 'Creates a new ingredient in the bc_ingredient taxonomy with price, quantity, and unit.',
        'input_schema' => [
            'type' => 'object',
            'properties' => [
                'name' => [
                    'type' => 'string',
                    'description' => 'The name of the ingredient.'
                ],
                'ingredient_price' => [
                    'type' => 'number',
                    'description' => 'The price of the ingredient.'
                ],
                'ingredient_quantity' => [
                    'type' => 'number',
                    'description' => 'The quantity of the ingredient.'
                ],
                'ingredient_unit' => [
                    'type' => 'string',
                    'description' => 'The unit of the ingredient.'
                ]
            ],
            'required' => ['name', 'ingredient_price', 'ingredient_quantity', 'ingredient_unit']
        ],
        'output_schema' => [
            'type' => 'object',
            'properties' => [
                'term_id' => ['type' => 'integer'],
                'name' => ['type' => 'string'],
                'ingredient_price' => ['type' => 'number'],
                'ingredient_quantity' => ['type' => 'number'],
                'ingredient_unit' => ['type' => 'string']
            ],
            'required' => ['term_id', 'name', 'ingredient_price', 'ingredient_quantity', 'ingredient_unit']
        ],
        'execute_callback' => function ($input) {
            $result = wp_insert_term($input['name'], 'bc_ingredient');
            if (is_wp_error($result)) {
                return [
                    'error' => $result->get_error_message()
                ];
            }
            $term_id = $result['term_id'];
            update_term_meta($term_id, 'ingredient_price', $input['ingredient_price']);
            update_term_meta($term_id, 'ingredient_quantity', $input['ingredient_quantity']);
            update_term_meta($term_id, 'ingredient_unit', $input['ingredient_unit']);
            return [
                'term_id' => (int) $term_id,
                'name' => $input['name'],
                'ingredient_price' => (float) $input['ingredient_price'],
                'ingredient_quantity' => (float) $input['ingredient_quantity'],
                'ingredient_unit' => $input['ingredient_unit']
            ];
        },
        'permission_callback' => function () {
            // Allow any authenticated user
            return current_user_can( 'edit_posts' );
        }
    ]);
});Code language: PHP (php)

MCP Adaptor

The MCP adaptor provides the plumbing to collect a group of abilities, expose them as an MCP server, and set authentication rules. I created a “recipe calculator” server that I could connect to and told it which abilities to expose. This server can be reached via a custom REST API endpoint, in my case wp-json/bc-recipe-calculator/mcp.

Expand to see an example server registration
<?php
use WP\MCP\Core\McpAdapter;

// Hook into the MCP adapter initialization
add_action( 'mcp_adapter_init', function( $adapter ) {
    $adapter->create_server(
        'bc-recipe-calculator-server',                          // Unique server ID
        'bc-recipe-calculator',                                // REST API namespace
        'mcp',                                      // REST API route
        'Recipe MCP Server',                      // Human-readable name
        'A simple MCP server for demonstration',    // Description
        '1.0.0',                                    // Version
        [                                           // Transport methods
            \WP\MCP\Transport\Http\RestTransport::class,
        ],
        \WP\MCP\Infrastructure\ErrorHandling\ErrorLogMcpErrorHandler::class, // Error handler
        \WP\MCP\Infrastructure\Observability\NullMcpObservabilityHandler::class, // Error handler
        [                                           // Abilities to expose as tools
            'bc-recipe-calculator/get-recipes',
            'bc-recipe-calculator/get-ingredients',
            'bc-recipe-calculator/create-ingredient'
        ],
        [],
        [],
        function(): bool {  // Permission callback
            return current_user_can('manage_options');
        }
    );
});Code language: PHP (php)

Your WordPress site doesn’t have just one MCP endpoint/server. Right now, LLMs can get overwhelmed by the amount of tools in a single MCP server. If every plugin on your site registered dozens of abilities, it would be too much noise for it to make sense of which tools to use. On the other hand, if WordPress and WooCommerce start shipping some basic abilities, I could include some of those in my “recipe” endpoint and limit the ones I need to make. A network of specialized agents could have specific roles and use these different connections as part of a larger strategy.

MCP Server

Once your WordPress site is ready to go, you have to shift gears to your MCP client. I used VS Code’s built-in MCP tooling to keep things simple, but there are other options, like Claude and Cursor. Adding an MCP server and connecting to a client is still weird. While the WordPress Core AI team has done a great job of abstracting the logic for you on the WordPress side of things, there’s still a lot of work in your client of choice, like setting up a local server and configuring some JSON files. A lot of platforms have made this easier, and I would bet WordPress is on it’s way to solving it, too.

I ended up using the automattic/mcp-wordpress-remote package to handle this. When you configure your MCP inside your client, you tell it to use this server to connect. Then you need to add that MCP endpoint and some authentication parameters (in my case, I used a WordPress application password).

Put it together, and your config might look something like this:

Expand to see my example mcp.json
{
	"servers": {
		"recipesite": {
			"command": "/Users/briancoords/Library/Application Support/Herd/config/nvm/versions/node/v22.19.0/bin/npx",
			"args": [
				"-y",
				"@automattic/mcp-wordpress-remote"
			],
			"env": {
				"WP_API_URL": "https://woocommercetestsite.test/wp-json/bc-recipe-calculator/mcp",
				"WP_API_USERNAME": "admin",
				"WP_API_PASSWORD": "1234",
				"NODE_TLS_REJECT_UNAUTHORIZED": "0"
			}
		},
        }
}Code language: JSON / JSON with Comments (json)

Then it’s just a matter of asking the chat to do some stuff! VS Code has a decent UI for turning servers on and off and reading the actual logs.

This was just a high level overview, but the three repos I mentioned (MCP WordPress Remote, Abilities API, and MCP Adaptor) all have full docs folders with more details.

Final Thoughts on MCP

As we move into our AI era, I still believe there’s a need for websites, for user interfaces, and for tangible applications that we can rely on to provide us with direct access to the source of truth. But more and more, we’re seeing opportunities to strip away the need for clunky dashboards and bespoke UIs.

The best part of not building a user interface is that I could do this with no JavaScript, no build process, no playing around with components and datalayers! It was hard at first, but- apart from the server- I didn’t feel like I was spending too much time fighting the process. Once I was up and running, I kept leveling up and iterating quickly. It’s been a while since I’ve been this excited about a potentially new paradigm for WordPress. If you have an afternoon to dedicate to it, I’d suggest it.

Links from around the web

In case you missed it, I had a panel discussion with a group of developer advocates at Automattic while at WCUS. We let ChatGPT pick the questions, mostly around WordPress and AI. Audio podcast or video.

If you missed WCUS this year, here’s a fun sizzle reel from Blue Ivory Creative. TW: I’m in it.

Justin Tadlock wrote a tutorial for building a light/dark mode block theme and toggle. The best part is- no custom blocks, just a lot of wizardry with block filters and theme.json.

WP Accessibility Day is coming back around and I’m stoked that Woo is sponsoring.

Automattic’s AI block-builder Telex is finally out in public and I’m glad you get to see one of the things I’ve been excited about for a while now. It’s an early-stages experiment, to be clear.

Justin Tadlock (again) pens this op-ed arguing for more blocks in core. As someone who wrote In Support of Canonical Plugins I fully agree that WordPress needs to ship more of the basic functionality people expect in core and fast.

The WordPress core docs team has been the topic of discussion recently. Personally I’m excited about the opportunity to get more AI into the process (with human curation of course).

I love command palettes and am stoked that the WordPress command palette has expanded to the entire WordPress admin.

Periodic reminder to come to WordCamp Canada. There’s a roster of good speakers and also me.

A WooCommerce-adjacent conference is happening in Italy next spring. Feel free to start a grassroots campaign to get me sent there. There’s also a WordPress Day for Ecommerce coming to Porto in November.

That’s all folks! If I missed anything huge, feel free to send it my way.

2 responses to “Are you down with MCP?”

  1. Erik Assis Cardoso Avatar

    I Stated to use the Telex to test because of this post Brian, great job about the MCP you created, thanks for helping us with the content. I’m also let the link of a Block that I created in Telex AI for anyone who wants’ to help our solve the minors details and contribute:

    https://telex.automattic.ai/MTc1ODYzMzM2NjowY2Q3MDMwZGM4ODc1YmJlYzZkYQ==~NTQ3NDU0MTM6NmJiOTk0MDktYzRjZi00MmE5LTg4YWQtOGM2MWYxNGNhODhlOjg2ZmMyNWFjZGJjNWViNGM3Yzhh

    I’ve had a hard time to the AI deal with the build process, until I fixed looking at the code and finding out how to deal with some imports the plugin development went very smooth, I’m still making some changings and testing the capabilities of it.

    The Block is a GSAP/Lenis Block Wrapper
    Give a try and let me know your feedback, also help me with tips please! 🙂

    Thanks.

    1. Brian Coords Avatar
      Brian Coords

      That’s impressive! I had the same issues of having to look at the code and tell the AI specifically where it messed up.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Follow Modern WordPress Development

Receive new posts in your inbox. Never spam.

Continue reading