Skip to main content
Glama

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.

Related MCP server: wp-cli-mcp

Tools

Tool

What it does

wp_init_config

Guided setup: detects your Docker container, WordPress path, and Terminus site, then writes .serena/wp-cli.conf (asking you for anything it can't detect).

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_sync_post

Sync a post's post_content onto the same post ID in another environment (updates an existing post; e.g. a multidev cloned from the same DB), with an md5 round-trip verification.

wp_sync_post_meta

Sync a post's complete meta (serialized arrays, multiple values per key, ACF repeaters) onto the same post ID in another environment, with a canonical checksum verification. All keys (full mirror) or an allow-list.

wp_sync_option

Sync one or more wp_options rows (site/plugin settings, and ACF options-page data incl. repeaters/nested groups) between environments — or between two subsites of one multisite — md5-verified. Select by exact option_names or a like prefix; multisite --url is resolved automatically per side from a bare subdomain. The options-table counterpart to wp_sync_post_meta.

wp_clone_post

Clone a post to another environment as a NEW post — the destination assigns its own ID (returned as new_id). Use when the post doesn't exist on the destination yet. Copies fields + all meta, verifies, and reports meta keys that hold ID references for manual remapping.

wp_block

Surgically edit one Gutenberg/ACF block of a post — list / get / insert / replace / update-attrs / remove / move — leaving every other block byte-identical. Uses WP core parse_blocks()/serialize_blocks() (never string surgery), with a re-parse md5 verification and the same production guard.

wp_create_post

Create a NEW post from scratch, with the body carried content-safe (base64 in code) — no hand-quoted wp post create, no throwaway PHP file. Give content (raw markup) or blocks (specs serialized server-side); returns new_id to build up with wp_block.

Sync vs. clone vs. block

  • Block (wp_block) is the single-block primitive: change, read, add, or reorder one block of a post without touching the rest. Reach for it instead of a whole-body wp_sync_post (which overwrites every block) or hand-written str_replace/eval surgery on post_content (which corrupts self-closing ACF blocks and inner blocks). Selectors: name:<blockName> (first of type), name:<blockName>#<N> (Nth, 0-based), anchor:<anchor>, index:<N>.

  • Sync (wp_sync_post, wp_sync_post_meta) updates an existing post that shares the same ID on both sides — the right tool when the environments were cloned from the same database (a Pantheon multidev, a staging copy). It fails if the destination ID doesn't exist.

  • Options (wp_sync_option) copies wp_options rows — data the post tools can't reach. Reach for it for settings / ACF options-page content (theme options, plugin config, an options-page repeater). For an ACF repeater, match both options_<field>% and the underscore-prefixed _options_<field>% field-reference rows; a like sync mirrors the pattern (surplus destination rows are removed) so a repeater shrinks correctly.

  • Clone (wp_clone_post) creates a new post on the destination from a source post; the destination assigns a fresh ID. Use it when the content is new to the destination (e.g. pushing a locally-authored post/alert up to a multidev). Meta values that look like ID references (_thumbnail_id, ACF relationship/image fields) are copied verbatim and reported — never silently remapped across databases.

Correctness guarantees

  • Never routes content through the model's text. Payloads are read into the server and base64-encoded in code.

  • Checksum-verified. Every sync/clone 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.

  • MCP-client tolerant. Some MCP clients (e.g. Claude Code) serialize object/array/number/boolean tool arguments as JSON strings before sending them (claude-code#5504, #24599). The tools coerce such stringified arguments back to their native types, so a block/blocks/data/fields object delivered as a string still works — while a genuine raw-markup string is never mis-parsed.

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

Guided setup with wp_init_config (recommended)

The easiest way to create the config is to ask your MCP client to run the wp_init_config tool. It works in two phases:

  1. Detect — called with no arguments, it probes the environment (running Docker containers, the WordPress path inside them, and any authenticated Pantheon Terminus site) and reports what it found plus a list of anything it couldn't determine.

  2. Write — the agent asks you for whatever was missing, then calls it again with write=true to save <project-root>/.serena/wp-cli.conf.

Just tell your agent: "set up the wp-cli config for this project" — it will call wp_init_config, fill in what it can, ask you for the rest, and write the file (it won't overwrite an existing config unless you say so).

Manual setup

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" }

// SYNC a front page's block markup onto the SAME post ID on production, verified
{ "tool": "wp_sync_post", "post_id": 42, "from": "local", "to": "production", "confirm": true }

// SYNC ALL meta for a post (full mirror) onto the same ID, verified
{ "tool": "wp_sync_post_meta", "post_id": 42, "from": "local", "to": "production", "confirm": true }

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

// CLONE a locally-authored post to production as a NEW post (returns new_id)
{ "tool": "wp_clone_post", "post_id": 268529, "from": "local", "to": "production", "confirm": true }

// Clone but force the new post to draft
{ "tool": "wp_clone_post", "post_id": 268529, "from": "local", "to": "production",
  "overrides": { "post_status": "draft" }, "confirm": true }

// LIST a post's top-level blocks (index, blockName, anchor, ACF data keys)
{ "tool": "wp_block", "op": "list", "post_id": 268483 }

// GET one block's parsed attrs + exact markup
{ "tool": "wp_block", "op": "get", "post_id": 268483, "selector": "name:acf/sps-hero-slideshow-block" }

// INSERT a feature-cards block just before the celebrations block (ACF data form)
{ "tool": "wp_block", "op": "insert", "post_id": 268483,
  "position": "before:name:acf/sps-celebrations-block",
  "block": { "name": "acf/sps-feature-cards-block", "data": { "cards": [268486, 268388, 268364] } } }

// UPDATE-ATTRS: switch the celebrations block to tag mode (merges into attrs.data)
{ "tool": "wp_block", "op": "update-attrs", "post_id": 268483,
  "selector": "name:acf/sps-celebrations-block",
  "data": { "source": "tag", "tag": 436, "posts_per_page": 10 } }

// REPLACE the 2nd paragraph with raw markup; MOVE / REMOVE by selector
{ "tool": "wp_block", "op": "replace", "post_id": 42, "selector": "name:core/paragraph#1",
  "block": "<!-- wp:paragraph --><p>New copy</p><!-- /wp:paragraph -->" }
{ "tool": "wp_block", "op": "move", "post_id": 42, "selector": "anchor:cta", "position": "first" }
{ "tool": "wp_block", "op": "remove", "post_id": 42, "selector": "index:3" }

// PREVIEW a change without writing (returns the intended new_content_b64 + new_md5)
{ "tool": "wp_block", "op": "remove", "post_id": 42, "selector": "index:3", "preview": true }

// SYNC a post's body to production but PRESERVE the destination's hand-built slideshow
{ "tool": "wp_sync_post", "post_id": 268483, "from": "local", "to": "production",
  "except_blocks": ["acf/sps-hero-slideshow-block"], "confirm": true }

// CREATE a new page from block specs in ONE call (no file, no arg-quoting) -> new_id
{ "tool": "wp_create_post", "title": "Landing", "post_type": "page", "status": "draft",
  "blocks": [
    { "name": "acf/sps-feature-cards-block", "data": { "cards": [268486, 268388] } },
    "<!-- wp:paragraph --><p>Intro copy.</p><!-- /wp:paragraph -->"
  ] }

// CREATE from raw markup, then keep building with wp_block on the returned new_id
{ "tool": "wp_create_post", "title": "Draft", "content": "<!-- wp:heading --><h2>Hi</h2><!-- /wp:heading -->" }
{ "tool": "wp_block", "op": "insert", "post_id": /* new_id */ 0, "position": "last",
  "block": { "name": "acf/sps-celebrations-block", "data": { "source": "tag", "tag": 436 } } }

// SYNC named options (site settings) local -> production
{ "tool": "wp_sync_option", "option_names": ["blogname", "blogdescription"],
  "from": "local", "to": "production", "confirm": true }

// SYNC a whole ACF options-page repeater — BOTH prefixes (values + field refs)
{ "tool": "wp_sync_option", "like": "options_page_callouts%",  "from": "local", "to": "production", "confirm": true }
{ "tool": "wp_sync_option", "like": "_options_page_callouts%", "from": "local", "to": "production", "confirm": true }

// COPY options between two SUBSITES of one multisite (same env; bare subdomains)
{ "tool": "wp_sync_option", "like": "options_hero%",
  "from": "local", "to": "local", "from_subdomain": "site-a", "to_subdomain": "site-b" }

wp_sync_* return verified: true/false with src_md5 / dst_md5, the delivery mode, and per-side transport. wp_sync_option adds options_written, the selector used, and (for a subsite copy) the resolved subsite. A bare wp_cli call that a specialized tool would do better (e.g. option get/update, post get --field=post_content, raw eval) also returns a suggestion pointing you at it — the command still runs. wp_clone_post returns new_id, verified, content_verified, meta_verified, and id_reference_keys (meta keys to review). wp_block read ops return the block list / one block's attrs+markup; write ops return wrote, verified (re-parse md5 round-trip), before_count/after_count, and target_index — and, when blocked by the production guard or preview: true, the intended new_content_b64 + new_md5 instead of writing. A block-filtered wp_sync_post (only_blocks/except_blocks) returns blocks_carried, intended_md5/reread_md5, and the filter applied.

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

187 stdlib-only unit tests (split by area under tests/) cover config parsing, transport selection (local/Terminus/SSH), the argv size guard + --url extra-token passthrough, newline handling, PHP-key safety, id-reference detection, option/ACF-repeater copy with pattern mirroring, multisite subdomain→URL resolution, the wp_cli discovery hints, and the full sync/clone/verify orchestration via an injectable command-runner seam (no real WP-CLI invoked).

Releasing

Releases publish to PyPI automatically via GitHub Actions (.github/workflows/publish.yml) using PyPI Trusted Publishingno API token is stored in the repo. The workflow builds, runs the tests, and uploads on every published GitHub Release.

One-time setup (per project, on PyPI):

  1. On PyPI, open the project → PublishingAdd a new publisher → GitHub, with:

    • Owner: EarthmanWeb · Repository: mcp-wp-cli-terminus

    • Workflow name: publish.yml · Environment: pypi

  2. (Optional) In GitHub repo Settings → Environments, create an environment named pypi to gate/approve publishes.

Cut a release (this triggers the publish):

# 1. Bump the version in pyproject.toml (e.g. 0.1.0 -> 0.1.1), commit, push.
# 2. Tag + create the GitHub Release — the workflow does the rest:
gh release create v0.1.1 --title "v0.1.1" --notes "What changed"

The action then builds, tests, and publishes mcp-wp-cli-terminus to PyPI. Within ~a minute uvx mcp-wp-cli-terminus (and the SWE plugin launcher) pick up the new version. You can also run it manually from the Actions tab (workflow_dispatch).

First release was published manually with uv build && uv publish; subsequent releases use the workflow above.

License

MIT

Available Tools

8 tools
wp_blockA

Surgically operate on ONE Gutenberg/ACF block of a single post without disturbing the rest of the body. This is the block-level primitive that whole-body wp_sync_post lacks: insert, replace, read, update-attrs, remove, or move exactly one block while every other block stays byte-identical. Use it INSTEAD of hand-written str_replace/eval surgery on post_content (which repeatedly corrupted markup: base64 transcription bugs, self-closing /--> terminators, multisite --url errors). All parsing/serialization runs in WordPress core (parse_blocks / serialize_blocks) via one PHP eval — never string surgery — so self-closing ACF blocks, inner blocks, and freeform HTML round-trip faithfully. ops: 'list' (ordered block summary: index, blockName, anchor, attr/ACF-data keys), 'get' (one block's parsed attrs + exact markup), 'insert' (add a block at a position), 'replace' (swap the matched block), 'update-attrs' (merge ACF field values into the matched block's attrs.data, preserving existing _field key pointers), 'remove' (delete the matched block), 'move' (reorder). Selectors: 'name:' (first of type), 'name:#' (Nth, 0-based), 'anchor:', or 'index:' (Nth top-level block). The block arg is either raw block markup OR an object {name, data} where data merges into the ACF attrs.data. Content never passes through the caller's text: post_content is read on the server, payloads are carried base64 in code, and every write RE-PARSES the saved post and reports verified=true only if the round-trip md5 matches. Read ops (list/get) are never guarded; write ops on target='production' require confirm=true when PROD_GUARD is enabled (a preview of the change is returned instead when blocked). Pass preview=true to get the intended change without writing. Transport (local Docker / Terminus / SSH) is resolved from wp-cli.conf exactly like wp_cli.

ParametersJSON Schema
NameRequiredDescriptionDefault
opYesThe block operation to perform.
envNoTerminus environment override (e.g. 'dev', 'test', 'live') for target='production' on a Terminus site. Omit for the site's TERMINUS_ENV.
dataNoFor op='update-attrs': field -> value pairs merged into the matched block's attrs.data (ACF). Existing _field key pointers are preserved.
siteNoWhich configured site to target (matches a [site:NAME] section in wp-cli.conf). Omit for DEFAULT_SITE or the sole site.
blockNoThe block to insert/replace, as raw block markup (string) OR an object {"name": "acf/...", "data": {field: value}}. For the object form, data merges into the ACF attrs.data. Required for insert/replace.
targetNoWhere the post lives. 'local' = Docker container (default). 'production' = remote environment; transport (Terminus vs SSH) is chosen by the site's conf.local
confirmNoRequired to write to a production post when the guard is enabled. Default: false.
post_idYesThe post whose blocks to operate on.
previewNoFor write ops: compute and return the intended new post_content (new_md5, new_content_b64) WITHOUT saving. Default false.
positionNoWhere to insert/move: 'first', 'last', 'index:<N>' (before top-level index N), 'before:<selector>', or 'after:<selector>'. For insert, defaults to 'last'. Required for move.
selectorNoWhich block to target. 'name:<blockName>' (first of that type), 'name:<blockName>#<N>' (Nth, 0-based), 'anchor:<anchor>', or 'index:<N>' (Nth top-level block). Required for get/replace/update-attrs/remove/move.
dedupe_byNoFor op='insert': skip the insert (idempotent) if a block already matches by 'anchor' or 'name'. Omit to always insert.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It discloses many behavioral details: parsing uses WordPress core functions via PHP eval, not string surgery; content is handled via base64; guard mechanisms for production; preview mode; verified=true on round-trip; transport resolved from config. No contradictions with annotations (none present).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is thorough but verbose, spanning multiple paragraphs. It is front-loaded with the purpose and logically structured, but contains many details that could be streamlined for conciseness. An agent may need to parse through substantial text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (12 parameters, 2 required) and no output schema, the description covers all essential aspects: all operations, selectors, block formats, safety mechanisms (preview, confirm), transport, and return value descriptions. The agent has sufficient information to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds some operational context (e.g., block arg formats, selector syntax) but much of this is already present in the schema descriptions. The additional value is more about tool behavior than parameter semantics specifically.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool performs surgical operations on a single Gutenberg/ACF block of a post. It specifies the verb ('surgically operate') and the resource ('ONE Gutenberg/ACF block of a single post'). It distinguishes itself from sibling tools like wp_sync_post by emphasizing block-level granularity and avoiding string surgery.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells when to use this tool: for block-level operations like insert, replace, read, update-attrs, remove, or move. It advises using it INSTEAD of hand-written str_replace/eval surgery, citing corruption issues. It contrasts with the whole-body wp_sync_post, providing clear alternatives and exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wp_cliA

Run a WP-CLI command against a configured WordPress site's local Docker container (default) or its remote production environment. Configuration is read from /.serena/wp-cli.conf, which may define one or MANY sites. Pass the WP-CLI command WITHOUT a leading 'wp' (e.g. args='plugin list --status=active'). When the conf defines multiple sites, pass 'site' = the site's top-level folder name; omit it to use the configured DEFAULT_SITE or the sole site. The production TRANSPORT is chosen by the site's conf: TERMINUS_SITE routes over terminus remote:wp (run on the host, Pantheon/Terminus); otherwise REMOTE_SSH routes over WP-CLI --ssh. For Terminus sites the environment is TERMINUS_ENV (conf default) unless overridden per-call with the 'env' arg. On production, destructive commands (db reset/import, post/user delete, search-replace without --dry-run, plugin/theme delete, etc.) are blocked unless confirm=true and the guard is enabled.

ParametersJSON Schema
NameRequiredDescriptionDefault
envNoTerminus environment override (e.g. 'dev', 'test', 'live') for target='production' on a Terminus site. Omit to use the site's TERMINUS_ENV default. Ignored for SSH and local targets.
argsYesThe WP-CLI command and its flags, without the leading 'wp'. Example: 'option get blogname' or 'plugin list --status=active --format=json'.
siteNoWhich configured site to target — matches a [site:NAME] section in wp-cli.conf. Omit to use DEFAULT_SITE, or the sole site if only one is configured.
targetNoWhere to run. 'local' = Docker container (default). 'production' = remote environment; transport (Terminus vs WP-CLI --ssh) is chosen by the site's conf.local
confirmNoRequired to run a destructive command on production when the guard is enabled. Default: false.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. Discloses destructive command blocking, production transport selection, and env override behavior. Lacks details on error states but covers major behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single dense paragraph efficiently covers all necessary aspects. Could be formatted with bullet points for readability, but no superfluous information present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers key aspects: configuration, target selection, destructive command protection. No output schema so return values not required. Lacks mention of error handling or output format, but acceptable for a CLI tool that returns raw WP-CLI output.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% but description adds significant context beyond schemas, such as how to format args (without 'wp'), how site selection works, that env is ignored for SSH/local, and the role of confirm in destructive commands.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it runs WP-CLI commands against a WordPress site's local Docker container or remote production environment. It distinguishes from sibling tools (wp_copy_post, wp_copy_post_meta) which have different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on when to use (run WP-CLI commands), how to configure via wp-cli.conf, how to pass args without leading 'wp', and handling multiple sites. Does not explicitly mention alternatives, but siblings are fundamentally different.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wp_clone_postA

COPY a source post to another environment as a NEW post — the destination assigns its own ID (returned as new_id). Use this (NOT wp_sync_post) when the post does not exist on the destination yet, e.g. pushing a locally-authored alert/notification up to a Pantheon multidev. It reads the source post's fields (title, content, excerpt, status, type, dates, parent, etc.) plus ALL meta, creates the post on the destination via wp_insert_post, writes the meta verbatim, then verifies (content md5 + meta digest). Meta values that look like ID references (e.g. _thumbnail_id, ACF relationship/image fields) are copied RAW and REPORTED in id_reference_keys for manual remapping — the tool never silently remaps IDs across databases. Pass overrides to set post fields on the new post (e.g. {"post_status":"draft"}). Content/meta never pass through the caller's text. Creating on a production destination requires confirm=true when the PROD_GUARD is enabled.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesDestination environment to create the new post IN. Must differ from 'from'.
fromYesSource environment to read the post FROM.
siteNoWhich configured site to target. Omit for DEFAULT_SITE or the sole site.
to_envNoTerminus environment override for the DESTINATION when to='production'. Omit for TERMINUS_ENV.
confirmNoRequired to create on a production destination when the guard is enabled. Default: false.
post_idYesThe SOURCE post ID to clone. The destination will get a NEW, different ID.
from_envNoTerminus environment override for the SOURCE when from='production'. Omit for TERMINUS_ENV.
overridesNoOptional post fields to set/replace on the new post (e.g. {"post_status":"draft","post_title":"..."}).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

In the absence of annotations, the description fully details the tool's behavior: it reads post fields and all meta, creates a new post via wp_insert_post, writes meta verbatim, verifies with content md5 and meta digest, reports ID references for manual remapping, and notes that content/meta never pass through the caller's text. It also mentions the production guard requiring confirm. No contradictions with annotations (none provided).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single paragraph of about 200 words. It is front-loaded with the key action and differentiated use case, but could benefit from bullet points or clearer separation of behavioral details. Still, every sentence provides necessary information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (8 parameters, nested overrides object, no output schema), the description is remarkably complete. It covers the full process, edge cases (ID references, verification, production guard), and explicitly mentions the returned new_id. The only minor gap is the lack of explicit output schema, but the description mentions the returned key new_id.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All 8 parameters are described in the input schema (100% coverage), so baseline is 3. The description adds useful context: explains the new_id is assigned by destination, provides an overrides example, clarifies confirm requirement for production, and mentions Terminus environment overrides. This adds value beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'COPY a source post to another environment as a NEW post' using a specific verb and resource. It distinguishes itself from the sibling tool wp_sync_post by specifying when to use it (post does not exist on destination) and provides a concrete example (pushing a locally-authored alert/notification up to a Pantheon multidev).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly contrasts with wp_sync_post: 'Use this (NOT wp_sync_post) when the post does not exist on the destination yet'. It also provides contextual guidance like pushing to a Pantheon multidev and requiring confirm=true on production with PROD_GUARD enabled.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wp_create_postA

Create a NEW post from scratch on a configured site, with the body carried content-safe (base64 in code) — so you never have to hand-quote multi-line block markup into a wp post create command or write a throwaway PHP file into the container just to author a post. Returns the new post's ID (new_id), which you then build up compositionally with wp_block (insert / update-attrs). Supply the body EITHER as content (a raw post_content markup string) OR as blocks (an array of block specs — raw markup strings and/or {name, data} objects — serialized server-side with serialize_blocks() so self-closing ACF blocks and inner blocks stay byte-faithful); omit both for an empty post. fields sets any additional post columns (post_excerpt, post_author, post_parent, menu_order, post_name, ...). The new post is re-read and its content md5 is compared to the intended body (verified). Content never passes through the caller's text. Creating on target='production' requires confirm=true when PROD_GUARD is enabled. To COPY an existing post across environments use wp_clone_post instead; this tool authors a brand-new post from given values.

ParametersJSON Schema
NameRequiredDescriptionDefault
envNoTerminus environment override (e.g. 'dev', 'test', 'live') for target='production' on a Terminus site. Omit for the site's TERMINUS_ENV.
siteNoWhich configured site to target (matches a [site:NAME] section in wp-cli.conf). Omit for DEFAULT_SITE or the sole site.
titleNoThe post title (post_title). Optional.
blocksNoArray of block specs to serialize as the initial body: each item is raw block markup (string) OR an object {"name": "acf/...", "data": {field: value}}. Serialized server-side via serialize_blocks(). Mutually exclusive with 'content'.
fieldsNoOptional additional post fields to set (e.g. {"post_excerpt":"...","post_author":2,"post_parent":10,"menu_order":3,"post_name":"slug"}).
statusNoPost status (e.g. 'draft', 'publish', 'private'). Default 'draft'.draft
targetNoWhere to create the post. 'local' = Docker container (default). 'production' = remote environment; transport (Terminus vs SSH) is chosen by the site's conf.local
confirmNoRequired to create on a production site when the guard is enabled. Default: false.
contentNoRaw post_content markup (a full block document). Mutually exclusive with 'blocks'. Omit both for an empty post.
post_typeNoPost type to create (e.g. 'post', 'page', a CPT slug). Default 'post'.post

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It discloses base64 encoding, md5 verification, production guard requirement, and that content never passes through caller's text. Could mention the exact return value (new_id) more explicitly but implied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is relatively long but every sentence serves a purpose, front-loading the main action. Slightly lengthy due to comprehensive details, but still efficient for the complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 10 parameters, no output schema, and full schema coverage, the description provides sufficient context: content options, production guard, return value, and compositional workflow. No gaps identified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, yet description adds critical context: mutual exclusivity of content/blocks, server-side serialization of blocks, base64 handling, and workflow with wp_block. Significantly enriches parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool creates a new post from scratch, distinguishes from sibling tool wp_clone_post (which copies existing posts), and specifies how content is supplied (content vs blocks).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool versus wp_clone_post, mentions required confirm=true for production guard, and gives guidance on mutually exclusive content parameters and composition with wp_block.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wp_init_configA

Create the server's configuration file (/.serena/wp-cli.conf) for a WordPress project. Call it FIRST when no config exists yet. Two phases: (1) DETECT — call with no arguments (write=false); it probes the environment (running Docker containers, the WordPress path inside them, and any authenticated Pantheon Terminus site) and returns what it found plus a missing list of values it could NOT determine. Ask the user for those, then (2) WRITE — call again with write=true and a complete site object to save the config. It refuses to overwrite an existing config unless overwrite=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
siteNoRequired when write=true. Fields: name (section id), LOCAL_CONTAINER (docker container with WP-CLI), LOCAL_PATH (WordPress path inside it). Optional: LOCAL_WORKDIR, LOCAL_URL, and for production EITHER TERMINUS_SITE(+TERMINUS_ENV) OR REMOTE_SSH (not both; omit both for local-only).
writeNofalse (default) = detect and report; true = write the config from `site`.
overwriteNoAllow replacing an existing wp-cli.conf. Default false.
prod_guardNoBlock destructive/production writes without confirm=true. Default true.
default_siteNoDEFAULT_SITE value; defaults to the site name.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses the behavioral traits: the detection vs. write phases, refusal to overwrite without flag, and environmental probing. It does not contradict any annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded with key info. It is comprehensive but not overly verbose, though it could be slightly more concise in detailing the phases.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (5 parameters, nested objects, no output schema or annotations), the description provides complete guidance on the two-phase workflow, parameter dependencies, and safety guards.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds significant context beyond the schema, especially for the nested 'site' object (field constraints and conditions like local-only vs. production).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses specific verbs ('Create', 'Call it FIRST') and clearly identifies the resource (configuration file for a WordPress project). It distinguishes itself from sibling tools like 'wp_cli' or 'wp_create_post' by focusing on initialization.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool ('Call it FIRST when no config exists') and describes the two-phase process. While it doesn't explicitly list alternatives, the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wp_sync_optionA

SYNC one or more wp_options rows (site/plugin settings, and ACF OPTIONS-PAGE data) from one environment to another, with a mandatory md5 round-trip verification. This is the options-table counterpart to wp_sync_post_meta: use it for settings that live in wp_options, which the post tools cannot reach (they only handle a post's content and post meta). Select rows two ways: option_names=[...] for exact names, OR like='prefix%' for a SQL LIKE pattern. NOTE for ACF repeaters/nested groups: a repeater is stored as a parent count row (options_), numbered sub-rows (options_), AND a parallel set of underscore-prefixed field-key references (options...). To copy one completely, match BOTH prefixes — run once with like='options_%' and once with like='options%', or enumerate the rows in option_names. Matching only 'options_%' omits the field references and ACF will not render the group. Each stored option_value is PHP serialize()'d on the source, base64-encoded IN CODE, and rebuilt verbatim on the destination (delete-then-add, values re-interpreted only via maybe_unserialize so arrays/objects round-trip byte-for-byte). The destination is re-read and md5-compared; a mismatch returns verified=false, never silently trusted. Multisite: pass from_subdomain / to_subdomain as a BARE subdomain to target a subsite per side; URL handling is AUTOMATIC PER-SIDE — each side is checked against its own environment and the correct --url is resolved from that environment's live blog table (a given subdomain → that blog; none → the main 'www' site), and single-site environments get no --url. You never construct a URL, and it stays correct even when local and production use different domains. Content never passes through the caller's text. Transport (local Docker vs Terminus vs SSH) is resolved per side from wp-cli.conf exactly like wp_cli. Writing to a production destination requires confirm=true when the PROD_GUARD is enabled.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesDestination environment to write options TO. May equal 'from' when copying between two DIFFERENT subsites of one multisite (set from_subdomain != to_subdomain); otherwise it must differ from 'from'.
fromYesSource environment to read options FROM.
likeNoSQL LIKE pattern selecting every matching option_name (e.g. 'options_my_repeater%'). Mutually exclusive with 'option_names'. For ACF repeaters, also copy the '_options_<field>%' field-reference rows.
siteNoWhich configured site to target (matches a [site:NAME] section in wp-cli.conf). Omit for DEFAULT_SITE or the sole site.
to_envNoTerminus environment override for the DESTINATION when to='production'. Omit for TERMINUS_ENV.
confirmNoRequired to write to a production destination when the guard is enabled. Default: false.
from_envNoTerminus environment override for the SOURCE when from='production'. Omit for TERMINUS_ENV.
option_namesNoExact option names to copy. Mutually exclusive with 'like'; one of the two is required.
to_subdomainNoBare subdomain of the DESTINATION multisite subsite. Omit for the main 'www' site. Ignored on single-site environments. The full --url is resolved from the destination environment automatically.
from_subdomainNoBare subdomain of the SOURCE multisite subsite (e.g. 'shop'). Omit for the main 'www' site. Ignored on single-site environments. The full --url is resolved from the source environment automatically.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses mandatory md5 verification, delete-then-add strategy, PHP serialize/base64 round-trip, automatic URL resolution for multisite, transport resolution, production guard, and that content never passes through caller's text.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with key purpose and behavior; however, the description is lengthy due to complexity. Nearly every sentence adds value, but some redundancy exists (e.g., md5 mentioned twice).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers input behavior comprehensively but lacks explicit description of return values/output beyond mentioning verified=false. No output schema exists, so description should detail full response format.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Adds meaning beyond the 100% schema coverage by explaining mutual exclusivity of option_names and like, ACF repeater behavior, confirm purpose, and subdomain/URL resolution details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the verb 'SYNC', the resource 'wp_options rows', and distinguishes it from siblings like wp_sync_post_meta by explaining that this tool handles settings that post tools cannot reach.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly advises when to use this tool vs alternatives (for options not reachable by post tools), explains two selection methods, warns about ACF repeater copying needing both prefixes, and notes when confirm is required for production.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wp_sync_postA

SYNC a single post's post_content onto the SAME post ID in another environment, with a mandatory md5 round-trip verification. This UPDATES an existing destination post that shares the source's ID (e.g. a multidev cloned from the same DB) — it does NOT create a post; if the destination ID is missing it fails. To copy a post that does NOT yet exist on the destination (creating a new post with a destination-assigned ID), use wp_clone_post instead. Use this instead of hand-assembling post update/eval calls to push post body content between local and production (e.g. update a front-page's block markup on a Pantheon multidev). The content NEVER passes through the caller's text: it is read from the source into the server, base64-encoded IN CODE, applied on the destination through a transport-safe PHP eval (STDIN eval-file for Docker/SSH so arbitrarily large posts work; size-guarded argv for Terminus), then re-read and md5-compared to the source. If the hashes differ, the tool reports verified=false and returns an error rather than leaving the destination silently unverified. Transport for each side (local Docker vs Terminus vs SSH) is resolved from wp-cli.conf exactly like wp_cli. Writing to a production destination requires confirm=true when the PROD_GUARD is enabled.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesDestination environment to write post_content TO. Must differ from 'from'.
fromYesSource environment to read post_content FROM.
siteNoWhich configured site to target (matches a [site:NAME] section in wp-cli.conf). Omit to use DEFAULT_SITE or the sole site.
to_envNoTerminus environment override for the DESTINATION when to='production' on a Terminus site. Omit to use TERMINUS_ENV.
confirmNoRequired to write to a production destination when the guard is enabled. Default: false.
post_idYesThe post ID to sync. Must be the SAME ID on both source and destination (they are assumed in sync, e.g. a multidev cloned from the same DB). The tool verifies the destination post exists and fails if it does not — use wp_clone_post to create a new post instead.
from_envNoTerminus environment override for the SOURCE when from='production' on a Terminus site. Omit to use TERMINUS_ENV.
only_blocksNoOptional allow-list of blockNames (e.g. 'acf/sps-celebrations-block'). When set, ONLY these top-level blocks are carried from the source; every OTHER block on the destination is kept as-is (the source and destination bodies are spliced block-by-block). Use this to push a changed block without clobbering blocks the destination edited independently. Mutually exclusive with except_blocks. For per-block edits prefer wp_block.
except_blocksNoOptional deny-list of blockNames to LEAVE ALONE on the destination while syncing everything else from the source (e.g. except_blocks=['acf/sps-hero-slideshow-block'] pushes the body but preserves the destination's hand-built slideshow). Mutually exclusive with only_blocks.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully discloses behavioral traits: mandatory md5 round-trip verification, content never passing through caller's text, transport resolved via wp-cli.conf, production guard requiring confirm, and block filtering behavior (only_blocks/except_blocks). This gives agents complete understanding of side effects and constraints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is relatively long but well-structured, with core purpose first followed by details. Every sentence adds value, though some redundancy (e.g., repeating post_id conditions) could be trimmed. Overall, it is concise enough for the complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 9 parameters, no output schema, and no annotations, the description covers all necessary aspects: parameter semantics, verification, error handling (fails if destination missing), transport resolution, and production guard. It provides sufficient context for an agent to correctly invoke the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds contextual meaning beyond schema descriptions, such as explaining the splicing behavior for block filters and the overall verification process. However, each parameter's schema description is already clear, so the extra value is moderate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool syncs a single post's post_content between environments with md5 verification. It explicitly distinguishes from sibling tools like wp_clone_post (for creating new posts) and wp_block (for per-block edits), making its unique purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use (e.g., pushing block markup between environments) and when not to (if destination post doesn't exist, use wp_clone_post instead). It also mentions alternatives like wp_block for per-block edits and notes that confirm=true is required for production sites with PROD_GUARD enabled.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wp_sync_post_metaA

SYNC a post's COMPLETE meta (all custom fields) onto the SAME post ID in another environment, with a mandatory checksum round-trip verification. This UPDATES an existing destination post that shares the source's ID; it does NOT create a post (use wp_clone_post to copy a post that doesn't exist on the destination yet). Preserves EVERYTHING: multiple values per key, serialized arrays/objects (e.g. ACF repeaters), and exact scalar representations — the raw stored meta map is PHP serialize()'d on the source, base64-encoded IN CODE, and rebuilt on the destination with each stored value written back verbatim (no re-interpretation). It then re-reads the destination and compares a canonical PHP-native digest to the transferred payload; a mismatch is returned as verified=false, never silently trusted. By default ALL meta keys are synced and any destination keys not present on the source are removed (full mirror). Pass keys=[...] to sync only specific keys (destination keys outside that list are left untouched). Content never passes through the caller's text. Transport (local Docker vs Terminus vs SSH) is resolved per side from wp-cli.conf exactly like wp_cli. Writing to a production destination requires confirm=true when the PROD_GUARD is enabled.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesDestination environment to write meta TO. Must differ from 'from'.
fromYesSource environment to read meta FROM.
keysNoOptional allow-list of meta keys to copy (each must match [A-Za-z0-9_:.-]+). Omit to copy ALL keys and mirror the source (destination-only keys are deleted). When provided, only these keys are touched on the destination.
siteNoWhich configured site to target (matches a [site:NAME] section in wp-cli.conf). Omit for DEFAULT_SITE or the sole site.
to_envNoTerminus environment override for the DESTINATION when to='production'. Omit for TERMINUS_ENV.
confirmNoRequired to write to a production destination when the guard is enabled. Default: false.
post_idYesThe post ID whose meta to sync (SAME ID on both sides).
from_envNoTerminus environment override for the SOURCE when from='production'. Omit for TERMINUS_ENV.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses critical behavioral details: mandatory checksum round-trip verification, preservation of serialized data, verbatim write with no re-interpretation, re-reads destination for comparison, content not passing through caller's text, and transport resolution matching wp_cli. No annotations provided, so full burden is met.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is in a single paragraph but front-loads the core action and is concise given the complexity. Every sentence adds value, though some structure (e.g., bullet points) could improve readability. Still well within acceptable length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (8 parameters, no output schema), the description covers all essential aspects: verification process, transport, production guard, default mirroring, and parameter effects. No critical gaps for an agent to misuse the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 100% parameter description coverage, but the tool description adds significant context beyond the schema: explains the mirroring behavior of the 'keys' parameter, the role of 'confirm' with production guard, and the override purpose of 'from_env'/'to_env'. Goes beyond baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the verb 'SYNC' and resource 'post meta' with the specific action of transferring complete meta between environments with checksum verification. Distinguishes from sibling tool 'wp_clone_post' by explicitly noting it updates an existing post rather than creating one.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use: updates existing post, does not create (references wp_clone_post for creation). Explains default full mirror behavior and the effect of the 'keys' parameter. Mentions production guard requiring 'confirm=true'. Offers clear alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.4/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: wp_block operates on individual blocks, wp_cli runs generic WP-CLI commands, wp_clone_post copies posts to a new environment, wp_create_post creates new posts, wp_init_config sets up configuration, wp_sync_post syncs post content, and wp_sync_post_meta syncs meta. There is no overlap in functionality.

Naming Consistency3/5

Most tools follow a verb_noun pattern (wp_create_post, wp_sync_post, etc.), but wp_block and wp_cli are noun-only, breaking consistency. The prefix 'wp_' is consistent, but the mix of naming styles is noticeable.

Tool Count5/5

With 7 tools, the server is well-scoped for its purpose: managing WordPress posts, blocks, and configuration across environments. Each tool is essential and there are no redundant or extraneous tools.

Completeness4/5

The tool set covers the core workflow of cross-environment post management: creating, cloning, syncing content and meta, and block editing. Minor gaps exist (e.g., no dedicated tool for updating post fields like title or status), but these can be handled via the generic wp_cli tool, preserving the server's focus on safe, high-level operations.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/EarthmanWeb/mcp-wp-cli-terminus'

If you have feedback or need assistance with the MCP directory API, please join our Discord server