Labsco
rnaga logo

WP-MCP

β˜… 9

from rnaga

Manage and publish WordPress content directly from your AI assistant β€” no PHP required. Supports both STDIO and Streamable HTTP for broad client compatibility.

πŸ”₯πŸ”₯πŸ”₯βœ“ VerifiedFreeAdvanced setup

wp-mcp

@rnaga/wp-mcp is a Model Context Protocol (MCP) server for WordPress that turns your site into an AI-operable surface. By exposing WordPress CRUD primitives to clients like Claude Desktop, an assistant can draft a post on demand, refine it collaboratively, and publish it straight into your databaseβ€”no trip through wp-admin required.

Here are a few common scenarios this unlocks:

  • Draft, revise, and publish posts directly from MCP clients such as Claude Desktop.
  • Inspect WordPress users, their roles, and capabilities to audit site permissions or generate access reports.

Built on top of @rnaga/wp-node, the server ships with a curated MCP toolset covering posts, users, comments, terms, revisions, metadata, options, and site settings. The MCP server can manage the following database tables/resources:

ResourceWhat you can do
PostsCreate, update, read, or delete posts and their revisions.
CommentsModerate discussion threads or inject generated replies.
UsersOnboard contributors, adjust roles, or disable accounts with native capability checks.
TermsManage categories, tags, and custom taxonomies.
MetadataInspect, create, update, or delete post, user, comment, term, and site meta fields.
Settings & OptionsToggle site-level configuration safely.

You can spin up a STDIO server for direct database access or host a Streamable HTTP MCP server for remote access. For convenience, layer on the CLI proxy whenever your MCP client needs a local bridge to the HTTP server. The proxy behaves like a local MCP server while relaying requests to the HTTP endpointβ€”perfect for clients that lack OAuth or WordPress Application Password supportβ€”so you can fit MCP workflows into existing editorial pipelines without re-implementing WordPress business logic.

The project includes a CLI (wp-mcp) that helps you:

  • configure and launch a local STDIO MCP server that connects straight to your WordPress database;
  • scaffold and initialize an Express-based Streamable HTTP MCP server (with env/TS boilerplate);
  • authenticate against a remote WordPress environment (OAuth or Application Password) and run a JSON-RPC proxy so MCP clients can reach it securely;
  • inspect available MCP primitives and manage the credentials stored under ~/.wp-mcp.

Run this command to list the available CLI commands:

npx @rnaga/wp-mcp -- --help
Usage: <command> <subcommand> [options]

Commands:
   local            Local MCP (stdio) server commands
   utils            Utility commands for configuration, debugging, and MCP inspection
   http             Scaffold a TypeScript project for the MCP streamable HTTP server and related tooling.
   remote           Remote MCP server commands

Together, the server, CLI utilities, and proxy tooling let you CRUD WordPress content, manage users, and sync settings through the MCP standard without re-implementing WordPress logic.

Streamable HTTP Server Internals

The Streamable HTTP deployment bundles Express middleware that bootstraps a WordPress context on each request, registers both the streaming HTTP and SSE transports, and layers in caching plus OAuth metadata handlers. The remote server operates as an OAuth 2.0 resource server β€” clients must supply either a bearer token or a WordPress Application Password, and the server never behaves as an OAuth client itself. Discovery metadata is served from /.well-known/oauth-protected-resource, keeping the implementation aligned with RFC 9728.

The CLI's device-code helper (npx @rnaga/wp-mcp -- remote login oauth) extends the MCP tooling with a terminal-friendly flow. It talks to the server's /auth/device/* endpoints, stores the resulting tokens in the secret vault (~/.wp-mcp), and enables the proxy to refresh and attach bearer credentials automatically.

Access Control

The HTTP layer applies authentication across /mcp and /sse so only authorized callers can negotiate sessions. It supports:

  • OAuth Bearer tokens – validated through the configured provider, with access tokens mapped to WordPress users before the MCP session initializes.
  • WordPress Application Passwords – accepted over HTTP Basic auth and verified before the WordPress user is assumed server-side.

Failed bearer requests receive RFC 6750-compliant WWW-Authenticate headers that include the authorization URI and requested scopes so clients can recover gracefully.

Endpoints

PathPurpose
/mcpStreamable HTTP MCP transport for client-to-server requests and session lifecycle management.
/sseLegacy SSE transport for clients that require server-sent events.
/messagesAllows SSE clients to post user messages back to the server.
/auth/device/startInitiates OAuth device authorization flow.
/auth/device/pollPolls for OAuth device flow completion and returns tokens.
/auth/refreshExchanges a refresh token for a new access token.
/auth/revokeRevokes an access token at the provider.
/auth/userinfoReturns the WordPress user associated with the supplied Authorization header.
/auth/passwordValidates a WordPress Application Password and returns the associated user.
/.well-known/oauth-protected-resourceServes OAuth resource metadata for discovery tooling.

Supported OAuth providers

The server ships with provider profiles for GitHub, Google, and Auth0. Each profile encapsulates device-code issuance, token polling, refresh, and revocation logic that can be wired in when you instantiate the HTTP server. To use a different identity system, supply your own provider implementation through the same hook and keep the rest of the deployment unchanged.

Setting up OAuth providers

To enable OAuth authentication, you need to register an application with your chosen provider and configure the credentials in your environment variables.

GitHub OAuth Setup
  1. Create an OAuth App: Navigate to GitHub Developer Settings > OAuth Apps > "New OAuth App"
  2. Configure your application:
    • Application Name: Your app's display name
    • Homepage URL: Your application's homepage
    • Authorization Callback URL: Your OAuth callback endpoint
  3. Get credentials: After creation, note your Client ID and generate a Client Secret
  4. Set environment variables:
    OAUTH_CLIENT_ID=your_github_client_id
    OAUTH_CLIENT_SECRET=your_github_client_secret
  5. Documentation: GitHub OAuth Apps Documentation
Google OAuth Setup
  1. Access Google Cloud Console: Go to Google Cloud Console
  2. Create OAuth credentials: Navigate to Menu > APIs & Services > Credentials > Create Credentials > OAuth client ID
  3. Configure OAuth consent screen: Set up app name, user support email, and audience settings
  4. Select application type: Choose the appropriate type (Web application, Desktop app, etc.)
  5. Get credentials: Note your Client ID and Client Secret
  6. Set environment variables:
    OAUTH_CLIENT_ID=your_google_client_id
    OAUTH_CLIENT_SECRET=your_google_client_secret
  7. Documentation: Setting up OAuth 2.0 in Google Cloud
Auth0 OAuth Setup
  1. Create application: Register a Native Application in your Auth0 Dashboard
  2. Configure grant types: In Application Settings > Advanced > Grant Types, enable:
    • Device Code (required for device flow)
    • Refresh Token (optional, for token refresh)
  3. Enable OIDC Conformant: In Application Settings > Advanced > OAuth, ensure OIDC Conformant is enabled
  4. Configure connections: Set up and enable at least one connection for the application
  5. Get credentials: Note your Client ID, Client Secret, and Domain
  6. Set environment variables:
    OAUTH_DOMAIN=your-tenant.us.auth0.com
    OAUTH_CLIENT_ID=your_auth0_client_id
    OAUTH_CLIENT_SECRET=your_auth0_client_secret
  7. Documentation: Auth0 Device Authorization Flow

Usage reference for environment variables

The HTTP server loads its configuration from environment variablesβ€”typically via a local .env file, inherited process environment, or settings provided by your hosting platform.

Environment variablePurposeExample valueWhen it is read
OAUTH_RESOURCE_URLPublic URL of the protected resourcehttps://mcp.example.comIncluded in OAuth resource metadata and DNS-rebinding protection checks.
OAUTH_RESOURCE_NAMEDisplay name for the protected resourceExample WordPress MCPReturned in discovery metadata.
OAUTH_SCOPES_SUPPORTEDComma-separated scopes supported by the resourceopenid,offline_access,posts.readAdvertised in discovery metadata and WWW-Authenticate headers.
OAUTH_SERVICE_DOCUMENTATION_URLDocumentation link for the resourcehttps://docs.example.com/mcpReturned in discovery metadata.
OAUTH_AUTHORIZATION_URLAuthorization server URLhttps://auth.example.comSent to clients in error headers and used by the CLI when initializing device flows.
OAUTH_CLIENT_IDOAuth client identifiermcp-remote-serverPassed to the provider when requesting device codes or refreshing tokens (provider dependent).
OAUTH_CLIENT_SECRETOAuth client secret (if required)super-secret-valueUsed for providers that expect confidential clients during token refresh.
ALLOWED_CORS_ORIGINSComma-separated HTTP origins allowed for CORShttps://claude.ai,https://inspector.modelcontext.comConfigures the HTTP server's CORS policy.
ENABLE_DNS_REBINDING_PROTECTIONEnable DNS rebinding protection for HTTP transporttrueEnables DNS rebinding protection for the streamable HTTP transport.
OAUTH_DOMAINOAuth domain (Auth0-specific)sample.us.auth0.comUsed when Auth0 Provider to construct device and token URLs.

If a variable is omitted, the server falls back to safe defaults (for example CORS defaults to *, DNS rebinding protection is disabled, and OAuth metadata is skipped). Set only the values your provider requires.

Developing Custom MCP Primitives

The Model Context Protocol defines three first-class primitives: tools (callable actions), resources (readable assets exposed by URI), and prompts (templated message sequences). defaultMcpPrimitives in this package currently ships tool implementations, but the same decorator + registration pattern lets you expose resources and prompts as well. The workflow below covers scaffolding, authoring a class, and wiring it into each transport.

1. Scaffold a project

Use the CLI to initialize the TypeScript scaffolding and install dependencies.

Local STDIO server

npx @rnaga/wp-mcp -- local init

The command implemented in src/cli/local.cli.ts installs @rnaga/wp-node and @rnaga/wp-mcp, places a starter src/index.ts, copies tsconfig.json, creates a .gitignore, and adds dev, build, and start scripts to package.json.

Resulting layout:

β”œβ”€β”€ package.json
β”œβ”€β”€ src
β”‚   └── index.ts
β”œβ”€β”€ tsconfig.json
└── package-lock.json

Streamable HTTP server

npx @rnaga/wp-mcp -- http init

This subcommand (see src/cli/http.cli.ts) runs the WordPress prompts, installs the same dependencies, copies the HTTP src/index.ts template, and appends the MCP-specific settings to .env or .env.<environment>. After the scaffold finishes you can run npm run dev to boot the Express transport.

2. Implement a primitive class

Create a file such as src/mcp/example-suite.mcp.ts and add a class decorated with @mcp and @mcpBind. Each @mcpBind method receives the MCP server instance plus runtime metadata so you can register tools, resources, or prompts in one place.

See the @modelcontextprotocol/typescript-sdk repository for end-to-end SDK usage and primitive registration examples.

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;
  }
}

Each handler receives the same tuple:

  • server – the McpServer instance from @modelcontextprotocol/sdk/server/mcp.js, which exposes registerTool, registerResource, and registerPrompt.
  • username – the WordPress identity attached to the session; pass it to Mcps.getWpContext to enforce capability checks when you touch WordPress APIs.
  • meta – the decorator metadata (name, title, description, capabilities, roles) that you can reuse when you register primitives.

Mcps.getWpContext yields the hydrated @rnaga/wp-node context. Use it inside tools, resources, or prompts to call CRUD helpers, gather site metadata, or enforce additional logic before returning MCP responses.

3. Register the class with the server entry point

Both transports expose an mcps array; append your class so the server wires it up when booting. All primitives registered inside the class methods (tools, resources, prompts) become available to connected MCP clients.

Local STDIO server

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],
  });

  // connect transport...
})();

Streamable HTTP server

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],
});

Start the server (npm run dev locally or npm start after building) and the registered tools, resources, and prompts appear to any MCP client connected through the local proxy or HTTP transport.

MCP Registry

This server is published to the Model Context Protocol Registry, making it easily discoverable and installable by MCP clients.

You can find the server at: https://registry.modelcontextprotocol.io/v0/servers?search=wp-mcp&version=latest

The registry entry includes configuration details, required environment variables, and installation instructions.