Changelog · plugin + MCP ship in lockstep

Releases

Latest: v3.15.4, released 2026-10-14. Licensed sites get plugin updates in WP Admin; the MCP server updates itself through the signed manifest.

v3.15.4

  • Structure guard + automatic rollback (Elementor 4.3). Elementor 3.30 silently tolerated a widget without widgetType, a widget placed directly in a legacy section, or an element without elType; Elementor 4.3 stores such elements stripped and then crashes the public page on render. Every Elementor write now refuses these trees up front (400 invalid_structure with the offending ids; force=true overrides) and, if Elementor still drops or corrupts an element during save, restores the previous tree automatically (save_mismatch with corrupted[], rolled_back: true) so the page never goes live broken.
  • WP Rocket 3.23 verified on the test lane (built from the public GPL source). purge_cache(post_id) now purges the post URL via rocket_clean_files when rocket_clean_post is not loaded (WP Rocket loads it only in admin/cron contexts, not on REST requests) and says so in notes[]; preload triggers WP Rocket's own rocket_preload_job_load_initial_sitemap event when registered. The call that crashed in the field (url + used_css + preload) returns 200 with the unsupported parts listed.

v3.15.3

  • Elementor 4.x Variables detection. Variables (list/create/update/delete_variable, get_design_system.variables, variable mapping in import_element) reported "not available" on Elementor 4.x, where the Variables module is gated by the atomic-elements experiment instead of the old e_variables flag. Detection now follows Elementor's own module constant. Verified on a second test lane: WordPress 7.1.3 + Elementor 4.3.3 + Rank Math.

v3.15.2

  • Fix (WP Rocket): purge_cache with preload=true called WP Rocket's deprecated run_rocket_preload_cache() without its required argument → PHP fatal (HTTP 500) after the page cache was already cleared. Preload now uses the public action when the installed WP Rocket exposes one and is otherwise reported as unsupported with the manual path.
  • purge_cache is now fault-isolated: every cache-plugin call runs in its own guard; failures are returned in failed[] instead of aborting the response. Per-URL Used CSS clearing is used when WP Rocket provides it; when only the site-wide clear exists the response says so in notes[] (that is why other pages rebuild their Used CSS after a single-URL purge).

v3.15.1

  • Fix (Elementor ≥4.3): every Elementor write ended in a PHP TypeError (HTTP 500) *after* the data was saved, because the atomic style cache hook elementor/atomic-widgets/styles/clear now expects an array path and AgenticWP passed the post id. The call now uses Elementor's own cache keys in the expected shape, is skipped when no listener is registered, and can never fail a completed save. Reported from a site on Elementor 4.3.4.

v3.15.0

  • Portable element bundles. export_element(page_id, element_id?, format, path?) returns a subtree (or the whole page) with the dependencies a bare copy loses: media (id, url, alt), global color/typography tokens with values, atomic variables, global classes, widget types, dynamic tags, source site and Elementor version. format=elementor writes Elementor's template JSON (importable in Elementor → Templates); path saves the bundle to a local file, so an agent can keep a library of sections across client sites. import_element(page_id, bundle|path, parent_id?, position?, dry_run, media=relink|download, globals=keep|strip|literal, variables=map|create) inserts with fresh ids, refuses unregistered widget types (missing_widget_types) and atomic-into-classic (dialect_mismatch), sideloads remote media into the target library (deduped by source URL) and rewrites ids/urls, maps or creates variables, and resolves missing kit tokens by keeping, stripping or writing the exported literal value. 112 tools.

v3.14.1

  • render_page reports final_url and redirect_chain (verify redirects by destination, not by status). get_page_snapshot tokens list literal_color_elements (element id, control, value; classic settings and atomic styles). find_elements gains {"matches": "<regex>"} conditions. The MCP

v3.14.0

  • list_elements: one catalog of everything an agent can insert — containers (incl. atomic e-flexbox/e-div-block) and widgets with title, categories, source plugin, atomic flag, panel visibility and allowed parents, plus placement rules. Cached 6 h per Elementor version. Free tier.
  • get_widget_schema(example=true): returns a minimal valid element (id, type, default settings) ready for insert_elementor_element / build_page, for classic widgets, containers and atomic types.
  • get_design_system: kit color/typography tokens, base typography + layout keys, global classes, variables, Astra custom-css blocks and usage across Elementor pages (referenced tokens/classes, literal hex colors with page + element ids). Free tier.
  • set_global_reference: bind a control to a kit token through settings.__globals__ (color or typography), validated against the kit and the widget's controls; remove or clear the literal value. 110 tools.

v3.13.0

  • Page settings: get_page_settings / set_page_settings — post fields (title, slug, status, parent, menu order, excerpt, template, featured image; template validated against the theme + Elementor canvas/header-footer/theme) and Elementor page settings merged through Document::save under the post lock.
  • Kit tokens: get_kit_tokens / update_kit_tokens — global colors and typography upsert/remove by _id or title (system tokens editable, not removable; colors validated), global CSS flushed, kit backed up.
  • Dynamic tags: list_dynamic_tags (registered tags + controls) and set_dynamic_tag (binds a control to a tag via __dynamic__, or removes it). 409 tag_dropped when Elementor's own sanitizer rejects an unregistered tag (needs Pro / add-on).
  • Media: resize_media (resized copy as a new attachment, or regenerate sizes); media_upload accepts SVG after sanitizing it (script/foreignObject/event handlers/javascript:/external references removed; DOCTYPE/ENTITY rejected).
  • search_content: find text across titles, slugs, content, Elementor settings (element id + widget type + setting path) and selected meta keys with snippets. Free tier.
  • Gutenberg blocks: get_post_blocks (outline with index paths) and edit_post_blocks (update / add / move / remove / replace_all by path; innerContent kept consistent; WP revision as backup; refuses Elementor-built posts unless forced).
  • Redirects + links: list_redirects / create_redirect / delete_redirect through Rank Math or Redirection (501 no_redirect_provider otherwise); find_broken_links checks URLs from content + Elementor data server-side (private hosts skipped, capped).
  • site_health_report: read-only scored report (core, updates, autoloaded options, cron, security, headers, home-page frontend; optional core checksum verification) with grade and prioritized findings. Free tier.
  • Stock images: search_stock_images (Openverse, no key) and place_stock_image (upload + alt + attribution caption + set as widget image). Agent onboarding: agent_context (site facts, rules, warnings, task→tool map) and prompt_library (bundled prompts.json, 18 prompts across 8 industries).
  • Hardening: per-credential rate limit (user + application-password uuid; 1200/min default, AGENTICWP_RATE_LIMIT / option agenticwp_rate_limit, 0 disables; 429 + Retry-After), change.credential with the application-password uuid, opt-in Host pinning (AGENTICWP_PIN_HOST / option agenticwp_pin_host, 400 host_mismatch), Cache-Control: no-store + X-Content-Type-Options: nosniff on every AgenticWP response. MCP client falls back to ?rest_route= when /wp-json/ serves HTML (plain permalinks). 107 tools.

v3.12.0

  • Structure ops: move_element (keeps id + subtree; root = containers only), duplicate_element (deep copy with fresh ids, local atomic style ids remapped, id_map), delete_element (removed subtree stored as an element backup; >10 elements need confirm), reorder_children (exact sibling list), delete_page_content (always confirm; previous tree backed up).
  • build_page: whole page from a nested {type, settings, styles, children} tree in one call — validates structure (top-level containers, no children on widgets, unique ids) and atomic props, dry_run, create a new draft page or replace/append an existing one. atomic=true maps heading/text-editor/image/button to e-* widgets and turns flat styles ("font-size@tablet", "color@hover") into a local class with variants.
  • get_page_snapshot: one context-cheap read — post, structure (counts by type, depth, 2-level outline), tokens (global refs, fonts, literal colors, class refs), responsive overrides, content (headings, word count, images without alt, links, buttons, forms) and warnings (no_h1, multiple_h1, deep nesting, empty containers). Cached 15 min per page version. Free tier.
  • Templates: save_as_template (subtree or whole page → elementor_library), apply_template (fresh ids, parent/position/sibling placement).
  • Confirm layer: confirmation_required 409 for destructive ops; site opt-in via AGENTICWP_REQUIRE_CONFIRM or option agenticwp_require_confirm extends it to build_page replace and every delete_element.
  • Editor-sync: Elementor ≥4.3 elementor/mcp/pre_execute_guard filter honoured (409 editor_locked), Editor_Sync_State::set_mcp_mutation + elementor/mcp/mutation action fired after every save; no-op on older Elementor.
  • Menus: update_menu_item, delete_menu_item (children re-parented), assign_menu_location, render_menu (nested tree + optional HTML, free tier).
  • MCP: render_page gains offset/max_bytes/raw chunked HTML with body_sha256. 88 tools.

v3.11.0

  • Elementor 4 Atomic Elements (phase A of the parity plan): get_wp_status.elementor reports version, atomic/variables state and registered e-* types; e-flexbox/e-div-block accepted as containers; bare values are wrapped into Elementor's {$$type, value} envelopes and validated with Elementor's own Props_Parser before saving (400 atomic_validation with per-element issues instead of a locked page); get_elementor_element(unwrap=true) strips envelopes for reading.
  • Global Classes + Variables: list/create/update/delete_global_class (flat CSS-like props validated against Style_Schema, breakpoint/state variants), set_element_classes, list/create/update/delete/restore_variable (color/font/size design tokens). Reads are free tier.
  • get_widget_schema: compact control map {t, opts, def, rv, if, arr, fields, units} per widget with tab/section/control_names/params_only filters (reads the full control stack even outside the editor).
  • Settings validation: update_elementor_element refuses select/choose/switcher values outside the control's options (400 invalid_values + schema_hint, force=true to override) and reports unknown_keys.
  • Safer saves: post-save verification by the full element-ID set (nested widgets of inactive add-ons or atomic elements without the experiment are reported as save_mismatch with missing_ids, a backup of the previous tree and no silent loss); Document::save() exceptions are caught and reported; per-post invalidation also clears Elementor Pro's _elementor_element_cache and the post CSS file; every Elementor write returns urls {view_url, preview_url, edit_url}.
  • Compare-and-swap restore: backups carry after_hash; restore_element_backup refuses (409 backup_stale) when the element/page changed after the backup unless force=true.

v3.10.0

  • Reads no longer need a license (IDEJE #6): every Elementor GET (pages, page, outline, element, revisions, widgets, components, kit), the diff dry-run, find and backups are free tier. Writes (Document::save(), media, bulk products, menus) stay paid.
  • Automatic pre-change backups + restore (IDEJE #3): every Elementor mutation stores the element (or page tree) as it was — ring buffer of 20 element + 3 page snapshots per post in _agenticwp_backups — and returns backup_id. New GET /elementor/page/{id}/backups, GET …/backups/{backup_id}, POST …/backups/{backup_id}/restore. Restores are themselves backed up.
  • Change record on every mutation (IDEJE #11): change: {ts, site, endpoint, target, user, before_hash, after_hash, changed} on options, post meta, CSS, Astra, Elementor and kit writes. The MCP server appends them as JSON lines to AGENTICWP_CHANGELOG_PATH when set.
  • purge_cache (IDEJE #4): POST /cache/purge {url?|post_id?, used_css?, preload?} detects WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache, WP Fastest Cache, Autoptimize and runs the matching purge; always flushes object cache + Elementor CSS; reports detected plugins, actions and unsupported requests.
  • patch_postmeta (IDEJE #2): POST /postmeta/{id}/{key}/patch deep-merges patch or sets/unsets a dotted path; JSON-string meta stays JSON. get_elementor_kit / update_elementor_kit: read and merge-update Site Settings through the Kit document (global CSS regenerated, previous settings backed up).
  • find_elements (IDEJE #8): POST /elementor/find scans element trees by widget_type, el_type and a where map of dotted paths with null / equals / contains / exists / not / in conditions.
  • fields / max_length on get_elementor_element, get_elementor_page and get_elementor_kit (IDEJE #5) — return only the setting keys you need and truncate long strings with a …[truncated N bytes] marker.
  • WPML sync state (IDEJE #10): when WPML is active, Elementor saves report translations: [{lang, post_id, is_source, same_elementor_data}].
  • MCP: get_wp_status returns connection_name (AGENTICWP_CONNECTION_NAME), configured_url and a warning when the WP_URL host differs from the site's own site_url (IDEJE #7). 64 tools.

v3.9.8

  • New: update_elementor_elements (batch). One call applies many element updates (settings merge or whole-element replace) across one or more pages. Entries are grouped by page; each page is locked once and saved once through Document::save(), so dozens of edits on a handful of pages cost a handful of saves. Per-entry results (ok / error), per-page summary, strict mode (abort a page if any of its entries fails), optional flush_css. New endpoint POST /agenticwp/v1/elementor/batch (paid tier, max 200 entries per call). Honors read-only mode.

v3.9.7

  • Security hardening release (full code audit, 2026-10-13). Plugin: media_upload no longer accepts server-side file_path (was an arbitrary file read/delete); agenticwp_* license options, agwp_lock_*, default_role, users_can_register, cron and {prefix}user_roles are protected; REST passthrough deny-list is case-insensitive, /settings refuses url/email/default_role/users_can_register, WooCommerce system_status/tools writes blocked; passthrough, flush_cache and bulk_update_pages now honor read-only mode; per-post lock is truly atomic (INSERT IGNORE + compare-and-swap, owner-checked release, TTL ≥ save limit) and astra-settings/patch_css writes are locked too; patch_css no longer expands \0/$1 inside your CSS and never writes null on a regex failure; get_option redacts secret-looking keys; Document::save() failures are reported instead of success: true.
  • Bug fixes: elementor_replace matches text containing quotes and only touches string values (never keys/ids); wp_rest_call paths with ?query work; restore_elementor_revision refuses revisions without Elementor data instead of blanking the page; bulk_update_products reports per-item WC_Data_Exception (duplicate SKU) instead of a 500; option/meta names keep their case (WPLANG); get_debug_log reads only the tail of the file; flush_cache?object_cache=false parsed correctly; media_set_alt dry-run reads the right id; list_elementor_pages accepts per_page/page; create_elementor_page validates status/elements.
  • Licensing: 429 / transient Worker errors no longer flip a valid license to invalid; 7-day grace now actually applies and re-verification retries at most hourly while the API is unreachable; update packages are only accepted from agenticwp.racunalnicar.eu / agenticwp.pages.dev; the download fallback filter returns a downloaded file as WordPress expects.
  • MCP server: requirements.txt pins mcp<2 (mcp 2.x removed the decorator API and crashed fresh installs); clear startup error if an unsupported mcp is installed; apply_mcp_update requires SHA-256, https on the official host, backs up into <install>/.backups, re-installs requirements and rolls back on failure; render_page and the reachability probe no longer send the WordPress application password to foreign hosts; path segments are URL-encoded; structured errors with isError; bulk_update_pages gains find/replace_with, refuses to blank a page and skips pages whose content can't be read; value is no longer auto-parsed as JSON (opt in with parse_json).

v3.9.5

  • Bundled agent-rules now include a working-style section in AGENTS.md (cascaded into agent-rules/CLAUDE.md, .cursorrules, .windsurfrules, .clinerules, copilot-instructions.md, CONVENTIONS.md). Two always-on defaults (verify-before-claiming, cheapest-read-first), a triggers table (diff before risky update, backup before bulk write, patch_css over read-modify-write, lock-aware sequencing on same page_id, etc.), and explicit anti-patterns.

v3.9.4

  • Edition-aware paid-tool gate. MCP server now caches the WP plugin's edition (free|pro) on first /status call and short-circuits paid-only tools with a clear "requires Pro" message instead of letting them hit a 404.
  • Plugin-side: paid plugin returns edition: pro in /status; WP.org-published free plugin (1.0.0) returns edition: free. Pre-3.9.4 plugins without the edition field default to pro (no behavior change for existing paid sites).
  • MCP_VERSION bumped to 3.9.4; mcp-latest.json updated with new SHA-256.

v3.9.3

  • Page revision tools for non-Elementor pages. Two new MCP tools, pure Python composition over the existing wp_rest_call passthrough — no plugin-side changes:
  • Do NOT use on Elementor pages — standard WP revisions only snapshot post_content, not _elementor_data. Use restore_elementor_revision for Elementor pages instead (already calls Document::save() to sync _elementor_data + _elementor_css + post_content atomically).
  • MCP_VERSION bumped to 3.9.3; mcp-latest.json updated with new SHA-256.

v3.9.2

  • Lowered minimum PHP to 7.4. The plugin never actually used any PHP 8-only syntax (no match, nullsafe ?->, readonly, enums, named arguments, str_contains/str_starts_with, or array_is_list). Only ternary + null-coalescing, both PHP 7+. This matches WordPress 6.0's own PHP 7.4 floor and lets the plugin install on shared hosts that haven't migrated to PHP 8 yet.
  • MCP_VERSION bumped to 3.9.2; mcp-latest.json updated with new SHA-256.

v3.9.1

  • Four more agent tools for high-friction tasks:
  • MCP_VERSION bumped to 3.9.1; mcp-latest.json updated with new SHA-256.

v3.9.0

  • Three productivity tools for agents:
  • MCP_VERSION bumped to 3.9.0; mcp-latest.json manifest updated with new SHA-256.

v3.8.2

  • Domain migration — licensing API + MCP self-update manifest moved to agenticwp.racunalnicar.eu. Legacy route kept alive as dual-route until 2026-07-01 for plugins installed before v3.8.2, then removed.
  • Email sender — license + portal emails now send from [email protected]. .eu TLD clears the SpamAssassin blacklist penalty of the prior TLD.
  • Cross-product footer — "Also from Računalničar s.p." section on landing links to WooQR UPN sister product.
  • MCP_VERSION bumped to 3.8.2; mcp-latest.json manifest updated with new SHA-256.

v3.8.1

  • "View details" popup — WP Admin → Plugins → click "View details" now shows the full plugin info modal (description, installation, FAQ, changelog, upgrade notice) parsed from readme.txt
  • Changelog on update nag — when a new version is available, "View version X.Y.

v3.8.0

  • Observability: get_debug_log — tail wp-content/debug.log, filter by level, paths redacted
  • SEO audit: seo_audit — cross-site snapshot (title/desc/focus/robots/og per post) with per-item issues[] + aggregate summary
  • Read-only mode: AGENTICWP_READONLY flag short-circuits every mutation to a dry-run — wired into 19 mutation callbacks
  • Security (Worker-only): constant-time Stripe signature compare, multi-v1 signature support, INSERT OR IGNORE + UNIQUE partial index against webhook race conditions

v3.7.9

  • Version parity + MCP self-update: MCP_VERSION constant in server.py must match plugin version; get_wp_status now returns mcp_version + version_parity
  • New MCP tools: check_mcp_update, apply_mcp_update, rollback_mcp_update
  • Published static mcp-latest.json manifest at agenticwp.racunalnicar.eu with SHA-256 verification

v3.7.8

  • MCP transport hardening: schemas widened to accept JSON-string values for struct params (element, elements, settings, meta, etc.); added _coerce_json_args in server.py
  • agenticwp_build_text now accepts html / text / editor aliases

v3.7.7

  • Per-post write locks on all Elementor mutations — atomic MySQL-backed, 30 s TTL, 409 on conflict
  • Extended time limit (set_time_limit(120) + ignore_user_abort(true)) prevents mid-save PHP timeouts
  • CPT support — list_elementor_pages gained type='any'; all save responses include post_type

v3.7.6

  • Raw UTF-8 in REST responses (JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) — Slovenian, emoji, Cyrillic, Chinese, Arabic as raw bytes
  • Elementor revisions: list_elementor_revisions, get_elementor_revision, restore_elementor_revision

v3.7.5

  • Large-page handling: 500 KB payload ceiling, 50-container warning threshold, X-AgenticWP-Size header, max_depth param on get_elementor_outline
  • 61 passing harness tests

v3.7.4

  • Element ID collision detection on insert
  • diff_elementor_element expanded: structural + children diffs for full-element replacement mode

v3.7.3

  • Top-level insert rule enforced — only containers at page root (widgets must be nested)

v3.7.2

  • Security: protected-option bypass closed (case-normalized comparison); insert_elementor_element hardened validation (parent-must-be-container, position enum, sibling-exists check)

v3.7.0

  • Field-report fixes: get_elementor_page size warning, flush_cache granular flags, diff_elementor_element dry-run tool, insert_elementor_element

v3.6.0

  • get_option returns {exists: false} instead of 404 on missing options (BREAKING)
  • list_elementor_pages type filter
  • find_products attribute filtering
  • Term meta CRUD
  • update_postmeta_multi (bulk across posts)

v3.5.0

  • License gate + Settings page + Cloudflare Worker licensing system (replaced Gumroad)
  • Installer scripts + agent rules for 6 AI tools

v3.0.0

  • Removed all frontend hooks — pure REST API plugin

v3.8.0

    v3.7.9