MCP Tools
This page lists every tool Unblock gives an MCP client, with the WordPress right each one needs, then the connection configurations and how the MCP Bridge works.
To connect a client first, see MCP Bridge.
How a client reaches them
This page names each tool by its WordPress ability, unblock/insert-blocks. Your client lists it with a dash instead: unblock-insert-blocks.
- Listed: 16 tools show in the client's tool list, on the MCP Adapter's default server (WP-CLI, Password) and on
mcp/unblock(OAuth). - Through the adapter: the other 31 stay out of the list, so it stays short, and 2 more for SEO with an SEO plugin active. Both servers also list the adapter's three tools: the client finds them with
mcp-adapter/discover-abilities, reads their input withmcp-adapter/get-ability-info, and runs them withmcp-adapter/execute-ability. - Chat only:
unblock/generate-imageis never shared over MCP. A client brings its own images and adds them withunblock/upload-media.
A call through the adapter names the ability and passes its input as parameters:
{
"ability_name": "unblock/list-media",
"parameters": { "where": { "search": "hero" } }
}
unblock/get-instructions names the tools that are not listed and when to use them, so a client that calls it first knows where to look.
Categories
In WordPress, the abilities sit in four categories:
| Category | Tools |
|---|---|
unblock-pages | Context, blocks and CSS, rendering |
unblock-content | Posts, terms, custom fields, media, SEO |
unblock-content-model | Post types, taxonomies and field groups |
unblock-site | Site settings, plugins, templates, global styles, fonts |
Who can run them
Every call passes two checks:
- The MCP right,
unblock/ai/mcp/can_use: Administrators by default. A user it refuses getsunblock_mcp_forbiddenon every Unblock tool, listed or run throughexecute-ability. - The tool's own right, in the tables below: the one WordPress asks when you do the same thing by hand.
Without an active license, no Unblock tool exists.
With MCP sessions turned off in the Unblock settings (Settings panel, Editor tab, AI), no client reaches any Unblock tool, and OAuth sign-in stops.
Read-only connections
A client connected by OAuth with Read only access lists only the tools marked Read below. execute-ability refuses the others with unblock_mcp_read_only, and discover-abilities leaves them out, the abilities of other plugins included.
WP-CLI and Password connections have no read-only mode: the client gets every tool your account may use.
Targets
The block tools work on one document. Pass one of these:
| Target | Works on |
|---|---|
session_id | The page or template open in an editor tab, from unblock/list-sessions. Unsaved changes included; nothing is saved until you click Save. |
post_id | Any post edited with the block editor, without a tab. The change is saved at once. |
template_id | A template or template part without a tab, by its theme//slug from unblock/list-templates. |
A post_id or template_id you have open in an editor session goes through that session, so your tab holds every change.
With a target, the tool also checks your right on it: edit_post on the post, edit_theme_options for a template, or that the session is yours. unblock/list-sessions returns only the sessions you opened.
unblock/update-css is the only one that also works with no target: it then writes the site's CSS alone.
A write without a tab takes three more fields:
| Field | Use |
|---|---|
content_hash | unblock/get-context, unblock/create-post, unblock/create-template and every write return one. Send the last one with the next write: a post changed since is refused with unblock_stale_post. unblock/update-css takes it without checking it. |
force | Write even though another user has the post open in the editor, whose next save would discard the write. |
live | Write to a published or private post, or to a template, which changes your live site at once. |
A write to a published or private post, or to a template, is refused with unblock_live_write until it carries live: true. The client passes it only once you agreed. A draft, a pending or scheduled post, and a write through a session write as before.
force means something else on unblock/delete-post and unblock/delete-template: delete for good instead of moving to the trash.
Context
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-sessions | Lists your open editor sessions: ID, post or template, title, active or paused | edit_posts | Read | Yes |
unblock/get-instructions | Returns Unblock's conventions and tool rules. Call it once, with the first read | edit_posts | Read | Yes |
Blocks and CSS
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/get-context | Reads a document: block tree with bid attributes, CSS, variables, breakpoints, fonts, and its content_hash; template: true adds what its template prints | edit_posts | Read | Yes |
unblock/get-css | Reads the site's CSS without a page; where.search gives the full rules of up to 100 selectors | edit_posts | Read | Yes |
unblock/insert-blocks | Adds blocks from HTML, with the CSS of their new classes | edit_posts | Write | Yes |
unblock/replace-blocks | Replaces a block's inner content with new HTML | edit_posts | Destructive | Yes |
unblock/update-block-attributes | Changes a block's HTML attributes or its tag; null removes an attribute | edit_posts | Destructive | Yes |
unblock/update-block-content | Changes a block's text or raw markup, the blocks inside it untouched | edit_posts | Destructive | Yes |
unblock/update-block-script | Adds, changes or removes a block's JavaScript | unfiltered_html | Destructive | Yes |
unblock/update-css | Writes rules, :root variables and at-rules; installs the Google Fonts it names | css/can_write | Destructive | Yes |
unblock/move-blocks | Moves blocks among their siblings or into another block | edit_posts | Write | Yes |
unblock/remove-blocks | Removes blocks | edit_posts | Destructive | Yes |
Every write returns the blocks it wrote, with their bid. The other blocks keep theirs.
unblock/insert-blocks adds the blocks at the root of the document, after after_block_id or at the end. Pass parent_block_id to add them inside a block instead, such as the <main> of a template. unblock/move-blocks takes parent_block_id the same way.
unblock/update-css writes a rule the way you would in a stylesheet:
- The declarations you send replace that selector's declarations in the same at-rule block. Send the complete rule.
:rootandhtmlvariables are only added or changed.- The at-rule blocks you leave out stay as they are. Send one empty to clear it:
@media (...) { .card {} }. removedeletes selectors with all their rules. The answer gives the CSS it removed, so the rule can be written back.- The answer gives the CSS of the selectors it wrote.
With no target, a selector a page already uses changes there at once. A new one loads on a page only once a block there that uses it is written.
A user who may open MCP but not write CSS keeps every other tool. The CSS sent with unblock/insert-blocks or unblock/replace-blocks is then dropped, and the blocks land without styles.
Posts
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-posts | Lists the posts of a post type, newest first; where.search, fields, custom field values with meta | edit_posts | Read | Yes |
unblock/create-post | Creates a post, a page and a draft unless asked otherwise; returns post_id, content_hash, what its template prints and the site's CSS | edit_posts | Write | Yes |
unblock/update-post | Changes the title, status, slug, excerpt, parent, date, template, featured image, terms and custom fields, never the content | edit_posts | Destructive | Yes |
unblock/delete-post | Moves a post to the trash, or deletes it for good with force | edit_posts | Destructive | No |
unblock/copy-post | Copies a post into a draft, or applies the draft back onto it | edit_posts | Destructive | No |
They go through the post type's REST route, which checks your right on each post as wp-admin does. They reach every post type shown in wp-admin and the REST API, with or without the block editor. The block tools build only posts edited with the block editor.
unblock/update-post refuses a post another user has open in the editor, unless you pass force.
For a post edited with the block editor, unblock/create-post also returns template and css, so the client needs no second read before it builds:
template: what the post's template prints around the content.h1is the text of the template's firsth1, andtitle_tagthe tag the post title prints in; each isnullwhen the template prints none. The client then knows whether the page needs anh1of its own.css: the site's CSS, asunblock/get-cssgives it, each part written even when empty.
unblock/get-context returns template too with template: true, for a page made before.
unblock/copy-post lets the client change a published page on a draft first:
- Copy: with
post_id, it makes a draft of the same post type holding the post as saved: its blocks, scripts, excerpt, author, date, parent, template, featured image, terms and custom fields, with the title followed by " (copy)" unlesstitlegives one. The slug stays empty, so the draft never takes the page's address. It returns the draft'spost_id, itspreview_urland itscontent_hash. - Apply: with
post_idset to the draft andtarget_idto the page, it writes back the draft's content and whatever else changed on it since the copy, with a revision. The page keeps its slug and status.
The apply goes only to the post the draft was copied from (unblock_not_a_copy), is refused when that post changed since the copy (unblock_copy_outdated), and needs live: true on a published post. The draft stays until you trash it with unblock/delete-post. The CSS stays the site's: what the client writes from the draft applies at once to every page it matches.
Terms
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-terms | Lists a taxonomy's terms; fields: ["meta"] adds their custom field values | edit_posts | Read | No |
unblock/create-term | Creates a term | edit_posts | Write | No |
unblock/update-term | Changes a term's name, slug, description, parent and custom fields | edit_posts | Destructive | No |
The taxonomy's REST route then checks its own rights.
Custom fields
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-custom-fields | Lists the fields ACF, Meta Box, Pods or JetEngine declare for a post type or a taxonomy, with the expression that reads each one | edit_posts | Read | No |
unblock/update-post, unblock/create-term and unblock/update-term write these fields by name in meta. An unknown key refuses the whole write.
Content model
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-post-types | Lists the post types, with the plugin keeping each one | manage_options | Read | No |
unblock/list-taxonomies | Lists the taxonomies, with the plugin keeping each one | manage_options | Read | No |
unblock/list-field-groups | Lists the field groups, their location and fields | manage_options | Read | No |
unblock/create-post-type | Creates a post type | manage_options | Write | No |
unblock/update-post-type | Changes a post type; its slug stays | manage_options | Destructive | No |
unblock/create-taxonomy | Creates a taxonomy | manage_options | Write | No |
unblock/update-taxonomy | Changes a taxonomy; its slug stays | manage_options | Destructive | No |
unblock/create-field-group | Creates a field group | manage_options | Write | No |
unblock/update-field-group | Changes a field group; fields left out stay | manage_options | Destructive | No |
The writes go through the site's field plugin, ACF or Pods, which also asks its own right. With several active, plugin picks one. Meta Box has its own abilities for this.
Site settings
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/get-site-settings | Reads the settings by their REST names, with permalink_structure and blog_public | manage_options | Read | No |
unblock/update-site-settings | Changes them; installs a missing language; url and email stay as they are | manage_options | Destructive | No |
Plugins
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-plugins | Lists the installed plugins, active or not | activate_plugins | Read | No |
unblock/install-plugin | Installs a plugin from WordPress.org by its slug and activates it, or activates one already installed | activate_plugins | Destructive | No |
To install, WordPress also asks install_plugins. It refuses it when file changes are disabled on the site, and on a multisite to anyone but a network admin. unblock/install-plugin takes a slug only, never a zip or a URL.
Templates
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-templates | Lists the active theme's templates and template parts, with their template_id and origin | edit_theme_options | Read | Yes |
unblock/create-template | Creates an empty template or template part; returns template_id and content_hash | edit_theme_options | Write | No |
unblock/delete-template | Reverts a changed one to the theme's version, trashes one you made, or deletes it with force | edit_theme_options | Destructive | No |
Global styles
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/get-global-styles | Reads the content and wide sizes, the palette, and the fonts of the text and headings | edit_theme_options | Read | No |
unblock/update-global-styles | Changes them | edit_theme_options | Destructive | No |
The theme and core blocks read these values. Unblock blocks take their design from unblock/update-css. A theme without a theme.json is refused.
Fonts
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-fonts | Lists the theme's and the font library's fonts, their faces and which are active | edit_theme_options | Read | No |
unblock/install-fonts | Installs Google Fonts by name, or a font from its files (woff2, woff, ttf, otf) by URL or base64 | edit_theme_options | Write | No |
unblock/update-fonts | Chooses the active fonts and faces | edit_theme_options | Destructive | No |
unblock/delete-fonts | Deletes library fonts and their files; a theme font is refused | edit_theme_options | Destructive | No |
The site serves the installed files itself.
Media
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/list-media | Lists the media library, newest first, with what an img element needs | upload_files | Read | No |
unblock/upload-media | Adds a file from a public URL or from base64 data | upload_files | Write | No |
unblock/update-media | Changes the alt text, title, caption or description of a media item | upload_files | Destructive | No |
unblock/generate-image | Generates an image: chat only, never over MCP | upload_files | Write | No |
WordPress checks an upload as any other: the allowed file types, which leave out SVG by default, and the size limit.
SEO
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/get-seo | Reads a post's SEO title and meta description, as Yoast SEO, Rank Math, SEOPress or All in One SEO keeps them | edit_posts | Read | No |
unblock/update-seo | Writes them, the same way with the four plugins | edit_posts | Destructive | No |
They exist only with one of the four plugins active. Both need edit_post on the post. A write follows the plugin's own rules: a post type it does not handle is refused, as are a user Rank Math's role manager or All in One SEO's access control keeps out and a role SEOPress blocks. A post another user has open is refused unless force. An empty value gives it back to the plugin's default.
Rendering
| Tool | Does | Right | Kind | Listed |
|---|---|---|---|---|
unblock/get-rendered-html | Renders a post or an address of the site as WordPress serves it to you, drafts included, scripts and styles emptied; a long page comes in parts | edit_posts | Read | No |
It shows the HTML only: no CSS and no layout, which need a browser.
Errors
The errors a block tool can return:
| Code | When | Applied? |
|---|---|---|
invalid_target | None or several of session_id, post_id and template_id | No |
invalid_session | session_id is not a valid UUID | No |
bridge_no_session | No open session of yours has this ID | No |
bridge_busy | The editor tab is still running a previous command | No |
bridge_timeout | The tab did not pick the command up within 10 seconds: paused, closed, or silent | No |
bridge_timeout | The tab picked the command up but gave no answer within 30 seconds | Maybe: read with unblock/get-context before retrying |
unblock_no_post | No post has this ID | No |
unblock_no_template | No template or template part has this ID | No |
unblock_ambiguous_template | A template and a template part both have this ID | No |
unblock_forbidden | You may not edit this post or templates | No |
unblock_no_block_editor | The post is not edited with the block editor | No |
unblock_post_locked | Another user has the post open in the editor | No |
unblock_live_write | The post is published or private, or is a template, and live: true is missing | No |
unblock_stale_post | content_hash is missing, or the post changed since you read it | No |
unblock_mcp_forbidden | Your account may not use MCP | No |
unblock_mcp_read_only | The OAuth connection is read only | No |
Connections
The MCP tab builds each client's configuration. For reference:
| Connection | Server | Needs |
|---|---|---|
| OAuth | mcp/unblock | HTTPS, pretty permalinks, the REST API open to visitors, MCP Adapter 0.7.0 or later |
| WP-CLI | mcp-adapter-default-server | WP-CLI on the computer that hosts the site |
| Password | mcp-adapter-default-server | Node.js, HTTPS, application passwords |
The tab picks OAuth when the site meets its requirements, WP-CLI on a local site (localhost, a .local or .test domain), and Password otherwise. claude.ai, ChatGPT and Grok take OAuth only. Claude Code, Claude Desktop, Cursor, VS Code and Kiro take all three, the other clients WP-CLI and Password. Other client gives the standard mcpServers configuration.
OAuth, in Cursor:
{
"mcpServers": {
"wp-example-com": {
"url": "https://example.com/wp-json/mcp/unblock"
}
}
}
WP-CLI, in Claude Desktop:
{
"mcpServers": {
"wp-localhost": {
"command": "wp",
"args": [
"--path=/path/to/your/wordpress",
"mcp-adapter",
"serve",
"--server=mcp-adapter-default-server",
"--user=admin"
]
}
}
}
Password, with the application password the tab generates:
{
"mcpServers": {
"wp-example-com": {
"command": "npx",
"args": ["-y", "@automattic/mcp-wordpress-remote@latest"],
"env": {
"WP_API_URL": "https://example.com/wp-json/mcp/mcp-adapter-default-server",
"WP_API_USERNAME": "admin",
"WP_API_PASSWORD": "abcd efgh ijkl mnop qrst uvwx"
}
}
}
}
WP_ENVIRONMENT_TYPE set to local in wp-config.php lifts the HTTPS requirement of OAuth and application passwords.
Grok reads the OAuth metadata at the root of the domain only. A site in a subfolder, such as example.com/blog, needs a rule at the root, for Apache or nginx, which the tab gives. A site of a multisite network in subfolders can't receive it, other than the main site.
How the bridge works
Everything runs through your site: no external server, apart from the proxy package of the Password connection, which runs on the client's machine. With OAuth, the site signs the client in itself.
Through an editor session
AI client
↓ calls a tool with session_id
MCP Adapter on your site
↓ queues the command in the database
Editor tab
↓ claims the command, runs it on the open page
↓ posts the result back
MCP Adapter returns the result to the AI client
The tab keeps short streams open to unblock/v1/mcp/stream and claims each command before running it, so a command never runs twice. Commands travel through the wp_options table: no WebSocket server, no extra service.
- Liveness: the tab pings the site every 30 seconds. A session is active while its last ping is under 90 seconds old.
- Paused: a hidden, frozen or sleeping tab shows as paused for up to an hour, then the session is dropped. The tab picks it up again once it's back in the foreground.
- Stream: each stream lasts about 25 seconds, then the tab opens the next one.
- End: closing or reloading the tab ends the session.
Without an editor session
AI client
↓ calls a tool with post_id or template_id
MCP Adapter on your site
↓ loads the post through its REST route
Unblock on the server
↓ runs the tool as the editor would, matches the CSS
↓ saves the post and the CSS through WordPress
MCP Adapter returns the result to the AI client
The server runs the same tool code as the editor, ported to PHP, so a change made without a tab gives the same blocks and CSS. Saving goes through WordPress's own routes, with their rights and checks, and the post keeps a revision. The editor of a user who has the post open shows "An AI tool changed this post since you opened it", with a Reload button.
Next steps
- MCP Bridge: connect a client and start a session
- Agent skills: the method that chains these tools into a site
- AI filters: who can use MCP