BeTheme MCP Server
BeTheme MCP Server
A secure, agent-friendly MCP server that turns one or more BeTheme-powered WordPress sites into a backend-equivalent environment for an AI agent.
┌──────────────────────────────────────────────────────────────┐
│ BeTheme MCP Server │
│ Agent-driven WordPress + BeTheme administration │
│ Pages • Templates • Plugins • WooCommerce • BeBuilder │
└──────────────────────────────────────────────────────────────┘What this project does
This project lets an AI agent manage BeTheme-powered WordPress sites without logging into wp-admin. It exposes MCP tools for:
creating, editing, publishing, and deleting pages
reading and writing BeBuilder payloads (
mfn-page-items)creating and updating BeTheme templates (headers, footers, archives, popups, etc.)
listing, activating, deactivating, and installing plugins
returning site context and capabilities so the agent knows what it can do
The design is built for agencies: one local MCP server can connect to many client sites, each with its own URL and API key.
Architecture — what runs where
The project has two parts. Almost all business logic lives in the WordPress plugin. The local Node process is only a thin protocol adapter between the MCP client and the REST bridge.
flowchart LR
A[MCP client e.g. Claude Desktop] -->|stdio| B[Local Node MCP server]
B -->|HTTPS + HMAC signed| C[WordPress REST API]
C --> D[BeTheme MCP Bridge plugin]
D --> E[WordPress + BeTheme]Part 1 — WordPress bridge plugin (plugin/betheme-mcp-bridge.php)
This runs on the web server inside WordPress. It:
registers REST routes under
/wp-json/betheme-mcp/v1/authenticates every request with an API key + HMAC-SHA256 request signature
enforces WordPress capability checks (
edit_pages,edit_theme_options,activate_plugins, etc.)sanitizes input, allow-lists BeTheme meta keys, and stores builder payloads in BeTheme's native format
audits every action through the
betheme_mcp_audithookapplies per-key rate limiting
Part 2 — Local MCP server (src/server.js)
This is a small Node.js process that runs on the machine where the AI agent runs. It:
speaks the MCP protocol over stdin/stdout
validates tool arguments against the declared JSON schema
routes each tool call to the correct WordPress bridge endpoint
supports multiple sites through a
siteargument or per-site configuration
Why does the MCP server run locally?
MCP clients today (Claude Desktop, etc.) usually launch an MCP server as a local child process over stdio. That local process can then talk to remote APIs. We keep the local part as thin as possible: it has no WordPress business logic, no database access, and no plugin installation logic. If your MCP client supports SSE, you can also host the Node server on your own infrastructure and point the client at it.
Installation — single site
1. WordPress requirements
WordPress 6.4+ with the BeTheme theme active
PHP 8.2+
HTTPS recommended in production
2. Install the bridge plugin
Copy
plugin/betheme-mcp-bridge.phpinto your WordPress site'swp-content/plugins/directory.In wp-admin, go to Plugins and activate BeTheme MCP Bridge.
Open
wp-config.phpand add a secure API key:define('BETHEME_MCP_API_KEY', 'replace-with-a-long-random-key');Optional but recommended policy flags:
define('BETHEME_MCP_AUDIT_LOG', true); define('BETHEME_MCP_ALLOW_PLUGIN_INSTALL', false);Verify the bridge is reachable:
curl -H "X-API-Key: replace-with-a-long-random-key" \ https://your-site.test/wp-json/betheme-mcp/v1/healthYou should get
{"ok":true,"site":"..."}.
3. Install and run the local MCP server
Clone this repository on the machine where your AI agent runs:
git clone <repo-url> betheme-mcp cd betheme-mcp npm installCreate the environment file:
cp .env.example .envEdit
.env:BETHEME_MCP_API_KEY=replace-with-a-long-random-key BETHEME_MCP_BASE_URL=https://your-site.test BETHEME_MCP_TIMEOUT_MS=10000Start the server:
npm startVerify with the demo harness:
npm run demo
4. Connect your MCP client
Pick the client you use and add the server configuration. In every case the local Node process is the same; only the client's config file or settings change.
Claude Desktop
Edit claude_desktop_config.json:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"betheme": {
"command": "node",
"args": ["/absolute/path/to/betheme-mcp/src/server.js"]
}
}
}ChatGPT Desktop
OpenAI's ChatGPT Desktop does not currently support local MCP servers. If support is added, the configuration file is expected to use the same mcpServers format as Claude Desktop. Use the same JSON structure and check OpenAI's documentation for the exact file location.
Copilot via VS Code
VS Code's Copilot Chat can use MCP servers configured in your user settings. Open Settings (JSON) (Cmd/Ctrl + Shift + P → Preferences: Open User Settings (JSON)) and add:
{
"chat.mcp.servers": {
"betheme": {
"command": "node",
"args": ["/absolute/path/to/betheme-mcp/src/server.js"]
}
}
}The exact setting name may vary across VS Code versions (chat.mcp.servers, chat.mcp.serverDefinitions, or github.copilot.chat.mcpServers). If one setting is not recognized, try the next or check the latest VS Code MCP documentation.
GitHub Copilot Desktop
There is currently no standalone "GitHub Copilot Desktop" application that exposes local MCP server configuration. Use Copilot via VS Code above, or use Copilot in any editor that supports MCP server settings.
After saving the configuration, restart the client. The agent can now call tools such as list_pages, create_page, save_page_builder_payload, and list_plugins.
Installation — multi-site (agency setup)
Agencies can manage many client sites from one local MCP server. There are two ways to configure multiple sites.
Option A: sites.json file (recommended)
Copy the example file:
cp sites.json.example sites.jsonEdit
sites.json:[ { "name": "client-a", "baseUrl": "https://client-a.test", "apiKey": "key-for-client-a", "timeoutMs": 10000 }, { "name": "client-b", "baseUrl": "https://client-b.test", "apiKey": "key-for-client-b", "timeoutMs": 10000 } ]Restart
npm start.
Option B: environment variable
In .env, set a single JSON array:
BETHEME_MCP_SITES=[{"name":"client-a","baseUrl":"https://client-a.test","apiKey":"key-for-client-a"},{"name":"client-b","baseUrl":"https://client-b.test","apiKey":"key-for-client-b"}]BETHEME_MCP_SITES overrides sites.json. The single-site variables are ignored when multi-site configuration is present.
Using multiple sites in conversation
The agent can list configured sites with list_sites. For any other tool, pass the site argument:
list_pages→ lists pages from the first/default sitelist_pageswith{"site":"client-a"}→ lists pages from client-acreate_pagewith{"title":"Home","site":"client-b"}→ creates a page on client-b
If site is omitted, the first site in the configuration is used.
Multiple sites from the agent's point of view
You can tell the agent:
"List the sites you can access, then create a homepage on
client-aand a contact page onclient-b."
The agent will call list_sites, pick the correct aliases, and route each action to the right WordPress installation.
How authentication works
Every request from the local MCP server to WordPress is authenticated in two ways:
API key — sent in the
X-API-Keyheader and compared againstBETHEME_MCP_API_KEYin wp-config.php.HMAC request signature — the local server signs the request with
HMAC-SHA256(method|timestamp|body)and sends it inX-Request-Signature. The bridge rejects requests outside a 5-minute replay window or with an invalid signature.
Keep the API key secret. Use HTTPS in production so the key and signatures are protected in transit.
Capability model
The bridge checks WordPress capabilities on every route:
Operation | Capability required |
Read pages |
|
Create pages |
|
Update pages |
|
Delete pages |
|
Templates |
|
List/activate/deactivate plugins |
|
Install plugins |
|
The authenticate tool returns the bridge-level capabilities the current context supports.
Security model
Authentication: API key + HMAC-SHA256 request signing with timestamp replay window.
Authorization: per-route WordPress capability checks.
Input validation: JSON Schema validation on the MCP side; sanitization and allow-lists on the PHP side.
Meta allow-listing: only known BeTheme page/template meta keys are accepted.
Payload hardening: builder payloads are stored in BeTheme's native format and capped at 1 MB.
Rate limiting: per-API-key token bucket using WordPress transients.
Audit logging: every administrative action is logged via
betheme_mcp_auditand optionally to the PHP error log.
Development and testing
Run the local test and lint suite:
npm test
npm run lint
php -l plugin/betheme-mcp-bridge.phpAll three should pass before any release.
Documentation
docs/README.md — documentation index
docs/sdd/02-architecture.md — system architecture
docs/sdd/07-mcp-capability-surface.md — MCP tools, resources, and prompts
docs/sdd/06-security-and-owasp.md — security posture
Release and versioning
Releases are published through GitHub Actions when a v* tag is pushed. Version numbers align with the BeTheme version they target, plus an alpha suffix. The current alpha is 28.5.4-alpha.003.
Alpha release notice
This project is currently an alpha release and is still under quality assurance. It is intended for evaluation, integration testing, and controlled internal use, not for production deployment until QA is complete.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/zacdreyer/wp-betheme-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server