wp-mcp-router
v0.3.3
Published
One MCP connection for a fleet of WordPress sites. Federates several mcp-adapter (Abilities API) sites behind a single MCP server with per-site capability discovery, cross-site search, fan-out, and a site-mismatch guard.
Maintainers
Readme
wp-mcp-router
One MCP connection for all your WordPress sites.
wp-mcp-router is an MCP (stdio) server that fronts any number of WordPress sites running the
Abilities API
via the mcp-adapter plugin. Instead of one MCP
server per site, you connect your AI client (Claude Desktop / Claude Code / Cursor / Codex)
once and address each site by name. The router discovers what each site can actually do,
lets you search abilities across all of them, and guards execution — calling an ability on a
site that doesn't have it returns "not on B; available on A and C" instead of an opaque error.
Quick start
npx wp-mcp-router setupThe wizard connects your first site (opens your browser; you approve, WordPress mints a scoped application password, you paste it back once) and wires the server into your AI client (auto-detects Claude Desktop / Claude Code / Cursor / Codex). Restart your client and you're connected.
Prefer the steps individually?
npx wp-mcp-router add-site example.com # connect a site (repeat per site)
npx wp-mcp-router install # add to your AI client's configAdd more sites any time with add-site — they all live behind the one connection.
npx wp-mcp-router --doctor checks connectivity and lists abilities per site.
Each target site needs the mcp-adapter plugin
active (it registers the /wp-json/mcp/… endpoint the router talks to).
Tools
| Tool | Purpose |
| --- | --- |
| wp_list_sites | Sites + tags + ability counts + namespace groups. |
| wp_search_abilities | Keyword search across sites; results grouped by site. |
| wp_get_ability | Input/output schema for one ability on one site. |
| wp_run | Execute an ability on one site (guarded). |
| wp_run_across | Execute the same ability on many sites in parallel. |
| wp_get_content_by_url | Resolve a URL/path → post, optionally with full content. |
Every site-targeting tool takes a site argument; omit it to use the configured defaultSite.
Configuration
The site registry carries credentials, so it is never committed. Resolved at runtime, in priority order:
WP_MCP_ROUTER_SITES— the whole registry as inline JSON in one env var.WP_MCP_ROUTER_CONFIG— path to a JSON file../sites.jsonnext to the package (gitignored).~/.config/wp-mcp-router/sites.json(Windows:%APPDATA%\wp-mcp-router\sites.json).
See sites.example.json. Each site needs a url, a username, and a
WordPress Application Password
(appPassword):
{
"defaultSite": "main",
"sites": [
{ "id": "main", "url": "https://example.com", "username": "agent", "appPassword": "xxxx xxxx …", "tags": ["ecommerce"] }
]
}Useful per-site / global options:
endpoint— override the MCP endpoint (default<url>/wp-json/mcp/mcp-adapter-default-server).customHeaders— extra headers merged into every request (Cloudflare Access service tokens, WAF allow-list headers, etc.).requestTimeoutMs(default 120000) /initTimeoutMs(default 25000) — call and handshake timeouts; also settable viaWP_MCP_ROUTER_TIMEOUT_MS/WP_MCP_ROUTER_INIT_TIMEOUT_MS.
Security
Auth is per-site WordPress Application Passwords (Basic auth over HTTPS) — scoped, revocable,
never your real login; rotate by deleting and re-minting the app password. Credentials live
only in the gitignored registry or env vars, never in the repo or the npm package. Every
routed call is written to a local audit log (~/.local/state/wp-mcp-router/audit.jsonl,
Windows: %LOCALAPPDATA%\wp-mcp-router\audit.jsonl; args redacted, owner-only permissions;
WP_MCP_ROUTER_AUDIT=off disables it, WP_MCP_ROUTER_AUDIT_FILE relocates it).
Recommendation: connect each site as a dedicated limited-role user — enough to edit content, not enough to execute code or manage users — so a leaked credential has a small blast radius.
License
GPL-2.0-or-later.
