Complete reference for the free WordPress MCP plugin — 40 tools, authentication, configuration, and data flows.
IATO MCP turns any self-hosted WordPress site into an MCP server. The plugin runs entirely inside WordPress as a REST API endpoint — no external server or infrastructure required. AI clients like Claude Desktop, Gemini, and ChatGPT connect directly to your site via the Model Context Protocol.
AI Client (Claude Desktop / Gemini / ChatGPT)
|
| MCP JSON-RPC over HTTP (one POST per call)
|
WordPress Plugin (iato-mcp)
POST /wp-json/iato-mcp/v1/message ← all MCP tool calls
POST /wp-json/iato-mcp/v1/rollback ← rollback a change by receipt ID
GET /wp-json/iato-mcp/v1/oauth/* ← Claude Desktop auth flow
|
| With IATO API key configured, bridge tools call:
|
IATO Platform (iato.ai/api/v1)
Auth: Authorization: Bearer {iato_api_key}
Read-only: sitemap, SEO fixes, orphans, broken links, suggestions
The plugin works on any self-hosted WordPress installation. No special server configuration needed.
| Requirement | Details |
|---|---|
| WordPress | 6.2 or higher |
| PHP | 8.0 or higher |
| IATO Account | Optional — only needed for bridge tools |
| Hosting | Any: shared (Bluehost, SiteGround), VPS (DigitalOcean, Linode), managed WP (WP Engine, Flywheel, Cloudways), or local dev |
One screen, five steps, under five minutes. The 40 WordPress tools work immediately. The 12 bridge tools require an IATO API key.
Restart your MCP client. The 40 WordPress tools (52 with an IATO key) will appear in the client's tool list.
All settings are managed in WP Admin under Settings → IATO MCP.
Read-only. Shows your site's MCP URL: https://yoursite.com/wp-json/iato-mcp/v1/message
Plugin-generated Bearer key (IATO-XXXXXXXX). Use Copy to clipboard or Regenerate to create a new one.
Enter your IATO account API key here to enable the 12 bridge tools. Validate explicitly via the Test connection button next to the field — saving is fast and local.
Fallback crawl ID used by bridge tools when crawl_id is not passed in the tool call.
Per-tool enable/disable checkboxes. Disable tools you don't need to reduce the tool list for your AI client.
Any AI client that supports the Model Context Protocol can connect to your WordPress site.
Go to Claude Desktop → Settings → Connectors → Add. Enter your site's MCP endpoint URL (shown in Settings → IATO MCP). Click Authorize — the OAuth flow completes automatically.
For other MCP clients, add this to your client's configuration file:
{
"mcpServers": {
"wordpress": {
"url": "https://yoursite.com/wp-json/iato-mcp/v1/message",
"headers": {
"Authorization": "Bearer IATO-XXXXXXXX"
}
}
}
}
Replace the URL and API key with the values from Settings → IATO MCP.
The plugin exposes 40 WordPress tools plus 12 IATO bridge tools (the bridge tools require an IATO API key). Grouped by category. Frozen as of plugin v1.4.0.
get_posts | List published posts with filters |
get_post | Single post details and meta |
create_post | Create a new post or page |
update_post | Edit title, content, excerpt, status |
search_posts | Full-text search across posts |
get_site_info | Basic site information and health |
get_site_settings | WordPress settings (admin only) |
resolve_url | Walk the WordPress rewrite cascade and detect Elementor Theme Builder template shadowing on a slug |
get_seo_data | Read SEO meta fields (Yoast / RankMath / SEOPress) |
update_seo_data | Update SEO title and meta description |
update_canonical | Set canonical URL for a post |
update_structured_data | Add JSON-LD structured data |
get_media | List media library items |
update_alt_text | Update image alt text |
get_menus | List navigation menus |
get_menu_items | Menu item details and structure |
create_menu_item | Add new menu item (admin) |
update_menu_item | Add a page to a menu (admin) |
update_menu_item_details | Edit menu item properties (admin) |
delete_menu_item | Remove a menu item (admin) |
get_terms | List categories, tags, or any taxonomy |
assign_term | Assign terms to a post |
create_term | Create a new term (admin) |
update_term | Edit an existing term (admin) |
delete_term | Remove a term (admin) |
update_taxonomy | Replace all terms on a post |
update_redirect | Create or update redirect rules (admin) |
get_comments | List and filter comments |
rollback | Reverse any AI-made write using its change_receipt ID. Validates before_value to prevent stale rollbacks. See Rollback Endpoint for receipt format and error semantics. |
get_page_builder | Detect which page builder a post uses |
get_elementor_data | Return Elementor data with format: raw | compact | summary. Includes a canonical revision hash for use as if_revision on subsequent writes |
update_elementor_data | Update Elementor JSON and regenerate rendered content |
Widget-grained editing — patch a single widget without re-uploading the whole document. All writes accept if_revision for optimistic concurrency and idempotency_key for safe retries (60-second replay window).
list_elementor_widgets | List every widget on a post with id, type, and breadcrumb path |
get_elementor_widget | Return a single widget's raw settings by widget id |
find_elementor_widgets | Find widgets across many posts by type and optional setting filters |
set_heading_level | Flip an Elementor heading widget's level (h1–h6) in one call |
set_widget_setting | Set a single setting on a single widget — the most common write |
update_elementor_widget | Patch a widget's settings; replace-only array semantics |
update_elementor_widgets_bulk | Update many widgets across many posts in one HTTP call |
update_elementor_patch | Apply RFC 6902 JSON Patch operations for surgical array edits (escape hatch for the replace-only semantics on the others) |
Tools that call the IATO API. The read tools resolve IATO node/page IDs to WordPress post IDs and slugs so your AI client can chain directly into the WP native tools. The crawl management tools let Claude trigger and monitor crawls without leaving the conversation.
| Tool | Returns |
|---|---|
get_iato_sitemap | Full site hierarchy with WordPress post IDs attached |
get_iato_nav_audit | Navigation menus + orphan pages in one audit |
get_iato_orphan_pages | Pages not linked from any nav menu |
get_iato_taxonomy | IATO categories/tags mapped to WordPress term IDs |
get_iato_seo_fixes | SEO issues with auto-fixable vs. manual classification and WP slugs |
get_iato_content_gaps | Thin content, missing H1, low image count, low internal link count |
get_iato_broken_links | Broken pages and broken resources, mapped to source posts |
get_iato_suggestions | AI-prioritized improvements across SEO / content / links / performance |
get_iato_perf_report | Slowest and largest pages with WP slugs |
| Tool | Description |
|---|---|
start_iato_crawl | Start a new crawl of the site (admin only; consumes IATO platform quota) |
get_iato_crawl_status | Check status and progress of a specific crawl job |
list_iato_crawls | List recent crawl jobs to find the most recent completed crawl_id |
Plugin v1.3.0 introduced 8 widget-level Elementor tools that patch a single widget without re-uploading the whole document. A 4-page heading-level flip dropped from ~100 KB / 16 requests on v1.2 to ~2.2 KB / 1 request on v1.3 — ~60× wire reduction.
| When… | Use |
|---|---|
| You're flipping a heading level | set_heading_level |
| You're setting one named setting on one widget | set_widget_setting (most common write) |
| You're patching multiple settings on one widget | update_elementor_widget |
| You're updating many widgets across many posts | update_elementor_widgets_bulk (single HTTP call) |
| You need to mutate inside an array (insert / remove / reorder items) | update_elementor_patch with RFC 6902 ops |
if_revision flowEvery get_elementor_data and widget-level read returns a canonical revision hash. Pass it as if_revision on a write to fail fast if the document changed since you read it:
// 1. read
const { revision, widgets } = await get_elementor_widget({ post_id: 42, widget_id: "abc123" });
// 2. write with the revision you read
await update_elementor_widget({
post_id: 42,
widget_id: "abc123",
settings_patch: { title: "New title" },
if_revision: revision,
idempotency_key: "set-hero-title-2026-04-28"
});
If the revision doesn't match the current document state, the write is rejected with a conflict error so your client can re-read and decide. Without if_revision, last-write-wins.
idempotency_key flowPass idempotency_key on any widget write to make retries safe. The plugin caches the response for 60 seconds, scoped per (user, tool) pair. A retry within that window with the same key returns the cached result without re-applying the write.
Use any string — UUID, slugified intent, request id from your client. The plugin only checks for collisions; it doesn't interpret the value.
settings_patch on update_elementor_widget and update_elementor_widgets_bulk uses replace-only semantics for arrays — if you patch an array setting, you replace the entire array. There is no merge for nested array elements.
To insert, remove, or reorder items inside an array without rewriting the whole array, use update_elementor_patch with RFC 6902 JSON Patch operations (add, remove, replace, move, copy, test).
Elementor's Theme Builder can override the default WordPress render of a slug with a template. A request to /about/ may render the singular page template, an Elementor Theme Builder singular template, or a more specific page-about template — depending on the rewrite cascade.
Two ways to detect this:
resolve_url walks the rewrite cascade for any URL and reports the resolved post + any shadowing template overriding it.get_post accepts include_shadowing: true for the same detection inline on a known post.Full detection requires Elementor 3.20+. On older versions, the resolver returns limited_resolution: true and falls back to the WordPress-only cascade.
The MCP initialize handshake advertises plugin capabilities so clients can feature-detect without a tools/list round-trip. When Elementor is active, the response includes:
{
"capabilities": {
"elementor": { "v2": true }
}
}
Absent or false means the v2 widget tools won't be registered — either Elementor isn't installed, or the plugin is on an older version. Clients should gate widget-level prompts on this flag.
Two prompts that exercise the v2 capability end-to-end:
find_elementor_widgets to locate all heading widgets, then update_elementor_widgets_bulk with set_heading_level semantics in a single HTTP call.find_elementor_widgets with type and setting filters, then update_elementor_widgets_bulk with settings_patch on each match.The plugin auto-detects which SEO plugin is active and reads/writes the correct post meta keys. Detection priority: Yoast → RankMath → SEOPress → Fallback. No configuration needed.
| Plugin | Title Key | Description Key | Canonical Key |
|---|---|---|---|
| Yoast SEO | _yoast_wpseo_title | _yoast_wpseo_metadesc | _yoast_wpseo_canonical |
| RankMath | rank_math_title | rank_math_description | rank_math_canonical_url |
| SEOPress | _seopress_titles_title | _seopress_titles_desc | _seopress_robots_canonical |
| Fallback | Native WordPress post title (no SEO plugin detected) | ||
The update_redirect tool auto-detects which redirect plugin is active and uses its API. If no plugin is found, a built-in option-based fallback handles redirects.
| Priority | Plugin | Notes |
|---|---|---|
| 1 | Redirection | Most popular redirect plugin. Uses its REST API to create/update rules. |
| 2 | Safe Redirect Manager | Stores redirects as custom post type. Supported via direct CPT creation. |
| 3 | Yoast Premium | Uses Yoast Premium's redirect manager when available. |
| Fallback | Built-in | Option-based fallback stored in iato_redirects. Capped at 500 rules. |
Every write tool returns a change_receipt object in its response, providing a full audit trail for AI-made changes.
{
"change_id": "wr_a1b2c3d4e5f67890",
"post_id": 42,
"target_type": "page",
"field": "meta_description",
"before_value": "Old description",
"after_value": "New SEO-optimized description",
"applied_at": "2026-03-26T14:30:00Z"
}
| Target Type | Used By |
|---|---|
page | update_seo_data, update_post |
image | update_alt_text |
menu_item | create_menu_item, update_menu_item, delete_menu_item, update_menu_item_details |
taxonomy | assign_term, create_term, update_term, delete_term, update_taxonomy |
redirect | update_redirect |
structured_data | update_structured_data |
Receipts are stored in the {prefix}iato_change_receipts database table, created automatically on plugin activation.
Restore any AI-made change using its change receipt ID.
POST /wp-json/iato-mcp/v1/rollback
Same as MCP endpoint: Bearer token (Authorization: Bearer IATO-XXXXXXXX).
{
"change_id": "wr_a1b2c3d4e5f67890",
"post_id": 42,
"target_type": "page",
"field": "meta_description",
"before_value": "New SEO-optimized description"
}
| Check | Error | Status |
|---|---|---|
change_id must exist | Change receipt not found | 404 |
| Not already rolled back | Change already rolled back | 400 |
before_value must match stored value | Stale rollback — value has changed since receipt was issued | 400 |
{
"success": true,
"rolled_back_at": "2026-03-26T15:00:00Z",
"change_id": "wr_a1b2c3d4e5f67890"
}
Supported rollbacks: all write tool changes including SEO meta, alt text, menu items, taxonomy, canonical URLs, structured data, and redirects.
Accessible at wp-admin/admin.php?page=iato-mcp-setup. Requires manage_options capability. One screen — no multi-step flow.
| Field | Purpose |
|---|---|
| MCP Endpoint URL | Read-only — the URL you paste into your MCP client config |
| MCP API Key | Plugin-generated Bearer token (IATO-XXXXXXXX). Copy or regenerate |
| Application Password setup | Link + instructions for generating a WordPress Application Password |
| JSON config snippet | Ready-to-paste MCP client configuration block with the correct URL and auth header |
| IATO API Key (optional) | Enter to enable the 12 bridge tools. Validate explicitly via Test connection — saving is fast and local. |
The plugin uses a plugin-generated API key stored in wp_options, plus support for WordPress-native Application Passwords. Four authentication methods are supported.
| Method | How | Notes |
|---|---|---|
| Application Password | Authorization: Basic <base64(username:app_password)> | WordPress-native auth (WP 5.6+). Generate at Users → Profile → Application Passwords. Recommended for non-OAuth MCP clients. |
| Bearer Token | Authorization: Bearer IATO-XXXXXXXX | Plugin-generated key. Created on activation, stored in wp_options as iato_mcp_key. |
| Query Parameter | ?mcp_key=IATO-XXXXXXXX | Fallback for clients that cannot set custom headers. |
| OAuth 2.0 | Automatic via class-oauth.php | Claude Desktop Connect button triggers this automatically. |
Key generation: on plugin activation, wp_generate_password(32, false) creates the key. Users can regenerate via Settings → IATO MCP → Regenerate Key.
Two example workflows showing how the plugin bridges AI clients, WordPress, and IATO.
1. AI calls get_iato_seo_fixes(crawl_id)
→ Plugin calls IATO: run_seo_audit + get_seo_issues
→ Returns: [{url, issue_type, current, suggested, wp_post_id, wp_slug}]
2. AI calls update_seo_data(id: wp_post_id, description: suggested)
→ Plugin writes to Yoast/RankMath/SEOPress meta on each post
1. AI calls get_iato_nav_audit(sitemap_id)
→ Plugin calls IATO: get_menus + get_menu_items + find_orphan_pages
→ Returns: {menus: [...], orphans: [{url, wp_post_id, wp_slug}]}
2. AI calls update_menu_item(menu_id, post_id: wp_post_id, dry_run: true)
→ Preview what would be added
3. AI calls update_menu_item(menu_id, post_id: wp_post_id)
→ wp_update_nav_menu_item() adds page to menu
Verify the API key in Settings → IATO MCP and click Test connection. The validation call goes to GET /api/v1/workspaces. If it fails, check your firewall or hosting egress rules allow outbound HTTPS to iato.ai. Ensure your IATO subscription is active.
The Application Password isn't configured, or the JSON config pasted into Claude Desktop is missing or malformed. Re-open the Setup Wizard, regenerate the Application Password, copy the JSON snippet exactly, paste into Claude Desktop's config, and restart Claude Desktop fully (quit, not just close the window).
Confirm your IATO subscription is active and the Default Crawl ID is set to a valid, completed crawl. Bridge tools require both an IATO API key and valid crawl data.
Ensure your site is publicly accessible (not behind basic auth or a firewall). Claude Desktop needs to reach your site's OAuth endpoints. Check that the MCP endpoint URL in Settings is correct.
Verify WordPress 6.2+ and PHP 8.0+. Check the Plugins page for error messages. The plugin requires the REST API to be enabled (default in WordPress).
Check that the tools are enabled in Settings → IATO MCP → Enabled Tools. Disabled tools are not exposed via the MCP endpoint.
update_elementor_widgets_bulk no longer echoes change_receipt on per-result rows. Receipts still persist to the iato_change_receipts audit table; bulk callers can query by post_id + applied_at. Saves ~120 bytes per result.update_elementor_widget and update_elementor_patch responses keep the slim receipt for backward compatibility and convenience.update_elementor_widget, update_elementor_patch, update_elementor_widgets_bulk) elide previous_revision from per-result responses unless the caller passed if_revision.if_revision already knows the prior hash; a client that didn't pass it gets current_revision to chain the next write. Saves ~93 bytes per result on the op: replace path.change_receipt with the entire applied_patch JSON-stringified into before_value. That duplicated the top-level applied_patch field and pushed bulk-update payloads over the spec's <2 KB target on a 4-page sweep. The before_value was also semantically wrong (should be the value being replaced, not the patch).previous_revision → current_revision pair; API response carries only the receipt id + metadata ({change_id, target_type, field, applied_at}). Full audit data still queryable from the iato_change_receipts table for rollback.update_elementor_widgets_bulk and find_elementor_widgets no longer reject every request with auth_denied. The handlers were calling current_user_can('edit_post', $post_id) per-target, but bearer-authenticated MCP requests don't establish a logged-in WP user — wp_get_current_user() returns 0 and meta-cap checks against post objects always fail. v2 handlers now match v1's IATO_MCP_Auth::require_cap() flag-check semantics.iato_mcp_tools toggle arrays didn't include the new names. The migration appends new tool names on first request after upgrade. New installs unaffected.list_elementor_widgets, get_elementor_widget, find_elementor_widgets, set_heading_level, set_widget_setting, update_elementor_widget, update_elementor_widgets_bulk, update_elementor_patchresolve_url tool walks the WordPress rewrite cascade and detects Elementor Theme Builder template shadowingif_revision (canonical revision hash returned by reads); idempotency via idempotency_key (60-second replay window, scoped per (user, tool))update_elementor_patch applies RFC 6902 JSON Patch operations as a surgical escape hatch for the replace-only array semantics on the higher-level write toolsget_elementor_data accepts format: raw | compact | summary for flexible introspectioninitialize handshake advertises capabilities.elementor.v2: true so clients can feature-detect without a tools/list round-triplimited_resolution: true and fall back to the WordPress-only cascadestart_iato_crawl, get_iato_crawl_status, list_iato_crawls MCP toolsInitial public release. Pure MCP server for self-hosted WordPress: 30 WordPress tools plus 9 IATO bridge tools.
Deliberate scope changes from pre-release builds:
sync_wp_pages_to_iato, sync_wp_taxonomy_to_iato, sync_wp_meta_to_iato, sync_wp_menus_to_iato — were removed in v1.0.0. The user-facing WordPress Sync feature on the IATO dashboard is unaffected because it composes the existing read tools (get_posts, get_terms, get_menus, get_menu_items) directly. The aggregator tools will return in a future release alongside Autopilot once the async-sync redesign is complete.What's in v1.0.0:
POST /wp-json/iato-mcp/v1/rollback endpointTurn your self-hosted WordPress site into an MCP server. Free, open source, works with any AI client.
Get it on WordPress.org