This reference, bundled with Skills 0.4.86, was checked against the registered schemas and execution boundaries of Companion 0.4.117 and Power 0.6.35. The confirmed count covers 414 Companion abilities, including 317 in the recommended Content profile, 440 combined Companion and Power schemas, 414 Companion tools, and 34 reviewed public paths. Free exposes exactly 34 Companion abilities. Explicitly approved abilities from other plugins may additionally appear depending on the installation. For the version actually installed, the schema returned by tools/list remains authoritative.
The documented Companion 0.4.117 and Power 0.6.35 release set, bundled with Skills 0.4.86, records 414 registered Companion abilities, including 317 in the recommended Content profile, 440 combined Companion and Power schemas, 414 Companion tools at the dedicated MCP endpoint, and 34 reviewed public paths. Without a paid licence, Free exposes exactly 34 of them without a call limit or site limit. The complete Companion surface and explicitly approved external plugin abilities require a paid licence. Power remains a separate plugin with its own off-by-default gates. The active ability profile can further reduce the visible subset.
Catalog counts and source-only signatures do not by themselves prove that every ability is available in every profile or provider state.
This reference covers exclusively the wp-agent-companion plugin (the "verified core"). The separate plugin wp-agent-power (raw-access/developer mode, including exec-php) is not documented here; it appears in this reference only insofar as wp-agent/disable-power can disable it as a panic switch.
Format per ability
Every entry contains: the full ability name (wp-agent/...), the purpose (from label and description), the input parameters (from input_schema, required fields from required), the output fields (from output_schema), the WordPress capability actually checked (from permission_callback and, where present, the fine-grained additional checks in execute_callback), a trait shorthand from meta.annotations (readonly/write, destructive yes/no, idempotent yes/no), and a brief example.
"Re-read-verified" means: the ability reads the target value back from the database after writing and reports a verified field in the output, instead of relying solely on the return value of the WordPress core function.
Dynamic JSON documents
Where a public ability exposes provider-defined or otherwise dynamic JSON, it does not publish an open MCP object. Native block attributes and supports use the closed, versioned {format,json,sha256,bytes} envelope. format is wpagently.native-block-json.v1; bytes and sha256 bind the UTF-8 JSON. The Spectra, GenerateBlocks, and Kadence attribute writers accept the same envelope and return it in written_attributes.
Elementor and Beaver Builder use their own closed builder-document envelope, {json,sha256,bytes}, for dynamic elements, settings, and patches. It intentionally has no format member. Before a response or mutation, the server decodes the value and validates it again against the documented provider boundary. A dynamic value that exceeds the applicable size, depth, or item limit, or cannot be normalized to the public contract, fails closed instead of being truncated. Static fields retain their individual schemas. The envelope neither expands the write allowlist nor opens other provider data.
The documented Companion 0.4.117 release set additionally wraps only explicitly allowlisted legacy dynamic provider values in {format,json,sha256,bytes}. Its format is either wpagently-json-object-v1 or wpagently-json-array-v1. This covers the SEO and post-schema paths, post, product, and variation readback, Fluent Forms fields and entries, Gravity Forms input, Formidable Forms, form migrations, and the dynamic sections of get-site-context. It applies only to the named dynamic value, not to the ability's other fields. Each document is limited to at most 2 MiB. The complete public input or output remains bounded to 8 MiB, 32 levels, and 16,384 values. New open shapes are rejected at registration. Dynamic maps remain permitted only with a fixed value schema and then have at most 256 properties. Their keys are 1-191 bytes long and contain no ASCII control characters.
The confirmed Live Editor uses a further separate {format,json,sha256,bytes} envelope with format=wpagently.live-editor-json.v1. Gutenberg receives attributes and blocks in this form; Elementor receives element, elements, settings, settings_patch, and style_patch. Live Editor command results use the same form under result. A request and every envelope within it are limited to 100,000 bytes. The envelopes do not replace visible confirmation, approval, or provider validation.
1. Content lifecycle (posts and pages)
wp-agent/create-post-from-markdown
Purpose: The plugin's sole remote write path for new content. Converts Markdown server-side into valid Gutenberg blocks and creates a new post. The optional post_id path only marks an update attempt and currently returns HTTP 409 with manual_only without mutation. It prevents the silent core/freeform fallback (Classic Editor fallback) and reports a block report. See also wp-agent/update-post: the existing-post path is currently manual-only as well.
Capability: edit_posts (coarse gate) plus a fine-grained post-type check for new posts: the create capability (wpagent_post_type_create_cap) and the matching edit capability of the target post type (e.g. edit_pages for post_type=page). A post_id is rejected with manual_only before a remote update.
Traits: create is write and non-destructive. update is manual_only. The flat annotations are remote_create=true and manual_only_update=true; idempotent is false.
| Parameter | Type | Required | Description |
|---|---|---|---|
markdown | string | yes | Article text in Markdown. |
title | string | yes | Post title. |
status | string (enum: draft, publish, pending, private) | no | Default draft. |
slug | string | no | |
excerpt | string | no | |
category | string | no | Category name; created if needed and set exclusively. |
post_id | integer | no | Marks an update attempt. The current contract returns HTTP 409 with manual_only and performs no mutation. |
post_type | string | no | Target type for new content, must be registered and public. No remote update is performed for the manual-only update attempt. |
expected_state_hash | string | no | Fresh content_state_hash from get-post, reserved for supervised update planning. The current update path does not mutate. |
| Output field | Type | Description |
|---|---|---|
post_id | integer | |
url | string | |
status | string | |
content_hash | string | SHA-256 of the converted content. |
content_state_hash | string | Full state hash of the newly created post. |
block_count | integer | |
freeform_count | integer | |
block_types | string[] | |
updated | boolean | false for a remote create; a manual-only update returns no success output. |
Example:
{ "title": "New blog post", "markdown": "# Heading\n\nText.", "status": "draft", "category": "SEO" }
A successful call creates a new post remotely. If post_id is supplied, the ability instead returns HTTP 409 with manual_only; no existing post is changed.
wp-agent/get-post
Purpose: Reads the core metadata of a post or page (any registered, public post type) including a block report, without needing a second render-check call.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id) (automatically resolves to the matching post-type capability, e.g. edit_pages).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | integer | yes |
| Output field | Type |
|---|---|
id, parent, menu_order, block_count, freeform_count | integer |
post_type, status, title, slug, excerpt, date, modified | string |
state_hash | string |
state_hash is the exact SHA-256 state for supervised update planning. The current update-post call keeps it in the documented input contract but returns HTTP 409 with manual_only before any remote mutation.
Example: { "post_id": 42 }
wp-agent/list-posts
Purpose: Lists posts or pages of a post type with search, status, and pagination filters as a lean list. The post type is generic but validated against registered, public types.
Capability: edit_posts (coarse) plus the edit capability responsible for the specific post_type (wpagent_post_type_edit_cap).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_type | string | no | Default post. |
status | string | no | Default any. |
search | string | no | |
per_page | integer | no | Default 20, capped at 100. |
page | integer | no | Default 1. |
| Output field | Type |
|---|---|
items[] | Objects with id, title, status, type, date, slug |
total | integer |
Example: { "post_type": "page", "status": "publish", "per_page": 10 }
wp-agent/update-post
Purpose: Preflight for a partial update of an existing post or page. The current remote writer is unavailable: the ability neither reads nor mutates the post, but returns HTTP 409 with manual_only. expected_state_hash remains part of the input contract but does not authorize a mutation. After a manual change, wp-agent/get-post can read the state again. The create mode of wp-agent/create-post-from-markdown remains a separate remote path.
Capability: edit_posts (coarse gate). The current callback exits before a post-specific remote check or mutation with manual_only.
Traits: manual-only, non-destructive, not idempotent. The current contract writes no post fields.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | integer | yes | |
expected_state_hash | string | yes | Exact state_hash from a fresh get-post call. The current execution returns HTTP 409 with manual_only regardless of the hash. |
title | string | no | |
content_markdown | string | no | Converted server-side into blocks, same as with create-post-from-markdown. |
excerpt | string | no | |
slug | string | no | |
status | string (enum: draft, publish, pending, private, future) | no | It is not changed remotely under the current contract. |
date | string | no | Parseable date/time, interpreted as site time when no timezone is given. |
menu_order | integer | no | |
parent | integer | no |
| Output field | Type | Description |
|---|---|---|
post_id | integer | |
post_type | string | |
written | object | Schema field from the former success contract. It is not present in the current manual_only result. |
verified | boolean | Schema field from the former success contract, not proof of a current mutation. |
block_count, freeform_count | integer | Schema fields for content_markdown; absent in manual_only. |
block_types | string[] | Schema field for content_markdown; absent in manual_only. |
has_freeform | boolean | Schema field for content_markdown; absent in manual_only. |
previous_state_hash, state_hash | string | Schema fields for a former verified update contract; absent in manual_only. |
Example:
{ "post_id": 42, "expected_state_hash": "<64-character SHA-256 from get-post>", "title": "New title" }
The current response is HTTP 409 with manual_only and recovery_required: false; WordPress receives no change. Edit the post under supervision in WordPress, then read it again with wp-agent/get-post.
wp-agent/set-post-status
Purpose: Preflights a requested post or page status transition (publish, draft, pending, private, future) against the complete state from get-post. The current lifecycle writer performs no remote mutation. After a fresh re-read and conflict-hash check, it returns HTTP 409 with manual_only before WordPress changes the status. A future date remains part of input validation for future.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id) plus the capability matching the target status (wpagent_check_post_status_cap, e.g. publish_posts for publish).
Traits: manual-only, non-destructive, not idempotent. The current contract does not mutate post status.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | integer | yes | |
status | string (enum: publish, draft, pending, private, future) | yes | |
date | string | for status=future | Must be in the future. |
| Output field | Type |
|---|---|
post_id | integer |
status | string |
verified | boolean |
Example: { "post_id": 42, "status": "publish" }
wp-agent/trash-post
Purpose: Preflights moving a post or page to the trash against the complete state from get-post. The current lifecycle writer performs no remote mutation and returns HTTP 409 with manual_only after a fresh re-read. The action must be completed in supervised WordPress administration. A manual trash action remains reversible through wp-agent/restore-post.
Capability: edit_posts (coarse) plus current_user_can('delete_post', $post_id).
Traits: manual-only, non-destructive, not idempotent. The current contract does not trash a post remotely.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
| Output field | Type |
|---|---|
post_id | integer |
status | string |
verified | boolean |
Example: { "post_id": 42 }
wp-agent/restore-post
Purpose: Preflights restoring a post or page from the trash against the complete state from get-post. The current lifecycle writer performs no remote mutation and returns HTTP 409 with manual_only after a fresh re-read. The action must be completed in supervised WordPress administration. There, the earlier status from _wp_trash_meta_status may be restored; future remains excluded because of the risk of immediate cron publishing.
Capability: edit_posts (coarse) plus current_user_can('delete_post', $post_id).
Traits: manual-only, non-destructive, not idempotent. The current contract does not restore a post remotely.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
| Output field | Type |
|---|---|
post_id | integer |
status | string |
restored | boolean |
verified | boolean |
Example: { "post_id": 42 }
wp-agent/delete-post
Purpose: Without force: behaves like trash-post. With force=true: deletes permanently via wp_delete_post($id, true), regardless of current status. Refuses to delete pages configured as the front page/posts page (wpagent_check_protected_post).
Capability: edit_posts (coarse) plus current_user_can('delete_post', $post_id).
Traits: write, destructive (real data loss only with force=true), idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | integer | yes | |
force | boolean | no | Default false. true = permanent and irreversible. |
| Output field | Type |
|---|---|
post_id | integer |
forced, trashed, deleted, verified | boolean |
Example: { "post_id": 42, "force": false }
wp-agent/search-replace-content
Purpose: Finds a literal string in the title, excerpt, or content of public posts and replaces it within strict bounds. Dry-run is the default. At most 1,000 candidates are scanned and at most 100 posts are changed per operation. HTML structure, block comments, and proprietary builder storage are rejected. Every real change is read back and linked to a seven-day undo snapshot.
Capability: edit_posts plus current_user_can('edit_post', $post_id) for every match.
Traits: write, non-destructive, not idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
search, replace | string | yes | Different literal values, at most 200 bytes each. |
fields | string[] | no | title, excerpt, content; all three by default. |
post_types, statuses, post_ids | arrays | no | Limit the search to public types, safe statuses, or at most 100 IDs. |
limit | integer | no | 1 to 100, default 100. |
dry_run | boolean | no | Default true. |
Output: dry_run, matched_posts, updated_posts, total_replacements, items, operation_id, verified.
Example: { "search": "490 dollars", "replace": "590 dollars", "post_types": ["page"], "dry_run": true }
wp-agent/undo-content-replace
Purpose: Restores the complete previous state of an operation created by search-replace-content. Before writing and again under an exclusive lock, it verifies that every affected field still exactly matches the replacement result. Any intervening change rejects the entire restore.
Capability: edit_posts plus edit_post for every affected post. Only the operation creator or a user with manage_options may undo it.
Traits: write, non-destructive, idempotent.
Input: operation_id (required), dry_run (default true). Output: dry_run, restorable_posts, undone, verified.
Example: { "operation_id": "123e4567-e89b-12d3-a456-426614174000", "dry_run": false }
2. Taxonomies
wp-agent/create-term
Purpose: Creates a new term in a taxonomy (e.g. category or tag). parent is only allowed for hierarchical taxonomies. Re-read-verified per field.
Capability: edit_posts (coarse) plus the manage_terms capability of the specific taxonomy (get_taxonomy($tax)->cap->manage_terms, fail-closed to do_not_allow).
Traits: write, non-destructive, idempotent (a duplicate name is rejected by wp_insert_term()).
| Parameter | Type | Required | Description |
|---|---|---|---|
taxonomy | string | yes | Must be registered (e.g. category, post_tag). |
name | string | yes | |
slug | string | no | |
parent | integer | no | Only for hierarchical taxonomies. |
description | string | no |
| Output field | Type |
|---|---|
term_id, parent | integer |
taxonomy, name, slug | string |
written | object |
verified | boolean |
Example: { "taxonomy": "category", "name": "WordPress" }
wp-agent/get-term
Purpose: Reads a single term (name, slug, description, parent term, count of assigned objects).
Capability: edit_posts (coarse) plus the weakest standard taxonomy capability, assign_terms (minimal sensible read gate).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
term_id | integer | yes |
taxonomy | string | yes |
| Output field | Type |
|---|---|
id, parent, count | integer |
taxonomy, name, slug, description | string |
Example: { "term_id": 5, "taxonomy": "category" }
wp-agent/list-terms
Purpose: Lists terms of a taxonomy with search, hide_empty, and parent-term filters. number caps the result count (default 100, maximum 500).
Capability: edit_posts (coarse) plus assign_terms of the specific taxonomy.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
taxonomy | string | yes | |
search | string | no | |
hide_empty | boolean | no | Default false. |
parent | integer | no | Only direct child terms. |
number | integer | no | Default 100, capped at 500. |
| Output field | Type |
|---|---|
items[] | Objects with id, name, slug, taxonomy, parent, count, description |
count | integer |
Example: { "taxonomy": "post_tag", "hide_empty": true, "number": 50 }
wp-agent/update-term
Purpose: Partial update of an existing term (name, slug, parent term, description). A term must not be its own parent term.
Capability: edit_posts (coarse) plus edit_terms of the specific taxonomy.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
term_id | integer | yes | |
taxonomy | string | yes | |
name | string | no | |
slug | string | no | |
parent | integer | no | Only for hierarchical taxonomies. |
description | string | no |
| Output field | Type |
|---|---|
term_id | integer |
taxonomy | string |
written | object |
verified | boolean |
Example: { "term_id": 5, "taxonomy": "category", "name": "WordPress Tutorials" }
wp-agent/delete-term
Purpose: Permanently deletes a term from a taxonomy (no trash for terms in WordPress). Refuses to delete a taxonomy's default term (e.g. the default category).
Capability: edit_posts (coarse) plus delete_terms of the specific taxonomy.
Traits: write, destructive, idempotent (the end state "no longer exists" doesn't change on repetition).
| Parameter | Type | Required |
|---|---|---|
term_id | integer | yes |
taxonomy | string | yes |
| Output field | Type |
|---|---|
term_id | integer |
taxonomy | string |
deleted, verified | boolean |
Example: { "term_id": 12, "taxonomy": "post_tag" }
wp-agent/set-post-terms
Purpose: Assigns taxonomy terms to a post. Entries may be term IDs (integer, must exist) or names (string, created if needed). append=false (default) replaces all of the post's existing terms for that taxonomy.
Capability: current_user_can('edit_post', $post_id) plus assign_terms of the specific taxonomy.
Traits: write, non-destructive (overwrite, no irreversible loss), idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | integer | yes | |
taxonomy | string | yes | Must be assigned to the post type. |
terms | array (integer|string) | yes | An empty array removes all terms of this taxonomy when append=false. |
append | boolean | no | Default false. |
| Output field | Type |
|---|---|
post_id | integer |
taxonomy | string |
append | boolean |
terms[] | Objects with id, name, slug |
written[] | Objects with input, matched |
verified | boolean |
Example: { "post_id": 42, "taxonomy": "category", "terms": ["SEO", 7], "append": true }
3. Media
wp-agent/upload-media
Purpose: Downloads an image from a public http(s) URL and creates it as a new media item via media_handle_sideload(). Alt text is required and is re-read-verified. SSRF-protected: only http/https, localhost/.localhost blocked, every resolved DNS address (A and AAAA) as well as every redirect hop (maximum 3) is checked against private/loopback/link-local ranges (FILTER_FLAG_NO_PRIV_RANGE/FILTER_FLAG_NO_RES_RANGE), fail-closed for unresolvable hosts.
Capability: upload_files.
Traits: write, non-destructive, not idempotent (every call creates a new media item).
| Parameter | Type | Required | Description |
|---|---|---|---|
source_url | string | yes | Public http(s) URL. |
alt | string | yes | Not empty. |
post_id | integer | no | Default 0 (unattached). Parent post. |
| Output field | Type |
|---|---|
media_id, post_id | integer |
url, mime_type, alt | string |
verified | boolean |
Example: { "source_url": "https://example.com/image.jpg", "alt": "Product photo, front view" }
wp-agent/create-direct-media-upload
Purpose: Prepares a direct upload of a local file. The file does not pass through REST or MCP and does not need a public intermediary URL. The ability returns a POST endpoint and the required headers. The client then sends the raw file bytes as application/octet-stream.
Capability: valid Companion gate, a connected safe Editor without Administrator or Super Administrator privileges, and upload_files. A parent post additionally requires edit_post.
Traits: write, non-destructive, not idempotent. A new call replaces the same user's pending slot. The 256-bit token is valid for five minutes and one use, appears only in the X-WPAgent-Upload-Token header, and is stored server-side only as a SHA-256 hash. HTTPS is mandatory outside local development environments. The limit is the smaller of the WordPress server limit and 64 MiB. The filename, permitted WordPress file type, actual MIME content, image alt text, parent permission, file size, and unmodified transfer are validated fail-closed.
| Parameter | Type | Required | Description |
|---|---|---|---|
filename | string | yes | Local basename without a path. Its extension must map to a WordPress MIME type allowed for the Editor. |
alt | string | for images | Non-empty alt text. Optional for other media types. |
post_id | integer | no | Default 0. Optional parent post. |
max_bytes | integer | no | Optional smaller limit for this slot. |
| Output field | Type |
|---|---|
url, method, expires_at, filename | string |
user_id, post_id, max_bytes | integer |
one_time | boolean |
headers | object with X-WPAgent-Upload-Token and Content-Type |
After a successful upload, the HTTP endpoint responds with attachment_id, post_id, the actual stored filename, mime_type, bytes, alt, url, and verified=true. The file, size, MIME type, author, parent post, URL, and alt text are re-read after saving. A mismatch deletes the new attachment.
wp-agent/revoke-direct-media-upload
Purpose: Revokes the current safe Editor's pending direct-upload slot.
Capability: same as create-direct-media-upload.
Traits: write, non-destructive, idempotent. The output contains revoked as a Boolean.
wp-agent/set-alt-text
Purpose: Sets the alt text of an existing media item (_wp_attachment_image_alt). An empty string is a valid target value (deliberate clearing is possible).
Capability: edit_posts (coarse) plus current_user_can('edit_post', $attachment_id).
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
attachment_id | integer | yes |
alt | string | yes |
| Output field | Type |
|---|---|
attachment_id | integer |
alt | string |
verified | boolean |
Example: { "attachment_id": 88, "alt": "Team photo at the summer party" }
wp-agent/set-featured-image
Purpose: Sets an existing media item as the featured image (_thumbnail_id) of a post or page via set_post_thumbnail(). Only edit_post on the target post is needed, no separate permission on the media item (mirrors WordPress's own REST API behavior for featured_media).
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
attachment_id | integer | yes |
| Output field | Type |
|---|---|
post_id, attachment_id | integer |
verified | boolean |
Example: { "post_id": 42, "attachment_id": 88 }
wp-agent/delete-media
Purpose: Without force: moves to the trash (directly via wp_trash_post(), regardless of the WordPress constant MEDIA_TRASH, which is unset by default). With force=true: deletes permanently including the file via wp_delete_attachment().
Capability: edit_posts (coarse) plus current_user_can('delete_post', $attachment_id).
Traits: write, destructive (only with force=true), idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
attachment_id | integer | yes | |
force | boolean | no | Default false. |
| Output field | Type |
|---|---|
attachment_id | integer |
forced, trashed, deleted, verified | boolean |
Example: { "attachment_id": 88, "force": false }
wp-agent/list-media
Purpose: Lists media items (post_type=attachment, post_status=inherit, excluding trash) with search, MIME-type, and pagination filters.
Capability: upload_files.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
search | string | no | |
mime_type | string | no | Full MIME type or prefix. |
per_page | integer | no | Default 20, capped at 100. |
page | integer | no | Default 1. |
| Output field | Type |
|---|---|
items[] | Objects with id, title, url, mime_type, alt, date |
total | integer |
Example: { "mime_type": "image", "per_page": 20 }
4. Menus
All five menu abilities share the same capability, edit_theme_options. This capability is, in WordPress's core roles, assigned exclusively to Administrators, not to the Editor role (wp-admin/includes/schema.php, populate_roles_300()). Menu management is Admin territory in WordPress itself, so a Companion bot set up as Editor gets a 403 from every ability in this group unless it is upgraded to Administrator.
wp-agent/create-menu
Purpose: Creates a new navigation menu (nav_menu taxonomy term). A duplicate menu name is reported as a user error (400), not a server error.
Traits: write, non-destructive, idempotent (a name conflict fails in a controlled way instead of creating a second menu).
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | Must be unique within the site. |
| Output field | Type |
|---|---|
menu_id | integer |
name | string |
verified | boolean |
Example: { "name": "Main menu" }
wp-agent/add-menu-item
Purpose: Adds a new item to an existing menu: either a custom link (object=custom, requires url) or a reference to an existing object (object=page/post/category, requires object_id). Optionally as a sub-item via parent (must be an item in the same menu).
Traits: write, non-destructive, not idempotent (wp_update_nav_menu_item($menu_id, 0, ...) creates a new item on every call; there is no update key).
| Parameter | Type | Required | Description |
|---|---|---|---|
menu_id | integer | yes | |
title | string | yes | Visible text. |
object | string (enum: custom, page, post, category) | yes | |
object_id | integer | if object != custom | |
url | string | if object=custom | |
parent | integer | no | An item in the same menu. |
| Output field | Type |
|---|---|
item_id, menu_id, object_id, parent | integer |
title, type, object, url | string |
verified | boolean |
Example: { "menu_id": 3, "title": "Blog", "object": "page", "object_id": 10 }
wp-agent/list-menus
Purpose: Lists all existing navigation menus as a lean list.
Traits: read, non-destructive, idempotent.
No input parameters.
| Output field | Type |
|---|---|
items[] | Objects with id, name, slug, count |
total | integer |
Example: {}
wp-agent/assign-menu-location
Purpose: Assigns a menu to a location registered by the active theme (e.g. primary). Locations are not a database entity but come from $_wp_registered_nav_menus; the assignment itself lives in the theme mod nav_menu_locations and therefore doesn't automatically survive a theme switch.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
menu_id | integer | yes | |
location | string | yes | Must be registered by the active theme. |
| Output field | Type |
|---|---|
menu_id, previous_menu_id | integer |
location | string |
verified | boolean |
Example: { "menu_id": 3, "location": "primary" }
wp-agent/delete-menu
Purpose: Permanently deletes a navigation menu, including all menu items, and removes it from every location it was assigned to. No trash equivalent for menus.
Traits: write, destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
menu_id | integer | yes |
| Output field | Type |
|---|---|
menu_id | integer |
deleted, verified | boolean |
Example: { "menu_id": 3 }
5. Settings
All three abilities share the same fixed allowlist WPAGENT_SETTINGS_ALLOWLIST (includes/settings-allowlist.php): blogname, blogdescription, posts_per_page, show_on_front, page_on_front, page_for_posts, permalink_structure, timezone_string, start_of_week, date_format, time_format, default_category. In addition to the allowlist, a hard denylist always applies: siteurl, home, active_plugins, wp_user_roles, users_can_register, admin_email, as well as any option name containing salt, key, or secret as a substring, are never readable or writable, even if they were accidentally in the allowlist.
wp-agent/get-setting
Purpose: Reads a single setting from the allowlist.
Capability: manage_options.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
name | string | yes |
| Output field | Type |
|---|---|
name | string |
exists | boolean |
value | any |
Example: { "name": "blogname" }
wp-agent/update-setting
Purpose: Sets a setting from the writable allowlist. Every name goes through its own type/enum/existence check before writing. Two special cases are handled explicitly: (1) show_on_front/page_on_front/page_for_posts are checked for logical consistency (show_on_front=page without a set page_on_front is rejected; page_on_front and page_for_posts must not be the same page); (2) permalink_structure runs via $wp_rewrite->set_permalink_structure() followed by flush_rewrite_rules(), because a raw update_option() call alone would not update the active rewrite rules.
Capability: manage_options.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | From the writable allowlist. |
value | any | yes | Type depends on the name (string, integer, or enum string). |
| Output field | Type |
|---|---|
name | string |
value | any |
verified | boolean |
actions[] | string[] |
Example: { "name": "posts_per_page", "value": 12 }
wp-agent/list-settings
Purpose: Lists all settings from the allowlist with their current value, without needing to query each setting individually via get-setting.
Capability: manage_options.
Traits: read, non-destructive, idempotent.
No input parameters.
| Output field | Type |
|---|---|
items[] | Objects with name, exists, value |
total | integer |
Example: {}
wp-agent/get-ase-free-generator-tag
Purpose: Reads only the verified ASE Free switch that removes the WordPress generator meta tag. The path applies only to Admin and Site Enhancements Free 9.0.0 and also reports whether its parent “Disable Smaller Components” group is enabled.
Capability: manage_options.
Traits: read, non-destructive, idempotent. No parameters.
| Output field | Type |
|---|---|
provider_version | string, exactly 9.0.0 |
smaller_components_enabled, generator_tag_disabled | boolean |
state_hash | SHA-256 over the blog, provider version, and unchanged provider state |
Example: {}
wp-agent/update-ase-free-generator-tag
Purpose: Changes only that ASE Free switch. The path requires the current conflict hash, binds the mutation to the WordPress blog, uses an atomic compare with a renewable lock, and reads the stored provider state back exactly. If the state is unsafe after writing, it returns recovery_required without an automatic follow-up mutation.
Capability: manage_options.
Traits: write, non-destructive, idempotent. ASE Free 9.0.0 and a manually enabled “Disable Smaller Components” group are prerequisites.
| Parameter | Type | Required |
|---|---|---|
disabled | boolean | yes |
expected_hash | SHA-256 from get-ase-free-generator-tag | yes |
| Output field | Type |
|---|---|
provider_version, smaller_components_enabled, generator_tag_disabled, state_hash | as on the read path |
verified, effective_after_new_request | boolean |
Example: { "disabled": true, "expected_hash": "<64-character SHA-256 from get-ase-free-generator-tag>" }
6. Comments
All four abilities share the coarse gate moderate_comments; a fine-grained edit_comment/edit_post check against the specific target is always additionally applied (see below for each), analogous to the content lifecycle pattern.
wp-agent/list-comments
Purpose: Lists comments with optional post, status, and pagination filters plus a total count.
Capability: moderate_comments.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | integer | no | |
status | string | no | Default all (approved + pending, excluding spam/trash). Accepts, among others, hold, approve, spam, trash, all, any. |
per_page | integer | no | Default 20, capped at 100. |
page | integer | no | Default 1. |
| Output field | Type |
|---|---|
items[] | Objects with id, post_id, parent, author, author_email, content, status, date |
total | integer |
Example: { "post_id": 42, "status": "hold" }
wp-agent/moderate-comment
Purpose: Sets an existing comment's status directly (approve, hold, spam, trash). Explicitly handles the vocabulary difference between the input (hold) and the return value of wp_get_comment_status() (unapproved), so the re-read verification doesn't fail falsely.
Capability: moderate_comments (coarse) plus current_user_can('edit_comment', $comment_id).
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
comment_id | integer | yes |
status | string (enum: approve, hold, spam, trash) | yes |
| Output field | Type |
|---|---|
comment_id | integer |
status | string |
verified | boolean |
Example: { "comment_id": 15, "status": "approve" }
wp-agent/reply-to-comment
Purpose: Creates a new, immediately approved comment: either as a reply to an existing comment (comment_id, becomes its child) or as a top-level comment on a post (post_id). Exactly one of the two is required. The author is always the currently logged-in user (the bot), never anonymous. Deliberately uses wp_insert_comment() instead of the public-facing wp_new_comment(), to bypass flood/duplicate checks meant for anonymous visitors and the comment_status=open check (the caller is already privileged).
Capability: moderate_comments (coarse) plus, depending on the target, edit_comment (for comment_id) or edit_post (for post_id).
Traits: write, non-destructive, not idempotent (every call creates a new comment).
| Parameter | Type | Required | Description |
|---|---|---|---|
comment_id | integer | no | Comment being replied to. |
post_id | integer | no | Post for a top-level comment, if comment_id is absent. |
content | string | yes |
| Output field | Type |
|---|---|
comment_id, post_id, parent, author_id | integer |
verified | boolean |
Example: { "comment_id": 15, "content": "Thanks for the heads-up, we'll look into it." }
wp-agent/delete-comment
Purpose: Without force: safe trash behavior (a no-op if already trashed or marked as spam, because wp_delete_comment() would otherwise permanently delete such comments even without force_delete=true). With force=true: deletes permanently, regardless of current status.
Capability: moderate_comments (coarse) plus current_user_can('edit_comment', $comment_id) (delete_comment is not a registered meta-capability case in WordPress and would otherwise always return false).
Traits: write, destructive (only with force=true), idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
comment_id | integer | yes | |
force | boolean | no | Default false. |
| Output field | Type |
|---|---|
comment_id | integer |
forced, trashed, deleted, verified | boolean |
Example: { "comment_id": 15, "force": false }
7. Users
The entire user management group is heavily gated: all five capabilities (list_users, edit_users, promote_users, create_users, delete_users) are reserved exclusively for Administrators in a default installation. The Companion bot, set up as Editor, always gets a 403 here.
wp-agent/list-users
Purpose: Lists WordPress users with role, search, and pagination filters.
Capability: list_users.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
role | string | no | Must be registered. Without it: all roles. |
search | string | no | |
per_page | integer | no | Default 20, capped at 100. |
page | integer | no | Default 1. |
| Output field | Type |
|---|---|
items[] | Objects with id, username, display_name, email, roles[], registered |
total | integer |
Example: { "role": "editor" }
wp-agent/get-user
Purpose: Reads a single user's profile data. Never returns the password hash field (user_pass), the password reset key, or session tokens; the result is deliberately assembled field by field from WP_User.
Capability: edit_users (the capability WordPress itself requires for access to a single user profile, not the leaner list_users).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
user_id | integer | yes |
| Output field | Type |
|---|---|
id | integer |
username, email, display_name, first_name, last_name, registered, url | string |
roles[] | string[] |
Example: { "user_id": 3 }
wp-agent/set-user-role
Purpose: Sets an existing user's role directly (replaces all existing roles with exactly one). Two hard, unbypassable protections: user ID 1 is never changed, and the calling account (i.e. the bot itself) may never change its own role. Additional soft gate: roles with the manage_options capability (administrator-equivalent) require the explicit flag i_grant_admin=true.
Capability: promote_users (the capability WordPress itself ties role changes to, not the broader edit_users).
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | integer | yes | |
role | string | yes | Must be registered. |
i_grant_admin | boolean | no | Default false. Required true for administrator-equivalent roles. |
| Output field | Type |
|---|---|
user_id | integer |
role | string |
verified | boolean |
Example: { "user_id": 7, "role": "author" }
wp-agent/create-user
Purpose: Creates a new user via wp_insert_user(). Without a password, a strong password is generated server-side and returned once in the result (generated_password, never appears in later read operations). Same administrator gate as set-user-role.
Capability: create_users.
Traits: write, non-destructive, not idempotent (a duplicate username fails at the WordPress core level instead of reporting the same state).
| Parameter | Type | Required | Description |
|---|---|---|---|
username | string | yes | |
email | string | yes | |
role | string | yes | Must be registered. |
password | string | no | Without it, one is generated. |
i_grant_admin | boolean | no | Default false. |
| Output field | Type | Description |
|---|---|---|
user_id | integer | |
username, email, role | string | |
password_generated | boolean | |
generated_password | string | Only present if password_generated=true. |
verified | boolean |
Example: { "username": "new.author", "email": "author@example.com", "role": "author" }
wp-agent/delete-user
Purpose: Permanently deletes a user via wp_delete_user() (no trash for users). Forces an explicit decision about the user's content: either reassign_to (content is taken over) or delete_content=true (content is deliberately deleted along with the user); if both are missing, the ability aborts with 400. User ID 1 and the calling account itself may never be deleted.
Capability: delete_users.
Traits: write, destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | integer | yes | |
reassign_to | integer | no | Target user for content takeover. |
delete_content | boolean | no | Default false. Alternative to reassign_to. |
| Output field | Type |
|---|---|
user_id, reassigned_to | integer |
content_deleted, deleted, verified | boolean |
Example: { "user_id": 9, "reassign_to": 2 }
8. Plugins and themes
wp-agent/list-plugins
Purpose: Lists installed plugins with file path, name, version, and active status. Serves as an independent re-read source for activate-plugin/deactivate-plugin.
Capability: activate_plugins.
Traits: read, non-destructive, idempotent.
No input parameters.
| Output field | Type |
|---|---|
items[] | Objects with file, name, version, active |
total | integer |
Example: {}
wp-agent/activate-plugin
Purpose: Activates an installed plugin and verifies via re-read (is_plugin_active). Catches throwables from a faulty plugin hook instead of taking down the whole REST request (genuine, uncatchable PHP fatals like memory limit/timeout remain a WordPress core edge case). wp-agent-companion and wp-agent-power are hard-excluded (self-protection).
Capability: activate_plugins.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
plugin_file | string | yes | Relative path as returned by get_plugins(), e.g. akismet/akismet.php. |
| Output field | Type |
|---|---|
plugin_file | string |
active, verified | boolean |
Example: { "plugin_file": "akismet/akismet.php" }
wp-agent/deactivate-plugin
Purpose: Deactivates an installed plugin and verifies via re-read. wp-agent-companion and wp-agent-power can never be deactivated through this ability (use wp-agent/disable-power specifically for power mode).
Capability: activate_plugins.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
plugin_file | string | yes |
| Output field | Type |
|---|---|
plugin_file | string |
active, verified | boolean |
Example: { "plugin_file": "hello-dolly/hello.php" }
wp-agent/list-themes
Purpose: Lists installed themes with stylesheet folder name, name, version, and active status.
Capability: switch_themes (the same capability as switch-theme; shares the scope analogously to list-plugins/activate-plugin; also not granted to Editor by WordPress by default).
Traits: read, non-destructive, idempotent.
No input parameters.
| Output field | Type |
|---|---|
items[] | Objects with stylesheet, name, version, active |
total | integer |
Example: {}
wp-agent/switch-theme
Purpose: Switches the active theme. Rejects unknown, faulty themes (WP_Theme::errors(), which goes beyond the plain exists() check) or themes incompatible with the current WP/PHP version up front, instead of activating them or letting switch_theme() internally trigger wp_die().
Capability: switch_themes.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
stylesheet | string | yes | Theme folder name, e.g. twentytwentyfive. |
| Output field | Type |
|---|---|
stylesheet, previous_stylesheet | string |
verified | boolean |
Example: { "stylesheet": "twentytwentyfive" }
9. Reusable blocks
Post type wp_block (Gutenberg synced patterns). wpagent_validate_post_type() is deliberately not used for this post type, because wp_block is registered in WordPress core with 'public' => false, and this generic allowlist check would otherwise falsely deny access.
wp-agent/create-reusable-block
Purpose: Creates a reusable block from Markdown. The server turns it into allowed Core blocks. Already-serialized block markup and free HTML are not accepted. The block is always created as publish, because core/block only renders a referenced block at this status (a block created as draft would silently stay empty on every page that embeds it).
Capability: edit_posts (coarse) plus the actual creation capability for wp_block: publish_posts (WordPress core comment: "You need to be able to publish posts, in order to create blocks"), not the usual create_posts/edit_posts.
Traits: write, non-destructive, not idempotent (every call creates a new wp_block post).
| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | yes | |
content_markdown | string | yes | Converted server-side into allowed Gutenberg Core blocks. |
| Output field | Type |
|---|---|
block_id | integer |
status | string |
written | object |
verified, has_freeform | boolean |
block_count, freeform_count | integer |
block_types | string[] |
Example: { "title": "Newsletter CTA box", "content_markdown": "**Sign up now!**" }
wp-agent/update-reusable-block
Purpose: Partial update of the title and/or content of an existing reusable block. No status field: a status change away from publish would silently make core/block references empty on every page that embeds it; use wp-agent/set-post-status deliberately for that instead.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $block_id).
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
block_id | integer | yes | Must be an existing wp_block post, otherwise 404. |
title | string | no | |
content_markdown | string | no | Converted server-side into allowed Gutenberg Core blocks. Raw block markup and HTML are rejected. |
| Output field | Type |
|---|---|
block_id | integer |
written | object |
verified, has_freeform | boolean |
block_count, freeform_count | integer |
block_types | string[] |
Example: { "block_id": 55, "title": "Newsletter CTA box (revised)" }
wp-agent/list-reusable-blocks
Purpose: Lists reusable blocks with search, status, and pagination filters. No post_type parameter; hardwired to wp_block.
Capability: edit_posts (coarse) plus explicitly the read capability responsible for wp_block (literally mapped to edit_posts in core).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | no | Default any. |
search | string | no | |
per_page | integer | no | Default 20, capped at 100. |
page | integer | no | Default 1. |
| Output field | Type |
|---|---|
items[] | Objects with id, title, status, date, slug |
total | integer |
Example: { "per_page": 10 }
wp-agent/delete-reusable-block
Purpose: Without force: moves to the trash. With force=true: deletes permanently. No wpagent_check_protected_post() call needed: page_on_front/page_for_posts can only point to post_type=page, and a wp_block can never take on that role.
Capability: edit_posts (coarse) plus current_user_can('delete_post', $block_id).
Traits: write, destructive (only with force=true), idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
block_id | integer | yes | |
force | boolean | no | Default false. |
| Output field | Type |
|---|---|
block_id | integer |
forced, trashed, deleted, verified | boolean |
Example: { "block_id": 55, "force": false }
10. SEO
wp-agent/get-seo-meta
Purpose: Reads stored post-level SEO data from Rank Math, Yoast, AIOSEO, or SEOPress through the provider's effective storage or Ability path and returns one normalized shape. Without a supported active SEO plugin, the Ability fails closed with HTTP 409. robots_noindex and robots_nofollow report the provider's post-level flags. Global SEO defaults are not misrepresented as stored post overrides. AIOSEO post-SEO runtime coverage is currently evidenced only on MariaDB; MySQL and SQLite are outside this evidence. A successful output is closed and contains every field listed below, including state_hash.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
| Output field | Type |
|---|---|
post_id | integer |
plugin | string |
seo_title, seo_description, focus_keyword, canonical_url | string |
robots_noindex, robots_nofollow | boolean |
open_graph_title, open_graph_description | string |
twitter_title, twitter_description | string |
cornerstone_supported | boolean |
cornerstone | boolean or null |
state_hash | string |
Example: { "post_id": 42 }
wp-agent/set-seo-meta
Purpose: Detects Rank Math, Yoast, AIOSEO, or SEOPress through their runtime APIs and preflights the requested post fields before a possible manual change. The current public writer performs no remote mutation for any provider. After input validation, a fresh provider re-read, and a conflict-hash check, it returns HTTP 409 with manual_only before the first provider write because no complete conditional provider write path is currently proven. This covers title, description, focus keyword, canonical URL, robots flags, and Open Graph and X/Twitter text for Rank Math, Yoast, AIOSEO, and SEOPress. get-seo-meta remains the provider-neutral read path. Changes currently belong in the relevant plugin administration UI and should then be read again. AIOSEO post-SEO read-path runtime coverage is practically evidenced only on MariaDB with transactional InnoDB tables; MySQL and SQLite are outside this runtime evidence. Without a supported active SEO plugin, the Ability also fails closed with HTTP 409 instead of storing ineffective fallback fields.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: manual-only, non-destructive, not idempotent. The current contract does not mutate provider state.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
seo_title | string | no |
seo_description | string | no |
focus_keyword | string | no |
canonical_url | string | no |
robots_noindex, robots_nofollow | boolean | no |
open_graph_title, open_graph_description | string | no |
twitter_title, twitter_description | string | no |
cornerstone | boolean | no, Rank Math and Yoast only |
| Output field | Type | Description |
|---|---|---|
post_id | integer | |
plugin | string | rankmath, yoast, aioseo, or seopress. Without a supported plugin, the call returns an error. |
written | object | At least { persisted } for every supplied field; direct meta paths also include meta_key. With rolled_back:true, this describes the failed write attempt before rollback, not the restored final state. |
verified | boolean | |
indexable_verified | boolean or null | For Yoast, true when the effective Meta Surface agrees with the written output fields. null for the other providers. |
rolled_back | boolean | true when WPAgently restored the previous state after a failed or unverified write. |
rollback_verified | boolean or null | For a rollback, true when the restored provider state was read back and confirmed. null without a rollback. false requires immediate manual inspection. |
In the current runtime contract, set-seo-meta returns HTTP 409 with manual_only before any provider mutation. The following success fields remain documented for schema compatibility and are not returned as a successful write in this manual result.
Example: { "post_id": 42, "seo_title": "Best WordPress Hosting 2026", "focus_keyword": "wordpress hosting" }
wp-agent/get-seo-settings
Purpose: Reads global title templates, archive rules, and identity data from the active Rank Math, Yoast SEO, AIOSEO, or SEOPress installation through one normalized contract. supported_fields describes the fields exposed by the normalized provider read path. It does not currently authorize a remote write because set-seo-settings returns HTTP 409 with manual_only after a fresh re-read and conflict-hash check, before any mutation. If an existing template contains an unknown native provider token, the field appears in unmapped_template_fields and remains readable but read-only. homepage_source distinguishes a global homepage from a static page. Templates use only the WPAgently placeholders returned in template_tokens. The complete raw state of the affected provider options contributes to state_hash but is never exposed.
Capability: manage_options.
Traits: read, non-destructive, idempotent.
The Ability takes no input. Its output contains plugin, supported_fields, unmapped_template_fields, template_syntax, template_tokens, homepage_source, settings, and the 64-character state_hash.
wp-agent/set-seo-settings
Purpose: Preflights a bounded subset of global SEO settings against the immediately preceding provider read. Depending on the plugin, this includes the title separator, global homepage templates, author, date, and search archives, identity, logo, and website names. Provider-native placeholders, HTML, control characters, line breaks, and surrounding whitespace are still rejected. After input validation, a fresh re-read, and the expected_hash check, the current writer returns HTTP 409 with manual_only for every provider before any mutation. Changes currently belong in the relevant plugin administration UI and should then be read again through get-seo-settings.
Capability: manage_options.
Traits: manual-only, non-destructive, not idempotent. The current contract does not mutate provider state.
expected_hash and a non-empty partial settings object are required. The authoritative field list is supported_fields from the immediately preceding read. Output includes plugin, the field-level written report, verified, rolled_back, rollback_verified, previous_hash, and the new state_hash.
In the current runtime contract, set-seo-settings returns HTTP 409 with manual_only before any provider mutation. The named success fields remain documented for schema compatibility and are not returned as a successful write in this manual result.
Example: { "expected_hash": "<64 hex>", "settings": { "homepage_title_template": "{{site_name}} {{separator}} {{tagline}}", "search_noindex": true } }
wp-agent/get-post-schema
Purpose: Reads custom Rank Math schemas with their stable schema_id values or Yoast's stored page and article types. It includes the provider's available type catalog and a SHA-256 state_hash for the complete managed state. AIOSEO and SEOPress fail closed with HTTP 409 because no equivalent post-schema path has been confirmed.
Capability: edit_posts plus edit_post. Rank Math additionally requires rank_math_onpage_snippet.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
wp-agent/set-post-schema
Purpose: Creates a Rank Math schema or updates exactly one existing schema by schema_id. New types must be available in the active Rank Math catalog and require a reusable idempotency_key. Size, depth, node count, keys, internal shortcode ID, primary status, and provider permissions are validated before the native write path runs. For Yoast, the Ability accepts only confirmed page_type and article_type values. An empty type removes the corresponding Yoast override. expected_hash, read-back, a per-post lock, and rollback protect against stale, silent, or concurrent failed mutations.
Capability: edit_posts plus edit_post. Rank Math additionally requires rank_math_onpage_snippet.
Traits: write, non-destructive, idempotent through schema_id or idempotency_key.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
expected_hash | string | yes, exact state_hash from get-post-schema |
idempotency_key | string | for a new Rank Math schema, 8-64 safe characters |
schema_id | string | no, for a Rank Math update |
schema | object | for Rank Math |
page_type, article_type | string | at least one for Yoast |
Example: { "post_id": 42, "expected_hash": "<64 hex>", "page_type": "AboutPage" }
wp-agent/delete-post-schema
Purpose: Deletes exactly one custom Rank Math schema. The stable schema_id must be repeated exactly as confirm_schema_id. The current complete state_hash covers the schema data, Rank Math's rich-snippet status, and internal shortcode mappings. The delete path disables rich snippets like Rank Math itself, reads back the schema, shortcode mapping, and final state, and restores the original schema meta ID and all affected side fields after a partial failure. Yoast, AIOSEO, and SEOPress fail closed with HTTP 409 for custom-schema deletion.
Capability: edit_posts plus edit_post. Rank Math additionally requires rank_math_onpage_snippet.
Traits: write, destructive, non-idempotent, conflict-protected, confirmation-gated, with verified rollback.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
schema_id | string | yes, stable ID from get-post-schema |
confirm_schema_id | string | yes, must exactly repeat schema_id |
expected_hash | string | yes, exact state_hash from get-post-schema |
The output confirms deleted, rich_snippet_disabled, verified, the previous and new state hashes, and any rollback.
Example: { "post_id": 42, "schema_id": "schema-731", "confirm_schema_id": "schema-731", "expected_hash": "<64 hex>" }
wp-agent/get-term-seo-meta
Purpose: Reads the stored SEO data of a term in a publicly viewable taxonomy through Rank Math, Yoast, or SEOPress. It normalizes the title, description, focus keyword, canonical, robots, and Open Graph and X/Twitter text. The complete raw provider state contributes to state_hash. AIOSEO Free has no native term SEO interface and therefore fails closed with HTTP 409.
Capability: edit_posts (coarse) plus the taxonomy's concrete edit_terms capability.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
term_id | integer | yes |
taxonomy | string | yes |
The output matches the normalized post SEO contract, replaces post_id with term_id and taxonomy, and adds the SHA-256 state_hash.
Example: { "term_id": 17, "taxonomy": "category" }
wp-agent/set-term-seo-meta
Purpose: Updates one or more term SEO fields through the effective Rank Math, Yoast, or SEOPress path. A fresh expected_hash, per-term short-lived lock, complete provider read-back, and exact rollback protect the write. Unknown Rank Math robots directives are preserved byte for byte. Duplicate or structurally invalid provider values close the write path. Yoast Indexables are rebuilt on production systems and compared with the persisted state. On local and staging systems, indexable_verified is deliberately null because Yoast does not persist Indexables there. Yoast has no per-term nofollow override, and AIOSEO Free has no native term SEO interface. Both boundaries return HTTP 409.
Capability: edit_posts (coarse) plus the taxonomy's concrete edit_terms capability.
Traits: write, non-destructive, idempotent, and conflict-protected.
| Parameter | Type | Required |
|---|---|---|
term_id | integer | yes |
taxonomy | string | yes |
expected_hash | string (SHA-256) | yes |
seo_title, seo_description, focus_keyword, canonical_url | string | no |
robots_noindex, robots_nofollow | boolean | no |
open_graph_title, open_graph_description | string | no |
twitter_title, twitter_description | string | no |
The output contains term_id, taxonomy, plugin, written, verified, indexable_verified, rolled_back, rollback_verified, and the new state_hash. A failed rollback returns an HTTP 500 error instead of a misleading state hash.
Example: { "term_id": 17, "taxonomy": "category", "expected_hash": "<64-character SHA-256>", "seo_title": "WordPress Tips" }
wp-agent/list-seo-redirections
Purpose: Lists up to 5,000 non-trashed Rank Math redirections. Rules with multiple sources or contains, start, end, or regex comparisons remain readable but are marked writable:false. collection_hash covers the complete collection and protects a subsequent create against concurrent changes.
Capability: rank_math_redirections.
Traits: read, non-destructive, idempotent.
Parameters: Optional status (any, active, inactive), search (at most 200 bytes), page, and per_page (1-100). The output contains redirections, total, page, per_page, total_pages, and collection_hash.
wp-agent/get-seo-redirection
Purpose: Reads one non-trashed Rank Math redirection. Each source contains pattern, comparison, and ignore_case. The output adds destination, HTTP code, activation status, hit count, writability, and state_hash. Hit count is deliberately excluded from the conflict hash so real traffic does not block a configuration-only change.
Capability: rank_math_redirections.
Traits: read, non-destructive, idempotent.
Parameters: redirection_id is required.
wp-agent/create-seo-redirection
Purpose: Creates exactly one local exact source. HTTP 301, 302, 307, 410, and 451 are supported. Sources are canonically decoded and may not contain the home page, a query, fragment, dot segments, control characters, or ambiguous percent encoding. Destinations must be absolute or local HTTP or HTTPS URLs without credentials. HTTP 410 and 451 require an empty destination. A fresh expected_collection_hash, atomic lock, source collision check, and cycle detection protect creation. A semantically identical retry returns the existing object with created:false.
Capability: rank_math_redirections.
Traits: write, marked destructive, idempotent, and conflict-protected.
Required parameters: source, destination, http_code, and expected_collection_hash. status and ignore_case are optional. The output contains redirection, created, and verified.
wp-agent/update-seo-redirection
Purpose: Updates only a single exact provider rule. Complex rules remain unchanged. expected_state_hash, the lock, collision and cycle checks, complete read-back, and verified rollback protect the write.
Capability: rank_math_redirections.
Traits: write, marked destructive, idempotent, and conflict-protected.
Required parameters: redirection_id and expected_state_hash, plus at least one of source, destination, http_code, status, or ignore_case. The output contains redirection and verified.
wp-agent/delete-seo-redirection
Purpose: Moves a Rank Math redirection to the provider trash. The row is not hard-deleted. The operation requires a current state hash and explicit confirmation. A failed read-back restores and verifies the previous row.
Capability: rank_math_redirections.
Traits: write, destructive, not idempotent, and conflict-protected.
Required parameters: redirection_id, expected_state_hash, and confirm:true. The output contains redirection_id, deleted, and verified.
wp-agent/get-seopress-post-redirection
Purpose: Reads the simple post redirect for a published, publicly reachable post through the native SEOPress Free route. The source is derived from the current canonical post URL. The response contains only the confirmed enabled state, HTTP 301, 302, or 307, a local destination on the same WordPress site, and a complete state hash. Ambiguous, duplicate, or non-local provider values fail closed.
Capability: object-specific edit_post. Traits: read-only, non-destructive, idempotent. Required: post_id.
wp-agent/set-seopress-post-redirection
Purpose: Sets or disables a simple local post redirect through the native SEOPress Free route. The destination must belong to the same WordPress site and may not contain credentials, a query, a fragment, dot segments, or ambiguous encoding. The complete graph of published and publicly reachable posts is read within strict bounds and without a postmeta N+1 query. Direct and multi-step cycles are rejected before the write. A current expected_hash, post and graph locks, exact raw-state attribution, provider read-back, and a real HTTP read-back protect the operation. Once the provider write has started, an uncertain state returns recovery_required. No automatic follow-up mutation can overwrite an external provider change.
Capability: object-specific edit_post. Traits: write, marked destructive, idempotent, conflict-protected. Required: post_id, expected_hash, and enabled; when enabled:true, also destination and optionally http_code with 301, 302, or 307.
11. Landing pages, global styles, theme files, and the Site Editor
wp-agent/upsert-pattern
Purpose: Builds a landing page (post_type=page) from a declarative section list (hero, features, media-text, logos, cta, pricing, testimonials, faq, stats, gallery, steps, comparison) as valid Gutenberg core blocks, and creates or updates it through slug or post_id. The contract is not annotated as idempotent, although slug resolution prevents unintended duplicates. Supports optional background images (core/cover for hero), image-text splits (core/media-text), galleries (core/gallery), accordions (core/details), comparison tables (core/table), and a native icon set (bundled Phosphor SVGs as core/image). Color, spacing, and font-size slugs are resolved against the effective global styles. Before saving, parse_blocks checks that guaranteedly 0 freeform blocks result; every section type is additionally confirmed recovery-free in the real Gutenberg editor.
Capability: edit_pages (not edit_posts, because post_type=page is always created).
Traits: write, non-destructive, not idempotent. Slug or ID resolution prevents unintended duplicates but is not an idempotency annotation.
| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | yes | |
sections | array | yes | Ordered list; each section has type (hero|features|media-text|logos|cta|pricing|testimonials|faq|stats|gallery|steps|comparison) plus the type-dependent text, color, button, image, icon, columns[], and items[] fields. The input_schema in tools/list is the binding source of truth. |
slug | string | no | For matching without post_id; prevents unintended duplicates but is not an idempotency guarantee. |
post_id | integer | no | Highest priority, ahead of slug. |
status | string (enum: draft, publish, pending, private) | no | Default draft. |
| Output field | Type |
|---|---|
post_id | integer |
url, status | string |
block_count, freeform_count | integer |
block_types | string[] |
updated | boolean |
Example:
{
"title": "Webinar landing page",
"slug": "webinar-signup",
"status": "draft",
"sections": [
{ "type": "hero", "heading": "Free webinar", "image_url": "https://your-domain.tld/wp-content/uploads/hero.webp", "cta_label": "Sign up now", "cta_url": "#form" },
{ "type": "features", "heading": "What you'll learn", "items": [ { "title": "First point", "text": "Briefly explained.", "icon": "rocket" } ] },
{ "type": "faq", "heading": "Frequently asked questions", "items": [ { "title": "What does the webinar cost?", "text": "Nothing, attendance is free." } ] },
{ "type": "cta", "heading": "Only a few spots left", "button_label": "Reserve your spot", "button_url": "#form" }
]
}
wp-agent/get-global-styles
Purpose: Reads the complete user Global Styles record as a type-preserving, exportable JSON snapshot. The snapshot is capped at 512 KiB and includes a SHA-256 conflict hash bound to the active theme, record ID, and exact stored content. That hash is required for every subsequent design write.
Capability: edit_theme_options.
Traits: read, non-destructive, idempotent.
| Output field | Type |
|---|---|
post_id, snapshot_bytes | integer |
theme, state_hash | string |
snapshot | object |
wp-agent/set-global-styles
Purpose: Sets colors, font sizes, spacing, font families, and a narrowly allowed subset of standard styles in WordPress's own wp_global_styles record. Theme files and theme presets remain unchanged. Custom presets are replaced or appended by slug. An exact conflict hash and a shared short-lived lock prevent concurrent overwrites. The state is read back directly from the database and any mismatch restores the previous bytes.
Capability: edit_theme_options.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
expected_hash | string | yes | Exact state_hash from get-global-styles. |
colors | array | no | Entries with slug, color, optional name. |
fontSizes | array | no | Entries with slug, size, optional name. |
spacingSizes | array | no | Entries with slug, size, optional name. |
fontFamilies | array | no | Entries with slug, fontFamily, optional name. |
styles | object | no | Selected color values, spacing.blockGap, and button/link colors are allowed. |
replace | boolean | no | Replaces only the supplied custom categories. Default is upsert by slug. |
At least one token category or styles must be set. Preset references in styles are checked against the slugs actually available after the merge.
| Output field | Type |
|---|---|
post_id, version | integer |
theme, state_hash | string |
replace, verified | boolean |
applied | object |
palette_slugs | string[] |
Example: { "expected_hash": "<SHA-256 from get-global-styles>", "colors": [{ "slug": "brand-primary", "color": "#6d45f9", "name": "Primary" }], "replace": false }
Native Global Style variations
The following three abilities mirror the WordPress Site Editor's style variations. They include a native default choice for resetting user design changes and every full, color, and typography variation supplied by the active theme. Variation IDs are bound to the theme, scope, position, and exact content. A theme switch or changed variation file intentionally invalidates an older ID.
| Ability | Purpose | Parameters |
|---|---|---|
wp-agent/list-global-style-variations | Lists the default choice and theme variations as compact records. | Optional scope: all, full, color, or typography. |
wp-agent/get-global-style-variation | Reads one variation completely and without losing JSON types. | variation_id. |
wp-agent/apply-global-style-variation | Applies the variation with conflict protection, a shared lock, exact read-back, and safe rollback. | variation_id, fresh expected_hash, confirm=true. |
All three require edit_theme_options. The write path is destructive and idempotent. Full variations replace user settings and ordinary styles. Free root and block CSS is retained according to the Site Editor's rules. Color variations replace color groups only. Typography variations replace typography and spacing groups. The resulting record is capped at 512 KiB. A mismatch caused by the write itself restores the exact previous bytes. If an external writer changes the already verified state again, that version is preserved and the ability returns HTTP 409.
Spectra One 1.2.3 is practically verified through these native WordPress paths. The test confirms its catalog of nine style choices, a verified Global Styles color write, and exact restoration of the initial state.
wp-agent/write-theme-file
Purpose: Writes a file exclusively into the active (child) theme directory. Only the extensions .html, .json, and .css are allowed. Path traversal is prevented both lexically (no .. segment, no absolute path) and via a realpath check against the theme directory; symlinks as a target are rejected.
Capability: edit_themes (a filesystem-adjacent, privileged action that an Editor does not have by default).
Traits: write, non-destructive, idempotent (overwriting the same file is repeatable).
| Parameter | Type | Required | Description |
|---|---|---|---|
rel_path | string | yes | Relative path within the theme folder, e.g. patterns/hero.html. |
contents | string | yes | File content. |
| Output field | Type |
|---|---|
path, rel_path, theme | string |
bytes | integer |
Example: { "rel_path": "patterns/hero.html", "contents": "<!-- wp:heading --><h2>Hello</h2><!-- /wp:heading -->" }
Site Editor templates, template parts, and block navigations
These 15 abilities manage the three native WordPress Site Editor data surfaces. All require edit_theme_options, so they are Administrator features by default. Template write paths refuse classic themes. Raw block markup is not an input field. The server instead serializes up to 50 structured Core components. Supported components are Markdown, template part, block pattern, site logo and title, block navigation, post title, featured image, content, excerpt, date, author, terms, query title, query loop, separator, and spacer.
Spectra One 1.2.3 is practically verified as a real block theme through a complete template-part create, read, and delete lifecycle. The compatibility matrix therefore reports the native wp_global_styles+site-editor storage path and marks the theme as installed only while it is active.
The write path recursively rejects free HTML, shortcodes, freeform blocks, unregistered blocks, and non-Core blocks. Registered and therefore executable shortcodes are blocked even inside an allowed Core block. Referenced template parts, block navigations, patterns, and synced Core blocks are also checked recursively. Validation covers both stored raw content and blocks that WordPress injects at runtime through Block Hooks. Circular references across these data surfaces are blocked. Content is capped at 1 MiB. Changes use a SHA-256 state hash, an atomic resource lock, complete read-back, and exact rollback including timestamps. Creation, update, and deletion of the same resource share the same lock key. Theme and plugin templates are overridden only with confirm_theme_override=true. Deletion first performs a reversible step, verifies it, and then removes only the database version. An underlying theme or plugin template remains available. Template parts and navigations that are still referenced additionally require confirm_references=true.
| Ability | Required fields | Result and special behavior |
|---|---|---|
list-site-templates | none | Effective theme, plugin, and database templates, with optional search and per_page. |
get-site-template | slug | Complete resource with raw content, origin, block report, and hash. |
create-site-template | slug, title, components | Creates only a new custom block template. |
update-site-template | slug, expected_hash | Partial title, description, or component update. A theme or plugin source requires the additional confirmation. |
delete-site-template | slug, expected_hash, confirm | Deletes a custom template or reverts an override to its source. |
list-template-parts | none | Same as the template list, optionally filtered by area. |
get-template-part | slug | Also returns the area such as header, footer, or uncategorized. |
create-template-part | slug, title, area, components | Creates a new template part in a registered area. |
update-template-part | slug, expected_hash | Partial update with an optional area change and the same conflict and override gates. |
delete-template-part | slug, expected_hash, confirm | Finds uses in posts, templates, and template parts. |
list-block-navigations | none | Published wp_navigation posts, with optional search and per_page. |
get-block-navigation | id | Navigation with raw content, item count, block report, and hash. |
create-block-navigation | title, items | Creates up to 100 internal, external, or nested items with a maximum depth of three levels. |
update-block-navigation | id, expected_hash | Updates the title or complete item list with exact rollback. |
delete-block-navigation | id, expected_hash, confirm | Finds references and uses verified two-stage deletion. |
Template resources contain id, wp_id, theme, slug, type, source, origin, title, description, status, content, area, has_theme_file, is_custom, modified, the deep block report, and hash. Navigation resources contain id, slug, title, status, content, modified, item_count, the deep block report, and hash. For a query-loop component, per_page, post_type, order, and order_by form an explicit query by default. Only inherit_query=true deliberately inherits the current archive query.
12. Verification and infrastructure
wp-agent/render-check
Purpose: Parses the post content, counts blocks, flags core/freeform (the silent Classic Editor fallback), and renders the server HTML (do_blocks()) for inspection.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
| Output field | Type |
|---|---|
post_id, rendered_html_length, word_count, block_count, freeform_count | integer |
has_freeform | boolean |
block_types | string[] |
Example: { "post_id": 42 }
wp-agent/refresh-hooks
Purpose: Catches up on admin-/save-only follow-up work that would otherwise be missing when writing via REST/abilities instead of via the editor: (1) flush_rewrite_rules(false), (2) clean_post_cache() for the most recently changed posts (or an explicit post_ids list), (3) if Rank Math is active, additionally invalidates the sitemap cache (Cache::invalidate_storage(), fallback Cache_Watcher::clear(), otherwise the documented WP-CLI fallback wp rankmath sitemap generate).
Capability: edit_posts.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Default 20 (1 to 100), number of most recently changed posts. |
post_ids | integer[] | no | Explicit list instead of the most recently changed posts. |
| Output field | Type |
|---|---|
actions[] | string[] |
cleaned_post_ids[] | integer[] |
rankmath | object (active, method, cli_fallback) |
Example: { "limit": 5 }
wp-agent/disable-power
Purpose: A panic switch that deliberately lives in the verified core plugin (not in wp-agent-power itself), so the core can disable raw-access/developer mode (wp-agent-power, including exec-php and all other power abilities) even if that plugin misbehaves. Immediately disables wp-agent-power via deactivate_plugins(), if installed.
Capability: activate_plugins.
Traits: write, non-destructive (reversible at any time via wp-agent/activate-plugin), idempotent.
No input parameters.
| Output field | Type |
|---|---|
power_installed, disabled | boolean |
note | string |
Example: {}
wp-agent/create-browser-link
Purpose: Creates a one-time link to the dashboard, posts, pages, or media for the currently authenticated safe non-administrator with content-editing permissions. The random token has 256 bits of entropy, only its SHA-256 hash is stored, it expires after 120 seconds, and HTTPS is required outside local development environments. The token is not placed in the URL. The browser tool must send it as the X-WPAgent-Browser-Token header so it cannot enter access logs, referrers, or browser history.
Capability: edit_posts, but neither manage_options nor super-administrator status. These are the same boundaries applied to guided connection users. The link does not expand WordPress permissions.
Traits: write, non-destructive, not idempotent.
Input: optional destination (dashboard, posts, pages, media). Output: url, headers, expires_at, user_id, destination, one_time. Use headers unchanged and only for this single request.
wp-agent/revoke-browser-link
Purpose: Revokes the currently authenticated safe non-administrator's pending one-time backend link.
Capability: the same as create-browser-link.
Traits: write, non-destructive, idempotent. Output: revoked.
13. Page builders, ACF, WooCommerce, and forms
Native WPForms abilities
WPForms provides its own abilities. WPAgently does not duplicate their form logic. It adds only abilities that are currently registered and published by WPForms with meta.mcp.public: true to its MCP server. The control center separates form reads (list-forms, get-form, get-form-stats), sensitive entries (get-entry-summaries, get-entry, search-entries), and the write surface published together with describe-editing-schema (create-form, add-field, update-field, update-form-settings). Unknown future WPForms abilities remain individually manageable only when WPForms also publishes them for MCP.
WPForms Lite normally restricts these paths to Administrators. The connection page can instead grant the three WPAgently capabilities wpagently_wpforms_forms_access, wpagently_wpforms_entries_access, and wpagently_wpforms_write_access to a safe Editor. The official wpforms_current_user_can filter then accepts only the documented form, entry, and write checks at the exact WPAgently MCP endpoint. Normal WPForms admin, AJAX, and foreign REST surfaces, as well as unknown permissions such as deletion, remain denied. WPForms' own write toggle remains an additional hard requirement. IP addresses in native entry responses are masked for this agent user through the official masking filter. Revocation and uninstallation remove only additions tracked by WPAgently. Tracked grants remain revocable from the connection page even after WPForms is deactivated.
wp-agent/get-wpforms-delivery
Purpose: Reads existing WPForms confirmations and compact email notifications through the native form handler. By default, notifications expose only their ID, name, subject, and a complete item hash. include_notification_details: true additionally returns recipients, sender, reply-to address, carbon copies, and message. Unknown add-on data participates in conflict detection but is never returned. state_hash binds a later write to the complete raw form content.
Capability: wpagently_wpforms_write_access at the WPAgently MCP endpoint plus WPForms' native object-specific edit_form_single check. Traits: read-only, non-destructive, idempotent. Requires form_id. Optional: include_notification_details, default false.
wp-agent/update-wpforms-confirmation
Purpose: Updates exactly one existing confirmation. Supported properties are its message, scroll behavior, a readable WordPress page, or a complete HTTP or HTTPS redirect without embedded credentials. Content remains limited to plain text and smart tags. A complete expected_hash, a form-specific short-lived lock, and an uncached database comparison prevent overwriting concurrent changes. After the native provider write, the complete delivery state and all remaining form data are read again. A mismatch restores the previous form content and returns a visible error.
Capability: the same as get-wpforms-delivery. Traits: write, non-destructive, idempotent. Requires form_id, confirmation_id, expected_hash, and confirmation.
wp-agent/create-wpforms-confirmation
Purpose: Creates the first effective confirmation or, with WPForms Pro, an additional confirmation with the next safe numeric ID. Name and type are required. Messages, page targets, and redirects use the same bounds as the update path. WPForms Lite rejects a second rule because safe multiple selection depends on Pro conditional logic. Multiple rules on WPForms Pro remain empirically unverified without a legally licensed practical fixture.
Capability: the same as get-wpforms-delivery. Traits: write, non-destructive, not idempotent. Requires form_id, expected_hash, and confirmation.
wp-agent/delete-wpforms-confirmation
Purpose: Deletes an existing additional confirmation. confirm_confirmation_id must exactly repeat confirmation_id. The last confirmation remains in place. Conflict detection, provider read-back, and rollback cover the complete form state.
Capability: the same as get-wpforms-delivery. Traits: write, destructive, not idempotent. Requires form_id, confirmation_id, confirm_confirmation_id, and expected_hash.
wp-agent/update-wpforms-notification
Purpose: Updates exactly one existing email notification and can change the global notification switch. Name, subject, recipients, sender, reply-to address, carbon copies, and message are length-bounded. Control characters and header injection are rejected. Address field tags must reference email fields that actually exist. The sender address does not accept a visitor-controlled form field. Addresses and message text remain hidden in write responses. Conflict detection, locking, provider read-back, and restoration follow the confirmation ability.
Capability: the same as get-wpforms-delivery. Traits: write, non-destructive, idempotent. Requires form_id, notification_id, and expected_hash. At least one of notification or notifications_enabled must be supplied.
wp-agent/create-wpforms-notification
Purpose: Creates the first effective email notification or, with WPForms Pro, another one with the next safe numeric ID. Name, recipient, subject, sender name, sender address, and message are required. notifications_enabled can explicitly set global delivery. WPForms Lite rejects a second rule because its runtime sends only the first notification. Multiple rules on WPForms Pro remain empirically unverified without a legally licensed practical fixture.
Capability: the same as get-wpforms-delivery. Traits: write, non-destructive, not idempotent. Requires form_id, expected_hash, and notification. Optional: notifications_enabled.
wp-agent/delete-wpforms-notification
Purpose: Deletes an existing email notification. confirm_notification_id must exactly repeat notification_id. Deleting the last notification disables global delivery. Conflict detection, provider read-back, and rollback cover the complete form state.
Capability: the same as get-wpforms-delivery. Traits: write, destructive, not idempotent. Requires form_id, notification_id, confirm_notification_id, and expected_hash.
Native Ninja Forms abilities
Ninja Forms 3.14.10 registers 32 abilities and publishes 29 of them for MCP. WPAgently does not blindly grant the broad provider capability nf_edit_forms. Instead, it places 24 known public tools into four separate groups:
| Group | Native abilities | Dedicated user capability |
|---|---|---|
| Form reads | list-forms, get-form, list-field-types, list-actions, list-calculations, export-form-definition | wpagently_ninjaforms_forms_access |
| Submissions | get-submissions, get-submission, get-submission-fields, export-submissions | wpagently_ninjaforms_submissions_access |
| Form editing | create-form, add-field, update-form, update-field, reorder-fields, duplicate-form, add-action, update-action, add-calculation, update-calculation, import-form, embed-form, get-public-link | wpagently_ninjaforms_write_access |
| Email delivery | process-submission | wpagently_ninjaforms_delivery_access |
The broad capability is mediated only during a matching request at the exact WPAgently MCP endpoint. It is never persisted on the user account. A JSON-RPC batch receives access only if every contained Ninja Forms tool is known and allowed through its respective group. Mixed tool batches and batches with more than 100 messages are rejected. A user who already has persistent nf_edit_forms access is not considered a safe agent user. Revocation and uninstallation remove only the four group capabilities recorded as additions by WPAgently.
The eight abilities ninjaforms/delete-action, ninjaforms/delete-calculation, ninjaforms/delete-form, ninjaforms/delete-submission, ninjaforms/get-plugin-settings, ninjaforms/remove-field, ninjaforms/update-plugin-settings, and ninjaforms/update-submission remain quarantined. The reasons are missing technical confirmation, permanent deletion, global side effects, and possible secrets in plugin settings. ninjaforms/process-submission can send real email. It therefore has its own double opt-in group and must be used only after an explicit instruction. Submissions may contain personal data and are never enabled together with the basic form-read permission.
wp-agent/detect-builder
Purpose: Detects, per post, which page builder/format its content is actually stored in (not merely which builder plugins are active). Checks three storage families introspectively (never merely assumed): JSON in postmeta (Elementor, Bricks, Beaver Builder, Breakdance, Oxygen), Gutenberg block comments in post_content (Core, Kadence, Spectra, GenerateBlocks), and shortcodes (WPBakery, [vc_*]). Cascade when there are multiple postmeta signals: Bricks before Beaver Builder before Oxygen before Breakdance before Elementor. ACF is always additive, unless the post itself is an ACF field group.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
| Output field | Type | Description |
|---|---|---|
primary | string | Detected authoritative builder, e.g. elementor, spectra, classic. |
signals[] | Objects with type, key, location | All signals found. |
storage_location | string | postmeta, post_content, or mixed. |
is_block_based | boolean | |
write_supported | boolean | True only when the existing storage can be changed through a safe WPAgently path. It is false for third-party block documents. |
recommended_ability | string | Safe next write path, or empty when none exists. |
block_types[] | string[] | |
notes[] | string[] |
Example: { "post_id": 42 }
wp-agent/list-block-types
Purpose: Lists the block types actually registered on the site for the Core, Kadence, GenerateBlocks, and Spectra namespaces. Search, namespace filtering, and pagination are bounded. Results contain the name, namespace, title, category, API version, dynamic flag, and attribute count, but no callbacks or local source paths.
Capability: edit_posts.
Traits: read, non-destructive, idempotent. Optional parameters are search, namespace with all, core, kadence, generateblocks, or uagb, page, and per_page up to 500.
wp-agent/get-block-type
Purpose: Reads one registered block type including redacted attributes, supports, parent rules, and ancestor rules. Keys that indicate passwords, tokens, API keys, cookies, or other secrets, as well as non-JSON runtime values, are removed. The dynamic attributes and supports fields are each the closed, versioned {format,json,sha256,bytes} envelope from the preceding section, not open objects.
Capability: edit_posts.
Traits: read, non-destructive, idempotent. name is required in namespace/block format from one of the four approved namespaces.
wp-agent/get-native-block-document
Purpose: Reads the complete stored post_content of an authorized post together with status, modification time, recursive block count, freeform count, block types, detected builder, and a stable content hash. This allows an agent to inspect real document structures instead of guessing from plugin documentation.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: read, non-destructive, idempotent. post_id is required. There is deliberately no ability that writes serialized block markup back. Core content is generated only through the existing Markdown or declarative server paths. Kadence and GenerateBlocks blocks remain fail-closed outside their respective narrow attribute paths. Static Spectra blocks remain closed as well, with exactly two version-bound abilities for the three responsive alignment attributes and the classic headingColor and subHeadingColor values of one uagb/advanced-heading on Spectra 2.20.1. The following bounded attribute path covers the server-registered dynamic Spectra subset.
wp-agent/get-spectra-blocks-separator
Purpose: Reads exactly one separately registered spectra/separator at an explicit recursive block path. The contract applies exclusively to Spectra Blocks 1.0.4 with a server-side render callback and a fully matching attribute schema. It returns only style, alignment, width, height, and color. Raw markup, free CSS values, inner blocks, further responsive values, and divergent provider attributes remain closed.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: read, non-destructive, idempotent. post_id and a path of 1 through 32 non-negative indices are required. The document must be below 1 MiB and stably parseable and serializable with WordPress.
| Output field | Type |
|---|---|
post_id, path, rendered_html_length | integer or integer[] |
version | string, exactly 1.0.4 |
settings | separator_style, separator_align, separator_width, separator_height, separator_color |
hash | SHA-256 of the complete document state |
Example: { "post_id": 42, "path": [0, 1] }
wp-agent/update-spectra-blocks-separator
Purpose: Changes only the style, alignment, width, height, and color of that exactly verified Spectra Blocks separator. Style is limited to eight provider values, alignment to left, center, or right, width to 1-100 % or 1-2,000 px, height to 1-400 px, and color to six-digit hexadecimal values. The action does not change text, raw markup, or any other provider attribute.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: write, non-destructive, non-idempotent. post_id, path, at least one approved settings value, and the current expected_hash are required. The path checks Spectra Blocks 1.0.4, canonical document structure, and provider markup, locks the post exclusively, creates a revision, writes with byte-exact CAS, renders, and reads the result back. On unsafe read-back it attempts to restore the previous state and otherwise returns recovery_required; a foreign change is never overwritten.
| Output field | Type |
|---|---|
post_id, path, rendered_html_length, revision_id | integer or integer[] |
version, hash, previous_hash | string |
settings | complete verified separator state |
changed, verified | boolean |
Example: { "post_id": 42, "path": [0, 1], "settings": { "separator_color": "#1a73e8" }, "expected_hash": "<64-character SHA-256 from get-spectra-blocks-separator>" }
wp-agent/update-spectra-block-attributes
Purpose: Changes only schema-known attributes of a visible dynamic Spectra block at an explicit recursive block path. The target must be present both in Spectra's visible registry and in WordPress with a callable render callback and an attribute schema. Bounded booleans, numbers, plain-text values, and bounded arrays with scalar item schemas are supported. Objects, internal IDs, metadata, locks, class names, Core styles, raw HTML, block comments, active script and HTML data URIs, free CSS declarations, unknown attributes, and static Spectra blocks registered only in JavaScript are rejected.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: write, non-destructive, non-idempotent. Required fields are post_id, a path of 1-32 indices, and expected_hash. attributes may set up to 50 values through the closed native-block {format,json,sha256,bytes} envelope, while remove_attributes may reset up to 50 registered values to their provider defaults. A successful write consumes the expected document hash, so automatically replaying the same request is unsafe. The path locks the post, checks the complete document hash, bounds the patch and document size, creates a verified revision, serializes through WordPress, confirms that the block structure did not change, renders server-side, reads content and attributes back exactly, and invalidates Spectra's post and asset cache. Once mutation begins, it restores the previous content only when the exact expected candidate is still stored and the restoration can be verified. On foreign drift, capability loss, or lock loss it preserves current state and returns recovery_required; the created revision is then the manual inspection path. Results include the target block, path, requested changes, revision ID, render length, and the previous and new hashes.
wp-agent/update-spectra-static-heading-alignment
Purpose: Changes only headingAlign, headingAlignTablet, or headingAlignMobile on a static uagb/advanced-heading at an explicit block path. This contract applies exclusively to Spectra 2.20.1. It accepts only left, center, or right; markup, text, block_id, and every other attribute remain unchanged. Any other Spectra version, a dynamically registered target, or a divergent provider contract fails closed before mutation.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id).
Traits: write, non-destructive, not idempotent. Required fields are post_id, path, alignment, and expected_hash. Optional viewport is limited to desktop, tablet, or mobile and defaults to desktop when omitted. The path requires a canonically parseable and serializable document, locks the post, renews and proves lock ownership before and after mutations, creates a revision, checks the structure and static target markup, refreshes Spectra's cache, and reads the stored state and target markup back. A failed check or lost lock after the mutation starts returns recovery_required. Lock loss never triggers an automatic counter-mutation; the current state and revision require manual inspection.
wp-agent/update-spectra-static-heading-colors
Purpose: Changes only headingColor, subHeadingColor, and optional separatorColor on a static uagb/advanced-heading at an explicit block path. The contract applies exclusively to Spectra 2.20.1 in classic color mode. Every supplied value must be a six-digit hex color or inherit. inherit stores the provider's native empty value. separatorColor is accepted only when exactly one existing separator with an allowlisted provider style and the exact static wrapper is proven. Gradients, CSS variables, free CSS syntax, markup, text, block_id, and every other attribute remain blocked.
Capability: edit_posts broadly plus current_user_can('edit_post', $post_id).
Traits: write, non-destructive, not idempotent. Required fields are post_id, path, heading_color, description_color, and expected_hash; separator_color is optional. The alignment and color paths share the same exclusive document lock. This path requires a canonical block document and the exact verified static provider wrapper, creates a revision before the byte-exact compare-and-swap, proves lock ownership around every effective phase, refreshes Spectra's cache, and reads content, attributes, and target markup back. The real end-to-end test binds all three colors to the exact target selectors emitted by Spectra 2.20.1 and rejects a separator color without the provider wrapper. Lock loss or unsafe read-back after mutation starts returns recovery_required without an automatic counter-mutation.
wp-agent/update-generateblocks-block-attributes
Purpose: Changes only five version-bound GenerateBlocks attributes. generateblocks/query-page-numbers.midSize accepts an integer from 0 through 10. generateblocks/query.paginationType accepts only standard or instant. In addition, tagName permits only div, section, article, aside, header, footer, nav, or main on the Query wrapper, only div, section, or nav on Page Numbers, and only p, span, div, or h1 through h6 on one canonical plain-text block. Interactive tags and existing inline markup remain blocked. The server replaces only the previously verified canonical provider markup and keeps the comment attributes, innerHTML, and innerContent consistent together. The block, attribute, and type must also exist in the live WordPress schema. Free markup, every other attribute, block type, and CSS function remain blocked.
Capability: edit_posts broadly plus current_user_can('edit_post', $post_id).
Traits: write, non-destructive, not idempotent. Required fields are post_id, path, and expected_hash; at least one approved attribute is written or removed through the closed native-block {format,json,sha256,bytes} envelope. The path uses a short-lived lock, verified revision, byte-exact database compare-and-swap, exact provider structure validation, GenerateBlocks cache invalidation, a frontend render reduced to verified Query ancestors and the target, and exact read-back. Only an approved tagName changes the canonical wrapper together with the attribute. A foreign concurrent change is preserved and returns recovery_required.
wp-agent/update-kadence-block-attributes
Purpose: Changes only forty-one narrowly approved attributes on existing kadence/advancedheading, kadence/spacer, or kadence/progress-bar blocks. Advanced Heading keeps its level, three responsive alignments, text transformation, font style, font weight, three responsive pixel font sizes from 8 through 200, three responsive pixel line heights from 8 through 300, three responsive pixel letter-spacing values from -10 through 50, four pixel margins from -500 through 500, and classic six-digit text and background colors. When an existing, safely shaped provider icon is present, icon and hover-icon color, icon side, and vertical icon alignment are also available. Margins use only the px unit. The canonical Spacer permits only positive desktop, tablet, and mobile heights from 1 through 2,000 and the px, rem, or vh unit. Desktop height remains mandatory while responsive overrides may be removed. The simple Progress Bar must use the native line type, contain no labels, masks, links, free text, or inner blocks, and accepts only the progress value, maximum, three stroke widths from 1 through 20, and two six-digit colors. The progress value cannot exceed the maximum. The block, attribute, and type must also exist in the live WordPress schema. Different markup, every other attribute, and free CSS functions remain blocked.
Capability: edit_posts broadly plus current_user_can('edit_post', $post_id).
Traits: write, non-destructive, not idempotent. Required fields are post_id, path, and expected_hash; at least one approved attribute is written or removed through the closed native-block {format,json,sha256,bytes} envelope. The path renews its short-lived lock around every critical transition and uses a verified revision, byte-exact database compare-and-swap, structure validation, frontend rendering including CSS verification, and exact read-back. Kadence Blocks 3.7.8 updates its output on render. Conflicts and foreign concurrent changes are never overwritten. If lock ownership is lost after a write starts, the mutation remains for manual review and the path returns recovery_required without an automatic rollback.
wp-agent/get-acf-fields
Purpose: Reads the ACF fields assigned to a post, user, term, comment, or ACF options store through the official ACF APIs (acf_get_field_groups(), acf_get_fields(), and get_field()), never through raw metadata. Returns the portable unformatted value, the real field_ key, the canonical ACF object identifier, and a SHA-256 hash over the target, value, side effects, and effective field definition. Post, media, and user references that the account cannot read are omitted.
Capability: Dynamic for the target. Requires edit_post, edit_user, edit_term, edit_comment, or manage_options for the generic options store. A registered ACF options page uses its configured capability. User fields additionally require list_users. Taxonomy fields are writable only when the account can assign terms in the configured taxonomy. Requires Advanced Custom Fields, otherwise returns HTTP 409.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | integer | alternative | Backward-compatible shorthand for a post. |
object_type | string | alternative | post, user, term, comment, or options. |
object_id | integer or string | alternative | Positive ID for WordPress objects. For options, use options or the registered options-page slug. |
| Output field | Type |
|---|---|
object_type | string |
object_id | integer or string |
acf_object_id | string, for example 42, user_7, term_9, comment_11, or options |
post_id | integer, only for a post target |
fields[] | Objects with key (field_...), name, label, type, state_hash, writable, redacted, unsupported_reason, and value |
Examples: { "post_id": 42 } or { "object_type": "term", "object_id": 9 }. post_id and the explicit object contract may appear together only when both identify the same post exactly.
wp-agent/update-acf-field
Purpose: Sets exactly one assigned ACF field on a post, user, term, comment, or options store through update_field(). The path requires the last-read state hash, locks concurrent changes per canonical ACF object and field, validates the value recursively against the fresh field definition, and confirms it through an unformatted re-read (get_field(..., false)). If the value differs, the previous state is restored and verified again.
Text, choice, number, date, media, post, taxonomy, and user fields are supported, as are group, repeater, and flexible content fields when the complete nested definition can be represented safely. The path checks required values, ranges, file restrictions, reference read permissions, taxonomy assignment permissions, user roles, an input ceiling of 100 KB, and a ceiling of 2,000 nodes. Saved taxonomy assignments are included in the hash, read-back, and rollback. Unknown layouts, redacted existing values, bidirectional ACF fields, and unsupported field types remain read-only.
Capability: Dynamic as described for get-acf-fields. References require the additional read or assignment permissions described above. An uploadedTo media field remains read-only outside a post. Taxonomy fields with load_terms or save_terms remain read-only in options storage. Requires Advanced Custom Fields.
Traits: write, non-destructive, not idempotent because the conflict hash is consumed by a changed value.
| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | integer | alternative | Backward-compatible shorthand for a post. |
object_type | string | alternative | post, user, term, comment, or options. |
object_id | integer or string | alternative | Target ID or options-page slug. |
field_key | string | yes | Must start with field_. |
expected_hash | string | yes | Current state_hash from get-acf-fields. |
value | any | yes | Type depends on the ACF field type. |
| Output field | Type | Description |
|---|---|---|
object_type | string | |
object_id | integer or string | |
acf_object_id | string | Canonical ACF object identifier. |
post_id | integer | Only for a post target. |
field_key | string | |
value | any | Portable unformatted re-read value. Object return formats are reduced to validated IDs. |
state_hash | string | Hash of the confirmed new state. |
verified | boolean |
Example: Pass the state_hash from the immediately preceding get-acf-fields response unchanged as expected_hash.
Shared contract for persistent ACF field groups
The following six abilities manage only ACF field groups stored in the database. Groups registered through PHP or Local JSON are neither listed as mutable nor opened through a known key. All six paths require manage_options, which normally means an Administrator. They use native ACF APIs and never change wp_posts or wp_postmeta directly.
The portable write path supports no more than 100 fields per group and 200 choices per field. It accepts text, textarea, number, range, email, url, true_false, select, checkbox, radio, and button_group. Location rules must consist of simple exact post_type == ... rules. Complex rules, conditional logic, other field types, and truncated definitions are marked portable: false when read and are rejected in full for updates or duplication.
Each response contains a SHA-256 hash over the complete raw group and field definitions without volatile database IDs. Update, duplication, and deletion require this last-read state as expected_hash. Update and deletion additionally use an atomic expiring write lock. Created and changed definitions are read back completely from ACF. If a save hook changes the requested state, an update is rolled back to the previous hash. An incomplete creation is removed again.
wp-agent/list-acf-field-groups
Purpose: Lists persistent field groups alphabetically with search and pagination. Each group contains its title, active state, simple post types, bounded field definitions, field count, portability, location-rule count, and conflict hash.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
search | string | no | Up to 100 characters, searches the title and group key. |
page | integer | no | Default 1. |
per_page | integer | no | Default 20, at most 50. |
wp-agent/get-acf-field-group
Purpose: Reads one persistent field group by its group_ key in the same complete response format as the list operation.
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
group_key | string | yes |
wp-agent/create-acf-field-group
Purpose: Creates a portable field group with new cryptographically random group_ and field_ keys. An unverifiable partial creation is removed.
Traits: write, non-destructive, not idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | yes | Plain text, 1-200 characters. |
post_types | string[] | yes | 1-20 registered post types with an administration UI. |
fields | object[] | yes | Complete portable field list. An empty list is allowed. |
active | boolean | no | Default true. |
wp-agent/update-acf-field-group
Purpose: Changes the title, active state, post types, or complete field list of a portable group. Group settings that were not provided remain unchanged. When fields is supplied, fields no longer present are deleted. Previous field keys may be reused only within the same group.
Traits: write, destructive, idempotent. A failed read-back check triggers a complete rollback.
| Parameter | Type | Required | Description |
|---|---|---|---|
group_key | string | yes | Persistent group_ key. |
expected_hash | string | yes | Current 64-character SHA-256 hash. |
title, active, post_types, fields | mixed | no | At least one of these change fields is required. |
wp-agent/duplicate-acf-field-group
Purpose: Copies a portable persistent group with new group and field keys. The source is reread under a write lock and must match expected_hash.
Traits: write, non-destructive, not idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
group_key | string | yes | Source group. |
expected_hash | string | yes | Last-read source state. |
title | string | no | Appends “Copy” when omitted. |
wp-agent/delete-acf-field-group
Purpose: Permanently deletes a persistent field group and its field definitions. The path then verifies that neither ACF nor WordPress still returns the group.
Traits: write, destructive, not idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
group_key | string | yes | Group to delete. |
expected_hash | string | yes | Current conflict hash. |
confirm | boolean | yes | Must be exactly true. |
Shared contract for persistent ACF post types and taxonomies
The following ten abilities manage only persistent ACF definitions stored in the database. Definitions from PHP or Local JSON remain excluded. Every path requires manage_options and Advanced Custom Fields 6.1 or newer. Writes use the native ACF APIs. Every new or changed record is reread as a complete definition and additionally checked against the effective WordPress runtime registration.
The lossless path supports shared labels, description, active state, visibility, hierarchy, REST and AI access, and an optional rewrite slug. Post types add a bounded WordPress support list, registered taxonomies, and archive enablement. Taxonomies add 1-20 registered object types and the admin column. The post-type or taxonomy slug itself is immutable after creation. Further ACF settings produce portable: false and block updates.
Every response contains content_count, portable, registration_conflict, and a SHA-256 hash over the complete definition. registration_conflict: true means that another WordPress component registered the same runtime slug. Such a definition is neither updated nor automatically deleted. Creates and updates use atomic expiring locks. Updates require the last-read expected_hash; deviations introduced by an ACF hook trigger rollback.
| Ability | Traits | Required parameters | Purpose |
|---|---|---|---|
wp-agent/list-acf-post-types | read, idempotent | none | Lists persistent post types with search and pagination. |
wp-agent/get-acf-post-type | read, idempotent | key | Reads a definition by its post_type_ key. |
wp-agent/create-acf-post-type | write, not idempotent | post_type, singular_label, plural_label, supports | Creates a post type with a random ACF key and verifies the definition and registration. |
wp-agent/update-acf-post-type | write, destructive, idempotent | key, expected_hash | Changes at least one portable property with conflict protection. |
wp-agent/delete-acf-post-type | write, destructive, not idempotent | key, expected_hash, confirm | Deletes only the definition. Posts remain. Existing posts additionally require confirm_content=true. |
wp-agent/list-acf-taxonomies | read, idempotent | none | Lists persistent taxonomies with search and pagination. |
wp-agent/get-acf-taxonomy | read, idempotent | key | Reads a definition by its taxonomy_ key. |
wp-agent/create-acf-taxonomy | write, not idempotent | taxonomy, singular_label, plural_label, object_types | Creates a taxonomy with a random ACF key and verifies the definition and registration. |
wp-agent/update-acf-taxonomy | write, destructive, idempotent | key, expected_hash | Changes at least one portable property with conflict protection. |
wp-agent/delete-acf-taxonomy | write, destructive, not idempotent | key, expected_hash, confirm | Deletes only the definition. Terms remain. Existing terms additionally require confirm_content=true. |
Lists optionally accept search, page, and per_page (at most 50). Post-type write paths additionally accept description, active, public, hierarchical, show_ui, show_in_rest, allow_ai_access, ai_description, rewrite_slug, supports, taxonomies, and has_archive. Taxonomy write paths accept the same shared fields plus object_types and show_admin_column.
Native Custom Post Type UI definitions
Ten administrator-only abilities manage persistent post-type and taxonomy definitions from Custom Post Type UI 1.19.3 or newer. Definitions registered through PHP remain excluded. The slug is immutable after creation. CPT UI applies the effective runtime registration on the next WordPress request, so successful mutations report reload_required: true.
Every read response contains a SHA-256 hash over the complete option state for that definition kind. Updates and deletions require this hash and use one atomic short-lived lock per option kind. Partial updates change only approved fields and preserve unknown provider data. The write path limits definition count and total size, reads the exact option state back, and restores the previous value including autoload metadata after a mismatch. Deletion removes only the definition. Posts and terms remain stored and require confirm_content=true when content exists.
| Ability | Traits | Required parameters | Purpose |
|---|---|---|---|
wp-agent/list-cptui-post-types | read, idempotent | none | Searches and paginates persistent CPT UI post types. |
wp-agent/get-cptui-post-type | read, idempotent | slug | Reads the definition, runtime state, content count, unknown fields, and option hash. |
wp-agent/create-cptui-post-type | write, not idempotent | slug, both labels, supports | Creates a bounded persistent post-type definition. |
wp-agent/update-cptui-post-type | write, destructive, idempotent | slug, expected_hash, at least one change | Changes labels, visibility, REST, hierarchy, rewrite, supports, taxonomies, or archive state. |
wp-agent/delete-cptui-post-type | write, destructive, idempotent | slug, expected_hash, confirm | Deletes only the definition and retains posts. |
wp-agent/list-cptui-taxonomies | read, idempotent | none | Searches and paginates persistent CPT UI taxonomies. |
wp-agent/get-cptui-taxonomy | read, idempotent | slug | Reads the definition, runtime state, term count, unknown fields, and option hash. |
wp-agent/create-cptui-taxonomy | write, not idempotent | slug, both labels, object_types | Creates a bounded persistent taxonomy definition. |
wp-agent/update-cptui-taxonomy | write, destructive, idempotent | slug, expected_hash, at least one change | Changes labels, visibility, REST, hierarchy, rewrite, object types, or admin column. |
wp-agent/delete-cptui-taxonomy | write, destructive, idempotent | slug, expected_hash, confirm | Deletes only the definition and retains terms. |
Native ACPT Lite definitions
Ten administrator-only abilities manage persistent post-type and taxonomy definitions from ACPT Lite 2.0 or newer through its native model and repository classes. Native synchronized WordPress or third-party definitions, reserved identifiers, slug changes, and rewrite collisions with existing pages, post types, or taxonomies remain blocked. The currently managed registration is excluded during safe partial updates. ACPT Lite applies new or changed runtime registrations on the next WordPress request, so successful mutations report reload_required: true.
Every read response includes a SHA-256 hash over the complete provider model, including its ID, labels, settings, and associations. Updates and deletions require that hash and use one shared atomic short-lived lock across both definition kinds. Concurrent post-type and taxonomy operations therefore cannot mutate the same ACPT association table. ACPT's persistent provider cache is cleared before each conflict comparison and read-back. Partial updates retain custom labels and unknown settings. A mismatch or partially failed association update triggers a verified rollback. Deletion removes only the definition. Posts and terms remain stored and require confirm_content=true when content exists. Linked ACPT meta fields block deletion.
| Ability | Traits | Required parameters | Purpose |
|---|---|---|---|
wp-agent/list-acpt-post-types | read, idempotent | none | Searches and paginates non-native ACPT Lite post types. |
wp-agent/get-acpt-post-type | read, idempotent | slug | Reads the definition, runtime state, content count, unknown settings, meta-field links, and model hash. |
wp-agent/create-acpt-post-type | write, not idempotent | slug, both labels, supports | Creates a bounded persistent post-type definition. |
wp-agent/update-acpt-post-type | write, destructive, idempotent | slug, expected_hash, at least one change | Changes labels, visibility, REST, hierarchy, rewrite, supports, taxonomies, or archive state. |
wp-agent/delete-acpt-post-type | write, destructive, idempotent | slug, expected_hash, confirm | Deletes only the definition and retains posts. |
wp-agent/list-acpt-taxonomies | read, idempotent | none | Searches and paginates non-native ACPT Lite taxonomies. |
wp-agent/get-acpt-taxonomy | read, idempotent | slug | Reads the definition, runtime state, term count, unknown settings, meta-field links, and model hash. |
wp-agent/create-acpt-taxonomy | write, not idempotent | slug, both labels, object_types | Creates a bounded persistent taxonomy definition. |
wp-agent/update-acpt-taxonomy | write, destructive, idempotent | slug, expected_hash, at least one change | Changes labels, visibility, REST, hierarchy, rewrite, object types, or admin column. |
wp-agent/delete-acpt-taxonomy | write, destructive, idempotent | slug, expected_hash, confirm | Deletes only the definition and retains terms. |
Native Pods content models and fields
Seven administrator-only abilities manage bounded Pods models and fields through its native PHP API. This model and field path covers only independent post types and taxonomies with storage=meta. Extended WordPress core objects, definitions of table-backed Advanced Content Types, renames, and unknown provider states remain read-only in this path. Five separate abilities for bounded records of existing, standard-configured ACTs are documented in the following section. New models and missing fields cannot be proven atomically and therefore fail closed with HTTP 409 before every mutation.
Model hashes include the complete raw model and field definitions. Field hashes include the complete raw field definition. Updates require the last observed hash, and every write uses an atomic short-lived lock followed by a complete provider read-back. A mismatch restores and verifies the previous state. Pods options not managed by WPAgently are reported by name and preserved during partial updates.
The field path supports text, website, phone, email, paragraph, wysiwyg, datetime, date, time, number, currency, file, avatar, oembed, pick, boolean, and color. Relationship fields may target registered post types, taxonomies, users, or media. Changing a field type when values exist requires confirm_data_migration=true. Deleting a definition retains normal WordPress content and simple meta values. Existing Pods relationship rows are removed only after confirm_relation_data_loss=true or confirm_data_loss=true.
| Ability | Characteristics | Required parameters | Purpose |
|---|---|---|---|
wp-agent/list-pods-models | read, idempotent | none | Searches and paginates supported Pods models. |
wp-agent/get-pods-model | read, idempotent | name | Reads the model, fields, content and relationship counts, and conflict state. |
wp-agent/create-pods-model | fail-closed, not idempotent | kind, name, singular_label, label | Rejects every new model with HTTP 409 before mutation because Pods has no atomically provable create-only path. |
wp-agent/update-pods-model | write, destructive, idempotent | name, expected_hash | Changes at least one approved model option with conflict protection. |
wp-agent/delete-pods-model | write, destructive, not idempotent | name, expected_hash, confirm | Deletes model and field definitions after separate content and relationship warnings. |
wp-agent/upsert-pods-field | write for existing fields, fail-closed for missing fields | model_name, expected_model_hash, name | Changes an existing approved field with its expected_field_hash; rejects a missing field with HTTP 409 before mutation. |
wp-agent/delete-pods-field | write, destructive, not idempotent | model_name, name, both hashes, confirm | Deletes a field definition and separately warns about values or relationships. |
Pods Advanced Content Type records
Five additional administrator-only abilities manage records only in standalone, table-based Pods Advanced Content Types with type=pod, storage=table, the standard table configuration, and no more than 20 non-repeatable text fields. Pods must provide version 3.3.9 or newer within major version 3. Modified system fields, author system fields, custom configurations, repeatable or non-text fields, foreign subsites, and unknown provider states remain fail-closed. SQLite is available for reads only. Writes remain blocked there because Pods 3.3.9 does not unambiguously confirm a create operation with a positive record ID.
Lists and individual reads use the native pods() API and return only the approved text values, the schema hash, and a complete SHA-256 conflict hash for each record. Writes require manage_options, bind the subsite, model, and schema under an atomic short-lived lock, use only Pods::add(), Pods::save(), or Pods::delete(), and read the result back through the provider. After a mutation starts, any result that cannot be confirmed exactly returns recovery_required and performs no automatic deletion, restoration, or follow-up mutation.
| Ability | Characteristics | Required parameters | Purpose |
|---|---|---|---|
wp-agent/list-pods-act-records | read, idempotent | model_name | Lists up to 50 records per page and returns fields, totals, pagination, and the schema hash. |
wp-agent/get-pods-act-record | read, idempotent | model_name, record_id | Reads exactly one record with value and conflict hashes. |
wp-agent/create-pods-act-record | write, non-idempotent | model_name, expected_schema_hash, values | Creates a record with no more than 20 bounded text values and exact read-back. |
wp-agent/update-pods-act-record | write, idempotent | model_name, record_id, expected_schema_hash, expected_hash, values | Updates only approved text fields of an unchanged record. |
wp-agent/delete-pods-act-record | write, destructive, non-idempotent | model_name, record_id, both hashes, confirm=true | Deletes an unchanged record and confirms its native absence. |
Native Meta Box content models, field values, relationships, and settings pages
Thirty-nine abilities provide bounded native paths for Meta Box 5.14, MB Builder 5.4, MB Custom Post Type 2.12, MB Relationships 1.13, and MB Settings Page. wp-agent/get-meta-box-status reports the detected core and Builder versions, the native provider ability count, and Settings Page contract availability. A missing extension returns HTTP 409 for the affected operation instead of silently falling back to raw post meta.
Meta Box proxy abilities never inherit an open native schema. They publish only a closed, bounded derived contract and validate both input and provider output against it. If the native ability contract, REST schema validator, or a required Meta Box extension is unavailable, the affected proxy returns HTTP 409. There is no raw-meta or raw-provider fallback. A provider result outside the derived contract is not emitted.
Field groups, individual field definitions, post types, and taxonomies require manage_options. ACF field values require the WordPress capability appropriate to the concrete target: edit_post, edit_user, edit_term, edit_comment, or, for option stores, manage_options or the capability configured for a registered ACF options page. Meta Box field values remain post-only and first require edit_posts as well as the provider's native object-level permission. Meta Box must know the field. Arbitrary meta keys, unreadable references, non-editable objects, and settings without administrator access remain blocked.
The field path corrects an MB Builder 5.4.2 defect that prevents the first field at index 0 from being read, changed, moved, or deleted. WPAgently uses a strict index lookup, an atomic field-group lock, the public Builder normalization, and complete read-back of fields, settings, and meta_box. A mismatch restores all three metadata values to their previous state. The post-type and taxonomy deletion path also avoids a typo in the native failure branch. The format ability removes only the extra field_id property that Meta Box 5.14 returns even though its output schema forbids it.
The eight relationship abilities always require manage_options. Definitions accept only approved settings and IDs of at most 44 characters. Persistent definitions never overwrite IDs already registered through PHP. Post types and taxonomies must be registered, nested query values have depth and size limits, and field output before or after the control is sanitized with wp_kses_post(). Updates and deletions require a fresh SHA-256 hash and share the same atomic relationship lock with connection changes. Definitions are fully normalized from settings, read back as the derived provider definition, and rolled back with verification after a mismatch. Connection writes read persistence and the registered provider state again while holding the lock and return HTTP 409 after a concurrent definition change. Connections use the public MB Relationships API, validate both object types, enforce one-connection limits, verify stored ordering, and read back the database state. Permanent deletion requires the exact relationship ID as an additional confirmation. With delete_data=true, connection rows are snapshotted, removed with verification, and restored if definition deletion fails.
The five settings-page abilities also require manage_options and the fully active combination of MB Settings Page and MB Builder. They manage persistent Builder definitions only. Pages registered in PHP are never overwritten. Input covers the documented page, menu, tab, Customizer, and network options while blocking PHP callbacks, active SVG data URLs, and known broad default capabilities. Network pages return HTTP 409 outside Multisite. Updates require a fresh hash and a short-lived lock. The Builder parser derives both persistent and active definitions, and both are read back in full. A mismatch triggers verified rollback. The page ID and option_name are immutable so field groups and existing option values cannot be orphaned silently. Deletion retains option data. Permanent deletion is available only after trashing and requires the exact page ID. The definition path and field-group binding are tested with the real Builder post type, parser, and mb_settings_pages filter. Value access through the proprietary runtime extension remains uncertified without a legally licensed practical installation.
| Abilities | Traits | Required parameters | Purpose |
|---|---|---|---|
wp-agent/get-meta-box-status | read, idempotent | none | Reads core, Builder, and ability status. |
wp-agent/list-meta-box-field-groups, wp-agent/get-meta-box-field-group | read, idempotent | id for a single item | Searches field groups or reads fields and settings. |
wp-agent/create-meta-box-field-group, wp-agent/update-meta-box-field-group | write | title or id | Creates or changes a persistent field group through MB Builder. |
wp-agent/delete-meta-box-field-group | write, destructive, not idempotent | id | Trashes a field group or permanently deletes it with force=true. |
wp-agent/list-meta-box-fields, wp-agent/get-meta-box-field | read, idempotent | field_group_id, plus field_id for one field | Reads all fields or one field, including the first list item. |
wp-agent/create-meta-box-field | write, not idempotent | field_group_id, field | Adds a normalized field definition with a unique ID. |
wp-agent/update-meta-box-field, wp-agent/move-meta-box-field | write, idempotent | field_group_id, field_id, change or target | Changes or moves a field with locking, read-back, and rollback. |
wp-agent/delete-meta-box-field | write, destructive, not idempotent | field_group_id, field_id | Removes a field definition with locking, read-back, and rollback. Stored field values remain in the database. |
wp-agent/list-meta-box-post-types, wp-agent/get-meta-box-post-type | read, idempotent | id for a single item | Searches persistent Meta Box post-type definitions or reads one definition. |
wp-agent/create-meta-box-post-type, wp-agent/update-meta-box-post-type | write | title, settings, or id | Creates or changes a post type through MB Custom Post Type. |
wp-agent/delete-meta-box-post-type | write, destructive, not idempotent | id | Deletes the definition without deleting existing content. |
wp-agent/list-meta-box-taxonomies, wp-agent/get-meta-box-taxonomy | read, idempotent | id for a single item | Searches persistent taxonomy definitions or reads one definition. |
wp-agent/create-meta-box-taxonomy, wp-agent/update-meta-box-taxonomy | write | title, settings, or id | Creates or changes a taxonomy through MB Custom Post Type. |
wp-agent/delete-meta-box-taxonomy | write, destructive, not idempotent | id | Deletes the definition without deleting existing terms. |
wp-agent/get-meta-box-field-value-format, wp-agent/get-meta-box-field-value | read, idempotent | field type or field_id, object_id | Reads the expected value shape or a registered field value. |
wp-agent/update-meta-box-field-value | write, idempotent | field_id, object_id, value | Stores a registered field value through rwmb_set_meta(). |
wp-agent/delete-meta-box-field-value | write, destructive, not idempotent | field_id, object_id | Removes a registered field's value. |
wp-agent/list-meta-box-settings-pages, wp-agent/get-meta-box-settings-page | read, idempotent | id for a single item | Lists persistent settings pages with pagination or reads the definition, active runtime state, and conflict hash. |
wp-agent/create-meta-box-settings-page | write, not idempotent | title, settings | Creates a published or draft Builder definition with strict validation and provider read-back. |
wp-agent/update-meta-box-settings-page | write, not idempotent | id, expected_hash, settings | Changes title, status, and safe options with locking and rollback. Page ID and option key remain immutable. |
wp-agent/delete-meta-box-settings-page | write, destructive, not idempotent | id, expected_hash | Moves the definition to trash. Permanent deletion requires force=true and the exact ID in confirm_settings_page_id. Option data remains. |
wp-agent/list-meta-box-relationships, wp-agent/get-meta-box-relationship | read, idempotent | id for a single item | Lists persistent definitions with pagination or reads one definition with its complete conflict hash. |
wp-agent/create-meta-box-relationship | write, not idempotent | title, settings | Creates a normalized definition with approved from and to sides and exact provider read-back. |
wp-agent/update-meta-box-relationship | write, not idempotent | id, expected_hash, settings | Replaces an unchanged definition under the same relationship ID with locking and rollback. |
wp-agent/delete-meta-box-relationship | write, destructive, not idempotent | id, expected_hash | Moves the definition to trash. Permanent deletion requires force=true and the exact ID in confirm_relationship_id. |
wp-agent/list-meta-box-connections | read, idempotent | relationship_id, direction, object_id | Lists at most 100 connections per page including order and state hash. |
wp-agent/add-meta-box-connection | write, not idempotent | relationship_id, from, to | Connects two matching objects through the provider API and verifies the database state. |
wp-agent/delete-meta-box-connection | write, destructive, not idempotent | relationship_id, from, to, expected_hash | Deletes an unchanged connection and restores it with its order if deletion cannot be confirmed. |
wp-agent/get-product
Purpose: Reads a complete WooCommerce product through WC_Product: core data, prices, stock, visibility, shipping dimensions, media, categories, tags, shipping class, and attributes. Raw post meta is never used.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $product_id) (resolved by WooCommerce's map_meta_cap() to the WooCommerce capability edit_products, by default only Shop Manager and Administrator, not Editor). Requires WooCommerce (otherwise 400).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
product_id | integer | yes |
| Output field | Type | Description |
|---|---|---|
product_id | integer | |
type, status, name, slug, sku, prices, stock status, descriptions, visibility, weight | string | |
stock_quantity | integer|null | null if stock isn't tracked. |
manage_stock, virtual, downloadable, featured | boolean | |
dimensions, attributes | object/array | Dimensions and native product attributes. |
| Media, category, tag, and shipping IDs | integer/array | IDs of associated WooCommerce objects. |
Example: { "product_id": 120 }
wp-agent/update-product
Purpose: Partial update of a WooCommerce product exclusively via the WC_Product object (official setters plus save()), never directly via wp_update_post()/update_post_meta(). Reason: a raw update_post_meta() call does change the postmeta row, but neither WooCommerce's object cache nor the lookup table wp_wc_product_meta_lookup, which the shop frontend uses for price sorting/filtering. Checks a duplicate SKU up front via wc_get_product_id_by_sku() (instead of letting the synchronously thrown WC_Data_Exception from set_sku() turn into an uncaught HTTP 500).
Capability: edit_posts (coarse) plus current_user_can('edit_post', $product_id) (WooCommerce edit_products). Requires WooCommerce.
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required | Description |
|---|---|---|---|
product_id | integer | yes | |
name | string | no | |
regular_price | string | no | Numeric string, e.g. 19.99. Empty removes the price. |
sale_price | string | no | Same as regular_price. |
sku | string | no | Checked up front for collision. |
stock_quantity | integer | no | |
manage_stock | boolean | no | |
status | string (enum: draft, publish, pending, private) | no | |
short_description | string | no | |
description | string | no | |
virtual, downloadable, featured | boolean | no | |
catalog_visibility, stock_status | enum | no | Native WooCommerce values. |
weight, length, width, height | string | no | Non-negative numeric strings. |
image_id, gallery_image_ids, category_ids, tag_ids, shipping_class_id | integer/array | no | Associated media and taxonomies. |
attributes | array | no | Name, options, visibility, and variation use. |
| Output field | Type |
|---|---|
product_id | integer |
type | string |
written | object |
verified | boolean |
Example: { "product_id": 120, "regular_price": "24.99", "stock_quantity": 50 }
wp-agent/get-woocommerce-store-settings
Purpose: Reads a bounded, secret-free snapshot of effective WooCommerce store configuration. It includes base country and state, currency and formatting, tax status, price and weight settings, dimension unit, stock management, guest checkout, account creation, HTTPS checkout, and the published shop, cart, checkout, and account pages. Credentials, payment-provider configuration, webhooks, email addresses, and raw options are never returned.
Capability: manage_woocommerce. Traits: read-only, non-destructive, idempotent. No parameters.
wp-agent/list-products
Purpose: Searches and filters products through WC_Product_Query and the official Product Data Store. Supports search, exact sku, status, type, page, and per_page up to 100. Returns complete product objects plus total and pages.
Capability: edit_products. Traits: read-only, non-destructive, idempotent.
wp-agent/preview-woocommerce-bulk-price-update
Purpose: Creates a confirmable preview for a bounded WooCommerce price operation across the products in one category or tag. selection contains only taxonomy with product_cat or product_tag, a positive term_id, and include_variations. operation permits an integer discount from 1 through 90 percent, a positive fixed sale price, or clearing the sale price. Products with scheduled sale windows fail closed.
The selection contains at most 50 independently priced products or variations. Product and variation queries stop at the 51st target before further objects are fully hydrated. The preview returns exact target IDs, previous and planned prices, related variable parent products, and a SHA-256 hash. That hash binds the subsite, WooCommerce version, currency and price formatting, selection, operation, target order, product state, and parent state.
Capability: edit_products. Traits: read-only, non-destructive, idempotent.
wp-agent/execute-woocommerce-bulk-price-update
Purpose: Executes only an unchanged bulk-price preview. Required fields are blog_id, the same selection and operation, the exact sorted item_ids list, preview_collection_hash, and confirm=true. Before writing, it revalidates the complete selection, target set, prices, term membership, parent state, and store context.
Every target has a separate short-lived lock, is read again immediately before its native WC_Product::save() mutation, and is read back afterward together with lookup state and, where applicable, the variable parent price. The global execution lease is renewed before and after every save. Lost ownership, an uncertain provider state, or divergent read-back returns recovery_required; prices already written are not automatically reverted, and foreign changes are never overwritten.
Capability: edit_products plus native edit_post permission for every target and variable parent product. Traits: write, non-destructive, not idempotent.
wp-agent/create-product
Purpose: Creates simple or variable products through WC_Product_Simple or WC_Product_Variable. type and name are required. Every product field accepted by update-product can be set directly. SKU collisions and invalid prices are rejected before saving, then the stored product is read back.
Capability: native product creation capability, plus publish_products when publishing. Traits: write, non-destructive, non-idempotent.
wp-agent/delete-product
Purpose: Permanently deletes a product through WC_Product::delete(true) and clears WooCommerce caches. Requires product_id and confirm: true.
Capability: object-specific delete_post. Traits: write, destructive, non-idempotent.
wp-agent/list-product-variations
Purpose: Lists every variation of a variable product through its native child IDs and WC_Product_Variation. Requires product_id.
Capability: object-specific edit_post on the parent product. Traits: read-only, non-destructive, idempotent.
wp-agent/upsert-product-variation
Purpose: Creates or updates a variation through WC_Product_Variation. Creation requires product_id and at least one variation attribute enabled on the parent. Supplying variation_id performs a partial update. Prices, SKU, stock, status, media, dimensions, and digital properties are stored natively. The parent, lookup data, and transients are synchronized afterward.
Capability: object-specific edit_post on the parent product. Traits: write, non-destructive, idempotent for updates.
wp-agent/delete-product-variation
Purpose: Permanently deletes a variation belonging to the supplied parent product. Requires product_id, variation_id, and confirm: true. The variable product is synchronized afterward.
Capability: delete_post on the variation plus edit access to the parent. Traits: write, destructive, non-idempotent.
wp-agent/list-product-attributes
Purpose: Lists all global WooCommerce product attributes freshly through wc_get_attribute_taxonomies(). Each result contains ID, name, slug, taxonomy name, type, ordering, archive status, dependent term count, and a complete SHA-256 state hash. Term counts for the whole list are loaded in one shared database query.
Capability: manage_product_terms. Traits: read-only, non-destructive, idempotent. Requires WooCommerce and its public attribute API.
wp-agent/get-product-attribute
Purpose: Reads exactly one global attribute definition by attribute_id and returns the same complete state as the list operation.
Capability: manage_product_terms. Traits: read-only, non-destructive, idempotent. An unknown ID returns HTTP 404.
wp-agent/upsert-product-attribute
Purpose: Creates or updates a global attribute definition exclusively through wc_create_attribute() or wc_update_attribute(). Creation requires name. slug, type, order_by, and has_archives are optional. An update requires attribute_id, expected_state_hash, and at least one changed field. Slugs may optionally start with pa_ and must contain no more than 28 characters after sanitization. Registered WooCommerce attribute types are validated at runtime.
Safety: The ability holds an atomic global short-lived lock, compares the fresh complete state including the dependent term count, reads the result back through WooCommerce, and verifiably rolls back any create or update that is not confirmed exactly. It also detects a partial failure where a WooCommerce hook aborts only after the database insert. Slug renames run through WooCommerce so product attributes, variation metadata, and the term ordering option are migrated natively.
Capability: manage_product_terms. Traits: write, destructive, non-idempotent. Updates are marked destructive because a rename changes catalog structure.
wp-agent/delete-product-attribute
Purpose: Deletes an unchanged global attribute definition through wc_delete_attribute() and then independently verifies that both the definition and every related attribute term are absent. Required fields are attribute_id, the fresh expected_state_hash, confirm: true, and confirm_data_loss: true. A term created after the read invalidates the hash with HTTP 409. If a provider failure leaves terms behind, the ability reports HTTP 502 with the remaining count instead of returning a false success.
Capability: manage_product_terms. Traits: write, destructive, non-idempotent. Deletion permanently removes the related attribute taxonomy and its terms. No lossless rollback exists for this operation.
Product categories, product tags, and terms of global attributes are managed through the generic taxonomy abilities. Shipping classes are explicitly blocked there and use the specialized abilities below. These four attribute abilities manage WooCommerce's global attribute definitions themselves.
wp-agent/list-product-shipping-classes
Purpose: Lists WooCommerce shipping classes with pagination and no N+1 queries. Each result contains its ID, name, slug, plain-text description, product usage, and complete state hash.
Capability: manage_woocommerce. Traits: read-only, non-destructive, idempotent. Optional: search, page, per_page.
wp-agent/get-product-shipping-class
Purpose: Reads one shipping class with the same confirmed state and conflict hash. An unknown ID returns HTTP 404.
Capability: manage_woocommerce. Traits: read-only, non-destructive, idempotent. Required: shipping_class_id.
wp-agent/upsert-product-shipping-class
Purpose: Creates or updates a shipping class through the native WooCommerce taxonomy. Names, slugs, and plain-text descriptions are bounded; duplicate names or slugs are rejected. Updates require a fresh expected_state_hash. Provider permissions, an atomic lock, exact read-back, and the unambiguous new term ID protect the operation. If WooCommerce reports success but the state cannot be attributed exactly afterward, the ability returns recovery_required and performs no automatic delete or rewrite.
Capability: manage_woocommerce. Traits: write, marked destructive, non-idempotent. Creation requires name. An update requires shipping_class_id, expected_state_hash, and at least one mutable field. Remote deletion remains blocked because external WooCommerce writers do not share the same lock, so an orphaned product relationship cannot be ruled out without a race.
wp-agent/list-orders
Purpose: Lists WooCommerce orders through wc_get_orders() and the active WooCommerce data store. The practically verified path uses HPOS. Personal, address, payment, and line-item data is omitted by default. Each group appears only through its separate include_customer, include_payment, or include_items switch. Responses are limited to 100 orders and 200 line items per order.
Capability: read_private_shop_orders. Traits: read-only, non-destructive, idempotent. Optional: status, customer_id, the three include_* switches, page, and per_page. Output: orders, total, total_pages, page, per_page.
wp-agent/get-order
Purpose: Reads exactly one order through wc_get_order(). The compact default response contains status, timestamps, and totals, but no customer, address, payment, or line-item data. Those groups must be requested separately as for list-orders. Refund objects are not accepted as orders.
Capability: read_private_shop_orders. Traits: read-only, non-destructive, idempotent. Requires order_id. Optional: include_customer, include_payment, include_items.
wp-agent/list-order-notes
Purpose: Lists at most 100 WooCommerce order notes. type limits the response to all, internal, or customer. Notes may themselves contain personal communications and therefore belong to the separately gated order group.
Capability: read_private_shop_orders. Traits: read-only, non-destructive, idempotent. Requires order_id. Optional: type, limit.
wp-agent/set-order-status
Purpose: Sets a registered order status through the native WC_Order object and reads the order back. confirm: true is mandatory because a transition can trigger emails, stock movements, webhooks, and third-party automation. expected_date_modified rejects stale writes with HTTP 409. refunded and checkout-draft are blocked. A refund requires its own payment and amount operation and is never simulated by this ability.
Capability: edit_shop_orders. Traits: write, destructive, idempotent. Requires order_id, status, confirm. Optional: expected_date_modified. Output: freshly read order and verified.
wp-agent/add-order-note
Purpose: Adds a sanitized plain-text note through WC_Order::add_order_note() and reads it back. Customer-visible notes require confirm_customer_notification: true because WooCommerce may send an email. The required idempotency_key binds one payload to one order. Retries return the existing note, while a different payload under the same key is rejected with HTTP 409.
Capability: edit_shop_orders. Traits: write, destructive, idempotent. Requires order_id, note, idempotency_key. Optional: customer_note, confirm_customer_notification. Output: note, verified, reused.
Order permissions are never granted with ordinary WooCommerce catalog access or when an agent user is created. The connection page can explicitly add read_private_shop_orders and edit_shop_orders to a safe Editor. Disabling access or uninstalling WPAgently removes recorded additions only and preserves pre-existing grants. The complete orders group appears only in Full and Custom profiles. Read-only may expose the three read abilities, but the capability remains mandatory. The Content profile contains no order abilities. Order creation, line-item changes, refunds, and payment operations are not supported.
wp-agent/list-contact-forms
Purpose: Lists Contact Form 7 forms through WPCF7_ContactForm::find(). Supports search and pagination and returns each form's ID, immutable provider identifier, complete SHA-256 state hash, slug, title, locale, and embeddable shortcode.
Capability: wpcf7_read_contact_forms. Contact Form 7 grants this plugin capability to Editors by default.
Traits: read-only, non-destructive, idempotent. Optional parameters: search (string), page (integer, at least 1), per_page (integer, 1-100). Output: forms[], total, page, per_page.
wp-agent/get-contact-form
Purpose: Reads a Contact Form 7 form through its object API, never raw post meta. Returns the form-tag template, parsed fields, safe projections of both mail configurations, messages, shortcode, the complete SHA-256 state hash, and current results from the native WPCF7_ConfigValidator. Mail projections contain activation, subject, sender, recipient, plain-text body, one managed Reply-To, blank-field handling, and format. Attachment paths, arbitrary additional headers, and raw additional_settings are omitted. Boolean indicators report preserved but hidden advanced configuration.
Capability: wpcf7_read_contact_forms plus object-specific wpcf7_edit_contact_form.
Traits: read-only, non-destructive, idempotent. Required parameter: form_id (integer).
wp-agent/create-contact-form
Purpose: Creates a form with wpcf7_save_contact_form(). Without a custom template, Contact Form 7 supplies its locale-aware default. A custom template may contain only CF7 form tags and tightly allowlisted structural markup without scripts, inline styles, or raw form controls. For a custom template, WPAgently builds a valid default notification from the field tags that actually exist. Safe mail changes are limited to subject, sender, recipient, body, reply_to, exclude_blank, additionally active for the autoresponder, and switching to format: plain. Messages are plain text under known CF7 keys. The candidate passes the native configuration validator and a mail-tag allowlist before it is stored. An exact complete read-back is mandatory. A mismatch removes the incomplete form automatically.
Capability: wpcf7_edit_contact_forms.
Traits: write, non-destructive, non-idempotent. Required parameter: title. Optional: locale, form, mail, mail_2, messages. Raw additional_settings, attachments, arbitrary headers, and enabling HTML mail are not writable. Output: form and verified.
wp-agent/update-contact-form
Purpose: Updates only the safe properties accepted by create-contact-form. expected_hash binds the write to the complete previously read state. An atomically acquired short-lived lock prevents concurrent agent writes. Omitted and hidden provider data is preserved in full. Structural markup, mail tags, mailboxes, confirmation text, and the complete affected CF7 configuration are checked before persistence. After persistence, the complete logical state must exactly match the validated candidate. A save error, drift, or post-save validation error restores the complete previous state through the native object API and verifies that rollback again by SHA-256.
Capability: wpcf7_edit_contact_forms plus object-specific wpcf7_edit_contact_form.
Traits: write, non-destructive, idempotent. Required parameters: form_id, expected_hash. Optional properties match create-contact-form.
wp-agent/duplicate-contact-form
Purpose: Duplicates a form through WPCF7_ContactForm::copy() and save(). expected_hash and the same form-specific short-lived lock prevent copying a stale or concurrently changed state. The complete source must be valid before persistence. The copy receives a new ID and preserves every provider property. Its complete logical state is read back exactly. A divergent copy is deleted automatically.
Capability: wpcf7_edit_contact_forms plus object-specific wpcf7_edit_contact_form.
Traits: write, non-destructive, non-idempotent. Required parameters: form_id, expected_hash; optional title. Output: form and verified.
wp-agent/delete-contact-form
Purpose: Permanently deletes a Contact Form 7 form through its delete() method. Contact Form 7 itself uses wp_delete_post(..., true), so a current expected_hash, the form-specific short-lived lock, and confirm: true are mandatory in addition to the destructive Ability annotation. A fresh lookup verifies deletion.
Capability: wpcf7_edit_contact_forms plus object-specific wpcf7_delete_contact_form.
Traits: write, destructive, non-idempotent. Required parameters: form_id, expected_hash, confirm. Output: form_id, deleted.
wp-agent/list-fluent-forms
Purpose: Lists Fluent Forms forms through the native FormService. Search, status, and pagination are bounded. The underlying Fluent Forms API path applies form-specific manager scopes. Unknown model, add-on, and form-meta data is omitted.
Capability: fluentform_dashboard_access. Traits: read-only, non-destructive, idempotent. Optional: search, status (published, unpublished, all), page, per_page (1-100).
wp-agent/get-fluent-form
Purpose: Reads a form through FormService::find(). The response allowlists only ID, title, status, type, payment flag, timestamps, shortcode, field count, and the complete field hash. Raw provider field structures remain internal. The native Fluent Forms ACL is checked with the concrete form ID.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: read-only, non-destructive, idempotent. Requires form_id.
wp-agent/create-fluent-form
Purpose: Creates the native blank template through FormService::store(), then applies the exact title, status, and optional submit label through the native updater. Fields are subsequently created only through the safe field ability. A fresh read-back is compared with the intended payload. A mismatched incomplete form is removed and that deletion is verified.
Capability: fluentform_forms_manager. Traits: write, non-destructive, non-idempotent. Requires title. Optional: status, submit_label. Output: form, verified.
wp-agent/update-fluent-form
Purpose: Updates only supplied values through FormService::update(). An empty write is rejected. Title, status, and submit label are checked against a fresh read-back. All form mutations use the same form-specific short-lived lock. A submit-label change additionally requires the current complete expected_hash. On mismatch, WPAgently restores the complete previously read state and verifies the rollback.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: write, non-destructive, idempotent. Requires form_id. Optional: title, status, submit_label, expected_hash. expected_hash is mandatory when changing submit_label.
wp-agent/duplicate-fluent-form
Purpose: Duplicates a form through FormService::duplicate() so Fluent Forms also copies its metadata and files. An optional rename uses the native updater. ID, status, and fields are compared with the source. A faulty or unverifiable copy is removed and that deletion is checked.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: write, non-destructive, non-idempotent. Requires form_id; optional title.
wp-agent/delete-fluent-form
Purpose: Permanently deletes a form through FormService::delete(). confirm: true is mandatory. A subsequent lookup verifies that the form no longer exists.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: write, destructive, non-idempotent. Requires form_id, confirm.
wp-agent/get-fluent-form-fields
Purpose: Reads a form's compact, secret-free field structure. The response includes field keys, normalized types, safe settings, submit label, field count, the complete fields_hash, and a type catalog derived from provider components loaded on the actual installation. Text, email, textarea, number, select, multi-select, radio, checkbox, name, address, country, URL, and date are safely mapped. Phone, file, and image are available only when the concrete Fluent Forms installation provides their native components. Unknown add-on fields are represented as unsupported placeholders without raw settings.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: read-only, non-destructive, idempotent. Requires form_id. Output: form_id, fields, field_count, fields_hash, empty, submit_label, field_types.
wp-agent/upsert-fluent-form-field
Purpose: Creates exactly one field from a native provider template or updates exactly one existing supported field. Only the type-specific safe settings in the schema are accepted, including label, help text, placeholder, required state, bounded defaults, text length, number range, choices, subfields, and date options. Raw provider structures are rejected. expected_hash, the shared form-specific short-lived lock, a 500-field maximum, complete provider read-back, and verified rollback protect the complete structure. Existing unknown siblings are preserved but cannot be changed through this ability.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: write, non-destructive, idempotent. Requires form_id, field_key, expected_hash, field. Optional: after_field_key. Output: the freshly read safe field state and verified.
wp-agent/delete-fluent-form-field
Purpose: Deletes exactly one supported field after confirm: true, a current expected_hash, and complete read-back. The last field remains protected unless allow_empty_form: true explicitly approves an empty form. Unknown add-on fields cannot be removed through this bounded path. A mismatch or provider exception triggers a verified complete rollback.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: write, destructive, non-idempotent. Requires form_id, field_key, expected_hash, confirm. Optional: allow_empty_form. Output: the freshly read field state, deleted, deleted_field_key.
wp-agent/get-fluent-form-delivery
Purpose: Reads the submission confirmation and compact email notifications through the native Fluent Forms SettingsService. By default, each notification contains only its ID, name, enabled state, recipient type, subject, and complete item hash. include_notification_details: true additionally returns the recipient address or form field, sender, reply-to address, BCC, message, and template key. Unknown add-on settings and secrets remain hidden in both views. confirmation_hash covers the complete raw general and advanced form settings. notifications_hash covers the complete raw notification records, including fields that are not returned. Compact and detailed responses use identical conflict hashes.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: read-only, non-destructive, idempotent. Requires form_id. Optional: include_notification_details, default false. Output: form_id, confirmation, confirmation_hash, notifications, notifications_hash, notification_details_included.
wp-agent/update-fluent-form-confirmation
Purpose: Selectively changes the confirmation message, same-page behavior, redirect destination, and bounded query parameters. Messages accept plain text with Fluent Forms smartcodes and are converted safely to HTML. HTML, control characters, invalid pages, and unsafe URLs are rejected. expected_hash, a form-specific short-lived lock, complete provider read-back, and verified rollback protect against concurrent or divergent changes. Omitted and unknown settings are preserved.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: write, non-destructive, idempotent. Requires form_id, expected_hash, confirmation. Output: the freshly read delivery state and verified.
wp-agent/upsert-fluent-form-notification
Purpose: Creates or updates exactly one email notification. Recipients, sender, reply-to address, BCC, subject, message, and template key are strictly bounded. Header injection is rejected. Messages are converted to safe HTML from plain text and smartcodes only. Siblings, conditional rules, and unknown add-on fields remain unchanged. A complete expected_hash, the same short-lived lock, raw read-back, and rollback protect the operation even when the provider throws after mutating state.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: write, non-destructive, non-idempotent. Requires form_id, expected_hash, notification; optional notification_id for an update. Output: form_id, notification, notifications_hash, verified.
wp-agent/delete-fluent-form-notification
Purpose: Deletes exactly one email notification after confirm: true and a complete conflict check. The record must be absent after the mutation. A provider exception after deletion or a divergent read-back triggers an attempt to restore the record with the same ID and verify the complete notification state. An explicit rollback error is returned if that is impossible.
Capability: fluentform_forms_manager plus form-specific Fluent Forms ACL. Traits: write, destructive, non-idempotent. Requires form_id, notification_id, expected_hash, confirm. Output: form_id, notification_id, deleted, notifications_hash.
Fluent Forms does not grant these permissions to a regular Editor automatically. The connection page can add fluentform_dashboard_access and fluentform_forms_manager specifically to a safe agent user. Form-specific manager restrictions remain effective. Disabling access or uninstalling removes only recorded additions made by WPAgently and preserves preexisting user permissions.
wp-agent/list-fluent-entries
Purpose: Lists at most 100 entries for one concrete form through the native Fluent Forms Entry API. Search, status, and pagination are bounded. Field values remain hidden by default. IP address, browser data, payment data, transactions, and unknown metadata are omitted even when include_values: true is requested.
Capability: fluentform_entries_viewer plus form-specific Fluent Forms ACL. Traits: read-only, non-destructive, idempotent. Requires form_id. Optional: search, status, include_values, page, per_page.
wp-agent/get-fluent-entry
Purpose: Reads the field values of one entry through the native Fluent Forms Entry API. The response contains only allowlisted core properties and bounded form values. A SHA-256 version covers status, favorite state, response, and modification time.
Capability: fluentform_entries_viewer plus form-specific Fluent Forms ACL. Traits: read-only, non-destructive, idempotent. Requires entry_id.
wp-agent/set-fluent-entry-status
Purpose: Sets a status supported by the concrete form through the native Fluent Forms bulk service. expected_version can reject concurrent changes with HTTP 409. The entry is read back. An exception after mutation or a mismatched read-back triggers a verified rollback to the previous status.
Capability: fluentform_manage_entries plus form-specific Fluent Forms ACL. Traits: write, destructive, idempotent. Requires entry_id, status. Optional: expected_version.
wp-agent/set-fluent-entry-favorite
Purpose: Idempotently sets or removes the favorite marker through the native Fluent Forms bulk service. The result is read back. Exceptions after mutation and mismatched results are rolled back to the previous value, and that rollback is verified.
Capability: fluentform_manage_entries plus form-specific Fluent Forms ACL. Traits: write, non-destructive, idempotent. Requires entry_id, favorite. Optional: expected_version.
wp-agent/delete-fluent-entry
Purpose: Permanently deletes an entry and the associated data managed by Fluent Forms through the native bulk service. confirm: true is mandatory. A subsequent lookup must confirm absence.
Capability: fluentform_manage_entries plus form-specific Fluent Forms ACL. Traits: write, destructive, non-idempotent. Requires entry_id, confirm. Optional: expected_version.
Fluent Forms entry permissions are separate from form permissions because submissions may contain personal data. They are never granted automatically when an agent user is created. The entries group is fully exposed only by the Full and Custom profiles. The connection page can add fluentform_entries_viewer and fluentform_manage_entries explicitly and later removes only recorded additions.
wp-agent/list-kadence-forms
Purpose: Lists native kadence_form objects on Kadence Blocks Free 3.7.8 with bounded pagination. The output contains only ID, title, status, and modified time, never recipients, messages, or other delivery data.
Capability: edit_kadence_forms and edit_post for every result. Traits: read-only, non-destructive, idempotent. Optional: search, status, page, per_page (1-100).
wp-agent/get-kadence-form-settings
Purpose: Reads one native Kadence form, its bounded field types, and the safe subset of description, browser validation, local redirect, hide-after-submit, and compact email settings. The output flags unknown or advanced actions, headers, and provider states and binds the complete raw form state to a SHA-256 hash.
Capability: edit_kadence_forms and edit_post for the form. Traits: read-only, non-destructive, idempotent. Required: form_id.
wp-agent/update-kadence-form-settings
Purpose: Changes only description, browser validation, a root-relative or same-origin redirect, hide-after-submit, and a single email action with exactly one recipient. Unknown actions, duplicate actions, Pro, CC, BCC, headers, unsafe URLs, and non-canonical provider states remain blocked. A complete expected_hash, a renewable create-only lock, repeated capability and provider checks, and exact raw-state read-back protect the operation. After a started mutation that cannot be confirmed unambiguously, the ability returns recovery_required and performs no automatic follow-up mutation.
Capability: edit_kadence_forms and edit_post for the form. Traits: write, non-destructive, idempotent. Required: form_id, expected_hash, settings.
wp-agent/list-gravity-forms
Purpose: Lists Gravity Forms forms through GFAPI::get_forms(). Supports search, pagination, and the status filters active, inactive, trash, and all. It returns documented basic properties only, never unknown add-on settings.
Capability: gravityforms_edit_forms. Traits: read-only, non-destructive, idempotent. Optional: search, status, page, per_page (1-100).
wp-agent/get-gravity-form
Purpose: Reads a form through GFAPI::get_form() and returns documented core properties, fields, button, notifications, confirmations, and an allowlisted set of documented form settings. Unknown form-level add-on data is deliberately omitted because it may contain credentials.
Capability: gravityforms_edit_forms. Traits: read-only, non-destructive, idempotent. Requires form_id.
wp-agent/create-gravity-form
Purpose: Creates a form through GFAPI::add_form() and reads it back through the public GFAPI. Supports title, description, up to 500 fields, up to 200 notifications and confirmations, and an allowlist of documented settings. Unknown form-level settings are rejected.
Capability: gravityforms_create_form. Traits: write, non-destructive, non-idempotent. Requires title. Output: form, verified.
wp-agent/update-gravity-form
Purpose: Updates only supplied properties through GFAPI::update_form(). An empty write is rejected. The form is read back and the requested subset is compared with Gravity Forms' normalized stored state.
Capability: gravityforms_edit_forms. Traits: write, non-destructive, idempotent. Requires form_id.
wp-agent/duplicate-gravity-form
Purpose: Duplicates a form through GFAPI::duplicate_form(). An optional title is set through GFAPI::update_form_property(). If renaming fails, the incomplete copy is deleted. Fields and optional title are verified by read-back.
Capability: gravityforms_create_form and gravityforms_edit_forms. Traits: write, non-destructive, non-idempotent. Requires form_id; optional title.
wp-agent/delete-gravity-form
Purpose: Permanently deletes a form through GFAPI::delete_form(). confirm: true is mandatory. A subsequent lookup verifies that the form no longer exists.
Capability: gravityforms_delete_forms. Traits: write, destructive, non-idempotent. Requires form_id, confirm.
Gravity Forms does not grant these three form capabilities to a regular Editor automatically. The connection page can add them specifically to a safe agent user. Removing access or uninstalling the plugin removes only capabilities that WPAgently itself added and recorded. Existing role or user grants are preserved.
Formidable Forms
The six abilities list-formidable-forms, get-formidable-form, create-formidable-form, update-formidable-form, duplicate-formidable-form, and delete-formidable-form use only the native model methods provided by FrmForm and FrmField. Lists are bounded to 100 results per page and 5,000 forms in total. Read responses contain only explicitly allowlisted form and field properties. Unknown add-on options are not exposed. Default values of existing password and hidden fields are redacted and cannot be changed.
New fields are limited to the portable types text, email, url, phone, number, textarea, checkbox, radio, and select. Descriptions and values are treated as plain text. Each form is limited to 500 fields and each field to 500 choices. Text lengths and nested default values are bounded as well. Larger existing forms are rejected with HTTP 413 instead of producing an unbounded MCP response. Creates, updates, and duplicates are read back and verified. Partial updates preserve omitted form values and unknown internal field options. Failures trigger a best-effort restoration of the complete prior internal state. Duplication may legitimately rewrite field IDs assigned by Formidable. Permanent deletion requires confirm: true and succeeds only after the form, previously known fields, and entries are gone. Remaining provider records are cleaned through the native individual models. expected_form_key can reject a concurrently replaced record with HTTP 409.
Reads require frm_view_forms, writes require frm_edit_forms, and deletion requires frm_delete_forms. The connection page can grant these three capabilities specifically to a safe agent user and later removes only additions recorded by WPAgently. The mutation lock expires and can be released only by its owner.
Form migration between six form providers
wp-agent/preview-form-migration supports WPForms, Ninja Forms, Contact Form 7, Fluent Forms, Gravity Forms, and Formidable Forms. It reads an existing form through its provider's permission-checked native path and converts the portable field structure into the versioned wpagently-portable-form format. For WPForms, the native response is internally supplemented with the stored field properties required for reliable structure verification. Contact Form 7 is read through its public object and form-tag APIs. Portable field types are text, email, textarea, number, checkbox, radio, and select. Title, field order, type, label, help text, placeholder, default value, required state, and choices are preserved. The submit label is preserved as well unless Formidable Forms is either the source or the target. Its bounded safe adapter does not expose that property. portable_submit_label: false and omitted: ["submit_label"] report the limitation.
Complex name fields, phone fields, HTML, layout, and proprietary special fields, as well as values requiring truncation or sanitization, appear in unsupported_fields. The same applies to non-portable field semantics such as calculations, input masks, ranges, multiple selection, separate choice values, choice images, or conditional logic. portable_fields_lossless is then false. Preview performs no writes and is bounded to 200 source fields and 200 choices per field.
wp-agent/migrate-form additionally requires confirm: true and rejects every portable field structure that the target cannot represent in full with HTTP 409. It creates only a new structure copy in one of the other five providers. It then reads the target back in full and compares every portable property. A mismatch deletes the target copy and fails visibly. If deletion also fails, the ability returns wpagent_form_migration_rollback_failed and requests a manual check. The source form is neither changed nor deleted. Contact Form 7 receives newly generated accessible markup. Checkbox and radio groups use a valid fieldset with legend, preventing CF7 from placing multiple controls inside one label. Each CF7 source field needs an unambiguous associated label. Duplicate field names, more than 200 choices, a missing, empty, or repeated submit control, and values that cannot be represented safely in a form tag all block the preview. Its radio fields are always required. A simultaneous placeholder plus default value cannot be migrated either. Notifications, confirmations, conditional logic, original markup and layout, provider-specific form settings, and existing entries are deliberately not copied. target_behavior: provider_defaults and omitted[] report this in machine-readable form. A new CF7 target receives a validated default notification built from its actually generated field tags. Other targets use their provider defaults. Every target must be reviewed before production use.
WPForms Lite, Ninja Forms, Contact Form 7, Fluent Forms, and Formidable Forms have been practically verified against real installed plugins. Fluent Forms, Gravity Forms, and Formidable Forms also have complete read, target, read-back, and rollback contract tests. The bidirectional Fluent Forms mapping is tested against a real Ninja Forms installation. Fluent Forms 6.2.11 and Formidable Forms 6.33.1 additionally pass a real portable create, read-back, and delete cycle. Practical migration testing with the licensed original Gravity Forms plugin remains outstanding.
Preview requires the corresponding WPAgently read permission for the source provider. Migration additionally requires both read and write permission for the target provider because the new target must be read back in full. If either permission is missing, the request fails before any write. WPForms' own MCP write opt-in and Ninja Forms quarantine remain effective. Traits: preview is read-only and idempotent; migration is write, non-destructive to the source, and non-idempotent.
Weglot
wp-agent/get-weglot-settings reads the active Weglot version, connection state, original and destination languages, automatic language redirection, bounded language-switcher presentation settings, and URL and CSS-selector exclusions. Private and public API keys, custom CSS, translation content, and unknown provider options are never returned. Existing regular expressions in URL exclusions are visible and included in the state hash, but cannot be created or changed through WPAgently because of their runtime risk.
wp-agent/update-weglot-settings requires expected_hash and at least one changed field. The key must already be configured in Weglot itself. The bounded contract permits up to 30 unique destination languages, four documented flag styles, 50 relative URL exclusions, and 50 bounded CSS selectors. Original, destination, and custom language codes may not collide. Unknown provider data and existing custom CSS survive partial updates. Every effective write takes a global short-lived lock, reads the latest provider state immediately before mutation, writes through Weglot's service, forces a fresh provider read-back, and compares the complete safe project state. Provider failures or mismatches trigger a verified rollback. A rollback that cannot be verified fails visibly with HTTP 500 and requests immediate manual inspection.
Both abilities require manage_options. Traits: read is idempotent. Update is write, non-destructive, and idempotent.
Astra
wp-agent/get-astra-design detects an active Astra theme or Astra child theme and reads 21 curated areas through Astra's native WordPress abilities. They cover the container, body and heading typography, H1 through H6, paragraph spacing, link underlines, the global palette, background colours, buttons, the blog archive, single posts, single pages, the sidebar, scroll to top, and Header and Footer Builder layouts. For each available area, the response contains the current provider state and strict input schema, plus a SHA-256 hash over astra-settings, astra-color-palettes, and the active theme identity. Raw options are not returned. If Astra is inactive or its read and edit abilities are disabled, the operations list remains empty.
wp-agent/update-astra-design requires expected_hash, exactly one of the 21 operations, and a non-empty settings object. Font names, responsive font sizes, line height, letter spacing, colours, container values, button presets, content widths, and Header or Footer zones are validated more narrowly than Astra's provider contract. The palette uses nine named roles instead of error-prone numeric JSON keys. Header and Footer layouts accept only documented components in known responsive zones, bound list sizes, and reject duplicates. Every submitted zone list is the complete desired final state of that zone, not a partial list to append. Background images, arbitrary CSS values, button spacing, logo downloads, local font files, and performance switches remain outside this global path. Individual post metadata uses the separate post-specific contract below. Every global write locks the complete Astra state for five minutes, checks the hash again after acquiring the lock, writes through Astra's implementation, and forces the matching native read ability through an uncached read-back. Only an exact semantic confirmation succeeds. Provider failures or mismatches restore both astra-settings and astra-color-palettes and verify the complete hash. A rollback that cannot be verified fails with HTTP 500 and requests immediate manual inspection.
wp-agent/get-astra-post-design reads 16 normalised Astra overrides for a specific post_id. They cover content and sidebar layout, content and sidebar style, global, above, primary, below, and mobile headers, the footer, title, banner, breadcrumbs, featured image, related posts, and transparent header. inherit means that no post-specific value is stored and Astra's global setting applies. Raw post metadata and unrelated metadata are not exposed. The state hash binds the theme identity, post ID, post type, existence and exact value of every permitted provider field, and Astra's internal layout migration flag.
wp-agent/update-astra-post-design requires the same post_id, a fresh expected_hash, and at least one strictly typed override. Partial updates change only named fields. inherit deletes only that individual override. Modern layout values maintain Astra's migration flag according to the layout overrides that actually remain. The write shares the global Astra short-lived lock, reads every permitted metadata field back after persistence, and confirms every requested end value. A failure or read-back mismatch restores the existence and exact value of all permitted fields, including the migration flag, and verifies the complete previous state. Unrelated post metadata remains untouched.
The two global abilities require manage_options. The two post-specific abilities broadly require edit_posts and additionally check WordPress' concrete edit_post meta-capability for the target on every call. All four belong to the Design exposure group. Astra itself needs Abilities and Edit Abilities enabled under Astra > Dashboard > Settings only for the two global paths. A regular WPAgently Editor does not gain administrator capabilities. Traits: both reads are idempotent. Both updates are write, non-destructive, and idempotent.
GeneratePress
wp-agent/get-generatepress-design detects GeneratePress or an active GeneratePress child theme and reads five curated areas from the theme's native settings state: layout, global colours, surface colours, buttons, and typography. The response contains the active theme version, the bounded sections, and a SHA-256 hash over the complete stored generate_settings value plus the parent and child theme identities. Raw options and unknown provider data are not exposed. When the theme is inactive, the safe section set remains empty. Missing GeneratePress runtime functions fail closed.
wp-agent/update-generatepress-design requires expected_hash, exactly one section, and a non-empty settings object. It permits bounded layout values, existing global-colour slugs, twelve selected surface colours, four button colours, and the typography targets body, h1, h2, h3, and buttons. Arbitrary CSS, new palette entries, arbitrary selectors, font files, GeneratePress Premium Elements, unknown theme options, and uncontrolled values remain outside this path. Every write locks the complete settings state for five minutes, checks the conflict hash inside the lock, preserves unknown provider data, and rebuilds GeneratePress's native dynamic CSS cache. Both the saved section and CSS cache must exactly confirm the expected state. A provider failure or mismatch restores and verifies the complete previous settings value and both GeneratePress cache options.
Both abilities require manage_options and belong to the Design exposure group. GeneratePress 3.6.1 is locally covered by real layout, colour, typography, lock, conflict, CSS-cache, and rollback tests. The prepared GitHub Actions fixture installs the current WordPress.org release and will run for the first time after commit and push. Traits: read is idempotent. Update is write, non-destructive, and idempotent.
wp-agent/get-generatepress-post-design reads four native overrides for a public post or page: sidebar layout, footer-widget count, content container, and title visibility. inherit means no effective individual value is stored. The state hash binds the post ID, post type, parent and child theme, and the existence and exact raw value of all four metadata fields. Missing and officially empty defaults both normalize to inheritance while remaining distinguishable for conflict detection and rollback. Duplicate single-value rows and unknown provider values fail closed.
wp-agent/update-generatepress-post-design requires post_id, a fresh expected_hash, and at least one change. Partial updates change only named fields. inherit removes only the selected override. The write checks the concrete edit_post capability, locks only the target post, compares the complete raw state inside the lock, and additionally confirms explicit values through GeneratePress's real runtime functions. Persistence failures or mismatches restore the exact previous representation, including stored empty defaults, and verify its hash. The configured posts page remains blocked because GeneratePress enforces the global blog layout there and individual page values would be ineffective. Attachments, revisions, autosaves, non-public post types, and Premium Elements remain outside this contract. Both abilities belong to the Design exposure group. Traits: read is idempotent. Update is write, non-destructive, and idempotent.
OceanWP
wp-agent/get-oceanwp-design detects OceanWP or an active OceanWP child theme from version 4.1 and reads five curated areas from native theme mods: layout, global colours, responsive typography, buttons, and header style. Typography covers body text and global headings with desktop, tablet, and mobile values. The response includes the active theme version and a SHA-256 hash over the complete theme-mod option plus parent and child theme identity. Raw options and unknown provider data are not exposed. Invalid known provider values fail closed.
wp-agent/update-oceanwp-design requires expected_hash, exactly one section, and a non-empty settings object. It permits documented layouts, container width and unit, six global colour roles, four button colours, seven built-in header styles, and bounded responsive typography. Custom headers, arbitrary CSS, font files, Ocean Extra modules, and unknown theme options remain outside this safe path. Every write locks the complete theme-mod option for five minutes, checks the hash inside the lock, preserves unknown provider data, and confirms the stored section with a fresh read-back. Provider failures or mismatches restore the complete previous option and verify its hash.
Both abilities require manage_options and belong to the Design exposure group. Writes are available only in OceanWP's head mode for Customizer CSS. The free theme has no reliably callable regeneration path for file mode, so a write stops before mutation with HTTP 409 and migration guidance. OceanWP 4.2.2 is locally covered by real layout, colour, typography, header, lock, conflict, persistence, and rollback tests. The public GitHub Actions fixture installs the current WordPress.org release. Traits: read is idempotent. Update is write, non-destructive, and idempotent.
wp-agent/get-oceanwp-post-design reads the native ocean_post_layout and ocean_both_sidebars_style overrides for a public post or page. The normalized response uses inherit when Ocean Extra stored its official empty default or when the meta row is absent. It also returns the post type and a SHA-256 conflict hash over the post, parent and child theme identity, and exact allowed raw meta state. Duplicate single-value rows and unknown provider values fail closed.
wp-agent/update-oceanwp-post-design requires post_id, expected_hash, and at least one change. layout permits inherit, a right or left sidebar, full width, full-screen width, or both sidebars. both_sidebars_style permits inherit and OceanWP's three native orders. The write checks edit_post, locks only the target post, compares the complete raw state inside the lock, preserves untouched metadata, and additionally verifies explicit values through OceanWP's runtime functions. Persistence failures or mismatches restore the exact previous representation, including a stored empty default, and verify its hash. Attachments, revisions, autosaves, non-public post types, and other Ocean Extra areas remain outside this contract. Both abilities belong to the Design exposure group. Traits: read is idempotent. Update is write, non-destructive, and idempotent.
wp-agent/get-oceanwp-post-title and wp-agent/update-oceanwp-post-title are two additional, version-bound Ocean Extra abilities for individual page-title overrides. They are available only while OceanWP 4.2.2 and Ocean Extra 2.5.8 are active. Read returns the normalized page-header, heading, style, custom-title, and subheading values with a state hash. Write requires post_id, expected_hash, and at least one narrowly validated setting. Only documented selection values and bounded text overrides are allowed. Other Ocean Extra modules, headers, and raw metadata remain excluded. Once an Ocean mutation has started, an unsafe persistence, read-back, or runtime check fails closed with recovery_required. There is then neither an automatic rollback nor an automatic follow-up mutation. Inspect the current state manually.
wp-agent/get-oceanwp-post-layout-overrides and wp-agent/update-oceanwp-post-layout-overrides add a separate layout path that is likewise bound exactly to OceanWP 4.2.2 and Ocean Extra 2.5.8. Read returns only normalized header visibility and style, footer widgets and bottom area, an active registered custom sidebar, and content width with a state hash. Write requires post_id, expected_hash, and at least one bounded setting. Individual content width is permitted only with the native both-sidebars post layout. CSS, HTML, file paths, unregistered sidebars, and every other provider field remain excluded.
The write revalidates the post, subsite, provider, permission, and selected provider values after acquiring the lock. It renews the post-bound lock immediately before mutation and after provider and runtime read-back. Divergent or unsafe-to-read state after mutation starts returns only recovery_required; there is no automatic follow-up mutation and no claim of a complete rollback.
wp-agent/get-oceanwp-extra-modules and wp-agent/update-oceanwp-extra-module read or change exactly one of five module switches verified against Ocean Extra 2.5.8. My Library, the demo catalogue, and admin notifications are readable and writable. SVG uploads and the front-end style editor can only be disabled. The state hash binds the subsite, theme and plugin versions, and all five raw options. Write requires manage_options, a create-only lock, a fresh hash, and exact full-state read-back. Ambiguity after mutation returns recovery_required without an automatic rollback. Changes take effect on a new WordPress request because Ocean Extra loads modules during bootstrap.
wp-agent/list-oceanwp-library-templates lists at most 100 published, passwordless My Library templates per page. Only static, shortcode-free Core blocks without Elementor, SiteOrigin, or Beaver Builder state are accepted. Each result includes a content hash and block types. wp-agent/get-oceanwp-post-library-templates reads the native header and footer assignments of an editable post. wp-agent/update-oceanwp-post-library-templates requires the post hash and the fresh content hash of every newly selected template. Write locks the target post, rechecks provider, permission, raw metadata, and templates, changes only ocean_header_style, ocean_custom_header_template, and ocean_custom_footer_template, and verifies OceanWP's native runtime functions. Any mismatch after mutation starts returns recovery_required without an automatic follow-up mutation.
Kadence
wp-agent/get-kadence-design detects Kadence or an active Kadence child theme from version 1.5 and reads six curated areas from native provider state: content widths, all 15 colours in the active global palette, global surface and link colours, responsive typography for body text and H1-H6, global buttons, and placements of free desktop and mobile Header Builder components. The response includes the active theme version and a SHA-256 hash over the settings storage actually used by Kadence, kadence_global_palette, and the parent and child theme identities. In the normal theme-mod mode, the settings storage is theme_mods_<stylesheet>. A different option mode is accepted only when the Kadence runtime reports the exact expected option name. Raw options and unknown provider data are not exposed. Invalid known provider values fail closed.
wp-agent/update-kadence-design requires expected_hash, exactly one section, and a non-empty settings object. It permits bounded content widths, switching between the three existing palettes, individual colours in the active palette, four global colour roles, font family, Google-font flag, weight, responsive size and line height, plus button colours and responsive radii. In the header section, exactly one approved Kadence Free component can be moved, inserted, or removed in a native desktop or mobile zone. Positions, components, rows, zones, total count, and uniqueness are validated strictly. Arbitrary CSS, new palette entries, font files, unknown theme options, and Kadence Pro settings remain outside this safe path. Kadence Forms use the separate contract documented above.
Every write locks both provider states together for five minutes, refreshes the lock before and after mutation, rechecks permission, runtime, and the conflict hash inside the lock, preserves unknown provider data, and confirms the stored section through an exact read-back. The write itself is a byte-exact compare-and-swap over the raw value and autoload attribute. A third-party change in the final write window is therefore retained and returns HTTP 409 without a WPAgently mutation. A rollback changes only the option row written by this request and only while it still matches the expected write byte for byte. Third-party changes, lock loss, or uncertain state are retained and return recovery_required. The test additionally confirms the Header Builder result through Kadence's real render function.
Both abilities require manage_options and belong to the Design exposure group. Kadence 1.5.2 is locally covered by real layout, palette, colour, typography, button, Header Builder, lock, conflict, expiry, concurrent-change, persistence, rendering, and atomic CAS write and rollback tests. The public GitHub Actions fixture installs the current WordPress.org release. Traits: read is idempotent. Update is write, non-destructive, and idempotent.
wp-agent/list-gravity-entries
Purpose: Lists at most 100 entries for one form through GFAPI::get_entries(). Status, full-text search, calendar range, and pagination are bounded. Field values, IP address, user agent, and payment data remain hidden by default and are returned only with include_values: true.
Capability: gravityforms_view_entries. Traits: read-only, non-destructive, idempotent. Requires form_id. Optional: status, search, start_date, end_date, include_values, page, per_page.
wp-agent/get-gravity-entry
Purpose: Reads one entry through GFAPI::get_entry(). The response contains documented core properties, values for field and input IDs that actually exist in the current form, and documented payment fields. All unknown add-on metadata is deliberately omitted because it may contain credentials.
Capability: gravityforms_view_entries. Traits: read-only, non-destructive, idempotent. Requires entry_id.
wp-agent/update-gravity-entry
Purpose: Updates read state, starred state, and up to 100 existing numeric field or input IDs through GFAPI::update_entry_property() and GFAPI::update_entry_field(). expected_date_updated can reject concurrent changes. Partial failures and failed read-backs trigger a best-effort rollback.
Capability: gravityforms_edit_entries. Traits: write, non-destructive, idempotent. Requires entry_id and at least one of is_read, is_starred, or field_updates.
wp-agent/set-gravity-entry-status
Purpose: Sets an entry to active, spam, or trash, reads it back, and rolls back a status change that cannot be verified. Optional expected_date_updated rejects a stale write with HTTP 409.
Capability: gravityforms_edit_entries. Traits: write, destructive, idempotent. Requires entry_id, status.
wp-agent/delete-gravity-entry
Purpose: Permanently deletes an entry through GFAPI::delete_entry(). confirm: true is mandatory. A subsequent lookup must confirm absence.
Capability: gravityforms_delete_entries. Traits: write, destructive, non-idempotent. Requires entry_id, confirm. Optional: expected_date_updated.
Entry permissions are fully separated from form permissions because entries can contain personal and payment data. They are never granted automatically when an agent user is created. The entries group is fully exposed only by the Full and Custom profiles. The Read-only profile may expose the two read tools, but the Gravity Forms capability is always required as an additional check. The connection page can add the three entry capabilities explicitly and later removes only recorded additions.
wp-agent/refresh-builder-cache
Purpose: Detects a post's builder signals (reuses detect-builder) and triggers the builder-specific cache/regeneration invalidations, so the frontend doesn't stay stuck on stale output. Empirically checked against the actually installed plugin versions (not merely taken from documentation): Spectra 2.20.1 (__uagb_asset_version option plus _uag_page_assets meta deletion, equivalent to wp spectra regenerate-css), GenerateBlocks 2.3.0 (GenerateBlocks_Enqueue_CSS::post_update_option()), WooCommerce 10.9.4 (wc_delete_product_transients()). Kadence 3.7.8 and WPBakery are self-healing on render, no action needed. Elementor, Breakdance, and Oxygen: best-effort via known in-request APIs, if the classes/functions are loaded; no WP-CLI shell-out from within the REST request. Bricks is not included in the cache map in the underlying blueprint, so no action is claimed for it.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id) (via reuse of detect-builder).
Traits: write, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
| Output field | Type |
|---|---|
primary | string |
actions[] | Objects with builder, action, executed, verified |
notes[] | string[] |
Example: { "post_id": 42 }
wp-agent/get-builder-compatibility
Purpose: Returns a machine-readable matrix for Gutenberg, Spectra One, Kadence, Spectra, GenerateBlocks, Elementor, Beaver Builder, Bricks, Breakdance, Oxygen, and WPBakery. Each entry reports active status, version, storage, native write support, cache coverage, and practical, practical-read, or defensive validation. Proprietary builders without a stable public write interface are explicitly listed under fail_closed.
Capability: edit_posts.
Traits: read, non-destructive, idempotent. The ability changes no builder data.
Output: builders[] contains the entries. summary.native_write[] lists natively supported data surfaces and summary.fail_closed[] lists deliberately rejected write paths. Spectra One uses the native WordPress Global Styles and Site Editor surfaces. Kadence Blocks, Spectra, and GenerateBlocks are practically readable but remain closed to raw block-markup writes.
wp-agent/get-elementor-document
Purpose: Reads an existing Elementor document through Elementor's public document API. The response contains the normalized element tree and stored page settings, each in the closed {json,sha256,bytes} builder-document envelope, together with an element and widget summary, Elementor version, edit URL, and a canonical SHA-256 conflict hash covering structure and settings.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id) and Elementor's own is_editable_by_current_user() check.
Traits: read, non-destructive, idempotent. Without active Elementor or for a post that was not built with Elementor, the ability fails closed with HTTP 409.
Required: post_id. Output: post_id, built_with_elementor, elements and settings as builder-document envelopes, element_count, widget_types[], elementor_version, edit_url, hash.
wp-agent/get-elementor-design-system
Purpose: Reads Elementor's active global kit through its native kit API. The response contains the four system colors, custom colors, four system typography tokens, custom typography, responsive sizes and spacing, fallback font, Elementor version, kit ID, and a canonical SHA-256 conflict hash over the complete semantic design state.
Capability: manage_options plus Elementor's own kit editability check.
Traits: read, non-destructive, idempotent. The ability fails closed without an active editable Elementor kit. Custom colors and typography are each limited to 100 tokens. Color values, IDs, titles, and typography values are validated during reads as well.
wp-agent/update-elementor-design-system
Purpose: Atomically replaces one or more previously read global design areas. Supported areas are system colors, custom colors, system typography, custom typography, and the fallback font. Responsive font size, line height, letter spacing, and word spacing are stored with bounded numeric values and units. expected_hash must match the current complete state. Hex, RGB, RGBA, and transparent color values are accepted. CSS injection, duplicate or reserved IDs, invalid fonts, units, sizes, and unknown new typography fields fail closed.
Capability: manage_options plus Elementor's own kit editability check.
Traits: write, non-destructive, idempotent. At least one design area is required in addition to expected_hash. The path uses Elementor's Kit::save(), serializes concurrent WPAgently mutations with a short-lived lock, and freshly reads the complete state afterward. Elementor's kit save clears the native site cache. Save or read-back mismatches restore the exact original kit settings through Elementor's public page-settings API. Output adds previous_hash, changed, verified, and rolled_back.
wp-agent/get-elementor-global-classes
Purpose: Reads the complete Global Class state of Elementor v4 Atomic Elements. The path exposes no raw CSS rules. It returns the classes managed by the active kit, their native variants, available breakpoints, and a canonical SHA-256 conflict hash for the complete state.
Capability: manage_options plus Elementor's own Global Class capability.
Traits: read, non-destructive, idempotent. Its input is exclusively an empty object. The ability fails closed unless Elementor v4 with Atomic Elements is active. It processes at most 1,000 Global Classes.
Output: kit_id, elementor_version, breakpoints[], classes[], total, hash.
wp-agent/create-elementor-global-class
Purpose: Creates a new Elementor v4 Global Class through the native Atomic Elements contract. The class receives a safe CSS class label and one or more validated variants, never an open CSS or raw-data surface.
Capability: manage_options plus Elementor's own Global Class capability.
Traits: write, non-destructive, non-idempotent. Required are expected_hash, a label of 2 to 50 safe CSS-class characters, and variants with 1 to 64 entries. Every variant permits only breakpoint and state in meta and requires a non-empty props object with at most 100 entries. Active breakpoints and Elementor's native schema validate every value. A lock, compare-and-swap, revision, full read-back, frontend check, and automatic rollback protect the write path.
Output: the complete Global Class state plus class, previous_hash, changed, verified, rolled_back.
wp-agent/update-elementor-global-class
Purpose: Changes only the label and/or variants of an existing Elementor v4 Global Class. Unrelated classes and open raw-CSS paths remain untouched or closed.
Capability: manage_options plus Elementor's own Global Class capability.
Traits: write, non-destructive, idempotent for an unchanged target state. Required are expected_hash and class_id. label and variants are optional, but at least one must be present. The same label, variant, meta, and props bounds apply as on creation. Lock, compare-and-swap, revision, read-back, frontend check, and rollback also protect this update.
Output: the complete Global Class state plus class, previous_hash, changed, verified, rolled_back.
wp-agent/delete-elementor-global-class
Purpose: Deletes an Elementor v4 Global Class only after explicit confirmation and an exact confirmation of its current usage. A stale list of affected documents therefore cannot silently trigger a delete.
Capability: manage_options plus Elementor's own Global Class capability.
Traits: write, destructive, non-idempotent. Required are expected_hash, class_id, confirm=true, and affected_post_ids as the exact current list of at most 100 IDs. The ability fails closed unless that list matches current usage. The write path uses a lock, compare-and-swap, document-specific revisions, read-back, frontend check, and rollback.
Output: the complete Global Class state plus deleted_class_id, affected_post_ids, revision_ids, previous_hash, changed, verified, rolled_back.
wp-agent/set-elementor-element-global-classes
Purpose: Sets the Global Class assignment of one Elementor element through its v4 Atomic Elements interface. The path accepts only known Global Class IDs and offers no raw-CSS substitute.
Capability: manage_options plus Elementor's own Global Class capability.
Traits: write, non-destructive, idempotent. Required are post_id, element_id, the document expected_hash, and global_class_ids as a unique list of at most 100 IDs. The target must belong to an Elementor v4 Atomic Elements document. Native schema and breakpoint validation, a lock, compare-and-swap, revision, full read-back, frontend check, and rollback protect the assignment.
Output: the normal Elementor element write state plus global_class_ids.
wp-agent/list-elementor-widgets
Purpose: Lists widget types from the active Elementor installation's registry with search, category filtering, and pagination. Raw HTML and shortcode widgets, as well as every legacy adapter prefixed with wp-widget-, remain excluded. Titles, categories, and keywords are sanitized and bounded. Faulty third-party widgets are skipped instead of breaking the entire registry request.
Capability: edit_posts.
Traits: read, non-destructive, idempotent. Optional: search, category, page, per_page (maximum 200). Output: widgets[], total, page, per_page, total_pages, elementor_version. Each widget reports its total number of writable controls as controls_count and whether its schema is capped by the 500-control limit as controls_truncated.
wp-agent/get-elementor-widget-schema
Purpose: Reads the writable value controls of a safe widget type directly from the active Elementor registry. Elementor 4 stores optimized style controls separately from ordinary controls. The read path merges both public registry areas instead of silently omitting colors and typography. Structural UI controls such as sections, tabs, headings, and buttons are not exposed as writable. Each control includes its name, type, label, tab, section, style, responsive and dynamic state, active devices, registered value type, a bounded JSON default, and at most 200 options. The output is limited to 500 controls. controls_count gives the number returned, controls_total the complete count, and controls_truncated indicates any truncation.
Capability: edit_posts.
Traits: read, non-destructive, idempotent. Required: widget_type. Unsafe and unknown widget types fail closed.
wp-agent/get-elementor-element
Purpose: Reads exactly one element by element_id from an existing Elementor document. The response includes its exact index path, the element in the closed {json,sha256,bytes} builder-document envelope, and the complete document's conflict hash. Lookup is bounded to 2,000 elements and 64 levels and rejects duplicate IDs.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id) and Elementor's own is_editable_by_current_user() check.
Traits: read, non-destructive, idempotent. Required: post_id, element_id. Output: post_id, element_id, path[], element, document_hash, elementor_version.
wp-agent/create-elementor-page
Purpose: Creates a new Elementor post through Document::save(). Every element must have a unique ID, an element or widget type registered in the active installation, JSON-compatible settings, and a child list. Raw HTML, shortcode, and unfiltered legacy widgets, as well as executable markup, remain blocked. The path is bounded to 2 MiB, 2,000 elements, and 64 levels. After saving, the Elementor-normalized structure, requested page settings, post status, and frontend output are checked again. A mismatch removes the new post.
Capability: edit_posts (coarse), the post type's concrete create_posts capability, and WordPress's required publish capability when publishing.
Traits: write, non-destructive, non-idempotent. Required: title, elements. Optional: post_type (default page), status (draft, pending, private, publish; default draft), settings.
wp-agent/update-elementor-document
Purpose: Replaces the complete Elementor structure and/or a subset of page settings through Document::save(). An explicitly empty settings object deletes stored page settings through Elementor's public settings API. expected_hash must match the last state read. An atomic short-lived lock serializes concurrent WPAgently writes. An Elementor-compatible WordPress revision is created and verified against the expected state before saving. Unknown, unsafe, or unregistered element and widget types, executable markup, duplicate IDs, oversized data, and excessive nesting are rejected before any write. The structure and requested settings are then read back, and frontend output is generated. Save, read-back, or render failures automatically restore structure and settings from the revision.
Capability: edit_posts (coarse) plus edit_post and Elementor's own editability check.
Traits: write, non-destructive, idempotent for the same conflict hash and input. Required: post_id, expected_hash, plus at least one of elements or settings. Output matches the read path and adds verified, frontend_verified, previous_hash, and the restorable revision_id.
wp-agent/update-elementor-element
Purpose: Changes or removes only registered value controls on one element without replacing sibling structure. style_patch adds a safe device-aware path for registered styles. Each style is keyed by its control name and Elementor's active desktop, tablet, or mobile device. null removes that device value. The path supports strictly validated colors, sliders, dimensions, numbers, selects, choices, and switchers with bounded CSS units and keywords. Media, URLs, free-form font values, shadow objects, and other CSS-adjacent raw structures remain closed. Responsive suffixes and required group activation values are derived only from Elementor's public control and breakpoint registries. expected_hash protects the complete document from stale writes. Before writing, the ability checks document permission, target ID, widget safety, the control registry, JSON values, markup, size, and structure. A short-lived lock serializes WPAgently writes. It then creates a revision, saves through Elementor's document API, performs an exact complete read-back check, verifies frontend rendering, and compiles the expected style values through Elementor's public post CSS class. Any mismatch triggers an automatic rollback. A semantic no-op creates no revision.
Capability: edit_posts (coarse) plus edit_post and Elementor's own editability check.
Traits: write, non-destructive, idempotent. Required are post_id, element_id, expected_hash, and at least one of settings_patch, remove_settings, or style_patch. settings_patch and style_patch each use the closed {json,sha256,bytes} builder-document envelope. CSS-adjacent controls must be changed or removed through style_patch. Output matches the Elementor write path plus element_id, path[], element, and changed.
wp-agent/create-elementor-element
Purpose: Creates a bounded Elementor subtree at a chosen position. Omit parent_id for the document root and omit index to append to the selected child list. The public element body accepts only elType, widgetType, settings, elements, and isInner. Caller-supplied IDs are discarded and securely regenerated throughout the subtree. Element and widget types and every supplied control must be registered and writable in the active Elementor installation. Widgets can act as parent nodes only when Elementor explicitly reports nesting support. Unsafe widgets, executable markup, unknown fields or controls, oversized data, and excessive nesting fail before any write.
Capability: edit_posts (coarse) plus edit_post and Elementor's own editability check.
Traits: write, non-destructive, non-idempotent. Required: post_id, expected_hash, element. Optional: parent_id, index. Output matches the Elementor write path and adds operation, changed, element_id, path[], and the freshly read element.
wp-agent/duplicate-elementor-element
Purpose: Duplicates an existing Elementor subtree and inserts the copy at the chosen position. Every structural ID in the copy is regenerated, while the source and its siblings remain unchanged. Provider-specific references inside settings are deliberately not guessed or rewritten. They remain exactly as stored in the source and are covered by the full read-back and frontend checks.
Capability: edit_posts (coarse) plus edit_post and Elementor's own editability check.
Traits: write, non-destructive, non-idempotent. Required: post_id, element_id, expected_hash. Optional: parent_id, index. Output additionally contains the new element_id, path[], source previous_path[], and duplicated element.
wp-agent/move-elementor-element
Purpose: Moves an existing subtree within the same document while preserving its IDs, settings, and children. Self and descendant targets fail as cycles, and widgets cannot accept children. index denotes the final position after removing the source. Omitting index appends the subtree.
Capability: edit_posts (coarse) plus edit_post and Elementor's own editability check.
Traits: write, non-destructive, idempotent. Required: post_id, element_id, expected_hash. Optional: parent_id, index. Output includes previous_path[], freshly read path[], element, and changed. An already reached target position creates no revision.
wp-agent/delete-elementor-element
Purpose: Removes a complete Elementor subtree only when confirm=true. The freshly read structure must no longer contain the target ID. The response includes the removed subtree for traceability. The verified pre-write revision is the recovery path.
Capability: edit_posts (coarse) plus edit_post and Elementor's own editability check.
Traits: write, destructive, non-idempotent. Required: post_id, element_id, expected_hash, confirm=true. Output includes previous_path[], deleted_element, revision_id, changed, and the verified new document state.
All four structural operations use the same conflict hash, atomic short-lived lock, revision verified against the initial state, Elementor public document API, exact full read-back, and frontend render check. Save, read-back, and render failures automatically restore the revision.
wp-agent/restore-elementor-revision
Purpose: Restores only Elementor structure and page settings from an Elementor revision belonging to the post. Before writing, the revision content is checked against the same size, structure, widget, and markup boundaries as a regular update. Empty revision settings fully remove newer page settings. The title, excerpt, status, and other WordPress post fields are deliberately not copied from the general revision. The current expected_hash protects intervening Elementor changes. An additional safety revision is created before restore. The target is read back and rendered through the frontend; failures automatically restore the safety revision.
Capability: edit_posts (coarse) plus edit_post and Elementor's own editability check.
Traits: write, destructive to the current Elementor structure, non-idempotent. Required: post_id, revision_id, expected_hash. Output additionally includes safety_revision_id.
wp-agent/get-beaver-document
Purpose: Reads an active Beaver Builder layout through its model API as a bounded flat node list. Output contains node type, module type, parent ID, position, writability, Beaver version, and a canonical SHA-256 conflict hash. Each node's settings are in the closed {json,sha256,bytes} builder-document envelope. Global, linked, unknown, and unsafe modules remain immutable, and oversized or unnormalizable public values are not exposed.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id). Traits: read, non-destructive, idempotent. Required: post_id.
wp-agent/list-beaver-modules
Purpose: Lists installed modules from the active Beaver Builder registry. Executable raw modules such as HTML, shortcodes, and embedded WordPress widgets are excluded. Search, group filtering, and pagination are bounded.
Capability: edit_posts. Traits: read, non-destructive, idempotent. Optional: search, group, page, per_page.
wp-agent/get-beaver-module-schema
Purpose: Reads the bounded writable fields of a safe module type from the active Beaver registry. Structural form fields, unknown field types, executable values, and oversized option lists remain excluded.
Capability: edit_posts. Traits: read, non-destructive, idempotent. Required: module_type.
wp-agent/create-beaver-page
Purpose: Creates a page through Beaver Builder's model API from bounded rows, columns, and safe modules. Layouts and modules must be registered in the active installation, and settings are validated against their provider schemas. After finalization, the page title, status, requested nodes, settings, parents, positions, safe provider-created default descendants, and frontend output are checked. A faulty or incomplete draft is removed completely.
Capability: edit_posts, the page type's concrete create_posts capability, and its publish capability when publishing. Traits: write, non-destructive, non-idempotent. Required: title, rows. Optional: status.
wp-agent/update-beaver-node
Purpose: Changes or removes only schema-validated settings on an existing local node. expected_hash protects the complete layout. Required: post_id, node_id, expected_hash, and settings_patch as the closed {json,sha256,bytes} builder-document envelope; optional: remove_settings.
Capability: edit_posts plus edit_post. Traits: write, non-destructive, idempotent.
wp-agent/create-beaver-module
Purpose: Inserts a registered safe module into an existing Beaver column. The position cannot exceed the end of the existing child list. Any default descendants created automatically by the module must also satisfy the safe write contract. Required: post_id, parent_id, module_type, expected_hash; optional: position, settings.
Capability: edit_posts plus edit_post. Traits: write, non-destructive, non-idempotent.
wp-agent/create-beaver-column-group
Purpose: Creates a native column group in a local row or exactly one nested column level inside a local column. The layout must be registered in Beaver Builder. Position is measured across every direct child of the parent and cannot exceed the end of that child list. Global or linked parents, a second nested level, and layouts exceeding the node boundary remain blocked. Required: post_id, parent_id, layout, expected_hash; optional: position.
Capability: edit_posts plus edit_post. Traits: write, non-destructive, non-idempotent.
wp-agent/duplicate-beaver-node
Purpose: Duplicates a local row, column, or safe module through the native model API. The complete subtree is checked before writing. Read-back requires the same structure and every explicitly stored setting. Provider default fields materialized by Beaver Builder during copying may additionally appear. Global, linked, unknown, or unsafe descendants reject the entire operation.
Capability: edit_posts plus edit_post. Traits: write, non-destructive, non-idempotent. Required: post_id, node_id, expected_hash.
wp-agent/move-beaver-node
Purpose: Moves only a local safe module into an existing Beaver column. Rows and columns are not reparented by the safe path. Required: post_id, node_id, parent_id, expected_hash; optional: position.
Capability: edit_posts plus edit_post. Traits: write, non-destructive, annotated as non-idempotent. An already reached target position creates no revision.
wp-agent/delete-beaver-node
Purpose: Deletes a local node and its descendants after confirm=true. The complete subtree must be free of global, linked, unknown, and unsafe modules.
Capability: edit_posts plus edit_post. Traits: write, destructive, non-idempotent. Required: post_id, node_id, expected_hash, confirm.
wp-agent/restore-beaver-revision
Purpose: Restores a Beaver revision belonging to the post after confirm=true. The revision content must also satisfy the current safety contract. A new recovery revision is created first.
Capability: edit_posts plus edit_post. Traits: write, destructive to the current layout, non-idempotent. Required: post_id, revision_id, expected_hash, confirm.
All seven write paths for existing Beaver layouts use the same complete conflict hash, atomic short-lived lock, revision verified against the initial state, semantically exact read-back, frontend render verification, and cache invalidation. Depending on the operation, verification covers complete node settings, parents and positions, equality of duplicated subtrees, every deleted descendant, or the exact revision hash. Positions outside the existing target node are rejected before writing. Provider, save, read-back, and render failures trigger a verified complete rollback. If even the rollback cannot be verified exactly, the recovery revision is retained and the operation reports an explicit rollback error.
wp-agent/list-spectra-blocks
Purpose: Reads the block library visible in Spectra's own administration UI from the native registry. Internal child blocks, extensions, deprecated blocks, and blocks with a missing plugin dependency remain excluded. Every item contains its slug, block name, title, description, categories, default state, and effective activation state. The hash covers the complete raw _uagb_blocks option, including unknown future keys.
Capability: manage_options. Traits: read, non-destructive, idempotent. Optional: search, status (all, enabled, disabled), page, per_page. Output: version, items[], pagination, and hash.
wp-agent/set-spectra-block-status
Purpose: Enables or disables exactly one visible Spectra block through UAGB_Admin_Helper::update_admin_settings_option(). Internal and unknown slugs are rejected. A short-lived lock and expected_hash prevent concurrent WPAgently writes and stale changes. The complete option value is read back. A mismatch restores only the target key so concurrently added unrelated keys remain intact.
Capability: manage_options. Traits: write, non-destructive, idempotent. Required: slug, enabled, expected_hash. Output: block, verified, previous_hash, hash.
wp-agent/list-spectra-popups
Purpose: Lists Spectra's spectra-popup post type with search, status, type, activation, and pagination filters. Output is limited to the ID, title, slug, status, type, activation, repetition, modified time, and state hash. Arbitrary unrelated post metadata remains hidden.
Capability: manage_options. Traits: read, non-destructive, idempotent. Optional: search, status, type, enabled, page, per_page, order, order_by.
wp-agent/get-spectra-popup
Purpose: Reads an existing Spectra popup including raw content and a recursive block report. The report exposes block count, freeform count, block types, and whether the required uagb/popup-builder wrapper exists. Content larger than 1 MiB is rejected. Unrelated metadata is not returned.
Capability: manage_options. Traits: read, non-destructive, idempotent. Required: id. Output: the popup summary plus content, block_count, freeform_count, block_types, has_popup_wrapper.
wp-agent/create-spectra-popup
Purpose: Creates a native Spectra popup or banner from 1-20 bounded Core components. Supported components are Markdown, separators, and spacers up to 400 pixels. The provider wrapper matches the actual serialization emitted by Spectra 2.20.1. New objects remain disabled regardless of WordPress status and must be enabled separately after review.
Capability: manage_options. Traits: write, non-destructive, idempotent. Required: title, type (popup or banner), components, idempotency_key. Optional: status (draft, pending, private, publish), repetition (1-100). Reusing the same key returns the same object only while the requested and stored state remain identical. A different request or later edit under that key is rejected as a conflict. A key-scoped short-lived lock prevents concurrent duplicate creation. Title, status, type, disabled state, repetition, exact content, native wrapper, and the bounded inner Core blocks are verified after storage. Each of the three internal idempotency values must exist exactly once and remain unchanged. An incomplete or ambiguous creation is removed completely. Output: popup, verified, created.
wp-agent/update-spectra-popup
Purpose: Changes only the title, WordPress status, popup type, activation state, and repetition of an existing Spectra object. Only published popup or banner objects containing a Popup Builder wrapper may be enabled. A type change updates the native block attribute, wrapper and container classes, and accessible close label together. Arbitrary popup content and unrelated metadata cannot be written. A hash and short-lived lock protect against conflicts. All target fields and the expected content are read back, and hook mutations trigger a complete semantic rollback.
Capability: manage_options. Traits: write, non-destructive, idempotent. Required: id, expected_hash, and at least one of title, status, type, enabled, repetition. Output: popup, verified, previous_hash.
wp-agent/delete-spectra-popup
Purpose: Moves an existing Spectra popup to the trash after confirm: true. force: true deletes it permanently. If WordPress trash is disabled, the reversible path refuses the operation instead of silently deleting permanently. expected_hash prevents deletion of an object that changed in the meantime.
Capability: manage_options. Traits: write, destructive, idempotent. Required: id, expected_hash, confirm. Optional: force. Output: id, trashed, deleted.
The Spectra specialization continues to separate the general Core-block pipeline from the provider-specific wrapper. Only create-spectra-popup may emit the practically verified uagb/popup-builder contract. Free-form Spectra markup, provider-specific inner blocks, arbitrary popup-content edits, and deep style or breakpoint settings remain blocked.
wp-agent/render-verify
Purpose: Renders a post server-side against the effective frontend output (apply_filters('the_content', ...), not the raw DB row, not via a self-directed HTTP request) and checks it against four proven "read-back lies" traps: (a) core/freeform (silent Classic Editor fallback), (b) builder render mismatch (a postmeta-JSON builder dataset is stored, but the associated plugin is not active, so the frontend renders only raw post_content), (c) Contact Form 7 trap (form configuration lives in postmeta _form; post_content is inert for this post type), and (d) SEO read-back. Rank Math and SEOPress are read through their provider-owned post meta, AIOSEO through its native SEO Ability, and Yoast through its effective Meta Surface, which accounts for the Indexable in production. Only the currently active supported SEO plugin is checked.
Capability: edit_posts (coarse) plus current_user_can('edit_post', $post_id) (via reuse of detect-builder).
Traits: read, non-destructive, idempotent.
| Parameter | Type | Required |
|---|---|---|
post_id | integer | yes |
| Output field | Type | Description |
|---|---|---|
post_id | integer | |
rendered.html_length, rendered.word_count, rendered.block_count, rendered.freeform_count | integer | |
rendered.has_freeform | boolean | |
rendered.block_types[] | string[] | |
checks[] | Objects with check, subject, agrees, severity (info|warn), note | Up to four checks (a through d), depending on which apply. |
verdict.renders_ok | boolean | false on freeform or an active builder mismatch. |
verdict.warnings | integer | |
notes[] | string[] |
Example: { "post_id": 42 }
14. Agent knowledge and design profile
These 17 abilities store explicit, bounded site context in fixed WordPress options or read redacted local system diagnostics. They do not record conversations automatically and cause no external data transfer. Read paths require edit_posts. Changes to site context, skills, the design profile, and design directions require manage_options. An Editor can deliberately save and delete memories.
| Ability | Input and limit | Output |
|---|---|---|
get-site-context | none | context with site name, audience, voice, goals, constraints, and notes |
update-site-context | the same six text fields, 200-5,000 characters per field | stored context, verified |
get-system-diagnostics | none | versions, environment, database driver, control checks, redacted connection diagnostics, and privacy flags without users, content, full URLs, plugin paths, or credentials |
list-skills | none, at most 100 stored skills | alphabetical items, total |
get-skill | safe id | one skill or 404 |
upsert-skill | id, title, description, instructions, up to 20,000 instruction characters | skill, verified |
delete-skill | id | deleted |
list-memory | optional search, tag, and limit up to 100, at most 250 stored memories | latest matches and total |
save-memory | optional id, otherwise UUID, title, content up to 10,000 characters, at most 20 tags | memory, verified |
delete-memory | id | deleted |
get-design-profile | none | colors, font families, base size, spacing, radii, and notes |
set-design-profile | at most 30 tokens per map, hex colors, bounded CSS lengths, and at most 10 font families | validated profile, verified |
list-design-directions | none, at most 20 stored design directions | compact list with version and active state |
get-design-direction | safe id | full direction with rules, design profile, and preview |
upsert-design-direction | id, title, and exactly one of profile or source; source accepts up to 30,000 characters as a JSON profile, safe CSS custom properties, or labelled lines with one literal heading and body font each; updates require expected_version | versioned direction, verified |
activate-design-direction | id, expected_version, optional approve_warnings | applies the profile after consistency review, verified |
delete-design-direction | id, expected_version; active direction is protected | id, deleted |
The six read collections Site Context, design profile, design directions, skills, memory, and system diagnostics are also exposed as authenticated MCP resources at wpagently://site/context, wpagently://site/design, wpagently://site/design-directions, wpagently://site/skills, wpagently://site/memory, and wpagently://site/diagnostics. Site skills with prompt exposure enabled additionally appear as native MCP prompts.
Font imports ignore CSS comments and values inside ordinary CSS strings, honor the last effective declaration when a custom property occurs more than once, and accept the final declaration in a block without a semicolon. Dynamic expressions such as var(), url(), calc(), or clamp() and dimensions supplied as fonts are rejected. The preview exposes separate heading and body fonts. When an administrator edits a direction, the backend preserves its stored profile unless a new import or the current global profile is selected explicitly.
15. Confirmed Live Editor
These five abilities connect the bound Editor user to a short-lived browser workspace opened by an administrator in the native Gutenberg or Elementor editor. They reuse the existing MCP connection. The agent receives neither the administrator cookie nor a second local server. Before every command, the server rechecks the session, user role, and permission to edit the open post. Every write is approved visibly and individually. Gutenberg changes remain in the browser until the separately approved save-post command. A complete SHA-256 state hash protects the block structure and post fields against concurrent changes. Autosaves remain locked for the duration of the session. New and changed Gutenberg blocks are limited to the core, kadence, generateblocks, and uagb namespaces. Their attributes are checked against the schema actually registered in the browser before mutation. Dynamic input and output use the Live Editor envelope described above. After approval, Elementor changes run through the verified server-side Elementor abilities with a separate document hash, revision, readback, and frontend verification.
wp-agent/get-live-editor-status
Purpose: Reads the active session, open post, readiness, dirty state, state hash, expiry, and pending-command count. Capability: a safe non-administrator with edit_posts, bound to this exact session. Traits: read, idempotent.
wp-agent/live-editor-read
Purpose: Enqueues a bounded read command. action accepts inspect-page, gutenberg-structure, list-block-types, get-block-schema, or get-block-attributes. Depending on the action, block_name, client_id, include_text, text_limit up to 10,000, or search up to 100 bytes is allowed. Page inspections, schema results, and attribute results share a result budget that accounts for WordPress's stronger JSON encoding of Unicode and slashes. Keys recognized as secrets and non-serializable provider values are redacted. Malformed unpaired UTF-16 surrogates are safely replaced. Runtime errors are limited to 8,000 bytes before completion. The response contains a command_id. Capability: the bound safe non-administrator with permission to edit the open post. Traits: read, not idempotent because it creates a short-lived queue entry.
wp-agent/live-editor-write
Purpose: Enqueues a visible action that requires individual approval. action accepts open-post, create-block, update-block, delete-block, move-block, replace-inner-blocks, undo, redo, or save-post. reason is always required. Except for open-post, the current 64-character expected_state_hash is required. Depending on the action, the input requires post_id, client_id, parent_client_id, block_name, index, bounded attributes, or at most 200 bounded blocks. Before mutation, agent changes are checked against the namespace allowlist, registered attributes, types, enum values, secret keys, and active content. The save gate checks the full structure again for size, depth, and active content. Safe existing blocks remain saveable when a provider ships schema-inconsistent defaults or when their plugin has been deactivated. Capability: the bound safe non-administrator with permission to edit the target post. Traits: write, marked destructive, not idempotent, always requires approval.
wp-agent/live-editor-elementor-write
Purpose: Enqueues one visible Elementor Free operation that requires individual approval. operation accepts open-document, update-document, update-element, create-element, duplicate-element, move-element, delete-element, or restore-revision. reason and post_id are always required. Every mutation requires the current 64-character expected_hash; depending on the operation, bounded elements, settings, style changes, identifiers, position, or a revision ID are also validated. After approval, only the server invokes the existing Elementor ability. It rechecks ownership, permissions, and session state after acquiring the lock, creates a revision, verifies readback and frontend state, and returns failures or recovery_required as terminal results. Capability: the bound safe non-administrator with permission to edit the target post plus individual administrator approval. Traits: write, marked destructive, not idempotent, always requires approval.
wp-agent/get-live-editor-result
Purpose: Reads the status, result, or redacted error for the caller's command using its 24-character command_id. Terminal results are retained within a fixed bound. Expired, foreign, and missing commands fail closed. Capability: the bound safe non-administrator. Traits: read, idempotent.
16. Quick reference: capability per ability
| Ability | Capability (coarse) | Traits |
|---|---|---|
create-post-from-markdown | edit_posts + post-type fine check | write, idempotent |
get-post | edit_posts + edit_post | read, idempotent |
list-posts | edit_posts + post-type fine check | read, idempotent |
update-post | edit_posts + edit_post | write, idempotent |
set-post-status | edit_posts + edit_post + status cap | manual-only, non-destructive, not idempotent |
trash-post | edit_posts + delete_post | manual-only, non-destructive, not idempotent |
restore-post | edit_posts + delete_post | manual-only, non-destructive, not idempotent |
delete-post | edit_posts + delete_post | write, destructive with force, idempotent |
search-replace-content | edit_posts + edit_post per match | write, not idempotent |
undo-content-replace | edit_posts + edit_post per match | write, idempotent |
create-term | edit_posts + manage_terms (taxonomy) | write, idempotent |
get-term | edit_posts + assign_terms (taxonomy) | read, idempotent |
list-terms | edit_posts + assign_terms (taxonomy) | read, idempotent |
update-term | edit_posts + edit_terms (taxonomy) | write, idempotent |
delete-term | edit_posts + delete_terms (taxonomy) | write, destructive, idempotent |
set-post-terms | edit_post + assign_terms (taxonomy) | write, idempotent |
upload-media | upload_files | write, not idempotent |
create-direct-media-upload | safe Editor + upload_files | write, not idempotent |
revoke-direct-media-upload | safe Editor + upload_files | write, idempotent |
set-alt-text | edit_posts + edit_post | write, idempotent |
set-featured-image | edit_posts + edit_post | write, idempotent |
delete-media | edit_posts + delete_post | write, destructive with force, idempotent |
list-media | upload_files | read, idempotent |
create-menu | edit_theme_options | write, idempotent |
add-menu-item | edit_theme_options | write, not idempotent |
list-menus | edit_theme_options | read, idempotent |
assign-menu-location | edit_theme_options | write, idempotent |
delete-menu | edit_theme_options | write, destructive, idempotent |
get-setting | manage_options | read, idempotent |
update-setting | manage_options | write, idempotent |
list-settings | manage_options | read, idempotent |
get-ase-free-generator-tag | manage_options (ASE Free 9.0.0 only) | read, idempotent |
update-ase-free-generator-tag | manage_options (ASE Free 9.0.0 only, with “Disable Smaller Components” enabled) | write, conflict-protected, idempotent |
list-comments | moderate_comments | read, idempotent |
moderate-comment | moderate_comments + edit_comment | write, idempotent |
reply-to-comment | moderate_comments + edit_comment/edit_post | write, not idempotent |
delete-comment | moderate_comments + edit_comment | write, destructive with force, idempotent |
list-users | list_users | read, idempotent |
get-user | edit_users | read, idempotent |
set-user-role | promote_users | write, idempotent |
create-user | create_users | write, not idempotent |
delete-user | delete_users | write, destructive, idempotent |
list-plugins | activate_plugins | read, idempotent |
activate-plugin | activate_plugins | write, idempotent |
deactivate-plugin | activate_plugins | write, idempotent |
list-themes | switch_themes | read, idempotent |
switch-theme | switch_themes | write, idempotent |
create-reusable-block | edit_posts + publish_posts | write, not idempotent |
update-reusable-block | edit_posts + edit_post | write, idempotent |
list-reusable-blocks | edit_posts | read, idempotent |
delete-reusable-block | edit_posts + delete_post | write, destructive with force, idempotent |
get-seo-meta | edit_posts + edit_post | read, idempotent |
set-seo-meta | edit_posts + edit_post | manual-only, non-destructive, not idempotent |
get-seo-settings | manage_options | read, conflict-protected, idempotent |
set-seo-settings | manage_options | manual-only, non-destructive, conflict-protected, not idempotent |
get-post-schema | edit_posts + edit_post + provider permission | read, conflict-protected, idempotent |
set-post-schema | edit_posts + edit_post + provider permission | write, conflict-protected, idempotent |
delete-post-schema | edit_posts + edit_post + Rank Math provider permission | write, destructive, conflict-protected, not idempotent |
get-term-seo-meta | edit_posts + taxonomy edit_terms | read, conflict-protected, idempotent |
set-term-seo-meta | edit_posts + taxonomy edit_terms | write, conflict-protected, idempotent |
list-seo-redirections / get-seo-redirection | rank_math_redirections | read, conflict-protected, idempotent |
create-seo-redirection | rank_math_redirections | write, marked destructive, conflict-protected, idempotent |
update-seo-redirection | rank_math_redirections | write, marked destructive, conflict-protected, idempotent |
delete-seo-redirection | rank_math_redirections | write, destructive, conflict-protected, not idempotent |
upsert-pattern | edit_pages | write, not idempotent |
get-global-styles | edit_theme_options | read, idempotent |
set-global-styles | edit_theme_options | write, conflict-protected, idempotent |
list-global-style-variations / get-global-style-variation | edit_theme_options | read, idempotent |
apply-global-style-variation | edit_theme_options | write, destructive, conflict-protected, idempotent |
write-theme-file | edit_themes | write, idempotent |
list-site-templates / get-site-template | edit_theme_options | read, idempotent |
create-site-template | edit_theme_options | write, non-idempotent |
update-site-template | edit_theme_options | write, conflict-protected, non-idempotent |
delete-site-template | edit_theme_options | write, destructive, conflict-protected |
list-template-parts / get-template-part | edit_theme_options | read, idempotent |
create-template-part | edit_theme_options | write, non-idempotent |
update-template-part | edit_theme_options | write, conflict-protected, non-idempotent |
delete-template-part | edit_theme_options | write, destructive, reference-protected |
list-block-navigations / get-block-navigation | edit_theme_options | read, idempotent |
create-block-navigation | edit_theme_options | write, non-idempotent |
update-block-navigation | edit_theme_options | write, conflict-protected, non-idempotent |
delete-block-navigation | edit_theme_options | write, destructive, reference-protected |
render-check | edit_posts + edit_post | read, idempotent |
refresh-hooks | edit_posts | write, idempotent |
disable-power | activate_plugins | write, idempotent |
create-browser-link | safe non-administrator with edit_posts | write, not idempotent |
revoke-browser-link | safe non-administrator with edit_posts | write, idempotent |
detect-builder | edit_posts + edit_post | read, idempotent |
get-builder-compatibility | edit_posts | read, idempotent |
list-block-types | edit_posts | read, idempotent |
get-block-type | edit_posts | read, idempotent |
get-native-block-document | edit_posts + edit_post | read, idempotent |
get-spectra-blocks-separator | edit_posts + edit_post (Spectra Blocks 1.0.4 only) | read, idempotent |
update-spectra-blocks-separator | edit_posts + edit_post (Spectra Blocks 1.0.4 only) | write, conflict-protected, non-idempotent |
update-spectra-block-attributes | edit_posts + edit_post (Spectra and a server-side dynamic schema required) | write, conflict-protected, non-idempotent |
update-spectra-static-heading-alignment | edit_posts + edit_post (only Spectra 2.20.1 and uagb/advanced-heading.headingAlign, uagb/advanced-heading.headingAlignTablet, and uagb/advanced-heading.headingAlignMobile) | write, conflict-protected, not idempotent |
update-spectra-static-heading-colors | edit_posts + edit_post (only Spectra 2.20.1, classic mode, and six-digit headingColor and subHeadingColor) | write, conflict-protected, not idempotent |
update-generateblocks-block-attributes | edit_posts + edit_post (GenerateBlocks and a live schema required) | write, conflict-protected, not idempotent |
update-kadence-block-attributes | edit_posts + edit_post (Kadence Blocks and a live schema required) | write, conflict-protected, not idempotent |
get-elementor-document | edit_posts + edit_post + Elementor check | read, idempotent |
get-elementor-design-system | manage_options + Elementor kit check | read, idempotent |
update-elementor-design-system | manage_options + Elementor kit check | write, idempotent |
get-elementor-global-classes | manage_options + Elementor Global Class check | read, idempotent |
create-elementor-global-class | manage_options + Elementor Global Class check | write, non-idempotent |
update-elementor-global-class | manage_options + Elementor Global Class check | write, idempotent |
delete-elementor-global-class | manage_options + Elementor Global Class check | write, destructive, non-idempotent |
set-elementor-element-global-classes | manage_options + Elementor Global Class check | write, idempotent |
list-elementor-widgets / get-elementor-widget-schema | edit_posts | read, idempotent |
get-elementor-element | edit_posts + edit_post + Elementor check | read, idempotent |
create-elementor-page | edit_posts + create_posts, optional publish capability | write, not idempotent |
update-elementor-document | edit_posts + edit_post + Elementor check | write, idempotent |
update-elementor-element | edit_posts + edit_post + Elementor check | write, idempotent |
create-elementor-element | edit_posts + edit_post + Elementor check | write, not idempotent |
duplicate-elementor-element | edit_posts + edit_post + Elementor check | write, not idempotent |
move-elementor-element | edit_posts + edit_post + Elementor check | write, idempotent |
delete-elementor-element | edit_posts + edit_post + Elementor check | write, destructive, not idempotent |
restore-elementor-revision | edit_posts + edit_post + Elementor check | write, destructive, not idempotent |
get-beaver-document | edit_posts + edit_post (Beaver required) | read, idempotent |
list-beaver-modules / get-beaver-module-schema | edit_posts (Beaver required) | read, idempotent |
create-beaver-page | edit_posts + concrete create_posts capability, optional publish capability | write, not idempotent |
update-beaver-node | edit_posts + edit_post (Beaver required) | write, idempotent |
create-beaver-module | edit_posts + edit_post (Beaver required) | write, not idempotent |
create-beaver-column-group | edit_posts + edit_post (Beaver required) | write, not idempotent |
duplicate-beaver-node | edit_posts + edit_post (Beaver required) | write, not idempotent |
move-beaver-node | edit_posts + edit_post (Beaver required) | write, not idempotent |
delete-beaver-node | edit_posts + edit_post (Beaver required) | write, destructive, not idempotent |
restore-beaver-revision | edit_posts + edit_post (Beaver required) | write, destructive, not idempotent |
list-spectra-blocks | manage_options (Spectra required) | read, idempotent |
set-spectra-block-status | manage_options (Spectra required) | write, conflict-protected, idempotent |
list-spectra-popups | manage_options (Spectra required) | read, idempotent |
get-spectra-popup | manage_options (Spectra required) | read, idempotent |
create-spectra-popup | manage_options (Spectra required) | write, idempotent, disabled by default |
update-spectra-popup | manage_options (Spectra required) | write, conflict-protected, idempotent |
delete-spectra-popup | manage_options (Spectra required) | write, destructive, conflict-protected |
get-acf-fields | object-specific: edit_post, edit_user, edit_term, edit_comment, or options capability (ACF required) | read, idempotent |
update-acf-field | object-specific as for get-acf-fields (ACF required) | write, not idempotent |
list-acf-field-groups | manage_options (ACF required) | read, idempotent |
get-acf-field-group | manage_options (ACF required) | read, idempotent |
create-acf-field-group | manage_options (ACF required) | write, not idempotent |
update-acf-field-group | manage_options (ACF required) | write, destructive, idempotent |
duplicate-acf-field-group | manage_options (ACF required) | write, not idempotent |
delete-acf-field-group | manage_options (ACF required) | write, destructive, not idempotent |
list-acf-post-types | manage_options (ACF 6.1+ required) | read, idempotent |
get-acf-post-type | manage_options (ACF 6.1+ required) | read, idempotent |
create-acf-post-type | manage_options (ACF 6.1+ required) | write, not idempotent |
update-acf-post-type | manage_options (ACF 6.1+ required) | write, destructive, idempotent |
delete-acf-post-type | manage_options (ACF 6.1+ required) | write, destructive, not idempotent |
list-acf-taxonomies | manage_options (ACF 6.1+ required) | read, idempotent |
get-acf-taxonomy | manage_options (ACF 6.1+ required) | read, idempotent |
create-acf-taxonomy | manage_options (ACF 6.1+ required) | write, not idempotent |
update-acf-taxonomy | manage_options (ACF 6.1+ required) | write, destructive, idempotent |
delete-acf-taxonomy | manage_options (ACF 6.1+ required) | write, destructive, not idempotent |
list-cptui-post-types / get-cptui-post-type | manage_options (CPT UI 1.19.3+ required) | read, idempotent |
create-cptui-post-type | manage_options (CPT UI 1.19.3+ required) | write, not idempotent |
update-cptui-post-type / delete-cptui-post-type | manage_options (CPT UI 1.19.3+ required) | write, destructive, idempotent |
list-cptui-taxonomies / get-cptui-taxonomy | manage_options (CPT UI 1.19.3+ required) | read, idempotent |
create-cptui-taxonomy | manage_options (CPT UI 1.19.3+ required) | write, not idempotent |
update-cptui-taxonomy / delete-cptui-taxonomy | manage_options (CPT UI 1.19.3+ required) | write, destructive, idempotent |
list-acpt-post-types / get-acpt-post-type | manage_options (ACPT Lite 2.0+ required) | read, idempotent |
create-acpt-post-type | manage_options (ACPT Lite 2.0+ required) | write, not idempotent |
update-acpt-post-type / delete-acpt-post-type | manage_options (ACPT Lite 2.0+ required) | write, destructive, idempotent |
list-acpt-taxonomies / get-acpt-taxonomy | manage_options (ACPT Lite 2.0+ required) | read, idempotent |
create-acpt-taxonomy | manage_options (ACPT Lite 2.0+ required) | write, not idempotent |
update-acpt-taxonomy / delete-acpt-taxonomy | manage_options (ACPT Lite 2.0+ required) | write, destructive, idempotent |
list-pods-models / get-pods-model | manage_options (Pods 3.0+ required) | read, idempotent |
create-pods-model | manage_options (Pods 3.0+ required) | write, not idempotent |
update-pods-model | manage_options (Pods 3.0+ required) | write, destructive, idempotent |
delete-pods-model | manage_options (Pods 3.0+ required) | write, destructive, not idempotent |
upsert-pods-field | manage_options (Pods 3.0+ required) | write, destructive, idempotent |
delete-pods-field | manage_options (Pods 3.0+ required) | write, destructive, not idempotent |
list-pods-act-records / get-pods-act-record | manage_options (Pods 3.3.9-3.x, table-storage ACT) | read, idempotent |
create-pods-act-record | manage_options (Pods 3.3.9-3.x, table-storage ACT) | write, not idempotent |
update-pods-act-record | manage_options (Pods 3.3.9-3.x, table-storage ACT) | write, not idempotent |
delete-pods-act-record | manage_options (Pods 3.3.9-3.x, table-storage ACT) | write, destructive, not idempotent |
get-product | edit_posts + edit_post (WooCommerce required) | read, idempotent |
update-product | edit_posts + edit_post (WooCommerce required) | write, idempotent |
list-products | edit_products (WooCommerce required) | read, idempotent |
preview-woocommerce-bulk-price-update | edit_products (WooCommerce required) | read, idempotent |
execute-woocommerce-bulk-price-update | edit_products + edit_post for every target | write, not idempotent, fail-closed with recovery_required |
create-product | create_products, optionally publish_products | write, not idempotent |
delete-product | edit_post + delete_post | write, destructive, not idempotent |
list-product-variations | edit_post on parent product | read, idempotent |
upsert-product-variation | edit_post on parent product | write, idempotent for updates |
delete-product-variation | parent edit_post + variation delete_post | write, destructive, not idempotent |
list-product-attributes | manage_product_terms (WooCommerce required) | read, idempotent |
get-product-attribute | manage_product_terms (WooCommerce required) | read, idempotent |
upsert-product-attribute | manage_product_terms (WooCommerce required) | write, destructive, not idempotent |
delete-product-attribute | manage_product_terms (WooCommerce required) | write, destructive, not idempotent |
list-orders | read_private_shop_orders | read, idempotent |
get-order | read_private_shop_orders | read, idempotent |
list-order-notes | read_private_shop_orders | read, idempotent |
set-order-status | edit_shop_orders | write, destructive, idempotent |
add-order-note | edit_shop_orders | write, destructive, idempotent |
list-contact-forms | wpcf7_read_contact_forms | read, idempotent |
get-contact-form | wpcf7_read_contact_forms + wpcf7_edit_contact_form | read, idempotent |
create-contact-form | wpcf7_edit_contact_forms | write, not idempotent |
update-contact-form | wpcf7_edit_contact_forms + wpcf7_edit_contact_form | write, idempotent |
duplicate-contact-form | wpcf7_edit_contact_forms + wpcf7_edit_contact_form | write, not idempotent |
delete-contact-form | wpcf7_edit_contact_forms + wpcf7_delete_contact_form | write, destructive, not idempotent |
list-fluent-forms | fluentform_dashboard_access | read, idempotent |
get-fluent-form | fluentform_forms_manager + form ACL | read, idempotent |
create-fluent-form | fluentform_forms_manager | write, not idempotent |
update-fluent-form | fluentform_forms_manager + form ACL | write, idempotent |
duplicate-fluent-form | fluentform_forms_manager + form ACL | write, not idempotent |
delete-fluent-form | fluentform_forms_manager + form ACL | write, destructive, not idempotent |
get-fluent-form-fields | fluentform_forms_manager + form ACL | read-only, idempotent |
upsert-fluent-form-field | fluentform_forms_manager + form ACL | write, idempotent |
delete-fluent-form-field | fluentform_forms_manager + form ACL | write, destructive, not idempotent |
get-fluent-form-delivery | fluentform_forms_manager + form ACL | read, idempotent |
update-fluent-form-confirmation | fluentform_forms_manager + form ACL | write, idempotent |
upsert-fluent-form-notification | fluentform_forms_manager + form ACL | write, not idempotent |
delete-fluent-form-notification | fluentform_forms_manager + form ACL | write, destructive, not idempotent |
list-fluent-entries | fluentform_entries_viewer + form ACL | read-only, idempotent |
get-fluent-entry | fluentform_entries_viewer + form ACL | read-only, idempotent |
set-fluent-entry-status | fluentform_manage_entries + form ACL | write, destructive, idempotent |
set-fluent-entry-favorite | fluentform_manage_entries + form ACL | write, idempotent |
delete-fluent-entry | fluentform_manage_entries + form ACL | write, destructive, not idempotent |
list-kadence-forms | edit_kadence_forms + edit_post per result | read-only, idempotent |
get-kadence-form-settings | edit_kadence_forms + edit_post | read-only, idempotent |
update-kadence-form-settings | edit_kadence_forms + edit_post | write, non-destructive, idempotent, fail-closed with recovery_required |
list-gravity-forms | gravityforms_edit_forms | read, idempotent |
get-gravity-form | gravityforms_edit_forms | read, idempotent |
create-gravity-form | gravityforms_create_form | write, not idempotent |
update-gravity-form | gravityforms_edit_forms | write, idempotent |
duplicate-gravity-form | gravityforms_create_form + gravityforms_edit_forms | write, not idempotent |
delete-gravity-form | gravityforms_delete_forms | write, destructive, not idempotent |
list-formidable-forms | frm_view_forms | read, idempotent |
get-formidable-form | frm_view_forms | read, idempotent |
create-formidable-form | frm_edit_forms | write, not idempotent |
update-formidable-form | frm_edit_forms | write, idempotent |
duplicate-formidable-form | frm_edit_forms | write, not idempotent |
delete-formidable-form | frm_delete_forms | write, destructive, not idempotent |
preview-form-migration | WPAgently source-provider read permission | read, idempotent |
migrate-form | source read permission + target read and write permission | write, non-destructive, not idempotent |
get-weglot-settings | manage_options | read, idempotent |
update-weglot-settings | manage_options | write, non-destructive, idempotent |
get-astra-design | manage_options | read, idempotent |
update-astra-design | manage_options | write, non-destructive, idempotent |
get-astra-post-design | edit_posts plus edit_post for the target post | read, idempotent |
update-astra-post-design | edit_posts plus edit_post for the target post | write, non-destructive, idempotent |
get-generatepress-design | manage_options | read, idempotent |
update-generatepress-design | manage_options | write, non-destructive, idempotent |
get-oceanwp-design | manage_options | read, idempotent |
update-oceanwp-design | manage_options | write, non-destructive, idempotent |
get-oceanwp-post-title | edit_posts + edit_post (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | read, idempotent |
update-oceanwp-post-title | edit_posts + edit_post (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | write, fail-closed with recovery_required |
get-oceanwp-post-layout-overrides | edit_posts + edit_post (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | read, idempotent |
update-oceanwp-post-layout-overrides | edit_posts + edit_post (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | write, fail-closed with recovery_required |
get-oceanwp-extra-modules | manage_options (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | read, idempotent |
update-oceanwp-extra-module | manage_options (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | write, fail-closed with recovery_required |
list-oceanwp-library-templates | edit_posts + read_post (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | read, idempotent |
get-oceanwp-post-library-templates | edit_posts + edit_post (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | read, idempotent |
update-oceanwp-post-library-templates | edit_posts + edit_post (only OceanWP 4.2.2 + Ocean Extra 2.5.8) | write, fail-closed with recovery_required |
get-kadence-design | manage_options | read, idempotent |
update-kadence-design | manage_options | write, non-destructive, idempotent |
refresh-builder-cache | edit_posts + edit_post | write, idempotent |
render-verify | edit_posts + edit_post | read, idempotent |
get-site-context | edit_posts | read, idempotent |
update-site-context | manage_options | write, idempotent |
get-system-diagnostics | edit_posts | read, idempotent, redacted, no automatic transmission |
list-skills | edit_posts | read, idempotent |
get-skill | edit_posts | read, idempotent |
upsert-skill | manage_options | write, idempotent |
delete-skill | manage_options | write, destructive, idempotent |
list-memory | edit_posts | read, idempotent |
save-memory | edit_posts | write, idempotent |
delete-memory | edit_posts | write, destructive, idempotent |
get-design-profile | edit_posts | read, idempotent |
set-design-profile | manage_options | write, idempotent |
list-design-directions | edit_posts | read, idempotent |
get-design-direction | edit_posts | read, idempotent |
upsert-design-direction | manage_options | write, not idempotent |
activate-design-direction | manage_options | write, idempotent |
delete-design-direction | manage_options | write, destructive, idempotent |
get-live-editor-status | bound non-administrator + edit_posts | read, idempotent |
live-editor-read | bound non-administrator + edit_post | read, not idempotent |
live-editor-write | bound non-administrator + edit_post + individual administrator approval | write, marked destructive, not idempotent |
live-editor-elementor-write | bound non-administrator + edit_post + individual administrator approval | write, marked destructive, not idempotent |
get-live-editor-result | bound non-administrator + edit_posts | read, idempotent |
Evidenced contracts in the current release set
The following contracts are paid-only. They belong to the Companion 0.4.117 and Power 0.6.35 release set, bundled with Skills 0.4.86, and document its capability boundaries.
| Ability | Purpose and hard boundary | Capability | Traits |
|---|---|---|---|
get-oceanwp-breadcrumbs-customizer | Reads the native, bounded breadcrumb visibility, source, and position settings from OceanWP 4.2.2. | manage_options | read, idempotent |
update-oceanwp-breadcrumbs-customizer | Updates those three settings with complete theme-mod CAS, locking, read-back, and path-specific recovery. | manage_options | write, non-destructive, idempotent |
get-oceanwp-post-format-overrides | Reads link or quote format overrides for one post with Ocean Extra 2.5.8. HTML and shortcodes remain excluded. | edit_posts + edit_post | read, idempotent |
update-oceanwp-post-format-overrides | Updates only safe URL, target, plain-text, and format overrides with a hash, lock, provider read-back, and fail-closed recovery. | edit_posts + edit_post | write, non-destructive, not idempotent |
update-kadence-single-button | Updates only text, URL, target, and four link flags on a unique direct kadence/singlebtn child of kadence/advancedbtn in Kadence Blocks 3.7.8. Style, icons, CSS, and other attributes remain unchanged. | edit_posts + edit_post | write, non-destructive, not idempotent |
create-acpt-woocommerce-product-data | Creates only a new group with Text, Number, and Select fields using ACPT Lite 2.0.11 and WooCommerce 10.9.4. MySQL/MariaDB with InnoDB and a native SERIALIZABLE transaction are required; SQLite closes without mutation. | ACPT Lite product-data management permission | write, non-destructive, not idempotent |
delete-acpt-woocommerce-product-data | Deletes a safe product-data group and its field and option definitions only after a fresh hash and explicit confirmation. The transaction and InnoDB boundary remains in force. | ACPT Lite product-data management permission | write, destructive, not idempotent |
The Operation Ledger is an administrative HMAC-chained history without an ability or MCP tool. The installed MCP adapter does not provide a secure pre-execution hook for an additional WPAgently approval. The existing individual approval and each provider contract therefore remain authoritative.
Additional current release contracts
The following nine Companion abilities also belong to the current release set. Their provider contracts and remaining limits are documented in the compatibility matrix and the roadmap. The activity log and connection setup card are administrative and onboarding features without an ability registration.
| Ability | Purpose and hard boundary | Capability | Traits |
|---|---|---|---|
update-spectra-editor-settings | Changes only confirmed Spectra/UAGB Free 2.20.1 editor toggles and the bounded Google Font configuration. Unknown or secret provider data is retained, or the operation closes. | manage_options | write, conflict-protected, with read-back and its own recovery |
update-oceanwp-footer-customizer | Changes only modelled OceanWP 4.2.2 footer Customizer values. | manage_options | write, complete theme-mod conflict state, read-back, and selective recovery |
update-oceanwp-blog-customizer | Changes only modelled OceanWP 4.2.2 blog Customizer values. | manage_options | write, complete theme-mod conflict state, read-back, and selective recovery |
update-oceanwp-woocommerce-customizer | Changes only modelled OceanWP 4.2.2 WooCommerce Customizer values when WooCommerce is active. | manage_options | write, complete theme-mod conflict state, read-back, and selective recovery |
update-spectra-blocks-button-text | Changes only plain text of at most 200 characters in a directly contained spectra/button of a spectra/buttons block in Spectra Blocks 1.0.4. | edit_posts plus edit_post | write, document hash, revision, lock, cache, and render check |
configure-spectra-one-transfer-secret | Stores a separate transfer secret for portable Spectra One transfers. | manage_options | write; never returns the secret |
export-spectra-one-portable-snapshot | Exports an HMAC-bound, bounded snapshot of Spectra One 1.2.3. | edit_theme_options | read, time-limited, without raw markup or theme files |
preflight-spectra-one-portable-snapshot | Checks a transferred snapshot on the separate target site before every mutation. | edit_theme_options | read, HMAC, version, source, and collision checks |
import-spectra-one-portable-snapshot | Imports only new allowed Spectra One 1.2.3 resources. Overwriting, deletion, and cross-theme transfer remain excluded. | edit_theme_options | write, create-only, not idempotent |
The Operation Ledger records at most 100 write operations with succeeded, failed, rejected, or recovery_required status in a bounded HMAC chain and can be reset only by administrators. It is not an authorization, verification, or approval mechanism. The connection setup card guides through the required local prerequisites and client configuration without exposing credentials.
Further tightly bounded provider paths
The following 25 abilities extend the previously documented 373-item catalog. They do not create a general provider write permission. Every surface is limited to its named provider contract.
| Ability | Purpose and hard boundary | Capability | Traits |
|---|---|---|---|
get-oceanwp-footer-customizer | Reads modelled free footer-widget and copyright values from OceanWP 4.2.2. | manage_options | read, idempotent |
get-oceanwp-blog-customizer | Reads modelled archive and single-post values from OceanWP 4.2.2. | manage_options | read, idempotent |
get-oceanwp-woocommerce-customizer | Reads modelled shop and product-view values from OceanWP 4.2.2. | manage_options | read, idempotent |
list-oceanwp-free-hooks | Lists ten verified Ocean Extra shortcode positions. It neither executes shortcodes nor returns their content. | edit_posts | read, idempotent |
get-oceanwp-post-free-overrides | Reads bounded layout, visibility, and hook assignments for one post. | edit_posts + edit_post | read, idempotent |
export-spectra-one-design-snapshot | Exports only typed global-style tokens, owned Site Editor resources, and block navigations from Spectra One 1.2.3. Raw markup and theme files are excluded. | edit_theme_options | read, idempotent |
import-spectra-one-design-snapshot | Imports selected snapshot components only as new native resources. It checks blog, theme, hash, lock, and permission state. It is not a portable two-site transfer. | edit_theme_options | write, non-destructive, not idempotent |
get-spectra-blocks-provider | Confirms the exactly bound Spectra Blocks installation, absence of Pro, and available read surfaces. | manage_options | read, idempotent |
list-spectra-blocks-catalog | Lists live-registered Spectra Blocks with provider-resolved enabled state. | manage_options | read, idempotent |
get-spectra-blocks-settings | Reads only selected non-secret Spectra Blocks toggles. Credentials and CAPTCHA data are excluded. | manage_options | read, idempotent |
get-spectra-blocks-global-styles | Reads bounded metadata and safe color tokens. Raw CSS, declaration values, and unknown entries are excluded. | manage_options | read, idempotent |
get-spectra-blocks-popup | Reads one popup only after CPT, metadata, wrapper, size, and block-tree checks. | manage_options + read_post | read, idempotent |
get-spectra-editor-settings | Reads selected non-secret Spectra editor toggles and bounded Google Font configuration for Spectra 2.20.1. The separate candidate writer is documented above. | manage_options | read, idempotent |
preview-elementor-v3-v4-migration | Analyses an Elementor document read-only for the checked Elementor 4.2.1 target contract. It never writes, imports templates, or simulates Pro features. | edit_posts + edit_post | read, idempotent |
snapshot-content-model | Reads a bounded ACF, Pods, ACPT Lite, or Meta Box model as a strict, site- and provider-bound snapshot with a closed schema and snapshot hash. | manage_options | read, idempotent |
compare-content-model-snapshots | Compares two integrity-checked snapshots and reports additions, removals, compatible changes, and losses. Each entry's before and after values are closed, integrity-bound {json,sha256,bytes} envelopes. An oversized or invalid value fails the whole response closed rather than being truncated. It writes nothing. | manage_options | read, idempotent |
migrate-content-model | Migrates only the verified lossless definition intersection from a persistent ACF field group to a new ACPT Lite meta group. Field values and existing targets are excluded. | manage_options | write, non-destructive, idempotent |
list-pods-settings | Lists native Pods settings definitions without option values. | manage_options | read, idempotent |
get-pods-settings | Reads one native Pods settings definition with a bounded field list, but no saved settings or option values. | manage_options | read, idempotent |
list-pods-field-groups | Lists native Pods field groups and bounded definitions. Field values, relationships, and media data are excluded. | manage_options | read, idempotent |
get-pods-field-group | Reads one native Pods field group with bounded field definitions and a conflict hash. Field values are excluded. | manage_options | read, idempotent |
list-pods-object-extensions | Lists definition data for native Pods extensions of WordPress objects, not object or field values. | manage_options | read, idempotent |
get-pods-object-extension | Reads one native Pods object extension. Field values and unsupported relationship and media values are excluded. | manage_options | read, idempotent |
list-acpt-woocommerce-product-data | Lists existing safe ACPT Lite 2.0.11 product-data groups with Text, Number, and Select fields. Unsafe groups are skipped. | ACPT Lite product-data management permission | read, idempotent |
update-acpt-woocommerce-product-data | Changes only defaults, descriptions, required state, and UI visibility on an existing safe ACPT Lite 2.0.11 group. Content, groups, options, and field structure remain unchanged. | ACPT Lite product-data management permission | write, conflict-protected, idempotent |
The roadmap records the documented Companion 0.4.117 and Power 0.6.35 release set, bundled with Skills 0.4.86, alongside later gaps. Code Snippets single use and any Pods or provider lifecycle beyond the documented ACPT Product Data fields remain explicitly outside the current contract: roadmap.
Further tightly bounded design paths
The four Companion abilities added after the previous source state remain deliberately narrow:
- Admin and Site Enhancements Free 9.0.0 adds
get-ase-free-generator-tagandupdate-ase-free-generator-tag. They read or change only the documented switch that removes the WordPress generator meta tag. The parent ASE group must be enabled manually. The change uses blog binding, atomic comparison, a renewable lock, and complete provider read-back. - Spectra Blocks 1.0.4 adds
get-spectra-blocks-separatorandupdate-spectra-blocks-separator. They read or change only the style, alignment, width, height, and color of an exactly shaped, server-registeredspectra/separator. The write path uses a document hash, revision, byte-exact CAS, render and provider read-back, and the existing recovery path.
Further tightly bounded builder and model paths
The 16 Companion abilities added after the previous catalog remain deliberately narrow:
- Beaver Builder adds the seven abilities
list-beaver-user-templates,get-beaver-user-template,save-beaver-user-template,save-beaver-node-template,delete-beaver-user-template,get-beaver-global-settings, andsave-beaver-global-settings. Beaver Lite does not expose the native user-template registration. Those five template paths therefore fail closed as unavailable there; they never simulate or persist substitute templates. The primitive global-settings map remains a separate real provider path. - Pods adds
get-pods-field-valuesandupdate-pods-field-valuesfor existing, supported fields. Unmodelled field shapes, table configurations, and unsafe provider state stay closed. - ACPT adds
list-acpt-meta-groups,get-acpt-meta-group,create-acpt-meta-group,update-acpt-meta-group,delete-acpt-meta-group,get-acpt-field-values, andupdate-acpt-field-values. They use the native provider path and accept only the modelled persistent meta group or supported field values.
The GenerateBlocks write path remains limited to its allowlisted structural Query and pagination attributes. It writes neither rich text nor arbitrary plain text. The commercial Meta Box Settings Pages runtime for values remains externally uncertified until a legally licensed practical fixture exists. Further licensed or proprietary provider surfaces remain outside this contract.