Session errors
The WordPress MCP Adapter uses MCP’s session-based HTTP transport. Every request after initialize must include the Mcp-Session-Id header from the initialize response. Most MCP clients handle this; some don’t.
Symptom: every request after the first fails
Section titled “Symptom: every request after the first fails”Likely cause: client isn’t preserving the session ID. Test with curl:
# 1. Initialize, capture the response with -i (show headers)curl -i -X POST https://your-site.test/wp-json/mcp/emcp-tools-server \ -H "Content-Type: application/json" \ -u "admin:xxxx xxxx xxxx xxxx xxxx xxxx" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'Look for the Mcp-Session-Id header in the response. Copy that value.
# 2. List tools, include the session headercurl -X POST https://your-site.test/wp-json/mcp/emcp-tools-server \ -H "Content-Type: application/json" \ -H "Mcp-Session-Id: <paste-the-id-here>" \ -u "admin:xxxx xxxx xxxx xxxx xxxx xxxx" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'If step 2 returns a tools list, the server is fine. Your client is the problem.
Workaround: use the bundled Node proxy
Section titled “Workaround: use the bundled Node proxy”The plugin ships a Node.js stdio↔HTTP proxy that handles session lifecycle, auth, and JSON-RPC framing for clients that only speak stdio. The proxy runs as a local subprocess on the machine running your MCP client. For a remote WordPress site it does not, and cannot, run from the copy inside wp-content/plugins/... on the server. The simplest way to run it is the zero-install npx runner:
{ "mcpServers": { "emcp-tools": { "command": "npx", "args": ["-y", "@msrbuilds/emcp-proxy@latest"], "env": { "WP_URL": "https://your-site.com", "WP_USERNAME": "admin", "WP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx", "MCP_PROTOCOL_VERSION": "2024-11-05" } } }}Prefer a local file copy instead of npx? Extract bin/mcp-proxy.mjs from the plugin ZIP, save it locally, and set "command": "node", "args": ["C:\\local\\path\\to\\mcp-proxy.mjs"]. See the Claude Desktop guide for both options and the MCP_PROTOCOL_VERSION note. Node 18+ required.
Symptom: WP-CLI bridge says “Command ‘mcp-adapter’ not found”
Section titled “Symptom: WP-CLI bridge says “Command ‘mcp-adapter’ not found””The wp mcp-adapter subcommand is registered by the WordPress MCP Adapter plugin’s WP-CLI integration. It only exists when:
- The MCP Adapter plugin is active
- WP-CLI’s plugin discovery has loaded that plugin
Test:
wp plugin list --path=/path/to/wordpress | grep mcpIf the MCP Adapter doesn’t show as active, activate it. If it does but wp mcp-adapter list still fails, check that the CLI command file is being loaded. Sometimes a hook ordering issue stops it from registering. Force-load test:
wp eval 'do_action( "cli_init" );' --path=/path/to/wordpresswp mcp-adapter list --path=/path/to/wordpressSymptom: stdio bridge hangs
Section titled “Symptom: stdio bridge hangs”The wp mcp-adapter serve process should print JSON-RPC responses to stdout and stay running, waiting for more input on stdin. If it exits immediately, check for stderr output:
wp mcp-adapter serve --server=emcp-tools-server --user=admin --path=/path/to/wordpress 2>&1Common errors that look like a hang but are actually instant crashes:
Server 'emcp-tools-server' not found: the MCP server registration failed (plugin issue, see No tools appearing)User 'admin' not found: pass a valid WP username with--user--path is invalid: must be the absolute path to the WordPress directory containingwp-config.php
Symptom: 500 Internal Server Error
Section titled “Symptom: 500 Internal Server Error”PHP error during a tool call. Check wp-content/debug.log after enabling WP_DEBUG and WP_DEBUG_LOG:
define( 'WP_DEBUG', true );define( 'WP_DEBUG_LOG', true );define( 'WP_DEBUG_DISPLAY', false );The log will show the stack trace. Most common culprits:
- A widget type that doesn’t exist (
add-free-widgetwith a typo inwidget_type) - Invalid settings shape:
get-widget-schemafirst to see the expected structure - Elementor isn’t loaded (rare; means a plugin conflict broke its bootstrap)
Open a GitHub issue with the full stack trace if it’s not obvious.