Skip to main content

MCP server for WP-CLI over local Docker, Pantheon Terminus, or SSH — run WP-CLI and byte-faithfully copy posts/meta between WordPress environments, with checksum verification.

Project description

mcp-wp-cli-terminus

An MCP (Model Context Protocol) server that lets Claude and other AI agents run WP-CLI against WordPress — over local Docker, Pantheon Terminus, or SSH — and byte-faithfully copy posts and post meta between environments with checksum verification.

Built for developers using Claude Code / Claude Desktop (or any MCP client) to operate WordPress sites — including Pantheon multidevs reached through Terminus — without hand-assembling fragile wp eval commands.

wp-cli · wordpress · terminus · pantheon · mcp · model-context-protocol · claude · claude-code · anthropic · wordpress-migration · devops


Why

Moving a WordPress post's body or custom fields between environments (e.g. pushing a block-based front page from local to a Pantheon multidev) is deceptively hard to do correctly:

  • wp post update --post_content truncates at newlines (wp-cli#2712).
  • Piping content over STDIN hangs on terminus remote:wp (terminus#1615).
  • Hand-pasting base64 into an agent prompt is lossy — a single flipped byte silently corrupts production.
  • Large payloads passed as one shell argument hit the Linux MAX_ARG_STRLEN (131072 bytes) limit and fail with E2BIG.
  • Post meta with serialized arrays / multiple values per key is easy to corrupt by re-serializing.

This server solves all of that: content is read, base64-encoded in code, delivered over a transport-safe path, and then re-read and checksum-compared to the source. A mismatch is reported, never silently trusted.

Tools

Tool What it does
wp_cli Run any WP-CLI command against a configured site — target: local (Docker) or target: production (Terminus or SSH, chosen by config). Destructive commands are guarded on production.
wp_copy_post Byte-faithfully copy a post's post_content from one environment to another, with an md5 round-trip verification.
wp_copy_post_meta Byte-faithfully copy a post's complete meta (all custom fields — serialized arrays, multiple values per key, ACF repeaters) between environments, with a canonical checksum verification. Copy all keys (full mirror) or an allow-list.

Correctness guarantees

  • Never routes content through the model's text. Payloads are read into the server and base64-encoded in code.
  • Checksum-verified. Every copy re-reads the destination and compares it to the transferred source; verified: false + an error on any mismatch.
  • Transport-agnostic. The same logic runs over local Docker, Pantheon Terminus, and WP-CLI --ssh.
  • Large payloads. Docker/SSH deliver PHP over STDIN (wp eval-file -, exempt from the argv size limit); Terminus uses a size-guarded argv path and fails loud rather than emitting a raw E2BIG.
  • Meta fidelity. Values are round-tripped so WordPress's own maybe_serialize() reproduces the exact stored meta_value — arrays stay arrays, and strings that merely look serialized stay strings.
  • Production guard. Writes to a production destination require confirm: true when PROD_GUARD is enabled.

Install & run

The server is pure Python (stdlib only, zero dependencies).

With uvx (recommended — no install)

// Claude Desktop / Claude Code MCP config
{
  "mcpServers": {
    "wp-cli": {
      "command": "uvx",
      "args": ["mcp-wp-cli-terminus"]
    }
  }
}

With pip

pip install mcp-wp-cli-terminus
{
  "mcpServers": {
    "wp-cli": { "command": "mcp-wp-cli-terminus" }
  }
}

From source

git clone https://github.com/EarthmanWeb/mcp-wp-cli-terminus
cd mcp-wp-cli-terminus
python -m wp_cli_mcp   # PYTHONPATH=src, or `pip install -e .`

Configure

The server reads <project-root>/.serena/wp-cli.conf at runtime (set CLAUDE_PROJECT_DIR to point at your project). Copy wp-cli.conf.example and edit:

DEFAULT_SITE=example-site
PROD_GUARD=true

[site:example-site]
LOCAL_CONTAINER=my-container       # docker container running WP-CLI
LOCAL_PATH=/var/www/html           # WordPress path inside the container
TERMINUS_SITE=example              # Pantheon site — production routes over Terminus
TERMINUS_ENV=dev                   # default env (override per call)
# — or, for a non-Pantheon remote, omit TERMINUS_* and set:
# REMOTE_SSH=deploy@example.com:22/var/www/html
  • Production transport is chosen by config: TERMINUS_SITEterminus remote:wp; otherwise REMOTE_SSH → WP-CLI --ssh.
  • Multi-site: add more [site:NAME] sections and pass site per call.

Never commit .serena/wp-cli.conf — it may contain hostnames/SSH strings. The shipped .gitignore excludes it.

Usage examples

// Run a WP-CLI command locally
{ "tool": "wp_cli", "args": "plugin list --status=active --format=json" }

// Run against production (Terminus or SSH per config)
{ "tool": "wp_cli", "args": "option get siteurl", "target": "production" }

// Copy a front page's block markup from local to production, verified
{ "tool": "wp_copy_post", "post_id": 42, "from": "local", "to": "production", "confirm": true }

// Copy ALL meta for a post (full mirror), verified
{ "tool": "wp_copy_post_meta", "post_id": 42, "from": "local", "to": "production", "confirm": true }

// Copy only specific meta keys
{ "tool": "wp_copy_post_meta", "post_id": 42, "from": "local", "to": "production",
  "keys": ["_thumbnail_id", "my_field"], "confirm": true }

Each copy returns verified: true/false with src_md5 / dst_md5, the delivery mode, and per-side transport.

Debug logging

Failures (non-zero WP-CLI exits) are appended to a log in your system temp dir — failures only, successes are never logged:

  • Location: ${TMPDIR}/wp-cli-mcp/failures.log (override with WP_CLI_MCP_LOG_DIR).
  • Disable entirely with WP_CLI_MCP_LOG=0.
  • SSH connection strings are redacted in the log.

Requirements

  • Python 3.8+
  • WP-CLI reachable via one of: a local Docker container (docker exec), Pantheon Terminus on the host, or a host WP-CLI with --ssh.

Tests

python -m unittest discover -s tests -v

54 stdlib-only unit tests cover config parsing, transport selection (local/Terminus/SSH), the argv size guard, newline handling, PHP-key safety, and the full copy/verify orchestration via an injectable command-runner seam (no real WP-CLI invoked).

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_wp_cli_terminus-0.1.0.tar.gz (24.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_wp_cli_terminus-0.1.0-py3-none-any.whl (21.9 kB view details)

Uploaded Python 3

File details

Details for the file mcp_wp_cli_terminus-0.1.0.tar.gz.

File metadata

  • Download URL: mcp_wp_cli_terminus-0.1.0.tar.gz
  • Upload date:
  • Size: 24.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.8

File hashes

Hashes for mcp_wp_cli_terminus-0.1.0.tar.gz
Algorithm Hash digest
SHA256 cb688f9794b001687c99381a43fbf7619201af800de9d94eed426df2ec4c5ed1
MD5 a01ac337abf252f29296be092ef3a03d
BLAKE2b-256 87c6d8cfd314f6ab7238ac2a74d7294270ed4e851cb53276216e38d54b02cb95

See more details on using hashes here.

File details

Details for the file mcp_wp_cli_terminus-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mcp_wp_cli_terminus-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b12df31cb639241031e11e2312974b00fe1b68f1d0fb3e452b7df84b17dd810b
MD5 bc9fb75f601c3318ce2cac16aaf725e0
BLAKE2b-256 3ddcafe234302ee715b1252558c24c81981bc2f47fa8270a41c000b5ea7d3ec6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page