DEV Community

Cover image for MCP for WordPress: Write and Publish Posts from Your AI Assistant
rnaga
rnaga

Posted on

MCP for WordPress: Write and Publish Posts from Your AI Assistant

I recently introduced wp-node, which mirrors WordPress core data structures and CRUD operations.

Building on that idea, I’ve now developed wp-mcp — a Model Context Protocol (MCP) server for WordPress that exposes your site’s content and settings as AI-accessible primitives. With it, tools like Claude Desktop can draft, edit, and publish posts straight into your database without touching wp-admin — and no PHP or traditional LAMP stack required, just pure MCP and TypeScript.

Imagine telling Claude Desktop:

“Draft a post called Exploring Headless WordPress and publish it when done.”

wp-mcp makes that possible — all through the MCP standard.

example prompt to publish a post

You can check out the full documentation and setup instructions in the project’s README.md

If you find it useful, don’t forget to ⭐️ star the repo!


What is wp-mcp?

@rnaga/wp-mcp turns your WordPress into an AI-operable surface.

It extends the TypeScript foundation of @rnaga/wp-node and ships with a rich set of MCP tools that map directly to your WordPress database — including posts, users, comments, terms, metadata, options, and settings.

Through the MCP standard, any compatible AI client (like Claude Desktop) can perform WordPress CRUD actions — safely and capability-aware — without you writing custom endpoints or plugins.

Key capabilities

  • Draft, revise, and publish posts directly from an MCP client
  • Moderate comments or auto-generate replies using AI
  • Inspect and manage users with proper role and capability checks
  • Work with taxonomies like categories, tags, and custom terms
  • Read or update site options and network-level settings

Why wp-mcp?

  • 🧩 TypeScript-first — no PHP or traditional LAMP stack required
  • Local + Remote MCP server support (STDIO and Streamable HTTP)
  • 🔐 Built-in Remote Proxy for clients that only support STDIO
  • 🧠 Capability-aware — tools filter by actual WordPress roles
  • 🛠️ Extensible — easily build custom primitives (tools, resources, prompts)

Getting Started

All setup goes through the wp-mcp CLI.

You can check available commands with:

npx @rnaga/wp-mcp -- --help
Enter fullscreen mode Exit fullscreen mode

A) Local STDIO Server

Use this when you can connect directly to the WordPress database.

  1. Configure database connection
npx @rnaga/wp-mcp -- local config-set
Enter fullscreen mode Exit fullscreen mode

You’ll be prompted for host, port, database, username, and password.

  1. Set up your MCP client (for example, Claude Desktop):
{
  "mcpServers": {
    "wp-mcp": {
      "command": "npx",
      "args": ["-y", "@rnaga/wp-mcp", "--", "local", "start"],
      "env": {
        "LOCAL_USERNAME": "wp-admin"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Replace wp-admin with your WordPress username.

Restart Claude Desktop, and you’ll see WordPress tools appear under the MCP panel.

  1. Inspect available primitives
npx @rnaga/wp-mcp -- utils list-prims
Enter fullscreen mode Exit fullscreen mode

This shows which MCP tools your WordPress role can use (create posts, manage users, etc.).


B) Streamable Remote HTTP Server

Use this when you need to share access or host your MCP server remotely.

  1. Scaffold the project
npx @rnaga/wp-mcp -- http init
Enter fullscreen mode Exit fullscreen mode

This generates an Express-based TypeScript project with all boilerplate in place.

  1. Run in development
npm run dev
Enter fullscreen mode Exit fullscreen mode
  1. Build and start in production
npm run build
npm run start
Enter fullscreen mode Exit fullscreen mode

The HTTP transport supports streaming MCP and SSE fallback, with built-in OAuth and Application Password authentication.


Remote Proxy Mode

If your MCP client doesn’t fully support OAuth authentication or Streamable HTTP, you can use the proxy. It acts as a local STDIO server while securely forwarding requests to the remote HTTP endpoint.

This is especially helpful for clients like Claude Desktop, where HTTP connections are available only in the paid tier or OAuth support is limited.

Diagram Remote Proxy

1) Authenticate

WordPress Application Password:

npx @rnaga/wp-mcp -- remote login password
Enter fullscreen mode Exit fullscreen mode

OAuth Device Flow:

npx @rnaga/wp-mcp -- remote login oauth
Enter fullscreen mode Exit fullscreen mode

Credentials are stored securely in ~/.wp-mcp.

You can inspect them later with:

npx @rnaga/wp-mcp -- remote config
Enter fullscreen mode Exit fullscreen mode

2) Start the Proxy

In your Claude Desktop config:

{
  "mcpServers": {
    "wp-mcp": {
      "command": "npx",
      "args": ["-y", "@rnaga/wp-mcp", "--", "remote", "proxy"],
      "env": {
        "REMOTE_AUTH_TYPE": "oauth",
        "REMOTE_URL": "https://wp-mcp.example.com/mcp"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now your MCP client connects locally, and the proxy securely forwards every request to the remote server.


Building Custom MCP Primitives

You can extend wp-mcp with your own MCP primitives — tools, resources, or prompts — using decorators.

1) Scaffold your project

Local (STDIO)

npx @rnaga/wp-mcp -- local init
Enter fullscreen mode Exit fullscreen mode

Remote (HTTP)

npx @rnaga/wp-mcp -- http init
Enter fullscreen mode Exit fullscreen mode

2) Add a primitive class

Create src/example-suite.mcp.ts:

import { z } from "zod";
import { mcp, mcpBind } from "@rnaga/wp-mcp/decorators";
import { Mcps } from "@rnaga/wp-mcp/mcp";
import type * as types from "@rnaga/wp-mcp/types";

@mcp("example_suite", {
  description: "Example bundle showing tools, resources, and prompts.",
})
export class ExampleSuiteMcp {
  @mcpBind("example_tool", {
    title: "List Options",
    description: "Return the WordPress options table as JSON.",
    capabilities: ["read"],
  })
  example(...args: types.McpBindParameters) {
    const [server, username, meta] = args;

    server.registerTool(
      meta.name,
      {
        title: meta.title,
        description: meta.description,
        inputSchema: undefined,
      },
      async () => {
        const wp = await Mcps.getWpContext(username);
        const options = await wp.utils.crud.options.getAll();

        return {
          content: [
            { type: "text", text: JSON.stringify(options, null, 2) },
          ],
        };
      }
    );

    return server;
  }
}
Enter fullscreen mode Exit fullscreen mode

3) Register it in your entry point

Local STDIO:

import { createLocalServer } from "@rnaga/wp-mcp/cli/local";
import { ExampleSuiteMcp } from "./example-suite.mcp";

(async () => {
  const mcpServer = await createLocalServer({
    username: process.env.LOCAL_USERNAME,
    mcps: [ExampleSuiteMcp],
  });
})();
Enter fullscreen mode Exit fullscreen mode

Remote HTTP:

import { MemoryCache } from "@rnaga/wp-mcp/http/cache/memory-cache";
import { createHttpServer } from "@rnaga/wp-mcp/http/express";
import { ExampleSuiteMcp } from "./example-suite.mcp";

const app = createHttpServer({
  cacheClass: MemoryCache,
  mcps: [ExampleSuiteMcp],
});
Enter fullscreen mode Exit fullscreen mode

Restart your server, and your custom tools appear instantly in your MCP client.


In Summary

wp-mcp bridges WordPress and AI clients through the Model Context Protocol, letting you manage, create, and publish WordPress content without touching PHP or wp-admin.

✅ Works with Local STDIO and Remote Streamable HTTP servers

✅ Includes a Remote Proxy for STDIO-only clients

Extensible through custom primitives

Built on TypeScript — no PHP, no LAMP stack


Quick Start Recap

# Configure local STDIO server
npx @rnaga/wp-mcp -- local config-set

# Start locally
npx @rnaga/wp-mcp -- local start

# Scaffold remote HTTP server
npx @rnaga/wp-mcp -- http init

# Authenticate for remote proxy
npx @rnaga/wp-mcp -- remote login oauth
npx @rnaga/wp-mcp -- remote proxy
Enter fullscreen mode Exit fullscreen mode

With wp-mcp, WordPress becomes a seamless extension of your AI assistant — ready to draft, edit, and publish at your command.

Top comments (0)