one-line, honest description of its reach. * * Each line states what the ability touches and, where it matters, what it leaves alone. * Keys match aafm_get_abilities_registry() one-to-one; the render layer falls back to the * registry description if a key is ever missing. * * Outbound-request exemption: the only ability-facing outbound HTTP call * is the SSRF-hardened aafm/upload-media-from-url fetch. One admin-only exception sits * outside the ability surface entirely: aafm_ajax_test_connection() (connection.php) * self-calls the MCP endpoint to confirm it answers, gated behind manage_options plus a * nonce and never reachable by an MCP agent. Its target, aafm_endpoint_url(), resolves * through WordPress core's own rest_url(), which any active plugin can filter to a * different host - trusting that destination means trusting whatever rest_url filter the * site already runs, the same already-privileged trust any other installed plugin * requires, not attacker-controlled input. Carved out by name in * SecurityRegressionTest::test_source_tree_has_no_dangerous_primitives(). * * @return array */ function aafm_ability_disclosures(): array { return array( // Reads. 'aafm/get-posts' => __( 'Lists posts by type, status, or search. Returns the title, status, excerpt, link, dates, and author id by default; the full body only when the agent passes include_content, and never private fields.', 'agent-abilities-for-mcp' ), 'aafm/get-post' => __( 'Reads one post by id: title, status, excerpt, link, dates, author id, and the full body (rendered by default, raw on request). A password-protected post never exposes its body.', 'agent-abilities-for-mcp' ), 'aafm/get-pages' => __( 'Lists pages by status or search, with the same fields as posts.', 'agent-abilities-for-mcp' ), 'aafm/get-page' => __( 'Reads one page by id, with the same fields as a post, including the full body.', 'agent-abilities-for-mcp' ), 'aafm/get-post-meta' => __( 'Reads one allowlisted scalar meta value from a post the agent can already edit. Protected and underscore keys are off limits.', 'agent-abilities-for-mcp' ), 'aafm/get-all-post-meta' => __( 'Reads every allowlisted scalar meta value from a post the agent can already edit, as a key/value map. Protected, underscore, and non-scalar values are left out.', 'agent-abilities-for-mcp' ), 'aafm/get-comments' => __( 'Lists approved comments on a post. Author email and IP are never returned.', 'agent-abilities-for-mcp' ), 'aafm/get-pending-comments' => __( 'Lists the comment moderation queue. Requires the moderate_comments capability.', 'agent-abilities-for-mcp' ), 'aafm/get-comment' => __( 'Reads one comment by id: author name, content, status, and date. Author email and IP are never returned.', 'agent-abilities-for-mcp' ), 'aafm/get-media' => __( 'Lists media library items: URL, alt text, mime type, and dimensions.', 'agent-abilities-for-mcp' ), 'aafm/get-media-item' => __( 'Reads one media item by id: caption, description, date, byte size, parent post, and every image size URL. Never the server file path.', 'agent-abilities-for-mcp' ), 'aafm/count-media' => __( 'Counts media library items, total and by mime type. An optional mime filter narrows the breakdown.', 'agent-abilities-for-mcp' ), 'aafm/count-posts' => __( 'Counts posts of an allowlisted type, total and by status (publish, draft, pending, and so on). No post content is returned. Agents that cannot edit the type see zero for non-public statuses instead of the real counts.', 'agent-abilities-for-mcp' ), 'aafm/get-users' => __( 'Lists users with their id, display name, email, roles, and post count. Gated by the list-users capability. Never login or password.', 'agent-abilities-for-mcp' ), 'aafm/get-user' => __( 'Reads one user by id: display name, email, roles, post count, registration date, and bio. Gated by the list-users capability. Never login or password.', 'agent-abilities-for-mcp' ), 'aafm/get-user-meta' => __( 'Reads one allowlisted user meta value from a user the agent can edit. Session tokens, passwords, capabilities, and 2FA keys are never readable.', 'agent-abilities-for-mcp' ), 'aafm/get-terms' => __( 'Lists terms and their post counts in a public taxonomy.', 'agent-abilities-for-mcp' ), 'aafm/get-term' => __( 'Reads a single term (name, slug, description, post count) from a public taxonomy.', 'agent-abilities-for-mcp' ), 'aafm/get-term-meta' => __( 'Reads one allowlisted scalar meta value from a term. Protected and underscore keys are off limits, and nothing is exposed unless an allowlist is configured.', 'agent-abilities-for-mcp' ), 'aafm/get-taxonomies' => __( 'Lists the public taxonomies registered on the site.', 'agent-abilities-for-mcp' ), 'aafm/get-post-types' => __( 'Lists the public post types registered on the site.', 'agent-abilities-for-mcp' ), 'aafm/get-site-info' => __( 'Reads the site name, tagline, URL, and language.', 'agent-abilities-for-mcp' ), 'aafm/list-playbooks' => __( 'Reads the titles and descriptions of your Active playbooks.', 'agent-abilities-for-mcp' ), 'aafm/get-playbook' => __( 'Reads the steps of one Active playbook.', 'agent-abilities-for-mcp' ), 'aafm/get-site-settings' => __( 'Reads a small allowlist of site settings (name, tagline, timezone, date and time formats, posts per page). Requires the manage-options capability. Never the site URL or admin email.', 'agent-abilities-for-mcp' ), 'aafm/list-revisions' => __( "Lists a post's revisions by id, author, and date. No body content.", 'agent-abilities-for-mcp' ), 'aafm/get-revision' => __( "Reads one revision's id, author, date, and body content (rendered by default, raw on request), plus an optional diff against the current post. Gated by edit access to the parent post.", 'agent-abilities-for-mcp' ), 'aafm/search-content' => __( 'Searches the content types you have exposed in a single query, returning the same curated fields as the list reads: metadata by default, the full body only when the agent passes include_content.', 'agent-abilities-for-mcp' ), 'aafm/list-plugins' => __( 'Lists installed plugins with their name, version, and active state. Read-only - it can never activate, deactivate, or change a plugin. Requires the activate-plugins capability.', 'agent-abilities-for-mcp' ), 'aafm/get-activity-log' => __( "Reads this plugin's own audit log (ability, status, acting user, argument keys, timestamp, and a short identifier-only detail such as an object id, a WP_Error code, or a crashed call's exception class and throw site; a code returned by another plugin's bridged ability is prefixed with foreign:), most recent first. Never free-text argument content or network addresses. Requires the manage-options capability.", 'agent-abilities-for-mcp' ), 'aafm/list-blocks' => __( 'Lists saved reusable blocks (synced patterns), not block types, by id, title, slug, status, and last-modified time. No block markup in the list. Requires the edit-posts capability.', 'agent-abilities-for-mcp' ), 'aafm/list-block-types' => __( 'Lists the block types registered on this site (core, theme and plugin blocks, including ACF blocks) by name, title, category and description. Requires the edit-posts capability.', 'agent-abilities-for-mcp' ), 'aafm/get-block-type' => __( 'Reads one registered block type: its attributes, supports and style variations, and for an ACF block its field names, types and choices. Shows editor configuration only, never stored values or file paths. Requires the edit-posts capability.', 'agent-abilities-for-mcp' ), 'aafm/get-block' => __( 'Reads one reusable block by id, including its raw block markup. Requires edit access to that block.', 'agent-abilities-for-mcp' ), 'aafm/list-menus' => __( 'Lists navigation menus by id, name, slug, and item count. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/get-menu' => __( 'Reads one navigation menu by id: name, slug, and item count. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/list-menu-items' => __( "Lists a navigation menu's items: title, URL, type, linked object, parent, and order. Requires the edit-theme-options capability.", 'agent-abilities-for-mcp' ), 'aafm/get-active-theme' => __( 'Reads the active theme: name, version, stylesheet, parent, and whether it is a block theme. Never a filesystem path. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/list-themes' => __( 'Lists installed themes by name, version, stylesheet, and active state. Never a filesystem path. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/list-templates' => __( 'Lists block templates (or template parts) by id, slug, title, type, and source. A classic theme without block-template support usually has none, so the list can be empty there. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/get-template' => __( 'Reads one block template by id, including its markup. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/get-global-styles' => __( "Reads the site's resolved theme.json settings and styles, on block and classic themes alike: colour palette, font sizes, spacing, layout widths and fluid typography. Requires the edit-theme-options capability.", 'agent-abilities-for-mcp' ), 'aafm/yoast-get-post' => __( "Reads a post's Yoast SEO fields from its post meta: title, description, focus keyword, canonical URL, the social tags, and the three robots directives (noindex, nofollow, and the advanced list). Requires edit access to that post.", 'agent-abilities-for-mcp' ), 'aafm/yoast-get-head' => __( 'Reads the rendered Yoast SEO head markup for a post when it is available, and an empty string when it is not. Requires the edit-posts capability and edit access to that post.', 'agent-abilities-for-mcp' ), 'aafm/rankmath-get-post' => __( "Reads a post's Rank Math SEO fields from its post meta: title, description, focus keyword, canonical URL, the social tags, and the robots directives. Requires edit access to that post.", 'agent-abilities-for-mcp' ), 'aafm/rankmath-get-schema' => __( "Reads a post's structured-data schema of a given type (for example Article or FAQPage) from Rank Math. Requires edit access to that post.", 'agent-abilities-for-mcp' ), 'aafm/rankmath-get-head' => __( 'Reads the rendered Rank Math SEO head markup for a post when it is available. When Rank Math cannot render one, the call is refused with an error naming the likely cause. Requires the edit-posts capability and edit access to that post.', 'agent-abilities-for-mcp' ), 'aafm/aioseo-get-post' => __( "Reads a post's SEO fields from All in One SEO's own data store, not post meta: title, description, canonical URL, the social tags, and the noindex and nofollow flags. Requires edit access to that post.", 'agent-abilities-for-mcp' ), 'aafm/aioseo-get-head' => __( 'Reads the rendered All in One SEO head markup for a post when it is available, and an empty string when it is not. Requires the edit-posts capability and edit access to that post.', 'agent-abilities-for-mcp' ), 'aafm/acf-list-field-groups' => __( 'Lists your ACF field groups and the fields inside each one (key, label, and type) so an agent can discover what fields exist. It returns structure only, never stored values. Requires the edit-posts capability.', 'agent-abilities-for-mcp' ), 'aafm/acf-get-post-fields' => __( "Reads all of a post's ACF field values as a hydrated map keyed by field name. Requires edit access to that post.", 'agent-abilities-for-mcp' ), 'aafm/acf-get-term-fields' => __( "Reads all of a term's ACF field values as a hydrated map keyed by field name. Requires edit access to that term.", 'agent-abilities-for-mcp' ), 'aafm/acf-get-user-fields' => __( "Reads all of a user's ACF field values as a hydrated map keyed by field name. If a field stores an email address (a user_email-type field), the real address is returned under the integration disclaimer. Requires edit access to that user.", 'agent-abilities-for-mcp' ), 'aafm/wc-list-products' => __( 'Lists your WooCommerce products with their id, name, SKU, price, stock status, status, categories, and featured flag, and the total count. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-product' => __( 'Reads one WooCommerce product by id: description, prices, stock, images, attributes, variation ids, and categories. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-product-variations' => __( "Lists a variable product's variations by parent product id: each variation's id, parent id, SKU, price, stock status, and status, plus a total. Requires the manage-WooCommerce capability.", 'agent-abilities-for-mcp' ), 'aafm/wc-get-product-variation' => __( 'Reads one product variation by id: parent id, prices, stock, description, image, and its chosen attribute values. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-product-attributes' => __( 'Lists all global WooCommerce product attribute taxonomies: id, name, slug, type, sort order, and whether it has public archives. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-orders' => __( 'Lists WooCommerce orders with their id, number, status, total, currency, date, and customer id, plus a total count. List rows carry no billing or shipping details. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-order' => __( 'Reads one WooCommerce order by id: line items, totals, status, dates, customer note, and the full customer billing address - including email and phone - and the shipping address. Customer PII (email, phone, full address) is returned under the Integrations security disclaimer and is always gated by the manage-WooCommerce capability. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-order-notes' => __( 'Lists all notes on a WooCommerce order by order id. Returns each note\'s id, text, date, and whether it is customer-facing. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-order-refunds' => __( 'Lists all refunds on a WooCommerce order by order id. Returns each refund\'s id, amount, reason, and date. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-order-refund' => __( 'Reads a single WooCommerce order refund by refund id. Returns the refund amount, reason, and date. Reason text is returned verbatim under the Integrations security disclaimer. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-customers' => __( 'Lists WooCommerce customers with their id, email, name, username, order count, and total spent, plus a total count. Defaults to the customer role; pass role to target another role, or "all" for every role. The email is a customer\'s personal data and is returned under the Integrations security disclaimer. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-customer' => __( 'Reads one WooCommerce customer by id: email, the billing address (including phone), the shipping address, order count, total spent, and the registration date. The email, phone, and addresses are personal data, returned under the Integrations security disclaimer and gated by the manage-WooCommerce capability. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-order' => __( 'Creates a new WooCommerce order from optional status, customer id, customer note, billing address, shipping address, and line items. Returns the full order shape including billing and shipping PII under the Integrations security disclaimer. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-order' => __( 'Updates a WooCommerce order by id, changing only the fields you send. An empty request is a no-op success. Returns the full order shape including PII under the Integrations security disclaimer. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-order-status' => __( 'Sets the status of a WooCommerce order by id. Returns the full order shape, including the customer billing and shipping PII, under the Integrations security disclaimer. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-customer' => __( 'Creates a WooCommerce customer from an email, name, username, and optional billing and shipping addresses. Returns the full customer record, including the email and addresses, under the Integrations security disclaimer. Creates a real WordPress user account, so it requires the create-users capability as well as the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-customer' => __( 'Updates a WooCommerce customer by id, changing only the fields you send. An empty request is a no-op success. Returns the full customer record, including PII, under the Integrations security disclaimer. Requires the manage-WooCommerce capability, the edit-users capability, and permission to edit that user. It stays locked until High-risk abilities is turned on under Settings.', 'agent-abilities-for-mcp' ), // Writes. 'aafm/create-draft' => __( 'Creates a new draft post. The agent drafts, a human publishes. It never goes live on its own.', 'agent-abilities-for-mcp' ), 'aafm/create-post' => __( 'Creates and publishes a post. Requires the publish capability, and respects force-draft if you turned it on.', 'agent-abilities-for-mcp' ), 'aafm/update-post' => __( "Updates an existing post's fields by id. Publishing is gated separately.", 'agent-abilities-for-mcp' ), 'aafm/replace-in-post' => __( 'Finds and replaces literal text in a post\'s body, sanitizing the inserted text. It edits only the replaced spans, leaves the rest of the content untouched, never changes the status, and the change can be restored from revision history when WordPress revisions are enabled.', 'agent-abilities-for-mcp' ), 'aafm/replace-block' => __( 'Replaces one whole block in a post or page, picked by its position, with new block markup. The plugin leaves other blocks\' parsed attributes and HTML unchanged; WordPress may sanitize the whole page on save for users who cannot post unfiltered HTML. The replacement is sanitized like any content write, and the change can be restored from revision history when WordPress revisions are enabled. Requires edit access to that post.', 'agent-abilities-for-mcp' ), 'aafm/replace-sitewide' => __( 'Finds and replaces literal text across multiple posts of one type and status, bounded to 50 posts per call. Previews the match by default; you pass dry_run:false to apply it. Every candidate post goes through the same structure-preserving guard as replace-in-post, so a match inside markup is skipped and reported, never applied.', 'agent-abilities-for-mcp' ), 'aafm/create-page' => __( 'Creates and publishes a page. Requires the publish_pages capability.', 'agent-abilities-for-mcp' ), 'aafm/update-page' => __( 'Updates an existing page by id. Publishing is gated separately.', 'agent-abilities-for-mcp' ), 'aafm/create-cpt-item' => __( 'Creates an item of a custom content type you have allowlisted. It stays a draft unless the agent holds that type\'s publish capability, and force-draft still applies.', 'agent-abilities-for-mcp' ), 'aafm/update-cpt-item' => __( 'Updates an item of an allowlisted custom content type by id. Publishing needs that type\'s own publish capability.', 'agent-abilities-for-mcp' ), 'aafm/update-post-meta' => __( 'Writes one allowlisted scalar meta value to a post the agent can edit. Only allowlisted keys. The response returns the old value when it is plain text or a number.', 'agent-abilities-for-mcp' ), 'aafm/update-user-meta' => __( 'Writes one allowlisted scalar user meta value to a user the agent can edit. Auth, capability, and 2FA keys are blocked outright. The response returns the old value when it is plain text or a number.', 'agent-abilities-for-mcp' ), 'aafm/set-featured-image' => __( "Sets a post's featured image to an existing attachment id. It does not upload anything.", 'agent-abilities-for-mcp' ), 'aafm/upload-media' => __( 'Uploads an image from base64 data (jpg, png, gif, webp; SVG is rejected) and adds it to the media library. For anything larger than a small icon, upload from a URL instead. Requires the upload-files capability.', 'agent-abilities-for-mcp' ), 'aafm/upload-media-from-url' => __( 'Fetches an image from an HTTPS URL and adds it to the media library. The URL is resolved and validated before any bytes are fetched, private/loopback/link-local targets are refused, and redirects are not followed into them either. Requires the upload-files capability.', 'agent-abilities-for-mcp' ), 'aafm/update-media' => __( "Updates an attachment's title, alt text, caption, or description. Requires edit access to that attachment.", 'agent-abilities-for-mcp' ), 'aafm/moderate-comment' => __( 'Approves, unapproves, spams, or trashes a comment. Requires the moderate_comments capability.', 'agent-abilities-for-mcp' ), 'aafm/create-comment' => __( 'Adds a comment to a post as the agent user. It is held for moderation, never auto-published, and the author is always the agent, not free-form input. Requires the moderate_comments capability.', 'agent-abilities-for-mcp' ), 'aafm/update-comment' => __( "Edits a comment's text only. It cannot change the post, author, email, or IP. Requires edit access to that comment.", 'agent-abilities-for-mcp' ), 'aafm/create-term' => __( 'Creates a term in a public taxonomy. Requires that taxonomy\'s own manage-terms capability.', 'agent-abilities-for-mcp' ), 'aafm/update-term' => __( 'Updates a term. Reparenting is guarded against hierarchy loops.', 'agent-abilities-for-mcp' ), 'aafm/add-post-terms' => __( 'Adds terms to a post without removing its existing terms. Requires edit access to the post and the taxonomy\'s assign capability; only existing terms in that taxonomy can be added.', 'agent-abilities-for-mcp' ), 'aafm/update-term-meta' => __( 'Writes one allowlisted scalar meta value to a term you can edit. Only allowlisted keys; protected keys are blocked. The response returns the old value when it is plain text or a number.', 'agent-abilities-for-mcp' ), 'aafm/restore-revision' => __( 'Restores a post to one of its revisions. The current state is saved as a fresh revision first, so the change is reversible. Refuses to run when revisions are disabled for the post, because that snapshot could not be taken.', 'agent-abilities-for-mcp' ), 'aafm/update-user' => __( 'Edits a user\'s display name, name, or email. Changing a role needs the promote-users capability and never demotes the last administrator. Requires edit access to that user.', 'agent-abilities-for-mcp' ), 'aafm/create-block' => __( 'Creates a reusable block. Its markup is sanitized, and the author is always the agent. Requires the edit-posts capability, and respects force-draft if you turned it on.', 'agent-abilities-for-mcp' ), 'aafm/update-block' => __( "Updates a reusable block's title or markup by id. The markup is sanitized. Requires edit access to that block.", 'agent-abilities-for-mcp' ), 'aafm/create-menu' => __( 'Creates a navigation menu. The menu is not attached to any theme location; that step is manual. On a block theme it is invisible on the front end until a human wires it into a template, since the core/navigation block reads from a separate mechanism this ability does not touch. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/update-menu' => __( 'Renames a navigation menu by id. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/create-menu-item' => __( 'Adds an item (link) to a navigation menu. The URL is sanitized. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/update-menu-item' => __( "Updates a menu item's title or URL by id. Requires the edit-theme-options capability.", 'agent-abilities-for-mcp' ), 'aafm/update-template' => __( 'Updates a database block template by id. Its markup is sanitized, and theme-file templates cannot be edited. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/yoast-update-post' => __( "Writes a post's Yoast SEO fields to its post meta. URL fields are sanitized as URLs, and the robots directives are checked against what Yoast accepts before they are saved. Requires edit access to that post. The response returns each field's old value when it is plain text or a number.", 'agent-abilities-for-mcp' ), 'aafm/rankmath-update-post' => __( "Writes a post's Rank Math SEO fields to its post meta. URL fields are sanitized as URLs, and robots is stored in the directive-array form Rank Math expects. Requires edit access to that post. The response returns each field's old value when it is plain text or a number.", 'agent-abilities-for-mcp' ), 'aafm/rankmath-update-schema' => __( "Writes a post's structured-data schema of a given type to Rank Math. The whole object is sanitized, top to bottom. Requires edit access to that post.", 'agent-abilities-for-mcp' ), 'aafm/aioseo-update-post' => __( "Writes a post's SEO fields through All in One SEO's own data store, not post meta. URL fields are sanitized as URLs. Requires edit access to that post.", 'agent-abilities-for-mcp' ), 'aafm/acf-update-post-fields' => __( 'Writes ACF field values on a post by field key. Each value is sanitized for its field type before it is saved. Requires edit access to that post.', 'agent-abilities-for-mcp' ), 'aafm/acf-update-term-fields' => __( 'Writes ACF field values on a term by field key. Each value is sanitized for its field type. Requires edit access to that term.', 'agent-abilities-for-mcp' ), 'aafm/acf-update-user-fields' => __( "Writes ACF field values on a user by field key, each value sanitized for its field type. It only writes ACF fields, never the account's role or login. Requires edit access to that user.", 'agent-abilities-for-mcp' ), 'aafm/wc-create-product' => __( 'Creates a WooCommerce product from a name, plus optional type, status, description, prices, SKU, stock, categories, tags, images, and attributes. Requires the manage-WooCommerce capability, and respects force-draft if you turned it on.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-product' => __( 'Updates a WooCommerce product by id, changing only the fields you send. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-product-variation' => __( 'Creates a variation under a variable product (parent product id required) from optional status, description, prices, SKU, stock, image, and attribute values. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-product-variation' => __( 'Updates a product variation by id, changing only the fields you send. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-product-attribute' => __( 'Creates a global WooCommerce product attribute taxonomy from a name, plus optional slug, type, sort order, and public-archives flag. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-product-attribute' => __( 'Updates a global product attribute taxonomy by id, changing only the fields you send. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-order-note' => __( 'Adds a note to a WooCommerce order by order id. Optionally marks the note as customer-facing so it appears in the customer\'s account. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-order-refund' => __( 'Creates a refund on a WooCommerce order by order id. Accepts an amount, optional reason, and optional line-item breakdown. The refund reason is returned verbatim and may contain customer-entered text; it is returned under the Integrations security disclaimer. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), // Destructive (still recoverable). 'aafm/trash-post' => __( 'Moves a post the agent can edit to the Trash, where you can restore it. Never a permanent delete.', 'agent-abilities-for-mcp' ), 'aafm/trash-page' => __( 'Moves a page to the Trash, where you can restore it. Never a permanent delete.', 'agent-abilities-for-mcp' ), 'aafm/delete-post-meta' => __( 'Removes an allowlisted meta key and all its values from a post the agent can edit. Only allowlisted keys. The response returns the old value when it is plain text or a number.', 'agent-abilities-for-mcp' ), 'aafm/delete-block' => __( 'Moves a reusable block to the Trash, where you can restore it. Never a permanent delete. Requires delete access to that block.', 'agent-abilities-for-mcp' ), // Destructive (permanent). 'aafm/delete-revision' => __( "Permanently removes one revision from a post's history. The live post is unchanged, but the deleted revision cannot be recovered. Requires edit access to the parent post.", 'agent-abilities-for-mcp' ), 'aafm/delete-media' => __( 'Permanently deletes an attachment: the file and its library entry are removed and cannot be recovered. Requires delete access to that attachment.', 'agent-abilities-for-mcp' ), 'aafm/delete-term-meta' => __( 'Removes an allowlisted meta key and all its values from a term you can edit. This cannot be undone. Only allowlisted keys. The response returns the old value when it is plain text or a number.', 'agent-abilities-for-mcp' ), 'aafm/delete-comment' => __( 'Permanently deletes a comment. This bypasses the Trash and cannot be undone - use moderate-comment to trash a comment recoverably instead. Requires edit access to that comment.', 'agent-abilities-for-mcp' ), 'aafm/create-user' => __( 'Creates a new user with the site default role only (never an admin or a caller-chosen role). Requires the create-users capability. Off by default.', 'agent-abilities-for-mcp' ), 'aafm/delete-user' => __( 'Permanently deletes a user and reassigns their content to another user. Never deletes you or the last administrator. Requires the delete-users capability. Off by default. On multisite this removes the user from the current site only; the network account and its logins remain.', 'agent-abilities-for-mcp' ), 'aafm/delete-user-meta' => __( 'Removes an allowlisted user meta key from a user the agent can edit. This cannot be undone. Auth and capability keys can never be touched. The response returns the old value when it is plain text or a number.', 'agent-abilities-for-mcp' ), 'aafm/delete-post' => __( 'Permanently deletes a post, bypassing the Trash. This cannot be undone - use trash-post to remove a post recoverably instead. Requires delete access to that post. Off by default.', 'agent-abilities-for-mcp' ), 'aafm/delete-page' => __( 'Permanently deletes a page, bypassing the Trash. This cannot be undone - use trash-page to remove a page recoverably instead. Requires delete access to that page. Off by default.', 'agent-abilities-for-mcp' ), 'aafm/update-site-settings' => __( 'Writes a small allowlist of site settings only (name, tagline, timezone, formats, posts per page). It can never change the site URL, admin email, default role, or open registration. Requires manage-options. Off by default.', 'agent-abilities-for-mcp' ), 'aafm/delete-menu' => __( 'Permanently deletes a navigation menu and all of its items. This cannot be undone - menus have no Trash. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/delete-menu-item' => __( 'Permanently removes one item from a navigation menu. This cannot be undone. Requires the edit-theme-options capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-delete-product' => __( 'Permanently deletes a WooCommerce product, bypassing the Trash. This cannot be undone. Requires the manage-WooCommerce capability. Off by default.', 'agent-abilities-for-mcp' ), 'aafm/wc-delete-product-variation' => __( 'Permanently deletes a product variation, bypassing the Trash. This cannot be undone. Requires the manage-WooCommerce capability. Off by default.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-coupons' => __( 'Lists WooCommerce coupons with their id, code, amount, discount type, expiry date, and usage count, plus a total. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-coupon' => __( 'Reads one WooCommerce coupon by id: code, amount, discount type, expiry, usage limits, spend limits, product and email restrictions, and other config. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-coupon' => __( 'Creates a WooCommerce coupon from a code and discount type, with optional amount, usage limits, spend limits, product restrictions, and email restrictions. Returns the full coupon shape. The coupon is published and usable immediately. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-coupon' => __( 'Updates a WooCommerce coupon by id, changing only the fields you send. An empty request body is a no-op success. Returns the full coupon shape. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-shipping-zones' => __( 'Lists WooCommerce shipping zones with their id, name, and order. The Rest of World zone (id 0) is always present. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-shipping-zone' => __( 'Reads one WooCommerce shipping zone by id, including its name, order, and configured zone locations. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-shipping-zone' => __( 'Creates a WooCommerce shipping zone from a name and optional order. Returns the full zone shape. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-shipping-zone' => __( 'Updates a WooCommerce shipping zone by id, changing only the fields you send. An empty request body is a no-op success. Returns the full zone shape. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-shipping-methods' => __( 'Lists the shipping methods configured in a WooCommerce shipping zone, by zone id. Each method now includes its per-instance settings, which is where a carrier or gateway plugin may keep account details and API credentials. Field names matching a known secret pattern are dropped first, but that is a denylist over names third-party plugins choose, so it cannot cover every one. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-shipping-method' => __( 'Reads one shipping method from a WooCommerce shipping zone by zone id and instance id, including its type, title, enabled state, and per-instance settings. Those settings are where a carrier or gateway plugin may keep account details and API credentials. Field names matching a known secret pattern are dropped first, but that is a denylist over names third-party plugins choose, so it cannot cover every one. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-shipping-method' => __( 'Adds a shipping method to a WooCommerce shipping zone. Provide the zone id and method type (such as flat_rate, free_shipping, or local_pickup). Returns the new method shape. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-shipping-method' => __( 'Updates a shipping method in a WooCommerce shipping zone by zone id and instance id, changing only the fields you send. Returns the updated method shape. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-tax-rates' => __( 'Lists all WooCommerce tax rates across every tax class, returning id, country, state, rate, name, priority, compound flag, shipping flag, order, and class slug for each. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-tax-rate' => __( 'Reads one WooCommerce tax rate by id, returning id, country, state, rate, name, priority, compound flag, shipping flag, order, and class slug. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-tax-rate' => __( 'Creates a WooCommerce tax rate from a rate value, with optional country, state, name, priority, compound flag, shipping flag, order, and class slug. Returns the full rate shape. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-tax-rate' => __( 'Updates a WooCommerce tax rate by id, changing only the fields you send. An empty body (only id) is a no-op success. Returns the updated rate shape. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-tax-classes' => __( 'Lists all WooCommerce tax classes including the Standard class, returning name and slug for each. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-create-tax-class' => __( 'Creates a WooCommerce tax class from a name, with an optional slug. Returns the new class shape. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-sales-report' => __( 'Returns a sales summary (total sales, order count, net sales, average order value) for a date range you specify. Queries completed and processing orders only. Defaults to the current calendar month. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-top-sellers-report' => __( 'Returns the top-selling products for a period (week, month, or year) ordered by quantity sold. Returns product id, name, and quantity only - no pricing data. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-count-orders' => __( 'Returns order counts broken down by the built-in WooCommerce statuses (pending, processing, on-hold, completed, cancelled, refunded, failed) and a grand total covering every registered status, including custom ones. Read-only. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-count-products' => __( 'Returns product counts broken down by post status (publish, draft, private, pending, trash) and a total of non-trashed products. Read-only. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-list-payment-gateways' => __( 'Lists all registered WooCommerce payment gateways with id, title, and enabled state. Credential and secret settings are never returned. Read-only. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-get-payment-gateway' => __( 'Reads one payment gateway by id: title, description, enabled state, order, and non-secret settings. Fields whose names contain key, secret, token, password, api, or private are always stripped before the response is sent. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), 'aafm/wc-update-payment-gateway' => __( 'Updates a payment gateway by id, changing only the fields you send: enabled state, title, description, or display order. Credential and secret fields can never be written through this ability. Returns the updated gateway shape with secrets redacted. Requires the manage-WooCommerce capability.', 'agent-abilities-for-mcp' ), // The Events Calendar / Event Tickets. 'aafm/tec-get-events' => __( 'Lists events via the Events Calendar, filtered by an optional search term. An optional status filter can include draft/pending/future events you can edit, or private events if you have that access. Drafts, pending and future events are limited to the caller\'s own unless they can edit other people\'s events.', 'agent-abilities-for-mcp' ), 'aafm/tec-get-event' => __( 'Reads a single event by id, including its dates, venue, and organizers.', 'agent-abilities-for-mcp' ), 'aafm/tec-create-event' => __( 'Creates an event. Defaults to draft; a publicly-visible status additionally requires the publish-events capability. Requires the edit-events capability.', 'agent-abilities-for-mcp' ), 'aafm/tec-update-event' => __( 'Updates an event by id. A publicly-visible status additionally requires the publish-events capability. Requires edit access to that event.', 'agent-abilities-for-mcp' ), // Now guarded by the same aafm_trash_is_enabled() // check as trash-post/trash-page/delete-block, so this claim is true the same way theirs // is - refuses outright rather than falling through to WordPress's own permanent delete. 'aafm/tec-delete-event' => __( 'Moves an event to the Trash, where you can restore it. Never a permanent delete. Requires delete access to that event.', 'agent-abilities-for-mcp' ), 'aafm/tec-get-venues' => __( 'Lists venues via the Events Calendar. An optional status filter can include draft/pending/future venues you can edit, or private venues if you have that access.', 'agent-abilities-for-mcp' ), 'aafm/tec-get-venue' => __( 'Reads a single venue by id.', 'agent-abilities-for-mcp' ), 'aafm/tec-create-venue' => __( 'Creates a venue. Defaults to draft; a publicly-visible status additionally requires the publish-venues capability. Requires the edit-venues capability.', 'agent-abilities-for-mcp' ), 'aafm/tec-update-venue' => __( 'Updates a venue by id. A publicly-visible status additionally requires the publish-venues capability. Requires edit access to that venue.', 'agent-abilities-for-mcp' ), 'aafm/tec-get-organizers' => __( 'Lists organizers via the Events Calendar. An optional status filter can include draft/pending/future organizers you can edit, or private organizers if you have that access.', 'agent-abilities-for-mcp' ), 'aafm/tec-get-organizer' => __( 'Reads a single organizer by id.', 'agent-abilities-for-mcp' ), 'aafm/tec-create-organizer' => __( 'Creates an organizer. Defaults to draft; a publicly-visible status additionally requires the publish-organizers capability. Requires the edit-organizers capability.', 'agent-abilities-for-mcp' ), 'aafm/tec-update-organizer' => __( 'Updates an organizer by id. A publicly-visible status additionally requires the publish-organizers capability. Requires edit access to that organizer.', 'agent-abilities-for-mcp' ), 'aafm/tec-get-tickets' => __( 'Lists every ticket for one event, across every ticketing provider. Requires edit access to that event. Read-only - no ticket write ability is offered, since ticket creation and RSVP processing are commerce flows this plugin does not touch.', 'agent-abilities-for-mcp' ), 'aafm/tec-get-ticket' => __( 'Reads a single ticket by id. Requires edit access to its parent event.', 'agent-abilities-for-mcp' ), 'aafm/tec-get-attendees' => __( 'Lists attendees and RSVPs for one event. Requires edit access to that event. Read-only.', 'agent-abilities-for-mcp' ), // Slim SEO. 'aafm/slim-seo-get-post' => __( "Reads a post's Slim SEO fields (title, description, canonical, social images, and the noindex flag). Requires edit access to that post.", 'agent-abilities-for-mcp' ), 'aafm/slim-seo-update-post' => __( "Writes a post's Slim SEO fields. A field omitted from the call is left untouched. Requires edit access to that post.", 'agent-abilities-for-mcp' ), // Avada / Fusion Builder. 'aafm/avada-get-page-content' => __( 'Reads the raw post content of an Avada/Fusion Builder page, unchanged. Fusion Builder shortcodes are returned exactly as stored, never rendered or stripped. Requires edit access to the post.', 'agent-abilities-for-mcp' ), // shortcode_parse_atts() (what the guard actually compares) discards // quoting style and whitespace inside a tag, so a change limited to those is not caught // even though the tree it builds otherwise stays equal. Worded to the real guarantee // (structure and attribute values) rather than the "byte-identical" claim that didn't hold. 'aafm/avada-replace-text' => __( 'Replaces literal text within an Avada/Fusion Builder page while requiring the Fusion shortcode structure and every attribute value to stay the same before and after (quoting style and whitespace inside a tag are not part of this guarantee). A replacement that would touch a shortcode tag or its attributes is refused rather than risk breaking the layout. Requires edit access to the post.', 'agent-abilities-for-mcp' ), // GeoDirectory (default-off). 'aafm/geodirectory-get-listings' => __( 'Lists GeoDirectory business/place listings (title, status, link).', 'agent-abilities-for-mcp' ), 'aafm/geodirectory-get-listing' => __( 'Reads one GeoDirectory listing by id, including its address and coordinates.', 'agent-abilities-for-mcp' ), 'aafm/geodirectory-create-listing' => __( 'Creates a GeoDirectory business/place listing with a title, content, and optional address/coordinates.', 'agent-abilities-for-mcp' ), 'aafm/geodirectory-update-listing' => __( "Updates an existing GeoDirectory listing's title, content, or address/coordinates. Fields omitted from the call are left untouched.", 'agent-abilities-for-mcp' ), ); }