ItchWPMCP
# ItchWPMCP
Local MCP server for Codex/Claude to query and edit WordPress content through the WordPress REST API.
It can be used with any WordPress site that has the REST API enabled and supports Application Password authentication.
## Setup
1. Create a WordPress application password:
`WordPress Admin -> Users -> Profile -> Application Passwords`
2. Copy `.env.example` to `.env` and fill in:
```env
WP_BASE_URL=https://your-wordpress-site.example
WP_USERNAME=your-wordpress-username
WP_APP_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx
WP_ALLOW_PRODUCTION_WRITES=false
```
3. Install dependencies:
```sh
npm install
```
4. Run the server:
```sh
npm start
```
If Node cannot verify your site's certificate chain, set `NODE_OPTIONS=--use-system-ca` in your MCP client environment.
## Tools
### Pages
- `wordpress_list_pages`: list WordPress pages.
- `wordpress_get_page`: get a page by ID.
- `wordpress_create_page`: create a page, defaulting to draft status.
- `wordpress_clone_page`: clone an existing page into a new draft page.
- `wordpress_update_page`: update title, content, excerpt, slug, status, parent, or menu order.
- `wordpress_update_page_status`: update only a page status.
- `wordpress_delete_page`: trash or delete a page with confirmation.
### Posts
- `wordpress_list_posts`: list WordPress posts.
- `wordpress_get_post`: get a post by ID.
- `wordpress_create_post`: create a post, defaulting to draft status.
- `wordpress_update_post`: update a post.
- `wordpress_delete_post`: trash or delete a post with confirmation.
### Media
- `wordpress_list_media`: list media library items.
- `wordpress_upload_media`: upload a local file to the media library.
### Taxonomies
- `wordpress_list_categories`: list post categories.
- `wordpress_create_category`: create a post category.
- `wordpress_list_tags`: list post tags.
- `wordpress_create_tag`: create a post tag.
### Site & Users
- `wordpress_get_settings`: read general site settings.
- `wordpress_update_settings`: update selected general site settings.
- `wordpress_list_users`: list users if the authenticated user has permission.
- `wordpress_list_plugins`: list plugins if the authenticated user has permission.
- `wordpress_update_plugin_status`: activate or deactivate an installed plugin.
### Classic Navigation & Menus
- `wordpress_list_menus`: list classic WordPress menus.
- `wordpress_list_menu_items`: list menu items for a classic menu.
### Sidebars & Widgets
- `wordpress_list_sidebars`: list all registered widget areas (header, footer, sidebar, etc.).
- `wordpress_get_sidebar`: get a specific widget area and its widget IDs.
- `wordpress_list_widgets`: list widget instances with rendered HTML previews.
- `wordpress_create_widget`: create a widget instance in a sidebar.
- `wordpress_update_widget`: update widget instance settings.
- `wordpress_delete_widget`: delete a widget instance with confirmation.
### Post & Page Meta
- `wordpress_get_post_meta`: read registered REST meta fields for a page or post.
- `wordpress_update_post_meta`: update registered REST meta fields for a page or post.
### Elementor Page Builder
- `elementor_get_page_structure`: read a page's Elementor layout as a readable tree (sections → columns → widgets).
- `elementor_create_page`: create a page pre-configured for Elementor editing.
- `elementor_append_sections`: append one or more Elementor sections to the end of a page.
- `elementor_replace_section`: replace an Elementor section at a specific index.
- `elementor_delete_section`: remove an Elementor section at a specific index with confirmation.
- `elementor_update_widget_settings`: find a widget by ID and merge new settings into it.
- `elementor_list_templates`: list templates saved in the Elementor template library.
- `elementor_get_template`: get an Elementor template's content and structure.
- `elementor_apply_template`: apply a template to a page, replacing its current content.
- `elementor_save_as_template`: save a page's Elementor data as a new reusable template.
- `elementor_widget_reference`: return schema and example JSON for any Elementor widget type.
### Elementor Meta
- `wordpress_get_elementor_meta`: read Elementor-related meta and template fields for a page or post.
- `wordpress_update_elementor_meta`: update `_elementor_data`, `_elementor_edit_mode`, `_elementor_template_type`, `_elementor_version`, `_elementor_page_settings`, and `_wp_page_template`.
- `wordpress_update_elementor_data`: update only `_elementor_data` for a page or post.
- `wordpress_list_elementor_routes`: list Elementor REST API routes on the configured site.
- `wordpress_elementor_rest_request`: advanced REST API escape hatch limited to Elementor namespaces.
### FSE Templates _(WordPress 7.0)_
Full Site Editing templates control the overall layout of page types (single post, archive, 404, etc.).
- `wordpress_list_templates`: list FSE block templates on the site.
- `wordpress_get_template`: get a template by composite ID (e.g. `twentytwentyfour//single`) including its block markup.
- `wordpress_create_template`: create a new custom FSE block template.
- `wordpress_update_template`: update a template's content or title.
- `wordpress_delete_template`: delete a custom FSE template with confirmation.
### FSE Template Parts _(WordPress 7.0)_
Template parts are reusable layout regions such as headers and footers.
- `wordpress_list_template_parts`: list FSE template parts, optionally filtered by area (header, footer, sidebar).
- `wordpress_get_template_part`: get a template part including its block markup.
- `wordpress_update_template_part`: update a template part's content, title, or area.
### Synced Patterns / Reusable Blocks _(WordPress 7.0)_
Synced patterns (formerly reusable blocks) are shared block markup used across multiple pages.
- `wordpress_list_reusable_blocks`: list synced patterns on the site.
- `wordpress_get_reusable_block`: get a synced pattern by ID including its block markup.
- `wordpress_create_reusable_block`: create a new synced pattern.
- `wordpress_update_reusable_block`: update a synced pattern's content or title.
- `wordpress_delete_reusable_block`: delete a synced pattern with confirmation.
### Block Pattern Directory _(WordPress 7.0)_
- `wordpress_list_block_patterns`: list block patterns registered on the site, with optional category and search filtering.
- `wordpress_list_block_pattern_categories`: list all registered block pattern categories.
### Icons _(WordPress 7.0)_
WordPress 7.0 introduced a server-side SVG Icon Registry and a native Icon block.
- `wordpress_list_icons`: list registered SVG icons, with optional search and category filtering.
### Font Library _(WordPress 7.0)_
The Font Library was extended to all theme types in WordPress 7.0.
- `wordpress_list_font_families`: list font families installed in the Font Library.
- `wordpress_list_font_faces`: list font face variations (weight, style, src) for a specific font family.
### Global Styles _(WordPress 7.0)_
Global styles are the theme.json overrides managed through the Site Editor.
- `wordpress_get_global_styles`: get the active theme's global styles (colors, typography, spacing). Pass a stylesheet slug to target a specific theme.
- `wordpress_update_global_styles`: update the active theme's global styles by ID.
### Block Navigation Menus _(WordPress 7.0)_
Block navigation menus are FSE navigation posts, distinct from classic WordPress menus.
- `wordpress_list_navigation_menus`: list block-based navigation menus.
- `wordpress_create_navigation`: create a new block-based navigation menu.
### WP AI Connectors & Abilities _(WordPress 7.0)_
WordPress 7.0 introduced a Connectors API for sharing external service credentials across plugins, and an Abilities API for registering AI tasks.
- `wordpress_list_connectors`: list registered external service connectors (AI providers, etc.).
- `wordpress_list_ai_abilities`: list registered AI abilities available on this site.
### Advanced / Escape Hatches
- `wordpress_rest_request`: raw WordPress REST API access for any `/wp-json/` path.
- `external_api_fetch`: server-side HTTPS proxy for external APIs (CoinGecko, Oracle, etc.).
---
Write tools are enabled on staging URLs. If `WP_BASE_URL` is changed to production, writes are blocked unless `WP_ALLOW_PRODUCTION_WRITES=true` is set in `.env`.
## Elementor Meta Tools
Use `wordpress_update_elementor_meta` when you need to save Elementor layout data through WordPress REST. Pass `elementorData` as either a JSON string or a JSON object/array; the tool stores it as `_elementor_data`.
Example:
```json
{
"id": 123,
"postType": "page",
"elementorEditMode": "builder",
"elementorTemplateType": "wp-page",
"elementorVersion": "3.30.0",
"wpPageTemplate": "elementor_canvas",
"elementorData": []
}
```
The available Elementor REST endpoints depend on the target WordPress site and installed Elementor plugins. Use `wordpress_list_elementor_routes` to inspect what the configured site exposes, then use `wordpress_elementor_rest_request` for site-specific Elementor endpoints.
If a meta key does not update through `wordpress_update_post_meta`, the target WordPress site has not registered that key for REST writes. In that case, add a small WordPress helper plugin or mu-plugin to register the specific meta keys with `show_in_rest`.
## Use Another WordPress Site
Create an Application Password in that WordPress site's admin, then update `.env`:
```env
WP_BASE_URL=https://another-wordpress-site.example
WP_USERNAME=your-wordpress-username
WP_APP_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx
WP_ALLOW_PRODUCTION_WRITES=false
```
Keep `WP_ALLOW_PRODUCTION_WRITES=false` until you intentionally want write tools enabled on a production URL.
## Port It For Another Person
1. Copy this `ItchWPMCP` folder to their machine or publish it as a private/public repo.
2. Run `npm install` inside the folder.
3. Create a `.env` file from `.env.example`.
4. In their WordPress admin, create an Application Password:
`Users -> Profile -> Application Passwords`
5. Put their site URL, username, and app password in `.env`.
6. Register the MCP server in their MCP client.
Do not commit `.env` files. Application Passwords should stay local to each user/site.
## Codex Config
Add this to `~/.codex/config.toml`:
```toml
[mcp_servers.itch_wp_mcp]
command = "node"
args = ["<absolute-path-to-ItchWPMCP>/src/server.js"]
enabled = true
startup_timeout_sec = 20
tool_timeout_sec = 60
[mcp_servers.itch_wp_mcp.env]
WP_BASE_URL = "https://your-wordpress-site.example"
WP_USERNAME = "your-wordpress-username"
WP_APP_PASSWORD = "xxxx xxxx xxxx xxxx xxxx xxxx"
WP_ALLOW_PRODUCTION_WRITES = "false"
NODE_OPTIONS = "--use-system-ca"
```
If your MCP client cannot find `node`, set `command` to the absolute path of your Node executable. For example:
```toml
command = "<absolute-path-to-node>"
```
## Claude Desktop Config
Add this to Claude Desktop's `claude_desktop_config.json` under `mcpServers`:
```json
{
"mcpServers": {
"itch_wp_mcp": {
"command": "node",
"args": [
"<absolute-path-to-ItchWPMCP>/src/server.js"
],
"env": {
"WP_BASE_URL": "https://your-wordpress-site.example",
"WP_USERNAME": "your-wordpress-username",
"WP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx",
"WP_ALLOW_PRODUCTION_WRITES": "false",
"NODE_OPTIONS": "--use-system-ca"
}
}
}
}
```
Restart Claude Desktop after changing the config.
## Multi-Site Setup
You do not need a separate copy of ItchWPMCP for every WordPress website. Keep one codebase and register multiple MCP servers, each with different environment variables.
### Codex Multi-Site Example
```toml
[mcp_servers.wp_site_staging]
command = "node"
args = ["<absolute-path-to-ItchWPMCP>/src/server.js"]
enabled = true
startup_timeout_sec = 20
tool_timeout_sec = 60
[mcp_servers.wp_site_staging.env]
WP_BASE_URL = "https://staging.example.com"
WP_USERNAME = "site-admin"
WP_APP_PASSWORD = "xxxx xxxx xxxx xxxx xxxx xxxx"
WP_ALLOW_PRODUCTION_WRITES = "false"
NODE_OPTIONS = "--use-system-ca"
[mcp_servers.wp_client_site]
command = "node"
args = ["<absolute-path-to-ItchWPMCP>/src/server.js"]
enabled = true
startup_timeout_sec = 20
tool_timeout_sec = 60
[mcp_servers.wp_client_site.env]
WP_BASE_URL = "https://client-site.example"
WP_USERNAME = "client-admin"
WP_APP_PASSWORD = "xxxx xxxx xxxx xxxx xxxx xxxx"
WP_ALLOW_PRODUCTION_WRITES = "false"
NODE_OPTIONS = "--use-system-ca"
```
### Claude Multi-Site Example
```json
{
"mcpServers": {
"wp_site_staging": {
"command": "node",
"args": ["<absolute-path-to-ItchWPMCP>/src/server.js"],
"env": {
"WP_BASE_URL": "https://staging.example.com",
"WP_USERNAME": "site-admin",
"WP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx",
"WP_ALLOW_PRODUCTION_WRITES": "false",
"NODE_OPTIONS": "--use-system-ca"
}
},
"wp_client_site": {
"command": "node",
"args": ["<absolute-path-to-ItchWPMCP>/src/server.js"],
"env": {
"WP_BASE_URL": "https://client-site.example",
"WP_USERNAME": "client-admin",
"WP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx",
"WP_ALLOW_PRODUCTION_WRITES": "false",
"NODE_OPTIONS": "--use-system-ca"
}
}
}
}
```
The `.env` file is now only a local fallback. Per-site MCP environment variables take precedence when provided by Codex or Claude.
## Safety Model
- New pages/posts default to `draft`.
- Destructive tools require `confirmDelete=true`.
- Non-staging writes are blocked unless `WP_ALLOW_PRODUCTION_WRITES=true`.
- `wordpress_rest_request` only allows paths under `/wp-json/`.
TDQS
Scored across 26 tools
Each tool targets a distinct WordPress resource and action. There is minimal overlap; even the similar update_page and update_page_status are clearly differentiated by scope.
All tools follow a consistent wordpress_verb_noun pattern (e.g., wordpress_create_page, wordpress_list_posts). No mixing of conventions or ambiguous verbs.
26 tools cover a broad domain including posts, pages, media, menus, plugins, settings, and users. While slightly heavy, each tool serves a clear purpose and the count is justified for comprehensive WordPress management.
CRUD for posts and pages is well-covered, but categories and tags lack delete/update, menus only support listing, and there is no user management beyond listing. These are notable gaps for a complete site administration surface.