Skip to main content
Glama

wp-mcp-server

An MCP (Model Context Protocol) server that lets an AI design agent connect to any WordPress site, inspect its real rendered CSS/JS/theme, and create/update pages. It is a standalone, reusable server — nothing in it is tied to a specific WordPress install; the target site is configured entirely through environment variables at runtime.

It combines two things:

  • WordPress's native REST API (wp/v2/pages), authenticated with Application Passwords.

  • A small companion plugin, wp-mcp-theme-bridge (bundled in this repo under wordpress-plugin/wp-mcp-theme-bridge/), that exposes two extra read-only routes (wp-mcp-bridge/v1/theme-styles and wp-mcp-bridge/v1/asset-content) so the agent can see exactly which CSS/JS a page actually renders — theme-agnostic, since it parses the real rendered HTML instead of relying on theme.json (many themes, including Astra, resolve colors at PHP runtime, not in static files).

Prerequisites

  • Node.js >= 18 (for global fetch)

  • A WordPress site with:

    • Application Passwords enabled (WordPress core, no plugin needed for the page tools)

    • The wp-mcp-theme-bridge plugin installed and activated, if you want get_theme_styles / get_asset_content to work (see below)

Related MCP server: wp-mcp

Installing the WordPress-side plugin

get_theme_styles and get_asset_content need wp-mcp-theme-bridge running on the target WordPress site — it's a regular plugin (not a must-use/mu-plugins one), so it needs manual activation like any other plugin:

  1. Copy wordpress-plugin/wp-mcp-theme-bridge/ from this repo into that site's wp-content/plugins/ directory (git, SFTP, your host's file manager — whatever you already use to deploy). The folder must keep its name (wp-mcp-theme-bridge/) with wp-mcp-theme-bridge.php directly inside it.

  2. In wp-admin → Plugins, find WP MCP Theme Bridge and activate it.

  3. Verify it: curl -H "Authorization: Basic <base64 user:app-password>" "https://your-site.com/wp-json/wp-mcp-bridge/v1/theme-styles?path=/" should return JSON, not a 404.

The four page tools (list_pages, get_page, create_page, update_page) work without this plugin — it's only required for the two theme-inspection tools.

Install & build

cd mcp-server
npm install
npm run build

This compiles src/ to dist/. npm start runs the built server (dist/index.js) directly over stdio — this is what an MCP client will actually spawn.

Generating a WordPress Application Password

  1. Log into wp-admin as a user with the edit_pages capability (e.g. an Editor or Administrator).

  2. Go to Users → Profile.

  3. Scroll to Application Passwords, give it a name (e.g. wp-mcp-server), and click Add New Application Password.

  4. Copy the generated password immediately — WordPress only shows it once. It's fine to keep the spaces WordPress displays it with; Basic Auth works either way.

Configuration (environment variables)

Variable

Description

WORDPRESS_URL

Base URL of the WordPress site, no trailing slash (e.g. http://localhost:8080)

WORDPRESS_USERNAME

WordPress username to authenticate as

WORDPRESS_APP_PASSWORD

The Application Password generated above

Copy .env.example to .env and fill it in for local development (.env is git-ignored and is not read automatically by the built server — it's there for your own tooling/reference; pass the variables through your process environment or your MCP client's env config, as shown below).

The server validates these three variables at startup and exits with a clear error message if any is missing.

Registering with an MCP client

From a local checkout (development)

{
  "mcpServers": {
    "wordpress": {
      "command": "node",
      "args": ["/absolute/path/to/wp-mcp-server/dist/index.js"],
      "env": {
        "WORDPRESS_URL": "http://localhost:8080",
        "WORDPRESS_USERNAME": "your-wp-username",
        "WORDPRESS_APP_PASSWORD": "your-application-password"
      }
    }
  }
}

Point args at the built dist/index.js for the WordPress site you want this instance of the server to manage. To manage a different site, register another entry with different env values — the server itself is stateless and reusable.

Straight from GitHub (no local checkout, no npm registry)

This package isn't published to the npm registry. Any MCP client that can run a command can still add it directly from the git repository — npx clones it, installs dependencies, runs prepare (which builds dist/), then runs the bin entry, all in one shot:

{
  "mcpServers": {
    "wordpress": {
      "command": "npx",
      "args": ["-y", "github:eimon/wp-mcp"],
      "env": {
        "WORDPRESS_URL": "https://your-site.example.com",
        "WORDPRESS_USERNAME": "your-wp-username",
        "WORDPRESS_APP_PASSWORD": "your-application-password"
      }
    }
  }
}

With the Claude Code CLI specifically:

claude mcp add wordpress-<site-name> \
  -e WORDPRESS_URL=https://your-site.example.com \
  -e WORDPRESS_USERNAME=your-wp-username \
  -e WORDPRESS_APP_PASSWORD='xxxx xxxx xxxx xxxx xxxx xxxx' \
  -- npx -y github:eimon/wp-mcp

Pin to a tag or commit (github:eimon/wp-mcp#v0.1.0) once you cut a release, so a client's config doesn't silently pick up unreleased changes from the default branch.

Available tools

Tool

Description

list_pages

List/search WordPress pages (search, page, per_page, status)

get_page

Fetch a single page by ID

create_page

Create a new page (title, content HTML, status, optional meta)

update_page

Update an existing page by ID (same fields as create, all optional)

get_theme_styles

Inspect a page path's real rendered theme name, stylesheets, scripts, inline CSS/JS

get_asset_content

Fetch the raw text content of a same-origin CSS/JS asset URL

Verifying it works: the smoke test

There's no human clicking through this — scripts/smoke-test.ts is the verification. It spawns the built server as a child process using the official MCP SDK's Client + StdioClientTransport, calls tools/list, then exercises get_theme_styles and list_pages against a real WordPress instance:

npm run build
WORDPRESS_URL=http://localhost:8080 \
WORDPRESS_USERNAME=your-wp-username \
WORDPRESS_APP_PASSWORD=your-application-password \
npm run smoke-test

It exits non-zero and prints the failure if any tool errors or an expected shape isn't found.

Troubleshooting

Silent rest_not_logged_in / 401 errors despite correct credentials

On a non-HTTPS WordPress site, Application Passwords are silently disabled unless wp_get_environment_type() returns 'local' — WordPress core requires is_ssl() || wp_get_environment_type() === 'local' before it will accept them (wp_is_application_passwords_supported()). If you point this server at your own local (non-HTTPS) WordPress install and get 401 rest_not_logged_in even though the username and Application Password are correct, this is almost certainly the cause.

Fix it by setting the environment type to local, e.g. in wp-config.php:

define( 'WP_ENVIRONMENT_TYPE', 'local' );

(or the equivalent WORDPRESS_CONFIG_EXTRA env var if you're running the official wordpress Docker image.)

get_theme_styles / get_asset_content return 404

These two tools depend on the wp-mcp-theme-bridge plugin (bundled in this repo under wordpress-plugin/) being installed and activated on the target site — see "Installing the WordPress-side plugin" above. If it isn't, only the four page tools (list_pages, get_page, create_page, update_page) will work.

403 / capability errors

Both bridge routes and the page-write routes require the authenticated user to have the edit_pages capability (Editor role or above). Application Passwords authenticate as that WordPress user, so permissions follow normal WordPress role rules.

Available Tools

6 tools
create_pageCreate a WordPress pageA

Create a new page via POST /wp-json/wp/v2/pages. content is an HTML string. Requires edit_pages capability on the authenticated user.

Inputs: title (required), content (required), meta, status.

get_asset_contentGet the raw content of a theme CSS/JS assetA

Fetch the raw text content of a CSS or JS asset URL discovered via get_theme_styles. The URL must belong to the same host as the connected WordPress site (enforced server-side as a basic SSRF guard). Calls the site-local wp-mcp-bridge/v1 REST route.

Inputs: url (required).

get_pageGet a WordPress pageA

Fetch a single page by ID via GET /wp-json/wp/v2/pages/?context=edit. Returns both content.rendered (compiled HTML/output) and content.raw (the actual stored source — e.g. real Fusion Builder shortcodes on an Avada site, or Gutenberg block markup) — use content.raw to learn a site's real authoring syntax before writing new content.

Inputs: id (required).

get_theme_stylesGet a page's real rendered theme stylesA

Inspect the actual rendered HTML of a page path on the connected WordPress site and return its theme name plus the stylesheet URLs, script URLs, inline CSS and inline JS it really loads. Theme-agnostic: works by parsing the rendered HTML rather than relying on theme.json, so it reflects what a browser truly receives (colors resolved by PHP at runtime, page-builder output, etc). Calls the site-local wp-mcp-bridge/v1 REST route.

Inputs: path.

list_pagesList WordPress pagesA

List/search pages on the connected WordPress site via GET /wp-json/wp/v2/pages. Supports search, pagination and status filtering.

Inputs: page, search, status, per_page.

update_pageUpdate a WordPress pageA

Update an existing page via POST /wp-json/wp/v2/pages/. Only the fields provided are sent; omit a field to leave it unchanged.

Inputs: id (required), meta, title, status, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 6 tools

    Disambiguation5/5

    Each tool targets a distinct resource and action: list/get/create/update for pages, and get_theme_styles/get_asset_content for inspecting page-rendered assets. There is no overlap or ambiguity between any of the six tools.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern: list_pages, get_page, create_page, update_page, get_theme_styles, get_asset_content. Naming conventions are uniform and predictable.

    Tool Count5/5

    Six tools is a well-scoped size for this server's purpose, covering page operations and theme asset inspection without redundancy. Each tool earns its place and the set is not too thin or bloated.

    Completeness3/5

    The page CRUD covers list, get, create, and update, but notably omits delete_page, which is a significant gap in lifecycle management. The theme style and asset tools cover their niche well, but the missing delete operation prevents full page lifecycle management.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Connects WordPress sites to AI agents, enabling content management through natural language commands via the WordPress REST API.
      20 npm
      2
      MIT