claude-wp-mcp
<p align="center">
<img src="assets/banner.png" alt="claude-wp-mcp — MCP server for WordPress" width="100%">
</p>
# claude-wp-mcp
**MCP server for WordPress** — lets Claude (or any [Model Context Protocol](https://modelcontextprotocol.io) client) read and manage a WordPress site over the built-in WP REST API. No plugin required on the WordPress side.
[](LICENSE)
[](package.json)
Works with **Claude Code**, **Claude Desktop**, and any other MCP-compatible client (Cursor, Cline, Windsurf, etc.).
## Features
- **Posts** — list, get, create, update, delete
- **Pages** — list, get, create, update, delete
- **Taxonomies** — list categories, list tags
- **Media** — list media library items, upload images/files (from a URL or a local path, one or many in a batch)
- **Users** — list users
- **`wp_request` escape hatch** — call any other `/wp-json/...` route (any REST namespace, any method) for things not covered by a dedicated tool
- **`fetch_url`** — fetch any web page (not limited to the configured WordPress site), get back Markdown plus title/description, e.g. to turn another page's content into a WordPress post/page. Respects `robots.txt` and paginates long pages. Sites behind a Cloudflare bot challenge can't be solved by a plain HTTP fetch — `fetch_url` detects that case and errors with guidance to fetch the page via a real browser (e.g. Claude in Chrome) instead
- Works read-only out of the box against any public WordPress site; write operations use a WordPress Application Password (no custom plugin needed)
## Requirements
- Node.js 18+
- A reachable WordPress site with the REST API enabled (default on any WordPress install)
- For write operations: a WordPress user with an [Application Password](https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/)
## Installation
```bash
git clone https://github.com/gs4lthung/claude-wp-mcp.git
cd claude-wp-mcp
npm install
```
## Configuration
The server is configured entirely through environment variables:
| Variable | Required | Description |
|---|---|---|
| `WP_BASE_URL` | Yes | Base URL of the WordPress site, e.g. `http://localhost:10004` |
| `WP_USERNAME` | For writes | WordPress username |
| `WP_APP_PASSWORD` | For writes | WordPress [Application Password](https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/) (not your login password) |
Generate an application password in **wp-admin → Users → Profile → Application Passwords**.
## Usage
### Claude Code
```bash
claude mcp add claude-wp-mcp -s user \
-e WP_BASE_URL=http://localhost:10004 \
-e WP_USERNAME=<user> \
-e WP_APP_PASSWORD=<app-password> \
-- node /path/to/claude-wp-mcp/src/index.js
```
Omit `WP_USERNAME` / `WP_APP_PASSWORD` to run read-only. Verify it's connected with `claude mcp list`.
### Claude Desktop
Add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"claude-wp-mcp": {
"command": "node",
"args": ["/path/to/claude-wp-mcp/src/index.js"],
"env": {
"WP_BASE_URL": "http://localhost:10004",
"WP_USERNAME": "<user>",
"WP_APP_PASSWORD": "<app-password>"
}
}
}
}
```
### Any other MCP client
Point it at `node src/index.js` (stdio transport) with the environment variables above.
## Tools reference
| Tool | Auth required | Description |
|---|---|---|
| `wp_site_info` | No | Site name, URL, active REST namespaces — good connection sanity check |
| `wp_list_posts` | No | List posts (search, status, pagination) |
| `wp_get_post` | No | Get a single post by ID |
| `wp_create_post` | Yes | Create a post |
| `wp_update_post` | Yes | Update a post |
| `wp_delete_post` | Yes | Delete a post |
| `wp_list_pages` | No | List pages (search, pagination) |
| `wp_get_page` | No | Get a single page by ID |
| `wp_create_page` | Yes | Create a page |
| `wp_update_page` | Yes | Update a page |
| `wp_delete_page` | Yes | Delete a page |
| `wp_list_categories` | No | List categories |
| `wp_list_tags` | No | List tags |
| `wp_list_media` | No | List media library items |
| `wp_upload_media` | Yes | Upload one or more files (images etc.) from a URL or local path to the media library |
| `wp_list_users` | No (limited fields without auth) | List users |
| `wp_request` | Depends on route | Call any other WP REST API route directly |
| `fetch_url` | No | Fetch any web page and return its title, description, and content as Markdown (respects robots.txt, paginated; errors with guidance instead of a raw 403 if the page is behind a Cloudflare bot challenge) |
## Security notes
- Use an **Application Password**, never your real WordPress login password.
- Application Passwords can be scoped to a single site and revoked independently from **wp-admin → Users → Profile**.
- This server talks directly to the REST API you configure — don't point it at a production site with a write-capable password unless you mean to.
## License
[MIT](LICENSE)
TDQS
Scored across 17 tools
Each tool maps clearly to a distinct WordPress resource and action: full CRUD for posts and pages, read-only lists for categories/tags/media/users, plus site info, URL fetching, and an explicit REST escape hatch. The list/get/create/update/delete variants are not ambiguous because the target resource is always named.
The wp_ prefix and list/get/create/update/delete verb_noun pattern are highly consistent for the main post and page tools. Minor deviations like wp_site_info, fetch_url, and wp_request break the pattern slightly, but they are still readable and predictable overall.
At 17 tools, the server is slightly above the ideal 3-15 range, but the count is justified by parallel CRUD surfaces for posts and pages plus supporting resource lookups. No tool feels redundant, though the set is a bit heavy for casual use.
Posts and pages have complete CRUD/lifecycle coverage, and categories/tags/media/users provide the read-side needed for content authoring. There are minor gaps around dedicated create/update/delete tools for taxonomies, media, and users, plus comments/settings, but the wp_request escape hatch covers any remaining WP REST API route.