Let's give it up for Kinjal, thank you.
And if you haven't already, you can all now tick
your thank a volunteer bingo card.
All right.
As mentioned earlier, my
name is Jonathan Bossenger.
I'm from Cape Town in South Africa.
It is so weird to say good morning to you and my
body clock is telling me it's about
dinner time.
But the focus of today's workshop is enabling
model context protocol on your WordPress site.
If you would like to access all of the links that
we'll be using, all of the software that
we'll be using today, I recommend either scanning
the QR code or just going to my blog
jonathanbossenger.com/wcus2025
We are going to be needing to download some
software to install in our local environments.
There are some links to
some articles I'll be sharing.
It will be great if you have them open on your
browsers at the same time.
It makes it easier for everybody.
Does everybody have the link
or want to scan the QR code?
Excellent.
This is a hands on technical workshop.
So hopefully you're here to do some stuff, to
write some code, to build some things,
to connect some things.
If you're here to check
emails and do work, that's cool.
More people in my workshop, happy me.
But I would like to encourage you if you are here
today to sit and do the workshop together,
I would like to ask you two things.
Number one, if you're sitting at the back, please
come up to the front and join us.
Number two, if you don't have somebody sitting
close to you, if you're sitting on your own,
please look around and see if
you can find somebody to move to.
I would like to be able to pair folks off with
each other to help each other out as we go
along.
So if you're sitting on your own, have a look
around, seeing there's a gap you can move
to, it's just easier when we
support and help each other.
Okay.
You're going to need a laptop.
These requirements, hopefully if you saw this
workshop, you saw the requirements on
the WordCamp US site,
you're going to need a laptop.
As of yesterday, and I'll talk about this in a
second, you don't need Composer for today's
workshop, you will need Node.js installed on your
machine because you're going to be
using something called NPX.
Quick show of hands, who
doesn't have Node.js installed?
One or two people.
Okay, that's awesome.
So more people jumped on the
JavaScript bandwagon than I realized.
That's amazing.
I'm not going to be showing
you how to install Node.js today.
That's not the purpose of this workshop.
So while I'm doing my little preamble in a
second, that's a great
time to get that installed.
If you don't want to install it and you just want
to follow along, that's fine too.
This is being recorded and I will record a
version of this for my YouTube later.
So that's totally fine.
You will need a local WordPress installation.
I will be using WordPress Studio.
I do have some t-shirts that I will give away to
people with very, very interesting questions.
So if you come up with a very, very good
interesting question, you get a free t-shirt.
And then you will need an AI
powered code editor with MCP support.
If you don't know what that
is, I recommend using VS Code.
We all know what VS Code is.
VS Code comes with GitHub
Copilot built in on the free tier.
So if you haven't got that installed on your
laptop, please get that installed and set
up now.
So search VS Code, get VS Code installed, enable
the GitHub Copilot extensions and get
those up and running.
Okay.
Last but not least, I need a volunteer.
This volunteer needs to have
a very specific requirement.
They cannot be one of my
colleagues, so Ryan is right out.
They need to be somebody who is prepared to sit
and do all the work in the workshop,
even when it gets boring, which it might.
Okay.
Because I'm going to use you as my gauge as to
where we are in the workshop work.
So does anybody feel like doing that today?
Okay.
We've got a couple over there.
Jai and the chap behind.
When you greet each other, there's a
chap behind you who's keen as well.
Shake hands, say hi.
What's his name, Jai?
Give him the name.
Rocky.
I knew Jai had a loud voice, so
that's why I knew I could rely on him.
So Jai and Rocky, you guys
are going to be my checks.
When we're doing things, when we're doing steps,
I'm going to go, hey, are you guys still
busy or you're ready to rock and roll?
If you all aren't as fast as Jai
and Rocky, then you go and bag them.
Okay.
But we will keep it nice and slow and relaxed.
All right.
And then I do recommend if you aren't on the
WordCamp US WiFi, there's a free conference
center WiFi, but the
WordCamp US WiFi is a lot faster.
The details are on the back of your name badge.
If you haven't got it already,
hopefully you've all got it better.
All right.
We are entering in the realm of dragons.
We are entering into an area of WordPress that is
very, very brand new, fairly cutting
edge, and moving very fast every day.
Literally yesterday, about 4 p.m. local time, an
update was pushed to one of the plugins
we're going to be using in this workshop.
So this morning, I was very quickly
making sure everything still works.
All right.
So things may have changed in the last 24 hours.
So we may hit some snacks.
I'm hoping we don't.
But the stuff that we're going to be working with
is iterating very rapidly.
So bear with me if we hit
something that goes wrong.
I promise you this is not a way for me to just
cheat and not throw anything together
that I didn't test.
But things are moving very fast.
Okay.
Our learning objectives today.
I'm going to introduce MCP to
you if you don't know what MCP is.
I'm going to show you how you can configure your
site as an MCP server using core AI
plugin.
We'll talk about the abilities API.
And I think it is so cool that I'm talking about
the abilities API and Justin's in the
audience.
And I was at his talk about
the rest API 10 years ago.
And then I'm going to show you how to enable
abilities as MCP tools and the kind of things
you can do with it.
Hopefully we'll look at some cool use cases.
I'm hoping we get through
the setup pretty quickly.
Because then we can build some cool stuff.
If we don't, I've got some
example code that I can show you.
All right.
That wasn't the one that I wanted.
So let me open up this.
So quick show of hands.
Has anybody here not heard
of model context protocol?
Okay.
A couple of people.
The new here was in the what are we building with
AI talk with James and Felix a couple
of days ago.
Some of you might have
heard of some of these things.
Model context protocol is essentially this
protocol that has been developed by a company
by the name of anthropic.
They describe it as a USB connector for AI.
I think about it more like the USB
hub that you plug into your laptop.
It allows you to connect your HDMI and a USB
stick and some external drive.
It's essentially a way of connecting any piece of
software to your LLM to give your LLM
context.
So when you're coding in something like VS code
or PHP storm or whatever the case may
be and you're using Copilot or Claude or
whatever these AI tools are, the context that
you give it is what it uses to build stuff.
It has a whole bunch of
information that it gets from the LLMs.
But if you give it a file that you're working on
or you give it context of the plugin or
the theme that you're working on, it uses that to
build more code and figure out what
you're trying to do and
how you're trying to work.
What model context protocol does is it allows you
to give the AI tool context outside of
the code.
So let me give you a simple example.
If you're working on a plugin, let's say an
extension for WooCommerce, but you want to
be able to access the products in
your local copy of the database.
You have no way of giving the AI context of what
those products are, how they're stored
by the client, what the prices
are, because you just have the code.
The database doesn't pipe
straight into the code editor.
Model context protocol is
what allows you to connect.
You can connect the MySQL database.
You can connect various things.
Now in WordPress land, if you haven't seen it
already, let's jump back over here, there's
this thing called...
Why am I in the edit view?
Good grief
Wrong window.
There we go.
There's this package or this plugin.
It's one of the AI building
blocks called the MCP adapter.
Now what the MCP adapter does,
it runs on your WordPress site.
It's currently installable as a plugin, as a
composer package, or just manually, although
the manually is a bit wonky.
And it essentially enables your
WordPress site as an MCP server.
That's all it does.
So it still can't give any
kind of context to your AI tools.
Bu there's something else that's being worked on
called the abilities API.
Let's go down over here.
And one of the things that the abilities API does
is it allows you to build abilities that
you can then turn into MCP tools to be able to
give context to your AI coding editor.
So let me give you another good example.
Simple one.
Let's say I want to know...
I've just taken over a client site.
I've downloaded whatever backup version I use,
whatever Jetpack or Migrate DB Pro, whatever
I'm using.
And I just want to get a quick idea of what
WordPress version is running, what plugins
are installed, what themes are
installed, some basic site data.
As a developer, I'd have
to start going and digging.
I'd have to go and look maybe for the version
number, or go look in the database, or go
open up the dashboard and see what plugins are
installed, see what themes are set up
there.
What I could do is I could create
an ability that says get site info.
And it goes and uses get blog name to get the
name, and get WP version, and all of these
internal functions that WordPress already has,
and returns them as a JSON object.
And then I can adapt that ability into a tool, an
MCP tool, and I can then in my code editor
say, "Hey, tell me about the site, those English
words, whatever language you're using."
It'll then call a tool
and return that data for me.
Now that's a very simple example.
But you can also create tools
that actually will do things.
And one of my most favorite tools that I
developed was a tool that
fetches the debug log when
there's a bug, when there's a site break, or
whatever the case may be, reads through
the debug log, and then suggests fixes for me
based on what it's seeing in the debug
log.
So it allows you to enable all this kind of
additional functionality.
Okay.
So now I'd like you all to open
up your local WordPress install.
I'm going to open studio over here.
There's my AI experiment site.
There is my WordPress dashboard.
Is that big enough, or do
I need to make that bigger?
Bigger.
Bigger for the people in the back.
Bigger, smaller, happy, looking good.
All right.
So this is my, you can see
this is default WordPress install.
If I go to my plugins, the Kismet and Hello Dolly
are there, but they're disabled.
So this is a regular good old WordPress install.
And what I would like you to do with me is go to
github.com/WordPress/abilities-api
and just click on the code
button and click on the download zip
file option.
All right.
That's going to download the
abilities API trunk plugin.
This is installable as a
plugin on your WordPress site.
So you can go ahead and download that.
While you're downloading that, I also want you to
download the MCP adapter.
And you can do the same thing.
Go to code, download zip file, and
download it to your local machine.
Okay.
I'll give you a few minutes to do that.
Either Jai or Rocky.
Once you've done that, once
you pop your hand up, please.
Okay.
Good to go.
Everybody else good to go?
Everybody happy?
Awesome.
Okay.
So now we're just going to
do good old plugin install.
So the first thing I'm going to
install is the abilities API plugin.
Now if you don't know, and I don't know if James
mentioned this in his talk, but the
abilities API is something that is planned to be
shipped in WordPress 6.9.
It enables this MCP tooling for us.
It also enables a couple of other cool things.
So it creates a standardized way that you can
request any ability from a WordPress site
and expose that either to PHP
or to JavaScript via a REST API.
I'm not going to dive into all of that today, but
I do recommend going and checking it out,
going and reading up on the documentation.
So once you've got it installed and active, it
doesn't really do anything to your WordPress site
It just enables the API so
that you can start using it.
All right.
The other thing that I want you to do is install
and activate the MCP adapter.
So I'm going to do that now as well.
And if you try and install and activate it, it's
going to say to you the composer autoloader
was not found.
If you install the plugin from GitHub source
code, make sure to run composer install.
Okay.
Now that was a change that happened recently.
I was not expecting that.
Does anybody here not have composer installed?
One gentleman.
Anybody else?
Okay.
One guy over there.
All right.
So unfortunately for those of you who don't have
composer installed, if you can get it
installed quickly now, that'll be great.
But if you can't, you might have to just watch
the recording and do it later.
So with that installed, I'm
going to open up my terminal.
I'm going to navigate to my AI experiment site.
Can't type today.
Experiment site inside the WP content folder,
inside the MCP adapter, no plugins.
MCP adapter folder.
And I'm just going to run composer install.
That's going to install all the dependencies and
we are off to the races.
All right.
Everybody happy with that?
Everybody, anybody having any problems with that?
All good.
Yes.
Inside of the MCP adapter folder.
So change directory to the MCP adapter folder,
run composer install there, and it will install
all the dependencies.
Thank you.
Does that count as a good question?
It's a question.
Does it count as audience?
What do you think?
Yeah.
First question gets a T-shirt.
I like that.
So shall I get the T-shirt?
Yes?
Sorry, I didn't catch that
Let me take the mic over to you.
There is a mic here.
I tried to make it happen like so, and that would
normally work, I guess, but maybe there's
also a link for a repository.
So the question is being asked there, you're
using WPEnv, right, and he's trying to set
up the plugins in the WPEnv.
I honestly don't know, I've never tried.
So I'm sorry, it probably is possible, but I've
never tried, so I can't say.
That's why I'm going
through the simple plugin install.
Okay.
So does everybody have the plugins installed in
some way or another at least, except for
the folks that have questions?
Okay, good to go.
Great, thank you.
Not yet. So because you don't have Composer, right?
Yeah, so that's going to be, even with
downloading it from Git,
you need Composer installed to
install the dependencies, unfortunately.
So what I can do, actually let's see if I can
quickly zip it for you and stick it somewhere.
Give me one second.
No, not that one.
No, it's the wrong one.
[inaudible]
No, it's not, unfortunately.
It's a WordPress core repo.
[inaudible]
Yeah, that's what I was thinking.
Wrong one.
I'm going to try this once and see if this works,
and if it doesn't work, then unfortunately
we're going to have to move on.
Let's see how big this thing is.
Okay, let's see how big this is.
So let's go to my site.
It's got a media.
See if I can add this to media.
Will I be able to add a zip file to media?
Maybe.
Content, plugins. Let's try that.
It's 28 megs.
Let's see if it'll handle 28 megs.
That was pretty quick.
So oh, good grief.
I just uploaded it locally.
Stupid.
Let's try it here.
Add media files.
Select files.
AI experiments.
Don't look at content.
Come on.
Plugins.
All right.
And then what we'll do is we'll add it to this
page, and hopefully folks can download
it from there.
This could take a while.
Okay.
So while that's uploading, I'm going to carry on
for the gentleman in the corner.
I'm going to carry on with the workshops along
and we'll move on from there.
I want you to open up the VS Code IDE.
If you have it installed or whichever IDE you're
choosing to use, it needs to be able
to support MCP.
It needs to have an AI agent of some kind.
I'm using VS Code.
I'm going to make this a little bit bigger.
Let's go.
No, not zoom.
Appearance.
Zoom in.
That one.
Okay.
All right.
And I'm going to open up
the local site that I have.
So find wherever you have your local sites and
open that up in your VS Code.
All right.
Everybody there?
Cool.
So now what I want you to do is in the Copilot
window, open that up, please, if you don't
know how to open it, there's a
little Copilot icon over there.
So this is just the code of the site.
The site is running.
The site is a local WordPress site.
So it is running.
It's connected to a database.
And we're going to ask the agent and we're going
to say, can you tell me what active
plugins are installed?
And what's it going to do?
To determine, I need you
to do some things for me.
It has no context.
Besides the files that are available, it has no
context of the plugins that are installed
and active because that
requires database connection.
That requires access to the, I think it's an
options record that stores the active plugins.
So with MCP, what we can do is we can build an
ability that will do it for us.
So the first thing we need to do is we need to
set up the MCP adapter server.
So if you go back to your MCP adapter GitHub code
and you scroll down a little bit, quite
a bit actually, the documentation
needs a little bit of a cleanup.
You'll see it talks about installation.
We did it as a plugin.
And then below that there's
some checking availability.
We're not going to worry about that today, but
right over here, it talks about basic
usage.
I'm going to make this a little bit bigger.
Okay.
It talks about basic usage.
Everybody see that?
Okay.
So what it does is it exposes an MCP adapter, a
knit action hook that we need to hook into.
We set up a callback function.
The callback function receives
an instance of the MCP adapter.
We then use the MCP adapter to create a server.
The server has an ID, a namespace, sorry, a REST
API namespace, a REST API root, a name,
a description, a version number, and then some
classes for various different functionality
within the server.
So what's great about this is we can just copy
this code as is and set this up in a
new plugin.
So that's what I'm going to do.
So I'm going to copy that code out.
I'm going to go back to VS
Code, open up our plugins.
I'm going to check on that upload quickly.
It is done.
So please give me a second.
I'm going to pop this right
at the top of the window here.
That's going to try and embed.
Okay.
So if you don't have Composer installed, you can
try and download this version of the plugin
and see if it works.
Gentlemen, in the corner over there.
If you go to the jonathanbossenger.com/WCUS
page, it's the first link at the top
there.
Can you see that?
Yes.
Okay.
So let's go back to the code.
All right.
Who here has built a plugin in their life?
Awesome.
You're all plugin devs.
I love it.
Okay.
My people.
So if you know how to build a plugin, please go
ahead and create an example plugin, give
it a plugin header and
install the code that we just saw.
I'm going to start doing that now.
So you're welcome to do that along with me.
So I'm going to create a directory because all
plugins need to go in directories.
Is that not right, Andy?
And I'm just going to call
my plugin AI experiments.
Every time I do this, I
spell experiments incorrectly.
And I'm going to create my
new PHP file, AI experiments.php.
All right. And I'm going to open up my PHP tags.
I'm going to just close the
chat window so we can see the code.
Copilot gives me some lovely
autocomplete, which I'm going to accept.
And then I'm going to start writing my code.
Now, the code we're going to
write today is not well planned.
It's not going to be pretty.
It might not follow coding standards.
It might not be good architectural practices.
Please don't use code like this in production.
OK?
I'm not sure today teach you
how to use production code.
Today we're here to have fun and experiment.
So we probably should do
the if defined abs path thing.
That's probably a good idea.
So we'll do that.
And then we can take that code, as I said, from
the basic usage section.
You can just copy it as is.
And we can pop that down
over here in our plugin file.
Now, if you're somebody who doesn't like using
anonymous functions or
closures for your callbacks,
I totally understand that.
We all know there's a good reason to use name
functions so that you can unhook them if you
need to.
For the purposes of today, I'm just going to
stick with the example code.
But hopefully you all understand what it means to
have the function right there in the callback.
So for my ID, this is very
basic stuff today, folks.
This is copy, paste, replace.
I'm going to just call it AI experiments.
The namespace I'm going to
call AI experiments as well.
So what the MCP adapter does is it exposes a REST
API endpoint that the coding editor
can make a request to to
check which tools are available.
So that's why this REST
namespace and REST root are set up.
OK, so it's AI experiments.
I'm going to leave mine as MCP.
And then I'm not going to change my server name
and my description for this example.
You're welcome to do the same.
Then you'll see right down at the bottom here
there are three arrays of lists of ability
resources and prompts that you can set up as MCP.
Sorry, a list of abilities that you can expose as
either tools or resources or prompts.
I'm not going to dive too deeply into what tools,
resources and prompts are.
But essentially tools are things that you send
data to and receive data from.
So they're more dynamic.
Resources are things that
you just receive data from.
So like get site info is a good example.
So you can cache that data.
So therefore you can speed up reaction times.
And prompts are like a templating system.
So a good example for a prompt might be, tell me
how my products are performing last week.
And then it might have a
resource that gets all the products.
And then it might have a tool
that you send the products to.
And it gets some analytics
and merges that together.
But the prompt is the sort of template that puts
all that together for you.
So what I want you to do for now is just take out
the example ability that's there.
And that's what we're going to do for now.
With that in place.
If I go back to my local environment, which is
over here, and I go back to my list of
plugins, I should see my
AI experiments plugin there.
But before I activated this
one small thing I need to change.
If you are using a local development environment
like I am in the case of Studio, that doesn't
set a default permalink setting.
Your REST API endpoint for
the MCP server will fail.
Because for whatever reason, the MCP adapter
doesn't support the old school query URL version
of the REST API endpoints.
It's an issue that I'm going to
log very soon and submit a PR for.
But right now it needs to
be permalinked endpoints.
So go to your settings, go to your permalinks.
How old is this problem in WordPress?
The tail is old as time.
And just set it to anything other than plain.
If you're using a local environment that does
this already, you should be fine.
All right.
So with that in place, what I can now do to check
that this is working is I can go and
copy out, I'm not going to copy it out because I
know what it is, I can copy out this AI
experiments in MCP and I can
check that REST API endpoint.
So that on my local environment, here is my site.
So it's AIexperiments.wp-local.
I'm going to append WP-JSON to it.
And then the REST API endpoint.
And it's not working.
Oh, because I haven't activated the plugin.
I set the permalinks and
didn't activate the plugin.
Typical.
Okay.
So let's activate that.
Could have done that on the CLI but chose not to.
All right.
Let's open up the site.
You know, you do these things
over and over and over again.
You think you have it waxed
and then you still forget stuff.
[inaudible]
I'll do my best.
I think you did.
Did I spell it wrong again?
[inaudible]
I did.
I do it every time.
It's like a blocker in my head.
It's wild.
I've never been able to see if it's possible to
make the address bar bigger.
Does anybody know how to
make the address bar bigger?
I've never been able to do it.
But basically it's the URL of your local
environment, your local site,
slash WP-JSON, J-S-O-N, slash
whatever you have set for
your REST API namespace.
So that will be your URL to
check whether this endpoint exists.
I'm sorry.
I'm over.
I'm just slow.
No, you're not.
You're just very patient and meticulous.
That's what it is.
You're patient and meticulous.
Did you get that code snippet wrong?
Oh, the code snippet.
So the code snippet is inside of the MCP adapter
plugin under basic usage.
Yeah.
So if you scroll down in the read me
under basic usage, it's over there.
What changes were these made?
The only changes I made were
the server ID and the namespace.
Those are the only two you have
to make for this test to work.
Okay.
So now is a good time to pause and check.
Is anybody struggling with this?
Has everybody got theirs working?
Is anybody not seeing it?
Jai is good.
Rocky is good.
I'm going to wait for the patient and meticulous
and careful gentleman in the front here.
I love it.
Okay.
So now we know it's working.
We know the endpoint is there.
Now we need to give the server some tools.
We need to give it some context.
We need to be able to do something with this.
All right.
To do that, we use the abilities API.
Now as I mentioned before, the abilities API, the
goal for the AI team is to get the abilities
API shipped in core in WordPress version 6.9.
So right now it's installable.
My brain.
It's installable as a plugin.
So you can start setting it up and you can start
playing with it, but eventually it will
be available in WordPress core.
For this one again,
there's a great little example.
I think it's in the read me.
No, it's under the docs.
So in that GitHub repository, if you go to docs
and if you go to intro, there's a quick
introduction about how this will work.
And then there is an example ability being
registered and oh, look, it's a site info
ability.
Who saw that coming?
It's like I planned this.
All right.
So all we need to do there
again is copy that code snippet out.
So it's in the GitHub abilities, sorry, in the
abilities API, GitHub repo, click on docs,
click on intro.md and copy that out.
And what we can do is we
can place that in our plugin.
What I'm going to do is I'm going to place it
above the MCP adapter registration.
It's quite a bit long, but I want to go through
the code with you all so we can understand
what we're doing here.
Okay.
What I'm also going to do is I'm going to quickly
change the namespace of my call back.
So I'm going to take it.
I did it again.
It's like, it's like a mind thing with me.
I don't know.
Maybe I should say to myself, if I get it right,
I'll give myself a T-shirt.
Okay.
So I'm just going to change the callback function
from my plugin, whatever
it was, to AI experiments,
register ability.
Then I've got the function set up.
Then we call the WP register ability function.
Okay.
So when you register ability, you call the WP
register ability function.
It has a series of things you need to set.
You need to give it a label and
you need to give it a description.
Now who here knows who has worked with REST API
endpoints building frontends?
Okay, cool. Awesome.
So we know that when we have a list of REST API
endpoints, we want to use them to build
some kind of JavaScript application or PHP
application or whatever, and we want to know
what the endpoints are, what data they receive
and what data they return.
What do we do?
Where do we go?
Say again.
slash [inaudible] but if you want to know what data is
being sent and received, like what
arguments it receives and what
it'll give you back, where do you go?
You read the docs.
You go and read the docs because it's not
available in the REST API endpoints, right?
You don't know what it's doing, what it does
underneath, what data it resends and receives.
You go read the docs.
The cool thing about MCP is you give it a label,
a description and a schema, and then
it knows what it does.
So when you query it the first time, it gets all
that information, which is why giving
it a good label and giving it a
good description are very important.
Those of you who've worked with AI for a while,
what is the most important thing when we work
with AI?
Very good prompting, right?
Very descriptive, detailed prompts because we've
all one-shotted really bad code, right?
If you want to have a good
laugh, go to my GitHub profile.
There is a 3D shooter game that I one-shotted.
It is the most funny
piece of JavaScript animation.
It literally just loads up and eventually just
fries my browser and it does nothing.
It's like a red oval and a bunch of blobs and it
just keeps looping through the game
where you can fries my browser.
It's the funniest thing.
So you give it a label,
you give it a description.
You need to give it an input schema.
Now because this is going to be a resource, as I
said earlier, resources, we generally
receive data, we don't
worry about the input schema.
But if you're creating a
tool, you give it an input schema.
What is the input schema?
Well, what is the data it expects to receive?
So it might just be a string that it receives.
It might be an array of
data or an object of data.
So you've got to specify that.
Then you specify an output schema.
And as you can see in this instance, the output
schema, it is an object type and it has some
properties.
The properties are site name, site URL, active
theme, active plugins, PHP version
and WordPress version.
You'll also notice that every single property has
a type and a description for the same
reason that the tool has a label and a
description to give context.
Yes, Jay?
If you have a question, there's a
mic there if you want to be on mic.
I forgot to mention that earlier.
Sorry.
Once again, people were wondering where would
they get that code from?
Okay, where do they get that code from?
If you go to the github.com/WordPress/mcp-adapter/
and you scroll up here and you
click on docs.
No, it wasn't docs.
I'm talking nonsense.
Sorry, it wasn't MCP adapter.
It was abilities.
So if you go to WordPress
github.com/WordPress/abilities-api, it is
It is linked in my workshop posts right down here.
The abilities API, so that
will take you straight there.
And you go to docs and you go to number one
intro.md and you scroll down a little bit.
The code example is there.
The registration example is there.
Everybody happy with that?
Yes.
[inaudible]
Say again
[inaudible]
Oh, the URL of my post
My name jonathanbossenger.com/wcus2025
Okay.
So what this registration of this ability does is
it sets up what the ability does.
It sets up what we expect it to do.
It sets up what the inputs
are, what the outputs are.
Then it has an execute callback.
It's a callback function.
It's the function that's going to do whatever it
needs to do underneath to get this data
back.
So in this instance, I'm going to change this one
to AI underscore experiment.
I did it again.
This is like a rolling joke.
So I'm going to call that
AI experiments get side info.
That's just a standard WordPress callback.
That's going to do the core WordPress stuff that
needs to do underneath to get this information.
And then you can also set a permission callback.
Now if you want to read a really good article
about MCP and security, go and search.
Unfortunately it's on Medium, but the article is
called the S in MCP stands for security.
There are some concerns around security and MCP,
which is why I'm teaching you to do this
on a local environment today
and not some production site.
We can chat about that in a second and we will.
But it is a good idea to use the permission
callback that is configured just like a REST
API endpoint and use some version of current user
can, whichever you prefer.
Generally an admin depending on the functionality.
In this case, an admin doesn't maybe need to get
the site info, but we're going to go
with it for today.
All right.
So we've registered the ability.
The ability does nothing.
It has no context.
So now we have to actually create
the abilities callback function.
So underneath the registration,
I'm going to create the function.
Get site info.
And now I'm going to get the site info.
So what's nice is that, again,
Copilot has given me some example code.
I didn't prompt that this.
This is what it's given me.
So I'm just going to return an array with the
site name, site URL, active theme, active
plugins, PHP version, and WordPress version.
And you will see that those properties match the
properties of the output schema that I've
configured.
So it needs to match those things directly so
that when the MCP tool receives it, it
knows what to do with it.
Okay.
I'll leave that on the screen for a second if
anybody needs to see that.
Everybody happy with that?
Anybody still coding?
All good?
Okay.
This code, by the way, this code is all in a
repository, which I will share with you
at the end of the workshop.
So if you want to get hold of
all this code, you will be able to.
So now the moment of truth.
Now we need to set all this up to
be configured with GitHub Copilot.
So if you go back, I think I've got it in the
blog post or we can just search it.
Let me just see here.
No, I didn't.
Oh, wait.
Yes.
Okay.
If you go back to the blog post, you will see
under code repositories, there is something
called MCP-WordPress-Remote.
I would like you to open that up, please.
So let me tell you a story about
standard input output in JavaScript.
In MCP, if you go and read on the MCP
documentation, at the moment
there are two transport layers,
two ways that the data can be sent back and forth
between your application and your MCP
server.
The one is standard input output or STDIO.
That's essentially like just passing data on your
terminal, whatever the case may be.
And that's usually for servers that are running
on your machine, MCP servers that are running
on your machine.
My favorite personal MCP server
is the file system MCP server.
Once a week after I've created a whole bunch of
links and shortcuts and downloads and whatever
other craft on my desktop, I fire up Claude and I
say, "Clean my desktop."
And Claude knows that when I say that, it must
take all of those extra files and move
them into the documents folder on my desktop and
just make it all look pretty.
So it can connect to my file system and based on
a previous rule that I'd saved, when I
tell it clean up, it knows take all the files on
the desktop and move them into the documents
folder.
So that's local.
The other one is a
streamable HTTP transport protocol.
And I don't understand, I haven't read into the
technicalities of it, but for whatever
reason it's difficult to implement security as
one of the concerns, not everybody supports
it.
So what a clever bunch of devs started doing was
they started developing these JavaScript
proxies.
So it's basically a JavaScript file that takes
the standard input output transport and allows
you to then transport that
over HTTP back and forth.
And so most of these MCP
servers are using this method.
So they have a JavaScript package that runs,
that's why we need MPX because we're going
to run it with MPX.
That'll handle the transport layer part.
The one that we're going to use is something that
folks at Automattic developed.
So if you go to this URL, it's github.com/Automattic/mcp-wordpress-remote
And if you scroll down to the configuration,
you'll see the way it works is you create
an MCP dot JSON file in your cloud code or in
your cursor or whatever the case may be
with the right pieces of
information and it then allows you to connect.
So if we scroll, I think it's on this page, if we
scroll down a little bit further and
go down to WordPress
application passwords, right?
Who here has never heard of
WordPress application passwords?
Okay.
So a number of versions of WordPress ago, they
shipped something to the user setup where
you can create separate
application passwords per user.
It's great for when the REST API came out because
people were building applications
using the REST API, but we wanted a way of
authenticating people without giving out admin
passwords.
It is not recommended for production.
Production environments, you're going to want to
use something like OAuth, which is supported
on MCP.
This is not that talk.
That's a whole other conversation.
What I do think will happen one day is that
hosting environments will start implementing
this on a hosting level
with their own OAuth setup.
But for local application password is fine.
So what we do in VS code, we're going to create
an MCP dot JSON file inside of a dot
VS code folder.
You can read up about this in the VS code
documentation, but in the root of this project,
I'm going to create a directory.
No, that's not the root of the project.
Let's try that again.
That's creating a WP content.
That's not where I wanted.
Oh, I know.
I don't use VS code every day, so
that's why it bothers me sometimes.
So I'm going to create my folder dot VS code.
And inside of that folder, I'm going to create a
file called MCP dot JSON.
Inside of that, I'm going to copy out this
WordPress application password code.
I'm going to grab that.
I'm going to pop that into the MCP dot JSON.
Now a quick note, depending on what coding
environment or AI desktop tool or whatever
you might be using, how you
configure this might be slightly different.
In an anthropic based products, so Claude code or
Claude desktop or whatever, they use
this MCP servers keyword.
In VS code, they just use the word servers.
So you're going to have to
change yours to service for now.
Then you'll see it's got a name, essentially.
What I like to do with the name is I like to give
it the same sort of logical name as
my, let's see if I can spell it right.
Hey, GitHub is telling me to spell it right.
Yay.
Okay.
And what I found is if you give it a name that is
tied to the local URL of the site,
when you make queries of it and you refer to that
name, if you have multiple MCP servers
installed, it actually
knows which one to work with.
So the first time I tested
this, I just left it as WordPress.
And then I said, give me all of the site info
from my AI experiments site.
And it didn't know what to do.
So it's a good idea to name the server in your
MCP config the same as whatever you're
connecting it to.
You'll see it runs the NPX
command with some arguments.
In this case, it's just the flag to just use the
package and the link to the package on
NPM.js.
The API URL is the same URL that
you used earlier to test the endpoint.
So I think I still have it open over here.
Here we go.
So I'll copy this out and pop it in here.
The only difference here is you append the MCP
route at the end because what it does,
it creates a post request to that route.
Hang on.
MCP.
So this is the same one we
configured in the plugin.
Let me show you here quickly.
So AI experiments was the
namespace and MCP was the route.
So that ties into AI experiments MCP.
Then you give it your username and password.
I'm going to do this locally.
Somebody was in a workshop yesterday and said
don't use admin for your username.
But we're going to go with
admin today because this is local.
It's fine.
And then to create your application password,
what you're going to do is you're going to
go into-- let me check if
this is the right place.
No, that's not the right place.
That's not the right place.
Where is it?
There it is.
You're going to go into your user list of users.
You've probably got one local user.
If yours is not admin, please
make sure you use your username.
You're going to click on it and then scroll right
to the bottom and you're going to find
this area called application passwords.
Everybody got that?
Cool.
You're going to give the password a name.
It doesn't matter too much what you name it, but
I like to name it to whatever I'm using
it to.
So I'm going to say MCP server.
And then you're going to
add an application password.
That'll give you a password that you can use.
The other nice thing about the application
passwords is you can revoke them.
So you can use it for
testing and then disable it.
So I'm going to copy that password out.
And I'm going to pop it in there.
All right.
You don't need the OAuth enabled
stuff, so I'm going to remove that.
There is also a log.
Yes?
I got a critical error whenever I was trying to
create my admin password for that.
Got a critical error.
Okay.
That's awesome.
Can you just put, let me finish this.
No, no, that's, I love critical errors.
Let me finish this and
then I'll come over to you.
Okay.
There's also, as I was saying, if you have a
look, I'm going to find it here quickly.
Go back to WordPress remote.
Where was it?
There we go.
If you scroll down to the bottom of the readme
file for the MCP WordPress remote,
you'll see there's a
couple of environment variables.
And one of them is you can specify a log file.
Now this is very handy when things go wrong, when
it doesn't connect to whatever the case
might be.
So I always suggest setting up a log file.
I have, you can tell I've been playing with this,
I have an MCP logs directory in my home
folder.
Check, do I have anything here for now?
I think I might do.
Yes.
I'm going to just remove those quickly.
Star dot log.
There we go.
And I'm just going to use
that path as my log file.
You can have yours wherever you want to, but it's
a good idea to set this up so that when
you're setting this up for the first time and
testing it out and you want to know why
it's not working, you can
take a look at the log file.
You will see that when I configure this, there's
a little start button that comes up.
Now what happens in the background is VS Code
actually tries to sort of pre-make the request
to the API or the WP API
URL that we've configured.
And if it gets a response, it
goes, okay cool, this is a server.
I can start the server.
And this is one of the things I
like about VS Code's implementation.
Yes.
[inaudible]
Do you need to NPM install this?
Is that your question?
No.
You just need NPX.
So if you have node install,
you probably have NPX installed.
That's all you need.
It'll handle everything else for you.
Okay, if you want to check
if you have NPX installed?
[inaudible]
No.
Okay, so if you're worried about installing the
Automattic WordPress remote package, the
NPX will actually download, install it, run it,
and then clear it for you.
So it does all of that for you.
Yeah, excellent question.
That's a good question, right?
Size, small, medium, high?
There's a fellow speaker in Cape Town who throws
sweets at people when they start falling
asleep.
I don't think that would work at a WordCamp.
All right.
So the fact that that little start button shows
up tells me that I'm doing something
correctly.
So does anybody here not have
the little start button showing up?
Nobody. Nobody.
We're all ready to click
start and see what happens.
Let's do it.
I haven't forgotten my critical error friend.
I'll get to you in a second.
So when I click start, it
starts doing some things.
Now, I'm getting an error.
Who else is getting an error?
One?
Anybody else?
Everybody else is working.
Some of you might be seeing
running a number of tools.
Gentlemen is getting the error.
Are you using a locally signed SSL cert?
I'm not using SSL at all.
You're not using SSL at all.
Not the critical error, the person who said they
were getting an error when they ran the server
You believe you're using a local...
That's the error.
Okay?
So if you have a look at...
And this is why I'm getting the same error.
If you have a look in the WordPress remote
package and you go to docs,
there is a troubleshooting
section.
There's issues with different
versions of node if you have NVM installed.
And then there's an issue with
local development environments in SSL.
Node can't verify the locally signed SSL cert.
All you have to do is just turn it off basically.
So you copy this node, TLS reject unauthorized
bit, and you pop that at the top of your ENV.
Yes, Jai?
I was just a step behind.
What are we supposed to do
after putting in the log file?
What was the step you mentioned?
Click start.
Okay.
Let's start on where?
So you should get...
I'm going to restart mine
quickly and then I'm going to stop it.
You should get this little...
Why is it error again?
What?
So basically I'll fix it now.
Basically it's above where
you specified AI experiments.
You should see a little start button.
Oh, you're not seeing that?
Okay.
All right.
If you're not seeing that, I think
I might know what the problem is.
I'll come and help you debug in a second.
Okay.
Has everybody else started the MCP server?
You got the same error as Jai's getting.
Okay.
You don't see start.
Okay, cool.
Anybody else working?
Anybody else got tools running?
Those of you who have got tools running, open up
your GitHub Copilot while I'm walking around
helping folks and just do
the question I just asked.
Ask it to get you the site
info and see what happens.
Okay.
Let's have a look at the first photo.
[upbeat music]
Okay, so I managed to fix one of three problems.
I'm still gonna get back to the
folks who are having problems.
But those of you who had it installed,
did anything happen?
Did it do anything interesting?
Yes, no?
No, it shouldn't have, all right?
I did that on purpose.
I said, "Why don't you just figure it out?"
Who can tell me why it didn't do anything?
Who can take a guess?
We set up our MCP adapter.
We registered our ability.
Why is it not working?
Yes.
Say again.
Line 84.
Exactly.
We haven't told the MCP
adapter to adapt any abilities.
So it still doesn't have any tools, right?
So what we need to do is we
need to take the ability's name,
which is the one, let me close this.
We take the ability's name, which is there.
And...
No, why don't I just do fat fingers?
And we add it to that array of abilities
that need to be turned into tools or resources
or whatever the case may be.
I'm just adding it into the tools list by now,
but I should actually add it into resources.
So now, if this all works,
if I go back and I, let's say go here
and I open up Copilot and I say,
get the site info from my AI experiments site.
Can everybody see that
agent mode on the side there?
Can we see what's happening?
Let's see what that does.
So it's still not happy.
Oh, there's an error, that's why.
Let me fix this error.
[inaudible]
Ooh, who spotted that?
Well done.
That's a T-shirt right there.
That's a T-shirt.
I did it again.
Okay, let's try this one.
Ah, who is that?
Who said the error like?
[inaudible]
So when that's running, when it's all working,
and those of you who were having trouble earlier
will come and sort you out,
maybe we'll do it towards the end or something.
But when it's running, you'll see it says running
and there's one tool.
So that's the tool that
we set up from the ability.
So now if we run that same code,
or that same prompt should I say, look at that.
It detects that there's a
tool that can run SiteInfo.
Now what's happened here?
In the background, I prompted,
I send the request to the code agent.
It used the LLM to go,
what is this person asking?
Well, not really, I'm not
thinking, but doing its thing.
What is this person asking?
Do I have any available tools on the server
that could fulfill that request?
It detects that it's SiteInfo.
Notice how I use the word SiteInfo.
So when you're registering your abilities
and setting up your tools,
make sure they make logical sense
in terms of how you would call them in English.
Don't call them my plugin ability XYZ1.
If it's getting SiteInfo, call it get SiteInfo.
And then it says, can I run this tool?
Now you can obviously just continue.
You could set it for every session,
whatever the case may be.
So I run that.
It then makes the request,
gets the data back and says,
hey, this is what's running on your site.
Okay, is anybody not getting that right now
once they've added their ability to the list?
One person not getting it,
hands up if you are getting it?
If it's working, nobody's working.
Damn it.
Mine's working, works on my machine.
So what happens is it's still giving you the,
is it not running the tool?
Is the server, those of
you, it's not working for you.
Is the server running?
And it's showing one tool.
It's not showing one tool.
Okay, so we've got a bunch of people
with similar problems.
We have to figure that one out.
[inaudible]
It says the JSON schema is invalid.
Okay, so that might be, that's weird
because we all use the same code.
So what I will say, are you using VS Code?
I'm using VS Code and I grabbed it from the,
you know, docs, but it is a little different
than what you have, you
know, the docs got updated since.
[inaudible]
Possible, it's possible.
Okay, we'll have a look.
So has anybody got it working?
Anyone?
One chap, okay, we'll call it a win.
All right, we've got another 30 minutes,
so I'm gonna see if we can figure out
some of these bugs.
But what I'm hoping you'll start to see now,
and I wanna basically, I wanna disable this,
and I wanna show you kind
of some of the cool things
that you can do.
So let me go over here.
And down in the bottom of resources here,
I've got this AI experiments MCP server
that I built as an example for this workshop.
So you're welcome to have a look at this code.
It has four abilities inside of it.
The one ability is the get site info ability,
the one we just built.
Then I built a get plugins ability,
which just gets the list of active plugins.
Then there's my favorite, the debug log one.
So what that does is if debugging is enabled,
it'll pull the debug log in,
it'll show it on my site, I can then use it.
There's just a simple create post one,
so you can use it to create posts,
you can use it to update posts,
you can use it to do
whatever you want on your site.
But my favorite is this one.
So if you are a plugin developer,
you will know that when you submit a plugin,
you need to install a bunch of,
you need to run a bunch of plugin checks.
So you've probably heard of
the plugin check plugin, right?
So what this ability does is it allows you
to run the security checks on your plugins
while you're coding in the AI code editor.
It'll run those checks
and then return the results
to you in your chat.
And then you can say, right,
based on that, let's fix them.
And you can point at the files and the code
and then whatever the case may be.
So what it starts doing is it starts opening up
a different world of how you
can use your WordPress sites
and use the context that you give it
and drive your AI coding.
The last thing that I want to leave with you
before we start helping
folks debug some of these issues.
Abilities API is coming to
WordPress, hopefully 6.9.
That means just the API, no abilities.
So by the time it launches,
we can't do anything with it.
So if this was something
that was interesting to you
and you can see some use to this,
what I would like to encourage you to do
is to start building abilities for yourself.
For your plugins, for your
themes, for your websites.
Think about how people could use this
to use AI to power their content creation.
Simple examples that I've had before.
I've never managed a newsletter myself,
but my understanding of managing newsletters,
you need to pull posts in,
you need to format it in a certain way.
Imagine if you had an ability
that just said create newsletter.
And it knew to get the
last three posts on your site
and two posts from those sites over there
and put them together in a certain format,
maybe using a mail poet or any other,
what's the one that Leslie did?
The mail newsletter one plugin?
Newsletter glue, thank you Justin.
And it just does it all for you.
The other one that I'm
really hoping to kind of work on
and Ryan's experimented with this a little bit
is I want to build a couple of abilities
that while you're building a block theme,
it's automatically writing your save changes
to the theme files.
Instead of having to use
something like create block theme
which has to pull it out for you and save it
and do all that kind of stuff.
So it's just unlocking some automation,
some sort of chat enabled automations
that I think are really, really cool.
But right now it's a blank
slate, it's an empty canvas.
So if this is something that interests you
and it's something you want to play with
and you want to check out,
I do recommend installing those two plugins.
Think about some abilities you can use.
Some other examples I had was like, again,
running a WooCommerce store.
Give me an update on today's worth of sales
and then optimize for
whatever, whatever the case may be.
It just opens up so many things.
Okay, we've got about 42 minutes left.
Is there anybody here who would like to build
their own custom ability today?
Anyone?
No one?
You guys want to build one?
Build a custom one?
Any ideas?
Everybody's bored, it's Friday.
We want you to go have lunch and go home.
Jonathan, shut up.
Cool.
But what?
That's the question, but what?
So my challenge to you is to go home
and think about but what?
What do I want?
What would make my job as a developer easier?
And build it?
Okay.
Any other questions around all of this?
Anybody?
No, yes.
Do you want to use the mic so they can, cool.
Is this thing on?
Okay.
So when I first asked about
plugins in my little assistant,
for whatever reason, it
just called the command line
and it got a list of
plugins, which was very performant.
What has been your experience in the performance
between just letting your Copilot or whatever
use command lines versus an MCP server?
Great question.
So I will say this.
I use, at the moment, I
use Claude code to vibe code,
if you want for a better word.
So I'm in the command line anyway.
I would not build abilities that just replicate
command line things.
So my site info ability, my plugin list ability,
those aren't abilities that I would build,
they're just examples.
What I would build is things
like the plugin checks one.
Now there is a, when you
install the plugin check plugin,
there is a command line that you can run,
but then you have to go and get the results
and then you have to pass through them.
That to me is something useful,
because I can run it and then give that context
directly to the AI and it starts fixing issues.
So that's the one that I,
and I, here's a fun story.
When I was building the plugin check,
the plugin security check ability,
it, the AI agent coded a bug, well coded a bug.
There was a bug in the code.
So I needed to fix that bug.
So that's why I created the debug log ability.
Because I wanted to just
get that debug log to come in.
And so that actually helped me fix the bug.
I could then tell the
agent, oh, this is the error
that you've made, silly agent, go and fix it.
I know if it went and it fixed it.
So just those kind of
things that I would look at.
Stuff that doesn't easily exist.
I mean, another good example is I,
I work on a Linux workstation most days.
And I have a one-liner
command for setting up a new site.
I'm not gonna go and create an ability for that,
an MCP tool for that,
because it's one line, I'm not
gonna do something like that.
But for example, when I am preparing content,
I'm often needing to pull information
from a number of different sources.
Some of it might be text-based.
Some of it might be things on GitHub
that I wanna pull in.
So something that I've thought about,
there's an MCP server for GitHub
that you can install and set up.
Something I've thought about is how do I use
a WordPress server to
give me access to WordPress?
How do I use the GitHub server to give me access
to code repositories, my
code repositories on GitHub?
And then pull those together
to help me create the content.
So it uses the code that
I've built on my GitHub repos
as opposed to some AI-generated code.
It uses the access in my,
so for my personal WordPress block.
It uses the blogs that I,
because I'll often write a blog post
and it'll be linked to
something else that's happened
and I wanna pull some information in from there,
whatever the case may be.
Those are the kind of
things that I would use this for.
Yeah, any other questions?
Okay, does anybody want to,
so we've got, yes, we've
got one question over there.
Go for it.
Yeah, hi, I'm really interested specifically
around the debug log and WordPress upgrades.
I see a lot of potential use for that
and performance increases.
When we have other use cases,
what's the best way to reach out to you?
I see you have a lot of repositories.
How should we reach out to
you and maybe ask questions
or come up with new use cases
and collaborate with you on that?
Cool, so I would say reaching out to me
is probably not the best thing to do
because I'll do my best to
point you in the right direction.
But if you didn't know,
there is a Core AI team in the WordPress Slack
that you can join.
We're very friendly.
We're looking for people to come up with ideas
and abilities and that kind of thing.
So that would be the best place to start.
So join the, I think it's just Core AI.
Join the Core AI team in Slack.
And in fact, last week,
we have biweekly meetings every two weeks.
I have to say that for myself, don't mind myself.
But last week, the week
before we came to WordCamp US,
people were saying, hey,
is anybody building anything
that's really interesting with this stuff?
And I shared my repository of abilities.
What I would like to
start seeing is as a project,
and I'm gonna propose this in a future meeting,
we actually create a public GitHub repo
under the WordPress organization
where folks can submit abilities.
Those of you who will know Playground
will know that when blueprints came out,
you could submit blueprints.
And I would like to see a similar environment
because I feel like getting that kind of feedback
from the community about
what abilities they would like
to see, what abilities they
would like to be able to use,
we can look at which of
those abilities can come to Core
and which need to say maybe
canonical plugin environment
or whatever the case may be.
So start with the Core AI Slack channel.
I'll probably be there anyway
because that's where I'm
hanging out a lot lately.
And I'll point you in the
right direction if need be.
That's the best place.
Awesome, thank you.
That deserves a feature.
(laughing)
Even virtual or live?
I think that's what I'm talking about.
Okay, any other questions?
So I'm gonna be honest,
I didn't expect us to get this far this quickly.
So I didn't have anything else prepared.
So what I'm gonna suggest is this.
If you would like to hang around for a bit
and chat about this and come up to me
or whatever the case may be,
maybe help some of the folks
who are having struggles here, please do so.
Otherwise, I'm gonna give
you a little bit extra time off
and you can go and hang out in the sponsor hall.
If you have any other questions,
you're welcome to come and give me a shot.
But the main takeaway that I
would like to give to you today
is this is coming.
Start getting yourself ready for it
because it's gonna unlock and open up
a whole bunch of things for AI and WordPress.
Think about those use cases.
Think about the stuff that isn't solved already
or could be solved in a better way
or could be solved in a more streamlined way.
Think about the prompts.
Think about the workflows.
What are the things that I need to automate
to make my life easier,
my customer's life easier?
Simple things like, something
else that I've thought about
is like if you're managing
multiple WordPress sites,
the ability to be able to go, hey, update,
I mean, maybe you wouldn't do this,
but update all the plugins across these 10 sites.
Go off and do it.
Those are the kind of things that this unlocks.
So thank you so much for coming.
I hope this was interesting and useful.
If you were having any
problems or critical issues,
please do hang around.
I'll come around and help you.
But otherwise, thank you very much for your time
and enjoy the rest of your day.
[audience applauding]