WordPress MCP Server
by AhmadTheTech
README.md
# WordPress MCP Server
Production-oriented Model Context Protocol server for AI agents that need to manage WordPress websites through the official WordPress REST API and REST-exposed plugin resources.
## What It Provides
- MCP tools with typed input schemas for posts, pages, custom post types, media, terms, users, settings, Elementor data, menus, widgets, and guarded raw REST calls.
- MCP resources for site overview, REST route discovery, settings, content items, and Elementor layouts.
- Conservative policy gates for publishing, destructive actions, settings writes, user management, and raw REST mutations.
- WordPress authentication through Application Passwords, bearer/JWT tokens, basic auth, or no auth for read-only public testing.
- Stdio transport for local AI agents and optional Streamable HTTP transport for remote/deployed clients.
## Setup
```bash
npm install
cp .env.example .env
npm run build
```
Configure `.env`:
```ini
WP_SITE_URL=https://example.com
WP_AUTH_METHOD=application_password
WP_USERNAME=editor@example.com
WP_APPLICATION_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx
```
Use a WordPress user with the narrowest role that can perform the tasks you want the agent to perform. For production, use HTTPS and WordPress Application Passwords or a hardened OAuth/JWT plugin.
## Connect From an MCP Client
Stdio is the default transport:
```json
{
"mcpServers": {
"wordpress": {
"command": "node",
"args": ["C:/Users/Ahmed/Desktop/wp-mcp/dist/index.js"],
"env": {
"WP_SITE_URL": "https://example.com",
"WP_AUTH_METHOD": "application_password",
"WP_USERNAME": "editor@example.com",
"WP_APPLICATION_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
}
}
}
}
```
For HTTP:
```bash
MCP_TRANSPORT=http MCP_HTTP_BEARER_TOKEN=replace-me npm run start:http
```
Then connect the client to:
```text
http://localhost:3333/mcp
```
Include `Authorization: Bearer replace-me` when `MCP_HTTP_BEARER_TOKEN` is set.
## Safety Policy
The server starts with write operations available but sensitive changes blocked unless explicitly enabled:
| Environment flag | Allows |
| --- | --- |
| `WP_ALLOW_PUBLISH=true` | Publishing/private/future statuses and content-changing admin resources |
| `WP_ALLOW_DESTRUCTIVE=true` | Permanent deletes and destructive operations |
| `WP_ALLOW_SETTINGS_WRITE=true` | `/wp/v2/settings` updates |
| `WP_ALLOW_USER_MANAGEMENT=true` | Creating, updating, and deleting users |
| `WP_ALLOW_RAW_REST=true` | Non-GET calls through `wp_rest_request` |
| `WP_REQUIRE_CONFIRMATION=true` | Requires confirmation tokens for gated actions |
Confirmation tokens:
- `CONFIRM_PUBLISH`
- `CONFIRM_DESTRUCTIVE`
- `CONFIRM_SETTINGS_WRITE`
- `CONFIRM_USER_MANAGEMENT`
- `CONFIRM_RAW_REST`
This lets an AI agent inspect freely while requiring deliberate approval for high-impact actions.
## Core Tools
- `wp_discover`: Inspect REST routes, current user, post types, taxonomies, and policy.
- `wp_get_settings`, `wp_update_settings`: Read and update core site settings.
- `wp_list_content`, `wp_get_content`, `wp_create_content`, `wp_update_content`, `wp_delete_content`: Manage posts, pages, attachments, templates, and REST-exposed custom post types.
- `wp_upload_media`: Upload local files to the media library.
- `wp_manage_terms`: Manage categories, tags, and custom taxonomies.
- `wp_manage_users`: Manage users when policy and WordPress permissions allow it.
- `wp_get_elementor_data`, `wp_update_elementor_data`: Read/replace Elementor layout metadata.
- `wp_manage_navigation`: Manage REST-exposed menus, locations, and menu items.
- `wp_manage_widgets`: Manage REST-exposed widgets, sidebars, and widget types.
- `wp_rest_request`: Guarded escape hatch for plugin endpoints discovered by `wp_discover`.
## Elementor Notes
Elementor stores layout data as JSON in WordPress post metadata. This server reads Elementor data from the REST response `meta` object and updates `_elementor_data`, `_elementor_edit_mode`, and optional template metadata. Your site must expose the relevant meta keys to the REST API or provide a custom secure endpoint. If your site blocks private Elementor meta through core REST responses, use `wp_rest_request` against a custom endpoint with a proper WordPress `permission_callback`.
## Custom Post Types and Plugin Resources
Custom post types and taxonomies must be registered with REST support in WordPress. Discover the REST base with `wp_discover`, then pass that base as `type` or `taxonomy`.
For plugin-specific resources, prefer purpose-built tools. Use `wp_rest_request` only when a route has been discovered and the action is understood.
## Development
```bash
npm run dev
npm run dev:http
npm run typecheck
npm run build
```
## Production Hardening Checklist
- Use HTTPS for WordPress and remote MCP HTTP.
- Use a least-privilege WordPress account.
- Keep destructive and admin flags disabled unless needed.
- Keep `MCP_HTTP_BEARER_TOKEN` set for HTTP mode and rotate it regularly.
- Put HTTP mode behind trusted infrastructure with TLS, request logging, and rate limiting.
- Review tool calls before allowing publish, settings, user, raw REST, or destructive confirmations.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessSyncing