=== AgenticWP — AI-driven WordPress management ===
Contributors: sebastijanbandur
Tags: mcp, ai, claude, cursor, windsurf, rest-api, elementor, woocommerce, rankmath, agent
Requires at least: 6.0
Tested up to: 6.9.4
Requires PHP: 7.4
WC tested up to: 10.7
Stable tag: 3.9.5
License: GPL-2.0+
License URI: https://www.gnu.org/licenses/gpl-2.0.txt

Safe REST API + MCP server that lets any AI coding agent (Claude, Cursor, Windsurf, Cline, 18+ more) build, edit, and maintain WordPress sites.

== Description ==

**AgenticWP** exposes 30+ safe, scoped REST endpoints that let any MCP-compatible AI agent manage WordPress — options, Elementor pages, post meta, Astra theme, WooCommerce products, media, menus — without ever touching your frontend.

Paired with the bundled MCP server, you get a plug-in that turns any agent-capable IDE (Claude Code, Cursor, Windsurf, Cline, Continue, JetBrains AI, Aider, Zed, Cody, and more) into a WordPress co-pilot.

= Core features =

* **30+ MCP tools** — options, postmeta, term meta, Astra settings, cache flush, media upload, menu items, WooCommerce products, generic REST passthroughs
* **Elementor fine-grained** — update a single element, insert at position, find/replace, diff dry-run, outline-only fetch for context efficiency
* **Elementor revisions** — list / get / restore, with pre-restore state captured as a new revision (undoable)
* **Per-post write locks** — atomic MySQL-backed; concurrent edits return 409 with owner info instead of clobbering
* **Read-only mode** — `AGENTICWP_READONLY` flag turns every mutation into a server-side dry-run, perfect for demos and staging
* **Observability** — `get_debug_log` surfaces PHP fatals/warnings; `seo_audit` returns cross-site SEO snapshot with per-post issues list
* **CPT support** — works on products, portfolios, LearnDash courses, any Elementor-enabled post type
* **Raw UTF-8 responses** — Slovenian/Cyrillic/Chinese/emoji round-trip as bytes, not \uXXXX escapes
* **Built for scale** — 500 KB payload ceiling, 120 s save timeout, 50-container warning threshold, 109 passing edge-case tests

= How it works =

1. Install & activate the plugin (this plugin is the REST API surface)
2. Generate a WordPress application password
3. Install the bundled MCP server on your laptop (one-time: `install.sh` / `install.bat`)
4. Point any MCP-compatible AI client at the MCP server
5. Chat normally — the agent calls MCP tools, each mapped 1:1 to a REST endpoint

= Self-update (v3.7.9+) =

Plugin and MCP server ship in version parity. MCP agents can call `check_mcp_update`, `apply_mcp_update`, `rollback_mcp_update` tools to keep the MCP side in sync with the plugin — no manual `.venv` fiddling.

== Installation ==

1. Upload the plugin ZIP via **Plugins → Add New → Upload Plugin**
2. Activate AgenticWP
3. Go to **Settings → AgenticWP** and paste your license key, click **Verify license**
4. Generate a **WordPress application password** (Users → Profile)
5. Install the MCP server: `unzip agenticwp-mcp.zip && ./install.sh` (Linux/Mac) or `install.bat` (Windows)
6. The installer prompts for your WP URL + username + app password, generates `.mcp.json`
7. Connect your AI IDE to the MCP server (each IDE has its own config — installer drops rules files for Claude Code, Cursor, Windsurf, Cline, GitHub Copilot)

== Frequently Asked Questions ==

= Which AI agents are supported? =

Any MCP-compatible agent: Claude Code, Cursor, Windsurf, VS Code (Cline + Continue), JetBrains AI, Aider, Zed, Cody, Sourcegraph, and 10+ more. The MCP server is stdio-based and uses the standard Model Context Protocol.

= Does AgenticWP modify my frontend? =

Never. AgenticWP is a pure management REST API and adds zero frontend hooks. It does not filter `post_content`, `the_content`, `wp_head`, or WooCommerce output.

= What happens when two AI agents edit the same page? =

Per-post write locks serialize saves. The first agent wins the lock; the second gets HTTP 409 `lock_held` with the current owner in the response. Different posts don't contend.

= Can I roll back a bad edit? =

Yes — every `Document::save()` produces a WordPress revision. Use `list_elementor_revisions`, `get_elementor_revision`, and `restore_elementor_revision`. Restore itself creates a new revision of the pre-restore state, so it's undoable too.

= Is there a demo / read-only mode? =

Yes (v3.8.0+). Set `define('AGENTICWP_READONLY', true)` in wp-config.php, or `update_option('agenticwp_readonly', 'yes')`, and every mutation endpoint returns `{success: true, readonly_mode: true, would_save: {...}}` instead of writing. A true server-side dry-run.

= How does licensing work? =

Paid tier is license-gated via a self-hosted Cloudflare Worker + D1. The plugin sends `/api/verify` with `{key, site_url}`, worker auto-registers the site, returns `{valid, tier, latest_version, download_url}`. 7-day grace period on network failure.

= What about GDPR? =

AgenticWP is self-hosted — no customer data leaves your WordPress install. The licensing Worker only sees the **license key** and **site URL** for activation counting, nothing else. Optional: set `AGENTICWP_READONLY` for demo environments to be 100% certain.

== Changelog ==

= 3.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. Zero code changes — operational guidance for any AI agent driving AgenticWP.
* `MCP_VERSION` bumped to 3.9.5; `mcp-latest.json` updated with new SHA-256.

= 3.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.

= 3.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:
  * `list_revisions` — return `{id, date, author, content_bytes}` for each revision of a page/post, newest first.
  * `restore_revision` — fetch a revision's raw `post_content` via `?context=edit` and POST it back to the parent post. WP auto-snapshots the current state as a new revision before writing, so the restore is undoable.
* **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.

= 3.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.

= 3.9.1 =
* **Four more agent tools for high-friction tasks:**
  * `reorder_menu` — set the order of every item in a nav menu in one call. New endpoint `POST /agenticwp/v1/menus/{menu_id}/reorder` with `{ordered_item_ids: []}`. Saves N round-trips when inserting between siblings.
  * `list_menu_locations` — discover every registered theme menu location, whether it has a menu assigned, and item counts. New endpoint `GET /agenticwp/v1/menus/locations`. Removes the need to recall theme-specific locations like Astra's `mobile_menu`.
  * `css_has_selector` — substring-check a CSS selector string against astra-settings.custom-css. Run before `patch_css` to catch typos or verify a block was applied. Pure client-side.
  * `check_mcp_reachability` — probe plugin `/status` and the site root, report plugin/MCP version, latency, and a human hint for the failure mode (CF WAF 1010, plugin off, auth wrong, TLS, DNS). First call when tools start failing.
* `MCP_VERSION` bumped to 3.9.1; `mcp-latest.json` updated with new SHA-256.

= 3.9.0 =
* **Three productivity tools for agents:**
  * `patch_css` — atomic block-level patch of `astra-settings.custom-css`. Markers `/* === BEGIN:name === */ ... /* === END:name === */`. Modes: `replace_or_append` (default, idempotent), `append`, `replace`, `remove`. Server-side endpoint `POST /agenticwp/v1/css/patch` does the read-modify-write in one DB transaction — no more race windows or regex corruption.
  * `render_page` — fetch a public URL and return a structural snapshot (title, size, stylesheet count, inline-style bytes, optional selector-matched outerHTML). Verify what visitors actually receive without loading a browser.
  * `bulk_update_pages` — apply prepend/append/replace ops to many pages in one call. Per-entry errors don't abort the batch.
* `MCP_VERSION` bumped to 3.9.0; `mcp-latest.json` manifest updated with new SHA-256.

= 3.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 `agenticwp@racunalnicar.eu`. `.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.

= 3.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.Z details" link opens the info modal on the Changelog tab
* Added bundled `readme.txt`, `plugins_api` filter, enriched `site_transient_update_plugins` entry (icons, banners, tested, requires_php, upgrade_notice)

= 3.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

= 3.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

= 3.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

= 3.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`

= 3.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`

= 3.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

= 3.7.4 =
* Element ID collision detection on insert
* `diff_elementor_element` expanded: `structural` + `children` diffs for full-element replacement mode

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

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

= 3.7.0 =
* Field-report fixes: `get_elementor_page` size warning, `flush_cache` granular flags, `diff_elementor_element` dry-run tool, `insert_elementor_element`

= 3.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)

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

= 3.0.0 =
* Removed all frontend hooks — pure REST API plugin

== Upgrade Notice ==

= 3.8.0 =
**Recommended.** Observability tools (`get_debug_log`), SEO audit, read-only demo mode. Webhook security hardening on the licensing Worker. No breaking changes.

= 3.7.9 =
Required for the new MCP self-update flow (`check_mcp_update` / `apply_mcp_update`). Plugin + MCP now ship in lockstep.

= 3.7.7 =
Recommended — per-post write locks prevent race conditions when multiple agents edit concurrently. Fixes CPT support.

== Architecture ==

```
WordPress (plugin)  ←—— /wp-json/agenticwp/v1/* ——→  MCP server (stdio)  ←——→  AI agent
                                                          (Python)         (Claude, Cursor, ...)

License verification → agenticwp.racunalnicar.eu/api/verify (Cloudflare Worker + D1 + Stripe)
MCP self-update      → agenticwp.racunalnicar.eu/mcp-latest.json (static manifest + SHA-256)
```

== Credits ==

* Written by Sebastijan Bandur s.p.
* Pure-PHP implementation — no external dependencies beyond WordPress 6.0+ and PHP 8.0+
* License verification + auto-update via self-hosted Cloudflare Worker + D1
