WordPress MCP Server
46 tools one MCP Server. Access content, media, comments, CPTs and site management. See Github repo for all tools.
Documentation
@urdigital/mcp-server-wordpress
An MCP (Model Context Protocol) server exposing the WordPress REST API to Claude, Claude Code, and any other MCP-compatible client — content, media, comments, custom post types, and site management.
Install
No install needed — run directly with npx:
npx -y @urdigital/mcp-server-wordpress
Configure
Create an Application Password under wp-admin → Users → Profile → Application Passwords. This is Basic Auth over HTTPS, separate from your real account password.
Add to your MCP client config (e.g. Claude Desktop's claude_desktop_config.json):
{
"mcpServers": {
"wordpress": {
"command": "npx",
"args": ["-y", "@urdigital/mcp-server-wordpress"],
"env": {
"WORDPRESS_SITE_URL": "https://example.com",
"WORDPRESS_USERNAME": "your-username",
"WORDPRESS_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
}
}
}
}
WORDPRESS_SITE_URL should have no trailing slash.
Tools (46 total, all tested against a real headless WordPress site)
| Group | Tools |
|---|---|
| Posts | wp_list_posts, wp_get_post, wp_create_post, wp_update_post, wp_delete_post |
| Pages | wp_list_pages, wp_get_page, wp_create_page, wp_update_page, wp_delete_page |
| Categories | wp_list_categories, wp_get_category, wp_create_category, wp_update_category, wp_delete_category |
| Tags | wp_list_tags, wp_get_tag, wp_create_tag, wp_update_tag, wp_delete_tag |
| Media | wp_upload_media, wp_list_media, wp_get_media, wp_update_media, wp_delete_media |
| Comments | wp_list_comments, wp_get_comment, wp_create_comment, wp_update_comment, wp_delete_comment |
| Users | wp_list_users, wp_get_user |
| Discovery | wp_list_post_types, wp_list_taxonomies |
| Menus | wp_list_menus, wp_list_menu_items |
| Settings | wp_get_settings, wp_update_settings |
| Plugins/themes | wp_list_plugins, wp_list_themes (read-only — see below) |
| Custom post types (generic) | wp_list_custom_items, wp_get_custom_item, wp_create_custom_item, wp_update_custom_item, wp_delete_custom_item |
| Search | wp_search |
Posts and pages default new content to draft status so nothing publishes
unintentionally.
Deliberately not included: plugin/theme install, activate, deactivate, delete
Plugin and theme management is limited to read-only listing
(wp_list_plugins, wp_list_themes). Installing, activating, deactivating,
or deleting plugins/themes are the highest-risk write actions available on
a WordPress site — a bad activation can take a site down entirely — and
are a meaningfully different risk category than content operations. If you
need this, it's a deliberate scope decision, not an oversight.
Working with custom post types
wp_list_custom_items/wp_get_custom_item/etc. work with any post
type a plugin has registered — you're not limited to the types this server
knows about by name. Two things confirmed by testing against a real site
using Custom Post Type UI + ACF:
- Use
wp_list_post_typesfirst to find the correctrest_base, not the post type's internal slug — they're often different. On the test site, a type with slugeventhadrest_base: "events"(pluralized), andlead_magnethadrest_base: "lead-magnets"(pluralized and hyphenated instead of underscored). Calling the endpoint with the slug instead of the rest_base returns arest_no_route404 — confirmed by testing, not a hypothetical. - Field support (title, content, status, custom fields) varies by how the
plugin registered the type.
status: draftas a safe create-default worked correctly against a real custom type in testing, since most custom post types are still stored inwp_postslike standard posts — but this isn't guaranteed universal across every plugin.
Other behavior confirmed by testing, worth knowing
- Categories, tags, and media have no trash state in WordPress.
Deleting any of these is effectively always permanent — unlike posts,
pages, and comments, which default to a reversible trash. The
forceparameter on delete tools for categories/tags/media defaults totruefor this reason; posts/pages/comments default tofalse. - WordPress blocks comments on draft posts. Attempting
wp_create_commentagainst a draft-status post returns a 403 (rest_comment_draft_post) — the post needs to be published (or at least not in draft) first. Confirmed directly. - Comments created by an authenticated admin skip moderation and come
back with
status: "approved"immediately, rather than theholdstatus a real anonymous visitor's comment would likely get. If you're testing a moderation workflow, testing as admin can hide behavior that only shows up for genuine visitor-submitted comments. - The
wp_searchendpoint returns a much lighter object thanwp_get_post/wp_get_page— justid,title,url,type,subtype, no content or metadata. Follow up withwp_get_post/wp_get_page/wp_get_custom_itemfor full content. wp_get_user'srolesfield can come backundefinedeven for an admin account, depending on site/plugin configuration around theedit_userscapability — not necessarily a bug if you see this.- Media URLs may not live on your WordPress domain at all. Sites using
an offload plugin (e.g. to Cloudflare Images, S3, etc.) will return
source_urlpointing elsewhere entirely — confirmed on the test site, which offloads toimagedelivery.net.
License
MIT