Skip to main content

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 with mcp-adapter/get-ability-info, and runs them with mcp-adapter/execute-ability.
  • Chat only: unblock/generate-image is never shared over MCP. A client brings its own images and adds them with unblock/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:

Who can run them​

Every call passes two checks:

  1. The MCP right, unblock/ai/mcp/can_use: Administrators by default. A user it refuses gets unblock_mcp_forbidden on every Unblock tool, listed or run through execute-ability.
  2. 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:

TargetWorks on
session_idThe page or template open in an editor tab, from unblock/list-sessions. Unsaved changes included; nothing is saved until you click Save.
post_idAny post edited with the block editor, without a tab. The change is saved at once.
template_idA 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:

FieldUse
content_hashunblock/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.
forceWrite even though another user has the post open in the editor, whose next save would discard the write.
liveWrite 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.

Watch out

force means something else on unblock/delete-post and unblock/delete-template: delete for good instead of moving to the trash.

Context​

ToolDoesRightKindListed
unblock/list-sessionsLists your open editor sessions: ID, post or template, title, active or pausededit_postsReadYes
unblock/get-instructionsReturns Unblock's conventions and tool rules. Call it once, with the first readedit_postsReadYes

Blocks and CSS​

ToolDoesRightKindListed
unblock/get-contextReads a document: block tree with bid attributes, CSS, variables, breakpoints, fonts, and its content_hash; template: true adds what its template printsedit_postsReadYes
unblock/get-cssReads the site's CSS without a page; where.search gives the full rules of up to 100 selectorsedit_postsReadYes
unblock/insert-blocksAdds blocks from HTML, with the CSS of their new classesedit_postsWriteYes
unblock/replace-blocksReplaces a block's inner content with new HTMLedit_postsDestructiveYes
unblock/update-block-attributesChanges a block's HTML attributes or its tag; null removes an attributeedit_postsDestructiveYes
unblock/update-block-contentChanges a block's text or raw markup, the blocks inside it untouchededit_postsDestructiveYes
unblock/update-block-scriptAdds, changes or removes a block's JavaScriptunfiltered_htmlDestructiveYes
unblock/update-cssWrites rules, :root variables and at-rules; installs the Google Fonts it namescss/can_writeDestructiveYes
unblock/move-blocksMoves blocks among their siblings or into another blockedit_postsWriteYes
unblock/remove-blocksRemoves blocksedit_postsDestructiveYes

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.
  • :root and html variables are only added or changed.
  • The at-rule blocks you leave out stay as they are. Send one empty to clear it: @media (...) { .card {} }.
  • remove deletes 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.

Watch out

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​

ToolDoesRightKindListed
unblock/list-postsLists the posts of a post type, newest first; where.search, fields, custom field values with metaedit_postsReadYes
unblock/create-postCreates a post, a page and a draft unless asked otherwise; returns post_id, content_hash, what its template prints and the site's CSSedit_postsWriteYes
unblock/update-postChanges the title, status, slug, excerpt, parent, date, template, featured image, terms and custom fields, never the contentedit_postsDestructiveYes
unblock/delete-postMoves a post to the trash, or deletes it for good with forceedit_postsDestructiveNo
unblock/copy-postCopies a post into a draft, or applies the draft back onto itedit_postsDestructiveNo

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. h1 is the text of the template's first h1, and title_tag the tag the post title prints in; each is null when the template prints none. The client then knows whether the page needs an h1 of its own.
  • css: the site's CSS, as unblock/get-css gives 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)" unless title gives one. The slug stays empty, so the draft never takes the page's address. It returns the draft's post_id, its preview_url and its content_hash.
  • Apply: with post_id set to the draft and target_id to 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​

ToolDoesRightKindListed
unblock/list-termsLists a taxonomy's terms; fields: ["meta"] adds their custom field valuesedit_postsReadNo
unblock/create-termCreates a termedit_postsWriteNo
unblock/update-termChanges a term's name, slug, description, parent and custom fieldsedit_postsDestructiveNo

The taxonomy's REST route then checks its own rights.

Custom fields​

ToolDoesRightKindListed
unblock/list-custom-fieldsLists the fields ACF, Meta Box, Pods or JetEngine declare for a post type or a taxonomy, with the expression that reads each oneedit_postsReadNo

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​

ToolDoesRightKindListed
unblock/list-post-typesLists the post types, with the plugin keeping each onemanage_optionsReadNo
unblock/list-taxonomiesLists the taxonomies, with the plugin keeping each onemanage_optionsReadNo
unblock/list-field-groupsLists the field groups, their location and fieldsmanage_optionsReadNo
unblock/create-post-typeCreates a post typemanage_optionsWriteNo
unblock/update-post-typeChanges a post type; its slug staysmanage_optionsDestructiveNo
unblock/create-taxonomyCreates a taxonomymanage_optionsWriteNo
unblock/update-taxonomyChanges a taxonomy; its slug staysmanage_optionsDestructiveNo
unblock/create-field-groupCreates a field groupmanage_optionsWriteNo
unblock/update-field-groupChanges a field group; fields left out staymanage_optionsDestructiveNo

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​

ToolDoesRightKindListed
unblock/get-site-settingsReads the settings by their REST names, with permalink_structure and blog_publicmanage_optionsReadNo
unblock/update-site-settingsChanges them; installs a missing language; url and email stay as they aremanage_optionsDestructiveNo

Plugins​

ToolDoesRightKindListed
unblock/list-pluginsLists the installed plugins, active or notactivate_pluginsReadNo
unblock/install-pluginInstalls a plugin from WordPress.org by its slug and activates it, or activates one already installedactivate_pluginsDestructiveNo

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​

ToolDoesRightKindListed
unblock/list-templatesLists the active theme's templates and template parts, with their template_id and originedit_theme_optionsReadYes
unblock/create-templateCreates an empty template or template part; returns template_id and content_hashedit_theme_optionsWriteNo
unblock/delete-templateReverts a changed one to the theme's version, trashes one you made, or deletes it with forceedit_theme_optionsDestructiveNo

Global styles​

ToolDoesRightKindListed
unblock/get-global-stylesReads the content and wide sizes, the palette, and the fonts of the text and headingsedit_theme_optionsReadNo
unblock/update-global-stylesChanges themedit_theme_optionsDestructiveNo

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​

ToolDoesRightKindListed
unblock/list-fontsLists the theme's and the font library's fonts, their faces and which are activeedit_theme_optionsReadNo
unblock/install-fontsInstalls Google Fonts by name, or a font from its files (woff2, woff, ttf, otf) by URL or base64edit_theme_optionsWriteNo
unblock/update-fontsChooses the active fonts and facesedit_theme_optionsDestructiveNo
unblock/delete-fontsDeletes library fonts and their files; a theme font is refusededit_theme_optionsDestructiveNo

The site serves the installed files itself.

Media​

ToolDoesRightKindListed
unblock/list-mediaLists the media library, newest first, with what an img element needsupload_filesReadNo
unblock/upload-mediaAdds a file from a public URL or from base64 dataupload_filesWriteNo
unblock/update-mediaChanges the alt text, title, caption or description of a media itemupload_filesDestructiveNo
unblock/generate-imageGenerates an image: chat only, never over MCPupload_filesWriteNo

WordPress checks an upload as any other: the allowed file types, which leave out SVG by default, and the size limit.

SEO​

ToolDoesRightKindListed
unblock/get-seoReads a post's SEO title and meta description, as Yoast SEO, Rank Math, SEOPress or All in One SEO keeps themedit_postsReadNo
unblock/update-seoWrites them, the same way with the four pluginsedit_postsDestructiveNo

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​

ToolDoesRightKindListed
unblock/get-rendered-htmlRenders 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 partsedit_postsReadNo

It shows the HTML only: no CSS and no layout, which need a browser.

Errors​

The errors a block tool can return:

CodeWhenApplied?
invalid_targetNone or several of session_id, post_id and template_idNo
invalid_sessionsession_id is not a valid UUIDNo
bridge_no_sessionNo open session of yours has this IDNo
bridge_busyThe editor tab is still running a previous commandNo
bridge_timeoutThe tab did not pick the command up within 10 seconds: paused, closed, or silentNo
bridge_timeoutThe tab picked the command up but gave no answer within 30 secondsMaybe: read with unblock/get-context before retrying
unblock_no_postNo post has this IDNo
unblock_no_templateNo template or template part has this IDNo
unblock_ambiguous_templateA template and a template part both have this IDNo
unblock_forbiddenYou may not edit this post or templatesNo
unblock_no_block_editorThe post is not edited with the block editorNo
unblock_post_lockedAnother user has the post open in the editorNo
unblock_live_writeThe post is published or private, or is a template, and live: true is missingNo
unblock_stale_postcontent_hash is missing, or the post changed since you read itNo
unblock_mcp_forbiddenYour account may not use MCPNo
unblock_mcp_read_onlyThe OAuth connection is read onlyNo

Connections​

The MCP tab builds each client's configuration. For reference:

ConnectionServerNeeds
OAuthmcp/unblockHTTPS, pretty permalinks, the REST API open to visitors, MCP Adapter 0.7.0 or later
WP-CLImcp-adapter-default-serverWP-CLI on the computer that hosts the site
Passwordmcp-adapter-default-serverNode.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​