WP Manifestindependent plugin directory
manifest / developer / wordpress-mcp-modern

WordPress MCP (Modern)

Modern WordPress MCP server on the official mcp-adapter + Abilities API — 63 tools, 5 resources, 2 prompts, JWT + Application Password auth, HTTP & STDIO transports.

by consigcody94 · github.com/consigcody94/wordpress-mcp-modern

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/consigcody94/wordpress-mcp-modern/archive/refs/heads/main.zip

Readme

🤖 WordPress MCP (Modern)

Turn any WordPress site into a first-class Model Context Protocol server — built the modern way, on the WordPress Abilities API.

🔧 82 tools 📚 5 resources 💬 2 prompts 🔐 3 auth methods 🔌 2 transports 🛒 WooCommerce-aware

Quick start · Connect a client · Tools · Security · Extend it · FAQ


✨ What is this?

This plugin makes your WordPress site directly usable by AI assistants. Once installed, tools like Claude Desktop, Cursor, or VS Code Copilot can securely read and manage your content — posts, pages, media, users, taxonomies, settings, even your WooCommerce store — by talking to your site over the open Model Context Protocol (MCP).

In practice, that means conversations like these just work:

💬 You ask your AI… ⚡ …and it calls
"Draft a post announcing the spring sale and publish it." wp_add_post
"What are my five most recent draft pages?" wp_pages_search
"Upload this logo to the media library with proper alt text." wp_upload_media
"How did the store do last month?" wc_reports_sales
"Create a 'Tutorials' category and file the latest posts under it." wp_add_category + wp_update_post

Everything runs under your WordPress permissions — the AI can never do anything the authenticated user couldn't already do, and you can gate or disable any tool from a settings page.

🆕 New to MCP? A 60-second primer


The Model Context Protocol is an open standard (think "USB-C for AI") that lets AI applications discover and call capabilities exposed by servers. An MCP server offers three kinds of things:

  • Tools — actions the AI can take (create a post, search users, upload media).
  • Resources — data the AI can read for context (site info, active theme, settings).
  • Prompts — reusable, server-defined instruction templates ("analyze my sales").

Your WordPress site becomes one of those servers. Any MCP-compatible client — Claude Desktop, Cursor, VS Code, or your own agent — can connect to it, see what it offers, and use it. The protocol handles discovery, schemas, and transport; this plugin supplies the WordPress capabilities.


💡 Why this exists

The original Automattic/wordpress-mcp is deprecated. Its successor is the official WordPress/mcp-adapter AI Building Block, which sits on top of the new Abilities API shipping in WordPress Core 6.9.

This project is a ground-up re-implementation of the old plugin's capabilities on that modern stack:

Old way (deprecated) Modern way (this plugin)
Capabilities Bespoke Mcp*Tools PHP classes Every capability is a WordPress Ability
Transport Hand-rolled The official mcp-adapter transport
Reusability Tightly coupled to MCP Abilities are reusable by any AI building block
Shape Monolithic plugin Thin plugin + Composer dependency

[!TIP] The big idea: you don't register "tools" — you register Abilities (wp_register_ability()), and mcp-adapter exposes them as MCP tools, resources, and prompts. Same capability, many surfaces. When the next AI surface arrives in WordPress, your abilities come along for free.


🏛️ Architecture at a glance

flowchart LR
    Client["🧠 AI Client<br/>(Claude, Cursor, VS Code…)"]

    subgraph WP["🌐 WordPress 6.9+ / PHP 8.0+"]
        direction TB
        Perm["🔐 TransportPermission<br/>JWT · App Password"]
        Server["🗂️ MCP Server<br/>/wp-json/wpmcp/mcp"]
        Reg["📇 AbilityRegistrar<br/>(gating · name mapping)"]
        Abilities[("⚡ WordPress Abilities")]
        Core["WP REST API · core functions · WooCommerce"]

        Perm --> Server --> Reg --> Abilities --> Core
    end

    Client -->|"HTTP (Streamable) or STDIO"| Perm
    mcp["📦 wordpress/mcp-adapter<br/>(Composer)"] -.bridges.-> Server

Each piece has one job:

  • TransportPermission — the front door. Validates the JWT or relies on WordPress's own Application Password auth, then establishes the WordPress user for the request.
  • MCP Server (from wordpress/mcp-adapter) — speaks the MCP protocol: discovery, sessions, schemas, content blocks. This plugin never parses MCP itself.
  • AbilityRegistrar — the single source of truth for what's exposed. Applies your gating settings and maps modern ability names back to the legacy tool names clients already know.
  • Abilities — the actual capabilities, registered via the core Abilities API and mostly executing through the real WordPress REST API.

🚀 Quick start

[!IMPORTANT] Requirements: WordPress 6.9+ (ships the Abilities API) and PHP 8.0+.

Step 1 — Install the plugin

From a release (easiest — no Composer needed): grab wordpress-mcp-modern.zip from the Releases page — it bundles all PHP dependencies — and install it via Plugins → Add New → Upload Plugin.

From source:

cd wp-content/plugins/
git clone https://github.com/consigcody94/wordpress-mcp-modern.git
cd wordpress-mcp-modern
composer install --no-dev
wp plugin activate wordpress-mcp-modern

Your MCP endpoint is now live at /wp-json/wpmcp/mcp. 🎉

Step 2 — Create credentials

The fastest path is an Application Password: go to Users → Profile → Application Passwords, name it (e.g. mcp), and copy the generated password. That's it — no plugin configuration needed. (Prefer revocable tokens? See Authentication for JWTs.)

Step 3 — Connect your AI client

The server supports HTTP (Streamable) and STDIO transports. Pick your client:

🖥️ Claude Desktop / Cursor — via the official proxy + Application Password


Add this to your client's MCP config (e.g. claude_desktop_config.json):

{
  "mcpServers": {
    "wordpress": {
      "command": "npx",
      "args": ["-y", "@automattic/mcp-wordpress-remote@latest"],
      "env": {
        "WP_API_URL": "https://your-site.com/wp-json/wpmcp/mcp",
        "WP_API_USERNAME": "your-username",
        "WP_API_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
      }
    }
  }
}

The proxy bridges the client's STDIO transport to your site's HTTP endpoint and handles Basic auth for you.

📝 VS Code — direct HTTP transport with a JWT


{
  "servers": {
    "wordpress": {
      "type": "http",
      "url": "https://your-site.com/wp-json/wpmcp/mcp",
      "headers": { "Authorization": "Bearer <your-jwt>" }
    }
  }
}
⌨️ STDIO via WP-CLI (local / same machine)


wp mcp-adapter serve --server=wpmcp-modern --user=admin

Step 4 — Verify it works

🧪 Kick the tires with curl


# initialize → grab the Mcp-Session-Id response header, then send it back on every call
curl -i -u "admin:APP_PASSWORD" -X POST https://your-site.com/wp-json/wpmcp/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Protocol-Version: 2025-06-18" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize",
       "params":{"protocolVersion":"2025-06-18","capabilities":{},
                 "clientInfo":{"name":"curl","version":"0"}}}'

Or simply ask your connected AI: "What WordPress tools do you have?" — it should list the toolset below.


🔐 Authentication

Three interchangeable mechanisms, enforced by the server's transport-permission callback. Use whichever fits:

🔑 Application Passwords 🎫 JWT 🌐 OAuth 2.1 (experimental)
Setup None — built into WordPress Issue via REST route or admin UI Enable the toggle; clients self-register
Format HTTP Basic auth Authorization: Bearer <jwt> Bearer token (a plugin JWT under the hood)
Lifetime Until you delete it 1 hour by default, up to 30 days 1 day by default (filterable)
Revocation Delete from your profile Instant, per-token (jti) — independent of expiry Same as JWT — same registry
Best for Personal use, the proxy setup Short-lived agents, CI, shared automations Clients with built-in OAuth flows — no token pasting

Application Passwords (recommended start)

Standard WordPress HTTP Basic auth — zero extra setup. Create one under Users → Profile → Application Passwords.

JWT

Stateful, revocable HS256 tokens with a full management API:

Route Method Who Purpose
/wp-json/jwt-auth/v1/token POST anyone Issue a token (current user, or username/password; optional expires_in)
/wp-json/jwt-auth/v1/tokens GET admin List active tokens
/wp-json/jwt-auth/v1/revoke POST admin Revoke by jti

Tokens default to a 1-hour lifetime; you can request up to 30 days via expires_in (the ceiling is filterable through wpmcp_jwt_max_expiration_time). Configure the signing secret with a constant in wp-config.php (otherwise one is auto-generated and stored):

define( 'WPMCP_JWT_SECRET_KEY', 'a-long-random-string' );

[!NOTE] 🛡️ Tokens are stateful — every token is recorded server-side, so revocation works immediately and independently of expiry. (The legacy plugin documented WPMCP_JWT_SECRET_KEY but never read it; here it's honoured.)

You can also generate, list, and revoke tokens visually from Settings → WordPress MCP.

OAuth 2.1 (experimental, opt-in)

Turn on OAuth 2.1 authorization in Settings → WordPress MCP and OAuth-capable MCP clients can connect with zero token copy-pasting. The plugin implements the slice of the MCP authorization spec clients exercise:

  1. Discovery/.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource (RFC 8414/9728; no rewrite rules needed).
  2. Dynamic client registrationPOST /wp-json/wpmcp/v1/oauth/register (RFC 7591, public clients).
  3. Authorization code + PKCE (S256 only) — a WordPress consent screen asks the logged-in user to approve the client.
  4. Token exchangePOST /wp-json/wpmcp/v1/oauth/token returns a plugin JWT, so OAuth tokens are validated, listed, and revoked through the exact same machinery as manually issued ones.

[!NOTE] No refresh tokens yet — access tokens default to 1 day (wpmcp_oauth_token_expiration filter), after which the client re-runs the (one-click) consent flow.


🧰 What's exposed

82 tools (54 always-on + 28 WooCommerce when active), 5 resources, 2 prompts. Legacy tool names (wp_posts_search, wc_get_product, …) are preserved, so existing clients and prompts keep working.

🔧 Tools

Group Count Examples
📝 Posts 5 wp_posts_search, wp_get_post, wp_add_post, wp_update_post, wp_delete_post
📄 Pages 5 wp_pages_search, wp_add_page, wp_update_page, …
🏷️ Taxonomy 8 wp_list_categories, wp_add_category, wp_list_tags, wp_add_tag, …
👤 Users 7 wp_users_search, wp_add_user, wp_get_current_user, …
⚙️ Settings 2 wp_get_general_settings, wp_update_general_settings
🧩 Custom post types 6 wp_list_post_types, wp_cpt_search, wp_add_cpt, …
🖼️ Media 7 wp_list_media, wp_upload_media (base64 in), wp_get_media_file (URL · base64 · image/blob content blocks), …
💬 Comments 6 wp_comments_search, wp_add_comment (reply via parent), wp_moderate_comment, …
🔌 Plugins & themes 5 wp_list_plugins, wp_activate_plugin, wp_deactivate_plugin (never itself), wp_activate_theme, …
🧭 Core (reused) 3 get_site_info, get_user_info, get_environment_info
🛒 WooCommerce* 28 wc_products_search, wc_add_product, wc_list_product_brands, wc_add_order, wc_reports_sales, …
🧪 Generic (REST-CRUD mode) 3 list_api_functions, get_function_details, run_api_function

*WooCommerce tools register only when WooCommerce is active. The generic REST-CRUD tools appear only in REST-CRUD mode (see Security & gating).

Read the full README on GitHub →