Coming soon! The Kael'Nyrin Scrolls: The Atlas Edict

MCP integration success with WordPress and AI robot

Captain Walker

Success: Claude Desktop Connected to WordPress via MCP

AI, Claude, collaboration, connection, desktop, MCP, software, success, wordpress

Estimated reading time at 200 wpm: 15 minutes

Introduction

This document is a complete, honest account of a technical project to connect the Claude Desktop application to a self-hosted WordPress site using the Model Context Protocol (MCP). It records what was attempted, what failed, what was discovered, and what finally worked. It is written for anyone — technical or otherwise — who wants to understand the journey, and as a reference for anyone attempting the same integration.

Whether or not you agree our Fat Disclaimer applies

Why this was worth doing

Captain Walker is a working writer. He maintains captainswatch.org as a space for personal and philosophical reflection, and runs a separate professional blog at investigativepsychiatry.com covering forensic psychiatry, law, and governance. Alongside that, he is a practising consultant forensic psychiatrist, an expert witness, and the author of published science fiction. Writing is not peripheral to his work — it is how he thinks, and how he communicates.

Claude has been a regular collaborator in that writing process. The limitation, until this project, was mechanical. Every exchange between Claude and the WordPress site required manual intervention: copy from here, paste there, check, adjust, repeat. For someone whose time is divided across Health Services, Prisons, legal work, and creative projects, that friction accumulates.

The MCP integration was an attempt to remove it. The goal was not to automate the writing — Captain Walker’s voice and judgement remain central to everything published — but to allow Claude to interact with the site directly, so that Walker’s energy is focused on sculpting words. But the work of a writer and blogger is not just about individual posts or pages. This site has grown over the years to a massive collection. Walker can now mine the whole site – and extract new ideas and patterns. The ‘work’ can become quite granular: particular words, categories and tags, across the whole site can be changed in a flash without need to use plugins (and the need in some cases to pay for them).

Many of those ideas and more, justified the time invested. The setup was not trivial. It took two separate AI collaborations, multiple diagnostic sessions, and a methodical process of elimination before the connection worked. But it is a one-time investment. Once in place, it serves every future session and other websites, that will be similarly developed.


Part 1: The Gemini Chapter

The project did not begin with Claude. An earlier attempt was made using Google’s Gemini AI as the technical collaborator.

Gemini produced a summary document of the work undertaken. That document described the steps taken to configure the MCP connection and identified a “connection failed” error as the outstanding problem. However, the Gemini session ran into a fundamental and persistent obstacle: Gemini consistently confused the WordPress display name “The Captain” with the login username “Captain Walker”. These are two different things. The display name is how a user appears publicly on the site. The login username is the credential used to sign in.

Gemini was unable to get past this confusion. Because the username drives authentication, and because Gemini was working with the wrong value, no meaningful progress could be made on the authentication problem. The work was suspended and the Gemini thread was abandoned.

The Gemini summary document was preserved and later used as background context when the project resumed with Claude. Importantly, the document carried an explicit caveat: “Do not assume that all in this document is accurate.” That caveat proved prescient.


Part 2: Resuming with Claude

The project resumed in a single session with Claude Sonnet 4.6. The approach was methodical: read all available logs, form hypotheses, test each one, and proceed only on confirmed evidence.

The 5 rules agreed at the outset:

  1. If in doubt, ask questions
  2. If unknown, say so
  3. No confabulation or hallucination
  4. Binary questions get binary answers
  5. No assumption of technical expertise on the part of the user

These rules mattered. They kept the session honest and prevented the kind of confident misdirection that had derailed the Gemini work.


Part 3: Reading the Logs

Seven log files were provided. The key files were mcp.log and mcp-server-wordpress.log from Claude Desktop app.

What the logs revealed

Early attempts (09:11 and 09:12): The MCP server was failing immediately with spawn npx ENOENT. This means the system could not find the npx command at all. Node.js was installed, but Claude Desktop could not locate it because its PATH environment did not include the Node.js directory.

This had already been resolved in a previous session by changing the claude_desktop_config.json to use the full absolute path to npx.cmd via cmd.exe.

Where is claude_desktop_config.json ? In the Claude desktop app go: Setttings > Developer > click Edit config. A folder will pop open and the file is easily found. It can be edited with VSCode or Notepad++

The fix was:

"command": "C:\\Program Files\\nodejs\\npx.cmd"

Later attempts (09:16 onwards): Once the path fix was in place, npx ran successfully. The proxy software downloaded and started. However, every attempt then returned:

"instructions": "MCP WordPress Remote Proxy Server (Connection Failed)"
"message": "Cannot process tools/list: WordPress connection failed during initialisation"

The proxy was running locally without error. Something was preventing it from connecting to the WordPress site.


Part 4: Diagnostic Work

Step 1 — Confirming the WordPress endpoint exists

The URL that the proxy connects to is:

https://www.captainswatch.org/wp-json/mcp/mcp-adapter-default-server

A browser test (unauthenticated) returned:

{"code":"rest_forbidden","message":"Sorry, you are not allowed to do that.","data":{"status":401}}

This was a good sign. The endpoint existed and was responding in the expected format. A 401 from an unauthenticated browser request is normal.

Step 2 — Checking the config file

The claude_desktop_config.json was inspected. It was clean: valid JSON, correct URL, no Markdown formatting accidentally embedded in the URL (which the Gemini summary had suggested might be present). The username was "The Captain" — correctly matching the actual WordPress login username.

Step 3 — Testing authenticated access

A PowerShell command was used to replicate exactly what the proxy does: send a request to the MCP endpoint with Basic Authentication credentials (username and application password).

Result: 403 Forbidden, with the response body:

You are not authorized to perform this action.

This was significant. A 401 means “I do not know who you are.” A 403 means “I know who you are, but you cannot do this.” The distinction told us that authentication was being processed in some way — but something else was blocking access.

Note also that the response was HTML (a WordPress wp_die() page), not JSON. Standard REST API errors return JSON. The HTML response suggested the request was being intercepted before it reached the normal REST API handler.

Step 4 — Testing a standard REST API endpoint

To confirm whether authentication was working at all, the same credentials were tested against a completely separate endpoint:

https://www.captainswatch.org/wp-json/wp/v2/users/me

This endpoint returns the authenticated user’s profile. With valid credentials it should return 200.

Result: 403 Forbidden.

This was the key diagnostic finding. An Administrator with a valid application password should never receive a 403 on that endpoint. Something was blocking all authenticated REST API requests.

Step 5 — Identifying the server software

WordPress Site Health confirmed the web server was LiteSpeed, running on Linux with PHP 8.2.30 via the LiteSpeed SAPI. LiteSpeed, like Apache, can strip the Authorisation header before it reaches PHP, which would prevent application passwords from authenticating.

However, the .htaccess file also revealed something more immediate.

Step 6 — The AIOWPS discovery

The .htaccess file showed rules from the All In One WP Security (AIOWPS) plugin at the very top. The full AIOWPS settings were extracted and examined. One setting stood out immediately:

"aiowps_disallow_unauthorized_rest_requests": "1"

This was enabled. AIOWPS was configured to block REST API access for requests it considered unauthorised. Because the application password credentials were apparently not being accepted, every request was seen as unauthorised — and AIOWPS was blocking it with a wp_die() HTML response rather than a standard REST error.

Step 7 — The whitelist

Further examination of AIOWPS settings revealed a whitelist of REST API routes. Every registered route on the site was listed, each with a toggle. The mcp route was present — but its toggle was off.

Enabling the mcp toggle (and also the wp toggle, which covers standard WordPress REST endpoints) and saving the settings resolved the 403 immediately.


Part 5: Confirming the Fix

After enabling the AIOWPS whitelist entries, the PowerShell test against /wp-json/wp/v2/users/me returned 200, with the user profile JSON for Captain Walker.

Claude Desktop was fully restarted (including via Task Manager to ensure no background process remained). In a new chat window, the prompt:

“List all available WordPress abilities on my site.”

returned 11 abilities across three categories:

Core:

  • core/get-site-info
  • core/get-user-info
  • core/get-environment-info

WPCode:

  • wpcode/list-snippets
  • wpcode/detect-snippet-errors
  • wpcode/get-error-logs
  • wpcode/search-library
  • wpcode/get-settings

MCP Adapter (internal):

  • mcp-adapter/discover-abilities
  • mcp-adapter/get-ability-info
  • mcp-adapter/execute-ability

The integration was complete.


Part 6: The PHP Snippet — Essential or Optional?

The Gemini-generated summary had included a PHP snippet added via the Code Snippets plugin, intended to expose WordPress abilities to the MCP Adapter:

add_action( 'wp_abilities_api_init', function() {
   add_filter( 'wp_abilities_api_ability_args', function( $args ) {
       if ( ! isset( $args['meta'] ) ) { $args['meta'] = array(); }
       if ( ! isset( $args['meta']['mcp'] ) ) { $args['meta']['mcp'] = array(); }
       $args['meta']['mcp']['public'] = true;
       return $args;
  }, 20 );
}, 5 );

A controlled test was performed: the snippet was disabled, and the abilities were queried again. All 11 abilities disappeared. The snippet was re-enabled, and they returned.

Conclusion: the snippet is essential. Without it, the MCP Adapter does not expose any abilities to the connection.


Part 7: What Was Actually Required

Three things were all necessary. Remove any one of them and the integration fails.

ComponentPurposeWhere configured
PHP snippet (Code Snippets)Marks abilities as accessible to the MCP AdapterWordPress dashboard → Code Snippets
AIOWPS whitelist (mcp route enabled)Allows REST API requests to the MCP endpoint through the security firewallWP Security → Firewall → REST API
claude_desktop_config.jsonPoints Claude Desktop to the correct endpoint with valid credentialsC:\Users\R3\AppData\Roaming\Claude\claude_desktop_config.json

Part 8: What the Gemini Summary Got Wrong

The Gemini document was useful as background context, but contained several inaccuracies:

  • It showed "mcvServers" (a typo) in the config example, rather than "mcpServers". The actual config was correct.
  • The WP_API_URL in the Gemini document appeared to contain Markdown hyperlink syntax embedded within the JSON value. The actual config was clean.
  • The document described the problem as a “final handshake failure” — which was technically accurate but obscured the real cause. The actual cause was a security plugin blocking the request upstream.
  • The document made no mention of AIOWPS as a potential cause, despite AIOWPS being the single most significant obstacle.

Conclusion

What success looks like

The integration works. Claude Desktop, running on a Windows PC in Wolverhampton, can now communicate directly with captainswatch.org. When Claude is asked a question that requires information from the site — or asked to perform an action on it — it calls the appropriate WordPress ability via MCP, receives the response, and incorporates it into its reply. No manual copying, no switching between applications, no intermediary steps.

The root cause of the failure was not a complex technical fault. It was a security plugin doing exactly what it was configured to do. AIOWPS was blocking unauthenticated REST API requests, and because the MCP proxy’s credentials were not being recognised as legitimate by that layer, every request appeared unauthorised.

The diagnostic path to that conclusion required ruling out several other candidates first: the local configuration, the URL format, the username, the application password, the user role, the web server header-stripping behaviour, and the WordPress endpoint itself. Each was tested in turn, with evidence gathered at each step before moving to the next.

The lesson is straightforward: when connecting external tools to a secured WordPress site, the security plugins are as likely to cause problems as any configuration error.

What this means in practice for Captain Walker

Captain Walker maintains two blogs — captainswatch.org (personal and philosophical) and investigativepsychiatry.com (professional). He is also a working author, a consultant forensic psychiatrist, and an expert witness. Writing is central to everything he does.

Before this integration, using Claude to help with blog content meant a manual cycle: draft something in Claude, copy it, paste it into WordPress, check it, adjust it, and repeat. Each iteration required switching context and handling the mechanics of transfer by hand.

With the MCP connection in place, that changes. Claude can now interact with captainswatch.org directly. In practical terms this means:

Content work. Claude can retrieve existing posts, check what has already been written on a topic, and help draft new content that is consistent in tone and substance with what is already on the site — without the user having to paste in prior articles for context.

Site diagnostics. The WPCode abilities exposed through the integration allow Claude to inspect active code snippets, check for errors, and review plugin settings — useful when something on the site behaves unexpectedly.

Workflow efficiency. For a locum practitioner working across multiple NHS settings, time is a constrained resource. Reducing the friction involved in maintaining an active blog means more gets written, more consistently.

Future capability. The current 11 abilities are a foundation. As the WordPress Abilities API matures and more plugins register their own abilities, the range of tasks Claude can perform on the site will grow — potentially covering post scheduling, comment moderation, and content categorisation.

The integration does not make Claude an autonomous agent acting on the site without oversight. Every action still requires a prompt, and the user retains full control. What it removes is the mechanical labour between having an idea and getting it onto the page.

For a writer who thinks carefully about what he publishes — and who has spent considerable effort building a site that reflects that — that is a meaningful gain.


Glossary of Terms

Application Password A WordPress feature that generates a separate, revocable password specifically for API access. It is used instead of the main account password when connecting external tools. Generated under Users → Profile in the WordPress dashboard.

AIOWPS (All In One WP Security) A WordPress security plugin that adds multiple layers of protection, including a firewall, login lockdown, and the ability to block REST API access. In this project, its REST API blocking feature was the primary obstacle.

Authorisation Header An HTTP request header that carries credentials. For application password authentication, it contains a Base64-encoded string of username:password. Some web servers strip this header before it reaches PHP.

Basic Authentication A simple authentication method where credentials are encoded in Base64 and sent in the Authorisation header. Not encrypted by itself — relies on HTTPS for security.

Claude Desktop The desktop application version of Claude, which supports MCP servers configured locally via a JSON file.

claude_desktop_config.json The configuration file for Claude Desktop that defines MCP servers. Located at C:\Users\[username]\AppData\Roaming\Claude\claude_desktop_config.json on Windows.

Code Snippets Plugin A WordPress plugin that allows PHP code to be added to a site without editing theme files directly. Used in this project to expose WordPress abilities to the MCP Adapter.

ENOENT A system error meaning “no such file or directory.” In this project it appeared as spawn npx ENOENT, meaning Claude Desktop could not find the npx executable.

403 Forbidden An HTTP status code meaning the server understood the request and identified the requester, but is refusing to fulfil it. Distinct from 401 (unauthenticated) — a 403 means the identity is known but access is denied.

401 Unauthorised An HTTP status code meaning the request lacks valid authentication credentials.

HTTP Status Code A three-digit number returned by a web server to indicate the result of a request. Common codes: 200 (success), 401 (unauthenticated), 403 (forbidden), 404 (not found), 500 (server error).

JSON JavaScript Object Notation. A structured text format used widely for configuration files and API responses. The claude_desktop_config.json file is written in JSON.

LiteSpeed A web server software (an alternative to Apache or Nginx) commonly used by shared hosting providers. Can be configured to strip the Authorisation header, which prevents application password authentication from working.

MCP (Model Context Protocol) An open protocol that allows AI assistants like Claude to connect to external tools and services. Defined by Anthropic. Enables Claude to discover and call functions on connected systems.

MCP Adapter Plugin A WordPress plugin that implements the MCP server side of the protocol, exposing WordPress abilities (registered functions) to MCP clients like Claude Desktop.

mcp-wordpress-remote (@automattic/mcp-wordpress-remote) An npm package that acts as a local proxy between Claude Desktop and a remote WordPress site. It runs on the local PC, receives MCP requests from Claude Desktop, and forwards them to the WordPress site via HTTP.

npm / npx npm is the Node.js package manager. npx is a tool that runs npm packages without installing them permanently. Both require Node.js to be installed.

Node.js A JavaScript runtime environment. Required to run the mcp-wordpress-remote proxy package.

PATH (environment variable) A system variable that lists directories where the operating system looks for executable programs. If Node.js is not in the PATH visible to Claude Desktop, commands like npx will fail with ENOENT.

REST API Representational State Transfer Application Programming Interface. WordPress has a built-in REST API at /wp-json/ that allows external systems to read and write site data using standard HTTP requests.

wp_die() A WordPress function that terminates execution and outputs an error page. Unlike REST API errors (which return JSON), wp_die() returns HTML. Its presence in a response to a REST API request indicates that something intercepted the request before the normal REST handler ran.

WordPress Abilities API A WordPress API (core since version 6.9) that provides a standard way for plugins, themes, and core to register discrete units of functionality. The MCP Adapter exposes registered abilities as MCP tools.

wp-json The base path for the WordPress REST API. All REST API endpoints begin with /wp-json/.