@wootsup/yt-builder-mcp 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # @wootsup/yt-builder-mcp YT Builder MCP for YOOtheme Pro (unofficial)
1
+ # @wootsup/yt-builder-mcp. YT Builder MCP for YOOtheme Pro (unofficial)
2
2
 
3
- > Drive your page builder via MCP. Built for YOOtheme Pro 4.0+ connect **Claude Desktop**, **Cursor**, **Continue**, **Zed**, **Cline**, or **Roo Code** in one command.
3
+ > Drive your page builder via MCP. Built for YOOtheme Pro 4.0+ on **WordPress** and **Joomla 5/6**. Connect **Claude Desktop**, **Claude Code**, **Cursor**, **Zed**, **Continue**, **Cline**, **Roo Code**, **Codex CLI**, or **Gemini CLI** in one command.
4
4
 
5
5
  > Independent third-party project. YOOtheme® is a registered trademark of YOOtheme GmbH
6
6
  > ([yootheme.com](https://yootheme.com)). YT Builder MCP is built by WootsUp (getimo
@@ -8,20 +8,22 @@
8
8
  > The integration uses YOOtheme Pro's public extension points.
9
9
 
10
10
  **License:** MIT
11
- **Status:** Pre-alpha — under active development.
12
11
 
13
12
  ---
14
13
 
15
14
  ## Quick start
16
15
 
17
16
  ```bash
18
- # 1. Install the WordPress plugin (yt-builder-mcp).
19
- # See https://wootsup.com/products/yt-builder-mcp
20
-
21
- # 2. Generate a Bearer key in
22
- # wp-admin → Tools → "YT Builder MCP" → Bearer Keys → Generate New Key.
17
+ # 1. Install the host plugin for your CMS.
18
+ # WordPress: yt-builder-mcp-*.zip plugin.
19
+ # Joomla 5/6: pkg_ytbmcp-*.zip package (three sub-extensions in one go).
20
+ # See https://github.com/wootsup/yt-builder-mcp/releases
21
+
22
+ # 2. Generate a Bearer key.
23
+ # WordPress: wp-admin → Tools → "YT Builder MCP" → Bearer Keys.
24
+ # Joomla: Administrator → Components → "YT Builder MCP" → Bearer Keys.
23
25
  # Key format: ytb_(live|test)_<payloadB64Url>.<sigB64Url>
24
- # The key is shown ONCE copy it now; it cannot be recovered later.
26
+ # The key is shown ONCE. Copy it now; it cannot be recovered later.
25
27
 
26
28
  # 3. Run the wizard to configure your AI client(s):
27
29
  npx -y @wootsup/yt-builder-mcp setup
@@ -34,67 +36,66 @@ npx -y @wootsup/yt-builder-mcp install-skill
34
36
 
35
37
  The wizard prompts for:
36
38
 
37
- 1. Your WordPress site URL.
39
+ 1. Your site URL (WordPress or Joomla).
38
40
  2. The Bearer key you just generated.
39
41
  3. Which AI client(s) to configure (multi-select).
40
42
 
41
- It probes `/wp-json/yt-builder-mcp/v1/health` to confirm the
42
- plugin is reachable, `/etag` to validate the Bearer key, then writes
43
- the MCP server entry into each selected client's config file. After
44
- restart you should see the new tools prefixed with `yootheme_builder_*`.
43
+ It probes the host plugin's `/health` endpoint (`/wp-json/yt-builder-mcp/v1/health`
44
+ on WordPress, `/api/index.php/v1/yt-builder-mcp/health` on Joomla) to confirm
45
+ the plugin is reachable, then `/etag` to validate the Bearer key. After restart
46
+ you should see the new tools prefixed with `yootheme_builder_*`.
45
47
 
46
- ## Supported AI clients (6)
48
+ ## Supported AI clients
47
49
 
48
50
  The wizard auto-detects and configures the following clients:
49
51
 
50
52
  | Client | Config path | Notes |
51
53
  |--------|-------------|-------|
52
54
  | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) | DXT bundle also supported (see below) |
55
+ | Claude Code | `~/.claude.json` | |
53
56
  | Cursor | `~/.cursor/mcp.json` | |
54
- | Continue | `~/.continue/config.json` | |
55
57
  | Zed | `~/.config/zed/settings.json` | |
58
+ | Continue | `~/.continue/config.json` | |
56
59
  | Cline | `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` | VS Code extension |
57
60
  | Roo Code | same VS Code globalStorage path under `rooveterinaryinc.roo-cline` | VS Code extension |
61
+ | Codex CLI | `~/.codex/config.toml` | |
62
+ | Gemini CLI | `~/.gemini/settings.json` | |
58
63
 
59
- ## Tool surface gateway model
64
+ ## Tool surface (gateway model)
60
65
 
61
- The server registers **24 tools total**, but only **11 entries appear
62
- in `tools/list`** (well under Cursor's ~40-tool cap):
66
+ The server registers **26 domain tools + 1 gateway = 27 reachable** tools,
67
+ of which **20 are advertised in `tools/list`** (well under Cursor's ~40-tool
68
+ cap):
63
69
 
64
70
  - **2 direct top-level tools** (always in `tools/list`):
65
- `yootheme_builder_health`, `yootheme_builder_diagnose` — the
71
+ `yootheme_builder_health`, `yootheme_builder_diagnose`. The
66
72
  "the gateway itself might be broken" escape hatch.
67
- - **8 essential forwarded tools** (always in `tools/list`): the most-
68
- used reads and writes `pages_list`, `get_etag`, `element_list`,
69
- `element_add`, `element_update_settings`, `sources_list`,
70
- `element_types_list`, `inspect_multi_items_binding`.
71
- - **1 gateway tool** (`yootheme_builder_advanced`): exposes the
72
- remaining **13 advanced tools** behind a single entry. Call
73
- `yootheme_builder_advanced({ tool: "<name>" })` for discovery
74
- (returns the schema) or `({ tool, arguments })` to execute.
75
- - **13 advanced tools** dispatched via the gateway (page_get_layout,
76
- page_get_schema, page_save, page_publish, element_get,
77
- element_move, element_clone, element_delete,
78
- element_get_binding, element_bind_source, element_unbind_source,
79
- clean_implode_directives, element_type_get_schema).
80
-
81
- Total: **23 domain tools + 1 gateway = 24**. Surface: **11 entries
82
- in tools/list**. See `skills/yt-builder-mcp/SKILL.md` for the
83
- full catalog and the 5 canonical workflows.
84
-
85
- ## Tool catalogue — 23 domain tools
73
+ - **17 essential forwarded tools** (always in `tools/list`): the most-used
74
+ reads and writes (`pages_list`, `get_etag`, `element_list`, `element_add`,
75
+ `element_update_settings`, `sources_list`, `element_types_list`,
76
+ `inspect_multi_items_binding`, and the multi-site `sites_list` / `sites_test`,
77
+ among others).
78
+ - **1 gateway tool** (`yootheme_builder_advanced`): exposes the remaining
79
+ **7 advanced tools** behind a single entry. Call
80
+ `yootheme_builder_advanced({ tool: "<name>" })` for discovery (returns the
81
+ schema) or `({ tool, arguments })` to execute.
82
+
83
+ See `skills/yt-builder-mcp/SKILL.md` for the full catalog and canonical
84
+ workflows, and `docs/TOOL-CATALOG.md` for an auto-generated reference.
85
+
86
+ ## Tool catalogue
86
87
 
87
88
  | Domain | Count | Tools |
88
89
  |-------------|------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
89
90
  | Health | 2 | `health`, `diagnose` |
90
- | Pages | 6 | `pages_list`, `page_get_layout`, `page_get_schema`, `get_etag`, `page_save`, `page_publish` |
91
+ | Sites | 2 | `sites_list`, `sites_test` |
92
+ | Pages | 7 | `pages_list`, `page_get_layout`, `page_get_schema`, `template_summary`, `get_etag`, `page_save`, `page_publish` |
91
93
  | Elements | 7 | `element_list`, `element_get`, `element_add`, `element_update_settings`, `element_move`, `element_clone`, `element_delete` |
92
- | Sources | 4 | `sources_list`, `element_get_binding`, `element_bind_source`, `element_unbind_source` |
93
- | Multi-Items | 2 | `inspect_multi_items_binding`, `clean_implode_directives` |
94
- | Inspection | 2 | `element_types_list`, `element_type_get_schema` |
94
+ | Sources | 5 | `sources_list`, `element_get_binding`, `element_bind_source`, `element_unbind_source`, `inspect_multi_items_binding` |
95
+ | Inspection | 3 | `element_types_list`, `element_type_get_schema`, `clean_implode_directives` |
96
+ | Gateway | 1 | `advanced` |
95
97
 
96
- All tool names are prefixed with `yootheme_builder_` at the MCP
97
- server boundary.
98
+ All tool names are prefixed with `yootheme_builder_` at the MCP server boundary.
98
99
 
99
100
  ## Subcommands
100
101
 
@@ -105,7 +106,7 @@ yt-builder-mcp --version, -v Print package version.
105
106
  yt-builder-mcp --help, -h Show usage.
106
107
  ```
107
108
 
108
- ### `install-skill` bundled agent skill
109
+ ### `install-skill` (bundled agent skill)
109
110
 
110
111
  Copies the bundled `skills/yootheme-builder/` folder into
111
112
  `~/.claude/skills/` and appends a marker block to `~/AGENTS.md` so
@@ -121,10 +122,10 @@ The skill ships with the 5 canonical workflows (build hero, bind
121
122
  source, clone section, diagnose 401, add custom element) plus a
122
123
  23-tool auto-generated catalog appendix.
123
124
 
124
- ## DXT bundle Claude Desktop one-click install
125
+ ## DXT bundle (Claude Desktop one-click install)
125
126
 
126
127
  The repo includes a `manifest.json` and `scripts/build-dxt.js` that
127
- produces a `yt-builder-mcp.dxt` archive the
128
+ produces a `yt-builder-mcp.dxt` archive, the
128
129
  [Desktop Extension](https://github.com/anthropics/dxt) format used
129
130
  by Claude Desktop for one-click MCP installs. Build it from a
130
131
  source checkout:
@@ -145,8 +146,8 @@ When launched by an AI client (or directly):
145
146
  | Variable | Required? | Purpose |
146
147
  |----------|-----------|---------|
147
148
  | `YTB_MCP_SITE_URL` | Yes | Host CMS base URL (e.g. `https://example.com`). Works for BOTH WordPress and Joomla. Trailing slash is stripped. |
148
- | `YTB_MCP_WP_URL` | No (deprecated) | Legacy alias for `YTB_MCP_SITE_URL`; still honoured for pre-Wave-7 configurations. A non-fatal deprecation notice is written to stderr when this is used without `YTB_MCP_SITE_URL`. |
149
- | `YTB_MCP_BEARER_TOKEN` | Yes | Bearer key from wp-admin (WordPress: Tools → "YT Builder MCP") or Administrator → Components → "YT Builder MCP" (Joomla). Format-checked client-side: must match `ytb_(live\|test)_<payload>.<sig>`. Do **not** prepend `Bearer ` the MCP server adds it. |
149
+ | `YTB_MCP_WP_URL` | No (deprecated) | Legacy alias for `YTB_MCP_SITE_URL`. Still honoured for older WordPress-only configurations. A non-fatal deprecation notice is written to stderr when this is used without `YTB_MCP_SITE_URL`. |
150
+ | `YTB_MCP_BEARER_TOKEN` | Yes | Bearer key from wp-admin (WordPress: Tools → "YT Builder MCP") or Administrator → Components → "YT Builder MCP" (Joomla). Format-checked client-side: must match `ytb_(live\|test)_<payload>.<sig>`. Do **not** prepend `Bearer `. The MCP server adds it. |
150
151
  | `YTB_MCP_PLATFORM` | No | Explicit platform hint: `wordpress` or `joomla`. Set to `joomla` when `YTB_MCP_SITE_URL` is an origin-only Joomla URL (no `/api/index.php/` in the path). Defaults to URL-shape auto-detection. |
151
152
  | `YTB_MCP_TIMEOUT_MS` | No | REST timeout (default 15000). |
152
153
  | `YTB_MCP_TEST_MODE` | No | `1` skips the stdio loop (smoke tests). |
@@ -200,12 +201,12 @@ Supported flags:
200
201
  | Flag | Required? | Description |
201
202
  |------|-----------|-------------|
202
203
  | `--non-interactive` | Yes | Opt-in to non-interactive mode (no prompts). |
203
- | `--url <wp-url>` | Yes | WordPress base URL; trailing slash is stripped. |
204
- | `--token <bearer>` | Yes | Bearer key from wp-admin (do not prepend `Bearer `). |
205
- | `--client <id>` | Yes (≥1) | Client id; repeatable. Valid ids: `claude-desktop`, `cursor`, `zed`, `continue`, `cline`, `roo-code`. |
204
+ | `--url <site-url>` | Yes | Site base URL (WordPress or Joomla). Trailing slash is stripped. |
205
+ | `--token <bearer>` | Yes | Bearer key from the host plugin's admin UI (do not prepend `Bearer `). |
206
+ | `--client <id>` | Yes (≥1) | Client id; repeatable. Valid ids: `claude-desktop`, `claude-code`, `cursor`, `zed`, `continue`, `cline`, `roo-code`, `codex-cli`, `gemini-cli`. |
206
207
 
207
208
  The wizard still runs its plugin-health + auth probes and uses the
208
- exit codes documented in the table below so CI can branch on the
209
+ exit codes documented in the table below, so CI can branch on the
209
210
  exit code to detect whether the install actually succeeded.
210
211
 
211
212
  ## Exit codes (CLI)
@@ -225,7 +226,7 @@ The CLI returns POSIX-style exit codes for scripting / CI:
225
226
 
226
227
  ## Documentation
227
228
 
228
- - [SKILL.md (bundled agent skill)](./skills/yt-builder-mcp/SKILL.md) 5 canonical workflows, gateway model, tool catalog
229
+ - [SKILL.md (bundled agent skill)](./skills/yt-builder-mcp/SKILL.md): 5 canonical workflows, gateway model, tool catalog
229
230
  - [REST API Reference](https://github.com/wootsup/yt-builder-mcp/blob/main/docs/rest-api-reference.md)
230
231
  - [MCP Tool Reference](https://github.com/wootsup/yt-builder-mcp/blob/main/docs/mcp-tool-reference.md)
231
232
 
package/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "dxt_version": "0.1",
3
3
  "name": "@wootsup/yt-builder-mcp",
4
4
  "display_name": "YT Builder MCP for YOOtheme Pro (unofficial)",
5
- "version": "1.1.5",
5
+ "version": "1.1.6",
6
6
  "description": "Drive your YOOtheme Pro Page Builder programmatically from Claude, Cursor, Codex, Gemini and 5 other MCP-capable AI assistants — read layouts, edit settings, add elements, bind dynamic sources. Works on WordPress and Joomla 5/6. Built for YOOtheme Pro 4.0+. Independent third-party project, not affiliated with YOOtheme GmbH.",
7
7
  "long_description": "YT Builder MCP gives AI assistants a typed, scoped, and idempotent surface for your YOOtheme Pro Page Builder, on either WordPress or Joomla 5/6. Tools cover page discovery, layout inspection, element CRUD, source binding, and diagnostics. Bearer auth, optimistic locking via ETag, scope hierarchy (read < write < admin), and structured-error responses keep the agent safe and the workflow correct on first try. Independent third-party project — YOOtheme® is a registered trademark of YOOtheme GmbH (yootheme.com); YT Builder MCP is built by WootsUp (getimo productions) and is not affiliated with, endorsed by, or sponsored by YOOtheme.",
8
8
  "icon": "icon.png",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wootsup/yt-builder-mcp",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "type": "module",
5
5
  "description": "YT Builder MCP — drive your page builder from Claude, Cursor, Codex, Gemini and 5 other MCP-capable AI assistants. Built for YOOtheme Pro 4.0+. Independent third-party project, not affiliated with YOOtheme GmbH.",
6
6
  "license": "MIT",
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: yt-builder-mcp
3
- description: Drive the YOOtheme Pro Page Builder on WordPress or Joomla 5/6 discover pages, inspect layouts, add/move/clone/delete elements, bind dynamic sources, diagnose 401/403 auth failures. Use when the user works with a YOOtheme Pro site via the YT Builder MCP server.
3
+ description: Drive the YOOtheme Pro Page Builder on WordPress or Joomla 5/6. Discover pages, inspect layouts, add/move/clone/delete elements, bind dynamic sources, diagnose 401/403 auth failures. Use when the user works with a YOOtheme Pro site via the YT Builder MCP server.
4
4
  ---
5
5
 
6
- # YT Builder MCP for YOOtheme Pro (unofficial) Skill
6
+ # YT Builder MCP for YOOtheme Pro (unofficial). Skill
7
7
 
8
8
  > Independent third-party project. YOOtheme® is a registered trademark of YOOtheme GmbH
9
9
  > ([yootheme.com](https://yootheme.com)). YT Builder MCP is built by WootsUp (getimo
@@ -23,34 +23,34 @@ catalogued tool stays fully reachable.
23
23
 
24
24
  The user invokes you through Claude Desktop, Cursor, Zed, Continue, Cline,
25
25
  Roo Code, Claude Code, Codex CLI or any other MCP-aware AI client. Setup is
26
- **cross-platform** the same MCP server speaks to the same WordPress *or*
26
+ **cross-platform**. The same MCP server speaks to the same WordPress *or*
27
27
  Joomla 5/6 host plugin:
28
28
 
29
29
  1. The user installs the host plugin for their CMS:
30
- - **WordPress** install the `yt-builder-mcp` plugin (downloadable from the
30
+ - **WordPress**. Install the `yt-builder-mcp` plugin (downloadable from the
31
31
  [GitHub repository](https://github.com/wootsup/yt-builder-mcp)) and generate
32
32
  a Bearer key in **wp-admin → Tools → "YT Builder MCP" → Bearer Keys**.
33
- - **Joomla 5/6** install the `yt-builder-mcp` package (downloadable from the
33
+ - **Joomla 5/6**. Install the `yt-builder-mcp` package (downloadable from the
34
34
  [GitHub repository](https://github.com/wootsup/yt-builder-mcp)) and generate
35
35
  a Bearer key in **Components → YT Builder MCP → Bearer Keys**. The package
36
36
  installs three sub-extensions (system plugin, webservices plugin, component).
37
37
  2. The user runs `npx -y @wootsup/yt-builder-mcp setup` once; the wizard probes
38
38
  the host plugin, validates the key, and writes the MCP server entry into every
39
- selected AI client's config file. (Wizard prompts include a platform hint
40
- `auto` works for most cases; set it to `joomla` explicitly when the site URL
39
+ selected AI client's config file. (Wizard prompts include a platform hint;
40
+ `auto` works for most cases. Set it to `joomla` explicitly when the site URL
41
41
  has no `/joomla` segment.)
42
42
  3. The user restarts their AI client. The server is now visible.
43
43
  4. The user asks for a YOOtheme task (build, audit, change, diagnose).
44
44
 
45
- ### Two picker entries activate both
45
+ ### Two picker entries (activate both)
46
46
 
47
47
  Some clients (notably Claude Desktop with the `.dxt` bundle) expose **two**
48
48
  entries when the user types "YT Builder MCP" into the picker:
49
49
 
50
- - **`YT Builder MCP for YOOtheme Pro (unofficial)`** the MCP **server**.
50
+ - **`YT Builder MCP for YOOtheme Pro (unofficial)`**: the MCP **server**.
51
51
  Provides the 20 first-class tools (17 essential, 2 direct, 1 gateway).
52
52
  The `yootheme_builder_advanced` gateway routes 7 additional tools.
53
- - **`Von YT Builder MCP for YOOtheme Pro`** the bundled **skill** (this
53
+ - **`Von YT Builder MCP for YOOtheme Pro`**: the bundled **skill** (this
54
54
  document). Gives the agent the workflow knowledge needed to drive those
55
55
  tools correctly on first try.
56
56
 
@@ -58,7 +58,7 @@ entries when the user types "YT Builder MCP" into the picker:
58
58
  typed tools but no narrative guidance; the skill alone has no tools to call.
59
59
 
60
60
  When the user asks a YOOtheme-related question, **always start with
61
- `yootheme_builder_health`** it confirms the host plugin is reachable and (when
61
+ `yootheme_builder_health`**. It confirms the host plugin is reachable and (when
62
62
  the Bearer key is valid) returns the **plugin version, YOOtheme version, WordPress
63
63
  or Joomla version, PHP version, and the site_url + home_url of the connected
64
64
  site**. The site URL is how you know *which* site the agent is currently driving;
@@ -71,22 +71,22 @@ If a tool returns `401 Unauthorized` or `403 Forbidden`, jump straight to
71
71
 
72
72
  The server exposes:
73
73
 
74
- - **2 direct top-level tools** always callable, always in `tools/list`:
74
+ - **2 direct top-level tools**, always callable, always in `tools/list`:
75
75
  `yootheme_builder_health` and `yootheme_builder_diagnose`. These are
76
76
  the "the gateway itself might be broken" escape hatch.
77
- - **17 essential forwarded tools** common reads + the most-used writes
77
+ - **17 essential forwarded tools**: common reads + the most-used writes
78
78
  (pages_list, get_etag, element_list / add / update_settings / get / move /
79
79
  clone / delete, page_get_layout, sources_list, element_types_list,
80
80
  element_type_get_schema, template_summary, inspect_multi_items_binding,
81
81
  sites_list, sites_test). Always advertised in `tools/list` so AI clients
82
82
  see them first-class.
83
- - **7 advanced captured tools** everything else (page_save, page_publish,
83
+ - **7 advanced captured tools**: everything else (page_save, page_publish,
84
84
  page_get_schema, element_get_binding, element_bind_source,
85
85
  element_unbind_source, clean_implode_directives). Reachable through one
86
86
  gateway tool: `yootheme_builder_advanced({ tool: "<name>", input: { ... } })`.
87
- - **1 gateway tool** `yootheme_builder_advanced`.
87
+ - **1 gateway tool**: `yootheme_builder_advanced`.
88
88
 
89
- `tools/list` therefore advertises 20 names (17 + 2 + 1) — that's 17 L1
89
+ `tools/list` therefore advertises 20 names (17 + 2 + 1). That's 17 L1
90
90
  essentials + 2 L3 direct + 1 gateway. The total callable surface is 27
91
91
  (20 advertised + 7 advanced reachable through the gateway). If the AI
92
92
  client reports "tool not found", you are almost certainly calling an
@@ -110,7 +110,7 @@ guess where the agent is pointing:
110
110
  `frontend_url_template` (with placeholders the user fills in).
111
111
 
112
112
  Treat `frontend_url: null` as "host plugin could not resolve a public URL for
113
- this template" surface that honestly rather than fabricating one.
113
+ this template". Surface that honestly rather than fabricating one.
114
114
 
115
115
  ## Scopes (Bearer key permissions)
116
116
 
@@ -127,7 +127,7 @@ ask the user to regenerate the key with a higher scope **before** retrying.
127
127
  Do not loop on auth errors.
128
128
 
129
129
  > **Joomla note.** On the Joomla API surface (`com_api`), the Bearer token's
130
- > scope is the **sole** authority the L2 article-write `core.edit` ACL gate
130
+ > scope is the **sole** authority. The L2 article-write `core.edit` ACL gate
131
131
  > was intentionally removed (see ADR at https://github.com/wootsup/yt-builder-mcp/blob/main/docs/adr/2026-05-24-l2-bearer-as-authority.md).
132
132
  > Joomla ACL still governs the admin component (`com_ytbmcp`). On WordPress,
133
133
  > capabilities like `manage_options` gate the admin settings page only; the
@@ -298,33 +298,33 @@ for a focused diagnosis without touching the others.
298
298
  **Goal:** Add a fresh hero section (heading + sub-heading + CTA button)
299
299
  to an existing page.
300
300
 
301
- **Canonical tool-call sequence (real parameter names snake_case):**
301
+ **Canonical tool-call sequence (real parameter names, snake_case):**
302
302
 
303
- 1. `yootheme_builder_health` confirm host plugin reachable; note plugin
303
+ 1. `yootheme_builder_health`: confirm host plugin reachable. Note plugin
304
304
  version and `site_url` (some element types are version-gated; surface
305
305
  the site URL back to the user).
306
- 2. `yootheme_builder_pages_list({ fields: ["id", "label"] })` find
306
+ 2. `yootheme_builder_pages_list({ fields: ["id", "label"] })`: find
307
307
  the target template. Returns `[{ id, label, ... }]`. If the user
308
308
  named a specific page, match on `label` (exact then fuzzy).
309
- 3. `yootheme_builder_get_etag()` fetch the current top-level
309
+ 3. `yootheme_builder_get_etag()`: fetch the current top-level
310
310
  optimistic-lock ETag. Every write tool requires it via `etag`.
311
- 4. `yootheme_builder_element_add({ template_id: "<id>", parent_path: "", element_type: "section", props: { background: "primary" }, etag: "<etag>" })`
312
- append a new section at the template root (`parent_path: ""`).
311
+ 4. `yootheme_builder_element_add({ template_id: "<id>", parent_path: "", element_type: "section", props: { background: "primary" }, etag: "<etag>" })`:
312
+ append a new section at the template root (`parent_path: ""`).
313
313
  Returns `{ path: "/0/children/N", etag: "<fresh>" }`.
314
- 5. `yootheme_builder_element_add({ template_id, parent_path: "<section-path>", element_type: "row", etag: "<fresh-etag>" })`
315
- add a row inside the section. Use the etag returned by the
316
- previous write etags rotate every mutation.
317
- 6. `yootheme_builder_element_add({ template_id, parent_path: "<row-path>", element_type: "headline", props: { content: "<h1 text>" }, etag })`
318
- add a headline.
319
- 7. `yootheme_builder_element_add({ template_id, parent_path: "<row-path>", element_type: "text", props: { content: "<sub text>" }, etag })`
320
- add a text element.
321
- 8. `yootheme_builder_element_add({ template_id, parent_path: "<row-path>", element_type: "button", props: { content: "<cta>", link: "<url>" }, etag })`
322
- add the CTA button.
323
- 9. `yootheme_builder_advanced({ tool: "yootheme_builder_page_save", input: { template_id, etag } })`
324
- persist the working copy (visible in YOOtheme Customizer preview).
314
+ 5. `yootheme_builder_element_add({ template_id, parent_path: "<section-path>", element_type: "row", etag: "<fresh-etag>" })`:
315
+ add a row inside the section. Use the etag returned by the
316
+ previous write (etags rotate every mutation).
317
+ 6. `yootheme_builder_element_add({ template_id, parent_path: "<row-path>", element_type: "headline", props: { content: "<h1 text>" }, etag })`:
318
+ add a headline.
319
+ 7. `yootheme_builder_element_add({ template_id, parent_path: "<row-path>", element_type: "text", props: { content: "<sub text>" }, etag })`:
320
+ add a text element.
321
+ 8. `yootheme_builder_element_add({ template_id, parent_path: "<row-path>", element_type: "button", props: { content: "<cta>", link: "<url>" }, etag })`:
322
+ add the CTA button.
323
+ 9. `yootheme_builder_advanced({ tool: "yootheme_builder_page_save", input: { template_id, etag } })`:
324
+ persist the working copy (visible in YOOtheme Customizer preview).
325
325
  `page_save` is an advanced tool; call it through the gateway.
326
- 10. `yootheme_builder_advanced({ tool: "yootheme_builder_page_publish", input: { template_id, etag } })`
327
- make the changes live on the front-end. Also an advanced tool.
326
+ 10. `yootheme_builder_advanced({ tool: "yootheme_builder_page_publish", input: { template_id, etag } })`:
327
+ make the changes live on the front-end. Also an advanced tool.
328
328
 
329
329
  **Common pitfalls:**
330
330
 
@@ -340,19 +340,19 @@ to an existing page.
340
340
  row in between. The server returns a structured error with a
341
341
  human-readable hint when you skip the row.
342
342
  - **Saving without publishing.** `page_save` is the equivalent of the
343
- YOOtheme Customizer "Save" button content lives in the staging
343
+ YOOtheme Customizer "Save" button. Content lives in the staging
344
344
  copy. Visitors see nothing until `page_publish`.
345
345
  - **Reusing a stale etag across many writes.** Every write returns a
346
- fresh etag in the response. Pass THAT etag into the next write
347
- don't hold the one from the original `get_etag` call.
346
+ fresh etag in the response. Pass THAT etag into the next write.
347
+ Don't hold the one from the original `get_etag` call.
348
348
  - **Calling page_save / page_publish by name.** Both are advanced
349
- (L2) tools call them through `yootheme_builder_advanced({ tool, input })`,
349
+ (L2) tools. Call them through `yootheme_builder_advanced({ tool, input })`,
350
350
  not directly. The first sign you forgot is "tool not found".
351
351
 
352
352
  **Worked example (tool-call snippet):**
353
353
 
354
354
  ```jsonc
355
- // Step 4 add the section. parent_path: "" means template root.
355
+ // Step 4. Add the section. parent_path: "" means template root.
356
356
  yootheme_builder_element_add({
357
357
  template_id: "home",
358
358
  parent_path: "",
@@ -363,14 +363,14 @@ yootheme_builder_element_add({
363
363
  // Response: { path: "/0/children/3", etag: "def456" }
364
364
  // → next call uses etag "def456"
365
365
 
366
- // Step 9 page_save is L2; call via the gateway.
366
+ // Step 9. page_save is L2; call via the gateway.
367
367
  yootheme_builder_advanced({
368
368
  tool: "yootheme_builder_page_save",
369
369
  input: { template_id: "home", etag: "<latest>" }
370
370
  })
371
371
  ```
372
372
 
373
- **Edge case:** YOOtheme allows nested sections (rare) if the user
373
+ **Edge case:** YOOtheme allows nested sections (rare). If the user
374
374
  asks for a "card grid inside a hero", you still need the
375
375
  `section → row → column → grid` hierarchy, even when the parent
376
376
  section sits inside another section.
@@ -389,27 +389,27 @@ section as the last child of the template root.
389
389
  Source from API Mapper or the built-in YOOtheme Sources system so it
390
390
  renders dynamic items.
391
391
 
392
- **Canonical tool-call sequence (real parameter names snake_case):**
392
+ **Canonical tool-call sequence (real parameter names, snake_case):**
393
393
 
394
- 1. `yootheme_builder_health` confirm host plugin reachable.
394
+ 1. `yootheme_builder_health`: confirm host plugin reachable.
395
395
  2. `yootheme_builder_pages_list({ fields: ["id", "label"] })` and
396
- `yootheme_builder_page_get_layout({ template_id: "<id>", flat: false })`
397
- locate the target Grid. Note its JSON-Pointer `path` (e.g.
396
+ `yootheme_builder_page_get_layout({ template_id: "<id>", flat: false })`:
397
+ locate the target Grid. Note its JSON-Pointer `path` (e.g.
398
398
  `/0/children/2/children/0`).
399
- 3. `yootheme_builder_element_get({ template_id, element_path })` —
400
- fetch the Grid's current props so you can preserve them; binding
399
+ 3. `yootheme_builder_element_get({ template_id, element_path })`:
400
+ fetch the Grid's current props so you can preserve them. Binding
401
401
  sets `props.source` and leaves the rest alone.
402
- 4. `yootheme_builder_sources_list()` enumerate available Sources.
402
+ 4. `yootheme_builder_sources_list()`: enumerate available Sources.
403
403
  Each returns `{ name, label, origin, kind }`. Pick the one the
404
404
  user asked for.
405
405
  5. `yootheme_builder_advanced({ tool: "yootheme_builder_element_get_binding", input: { template_id, element_path } })`
406
- check whether the Grid is already bound (idempotency: skip step
406
+ check whether the Grid is already bound (idempotency: skip step
407
407
  7 if `source_name` already matches the user's intent).
408
- `element_get_binding` is an advanced (L2) tool call via the gateway.
409
- 6. `yootheme_builder_get_etag()` fetch the optimistic-lock etag for
408
+ `element_get_binding` is an advanced (L2) tool. Call via the gateway.
409
+ 6. `yootheme_builder_get_etag()`: fetch the optimistic-lock etag for
410
410
  the upcoming mutation.
411
411
  7. `yootheme_builder_advanced({ tool: "yootheme_builder_element_bind_source", input: { template_id, element_path, source_name: "<name>", etag: "<etag>" } })`
412
- apply the binding. Returns `{ path, etag, has_binding: true }`.
412
+ applies the binding. Returns `{ path, etag, has_binding: true }`.
413
413
  Pass `source_id: "<origin>:<name>"` as well **only** when two
414
414
  plugins register a source with the same `source_name` (the server
415
415
  surfaces the ambiguity as an elicitation prompt; if the host
@@ -423,7 +423,7 @@ renders dynamic items.
423
423
  - **Inventing `fieldMap`.** The bind tool's schema is just
424
424
  `template_id`, `element_path`, `source_name`, optional `source_id`,
425
425
  `etag`. Field mapping happens inside YOOtheme at render time based
426
- on the element's own field bindings not via an MCP parameter.
426
+ on the element's own field bindings, not via an MCP parameter.
427
427
  - **Wrong parameter names.** Use `template_id` (not `pageId`),
428
428
  `element_path` (not `path`), `source_name` (not `sourceName`),
429
429
  `etag` (not `ifMatch`).
@@ -431,21 +431,22 @@ renders dynamic items.
431
431
  they're PUBLISHED in API Mapper (not just saved). If
432
432
  `yootheme_builder_sources_list` returns no match for the name the
433
433
  user typed, send the user to API Mapper to publish it.
434
- - **Binding non-list elements.** Only multi-item element types (Grid,
435
- List, Switcher, Slider, Slideshow, Carousel, Map) accept a source
436
- binding. Binding a single-item element like Headline returns a
437
- structured `validation` error.
434
+ - **Binding non-list elements.** Only multi-item element types
435
+ (Accordion, Button, Description List, Gallery, Grid, List, Map, Nav,
436
+ Overlay-Slider, Panel-Slider, Popover, Slideshow, Social, Subnav,
437
+ Switcher, Table) accept a source binding. Binding a single-item
438
+ element like Headline returns a structured `validation` error.
438
439
  - **Forgetting `etag`.** Every write requires the optimistic-lock
439
440
  etag. On `412 Precondition Failed` re-fetch via
440
441
  `yootheme_builder_get_etag` and retry.
441
442
  - **Calling bind/unbind directly.** Both `element_bind_source` and
442
- `element_get_binding` are L2 advanced wrap in
443
+ `element_get_binding` are L2 advanced. Wrap in
443
444
  `yootheme_builder_advanced({ tool, input })`.
444
445
 
445
446
  **Worked example (tool-call snippet):**
446
447
 
447
448
  ```jsonc
448
- // Step 7 bind a Posts source onto a Grid element via the gateway.
449
+ // Step 7. Bind a Posts source onto a Grid element via the gateway.
449
450
  yootheme_builder_advanced({
450
451
  tool: "yootheme_builder_element_bind_source",
451
452
  input: {
@@ -468,7 +469,7 @@ yootheme_builder_advanced({
468
469
  **Edge case:** A Source can render zero items at runtime (e.g. empty
469
470
  search filter). The bind call still succeeds; the front-end Grid just
470
471
  shows the YOOtheme "no items" placeholder. Don't treat empty render
471
- as a binding failure verify by re-reading
472
+ as a binding failure. Verify by re-reading
472
473
  `yootheme_builder_element_get_binding` through the gateway.
473
474
 
474
475
  **Success criterion:** After publish, the Grid on the front-end shows
@@ -483,11 +484,11 @@ field-value spot-check). `yootheme_builder_element_get_binding`
483
484
  **Goal:** Duplicate a section inside the SAME template and tweak the
484
485
  copy. Common variants: A/B-style hero, repeated CTA blocks, mirroring
485
486
  a row layout. (Cross-template duplication is **not** supported by
486
- `element_clone` see "Important scope note" below.)
487
+ `element_clone`. See "Important scope note" below.)
487
488
 
488
489
  **Important scope note:** `yootheme_builder_element_clone` is
489
490
  **sibling-only and intra-template**. Its real schema is
490
- `{ template_id, element_path, etag }` there is **no** `destPageId`
491
+ `{ template_id, element_path, etag }`. There is **no** `destPageId`
491
492
  or `destParentPath`. The cloned element lands at the same parent,
492
493
  right after the source. To move the clone elsewhere in the SAME
493
494
  template, call `yootheme_builder_element_move` afterwards. To
@@ -495,23 +496,23 @@ duplicate into a DIFFERENT template, flag to the user that
495
496
  cross-template clone is not currently supported and suggest a
496
497
  CMS-level template duplication (in wp-admin or Joomla administrator).
497
498
 
498
- **Canonical tool-call sequence (real parameter names snake_case):**
499
+ **Canonical tool-call sequence (real parameter names, snake_case):**
499
500
 
500
- 1. `yootheme_builder_health` confirm host plugin reachable.
501
- 2. `yootheme_builder_pages_list({ fields: ["id", "label"] })` —
501
+ 1. `yootheme_builder_health`: confirm host plugin reachable.
502
+ 2. `yootheme_builder_pages_list({ fields: ["id", "label"] })`:
502
503
  locate the template by `label`. Note its `id`.
503
504
  3. `yootheme_builder_advanced({ tool: "yootheme_builder_page_get_schema", input: { template_id } })`
504
- flat schema view (lighter than `page_get_layout`) showing every
505
+ returns a flat schema view (lighter than `page_get_layout`) showing every
505
506
  element path + type. Pick the JSON-Pointer path of the section
506
507
  to clone. `page_get_schema` is L2; call via the gateway.
507
- 4. `yootheme_builder_get_etag()` fetch the optimistic-lock etag.
508
+ 4. `yootheme_builder_get_etag()`: fetch the optimistic-lock etag.
508
509
  5. `yootheme_builder_element_clone({ template_id, element_path: "<src-path>", etag: "<etag>" })`
509
- clone as sibling. Returns `{ path: "<new-path>", etag: "<fresh>" }`.
510
+ clones as sibling. Returns `{ path: "<new-path>", etag: "<fresh>" }`.
510
511
  The new path is at the same parent, immediately after the source.
511
512
  6. (Optional) `yootheme_builder_element_move({ template_id, element_path: "<new-path>", to_parent_path: "<other-parent>", to_index: 0, etag: "<fresh>" })`
512
- re-parent the clone within the same template if needed.
513
+ re-parents the clone within the same template if needed.
513
514
  7. `yootheme_builder_element_update_settings({ template_id, element_path: "<final-path>", props: { ... }, etag: "<fresh>" })`
514
- replace the `props` on the clone. **Existing props NOT in the
515
+ replaces the `props` on the clone. **Existing props NOT in the
515
516
  request are removed** (update_settings is a full replace by default;
516
517
  pass `merge: true` to apply a server-side deep-merge instead).
517
518
  Read the current props first via `yootheme_builder_element_get`
@@ -530,7 +531,7 @@ CMS-level template duplication (in wp-admin or Joomla administrator).
530
531
  first if you only want to tweak a subset and prefer not to use merge.
531
532
  - **Clone-then-update path drift.** The clone returns a path that's
532
533
  correct at the moment of the call. If you fire off many ops in
533
- parallel, a concurrent edit may shift indices refresh via
534
+ parallel, a concurrent edit may shift indices. Refresh via
534
535
  `get_etag` + `page_get_schema` (via gateway) between independent batches.
535
536
  - **Cloning a bound element keeps the binding.** `element_clone`
536
537
  copies the entire element including `props.source`. If the user
@@ -543,7 +544,7 @@ CMS-level template duplication (in wp-admin or Joomla administrator).
543
544
  **Worked example (tool-call snippet):**
544
545
 
545
546
  ```jsonc
546
- // Step 5 clone the section element as a sibling.
547
+ // Step 5. Clone the section element as a sibling.
547
548
  yootheme_builder_element_clone({
548
549
  template_id: "home",
549
550
  element_path: "/0/children/2", // the hero section to duplicate
@@ -551,7 +552,7 @@ yootheme_builder_element_clone({
551
552
  })
552
553
  // Response: { path: "/0/children/3", etag: "def456" }
553
554
 
554
- // Step 7 tweak the clone (replace props entirely, or pass merge: true).
555
+ // Step 7. Tweak the clone (replace props entirely, or pass merge: true).
555
556
  const current = yootheme_builder_element_get({
556
557
  template_id: "home",
557
558
  element_path: "/0/children/3",
@@ -580,16 +581,16 @@ shows the new section at the cloned path with the user's tweaks reflected in
580
581
  ## Workflow 4: Diagnose a 401 / 403 / auth failure
581
582
 
582
583
  **Goal:** Recover from `401 Unauthorized` or `403 Forbidden` without
583
- guessing and without rotating the user's key unnecessarily.
584
+ guessing, and without rotating the user's key unnecessarily.
584
585
 
585
586
  **Canonical tool-call sequence:**
586
587
 
587
- 1. `yootheme_builder_diagnose` single probe that hits `/health` (no
588
+ 1. `yootheme_builder_diagnose` is a single probe that hits `/health` (no
588
589
  auth) and then `/etag` (Bearer auth). Returns
589
590
  `{ plugin_reachable, plugin_version, yootheme_loaded, yootheme_version,
590
591
  endpoint_count, bearer_valid, bearer_error?, site_url?, home_url?,
591
592
  summary? }`. Call this **before** any other tool when you see
592
- auth errors. (Takes no arguments the schema is `{}`.)
593
+ auth errors. (Takes no arguments. The schema is `{}`.)
593
594
  2. **Interpret the result:**
594
595
  - `plugin_reachable: false` → the WordPress / Joomla install is down
595
596
  OR the host plugin is deactivated. Send the user to **wp-admin →
@@ -614,7 +615,7 @@ guessing — and without rotating the user's key unnecessarily.
614
615
  - WordPress: "wp-admin → Tools → YT Builder MCP → Bearer Keys."
615
616
  Joomla: "Components → YT Builder MCP → Bearer Keys."
616
617
  - "Click 'Generate New Key', pick the scope (admin for full access)."
617
- - "Copy the key — it's shown ONCE; you cannot recover it later."
618
+ - "Copy the key. It's shown ONCE; you cannot recover it later."
618
619
  - "Update your AI client config: replace `YTB_MCP_BEARER_TOKEN`
619
620
  with the new key. The fastest way is to re-run
620
621
  `npx -y @wootsup/yt-builder-mcp setup`."
@@ -626,7 +627,7 @@ guessing — and without rotating the user's key unnecessarily.
626
627
  **Common pitfalls:**
627
628
 
628
629
  - **Treating 401 as a network error.** A network error has no HTTP
629
- status — it's a TCP/TLS / DNS failure. 401 means the server
630
+ status. It's a TCP/TLS / DNS failure. 401 means the server
630
631
  responded "I do not accept this key", which is fundamentally a
631
632
  config problem.
632
633
  - **Stripping the `Bearer ` prefix.** The MCP server adds it
@@ -639,12 +640,12 @@ guessing — and without rotating the user's key unnecessarily.
639
640
  - **Confusing 401 with 403.** 401 = "I don't recognise this key"
640
641
  (rotate). 403 = "I recognise the key but it lacks the required
641
642
  scope" (regenerate with higher scope). Different error codes,
642
- different recovery never collapse them into one branch.
643
+ different recovery. Never collapse them into one branch.
643
644
 
644
645
  **Worked example (tool-call snippet):**
645
646
 
646
647
  ```jsonc
647
- // First never retry blindly. Call diagnose (no args).
648
+ // First. Never retry blindly. Call diagnose (no args).
648
649
  yootheme_builder_diagnose({})
649
650
  // Response shape:
650
651
  // {
@@ -662,7 +663,7 @@ yootheme_builder_diagnose({})
662
663
  ```
663
664
 
664
665
  **Edge case:** `plugin_reachable: true` but `yootheme_loaded: false`
665
- the user installed the MCP host plugin but YOOtheme Pro itself
666
+ means the user installed the MCP host plugin but YOOtheme Pro itself
666
667
  isn't active. The MCP server still answers, but every tool that
667
668
  touches the YOOtheme layout returns an empty/error response. Surface
668
669
  the mismatch ("YOOtheme Pro is not active on this install") instead
@@ -682,28 +683,28 @@ YOOtheme install (built-ins + YOOtheme Pro + YOOessentials + child
682
683
  theme + plugin-contributed elements), pick the right one, and place
683
684
  an instance with a sensible default props payload.
684
685
 
685
- **Canonical tool-call sequence (real parameter names snake_case):**
686
+ **Canonical tool-call sequence (real parameter names, snake_case):**
686
687
 
687
- 1. `yootheme_builder_health` note the YOOtheme version; custom
688
+ 1. `yootheme_builder_health`: note the YOOtheme version. Custom
688
689
  elements often require a minimum YOOtheme major.
689
690
  2. `yootheme_builder_element_types_list({ fields: ["name", "label", "origin"] })`
690
- narrow the catalogue with sparse-fields. Returns rows like
691
+ narrows the catalogue with sparse-fields. Returns rows like
691
692
  `{ name: "headline", label: "Headline", origin: "core", ... }`.
692
693
  3. `yootheme_builder_element_type_get_schema({ type_name: "<picked>" })`
693
- fetch the prop schema for the chosen type. Returns the field
694
+ fetches the prop schema for the chosen type. Returns the field
694
695
  definitions you can pass via `props`. Note: the parameter is
695
696
  `type_name`, not `name`.
696
697
  4. `yootheme_builder_pages_list({ fields: ["id", "label"] })` and
697
698
  `yootheme_builder_page_get_layout({ template_id, flat: false })`
698
- locate the `parent_path` (JSON-Pointer) where the new element
699
+ locate the `parent_path` (JSON-Pointer) where the new element
699
700
  should land.
700
- 5. `yootheme_builder_get_etag()` fetch the optimistic-lock etag.
701
+ 5. `yootheme_builder_get_etag()`: fetch the optimistic-lock etag.
701
702
  6. `yootheme_builder_element_add({ template_id, parent_path: "<path>", element_type: "<picked-name>", props: { ... }, etag })`
702
- the server validates `props` against the type schema and
703
+ asks the server to validate `props` against the type schema and
703
704
  returns a structured `validation` error with a per-field issue
704
705
  list if anything is missing or malformed.
705
706
  7. (Optional) `yootheme_builder_element_update_settings({ template_id, element_path: "<new-path>", props: { ... }, etag })`
706
- iterate on the props. **Note: this REPLACES `props` entirely by
707
+ iterates on the props. **Note: this REPLACES `props` entirely by
707
708
  default; pass `merge: true` for a server-side deep-merge.** When
708
709
  replacing, include every key you want to keep.
709
710
  8. `yootheme_builder_advanced({ tool: "yootheme_builder_page_save", input: { template_id, etag } })`
@@ -727,7 +728,7 @@ an instance with a sensible default props payload.
727
728
  element may not register a prop schema. In that case
728
729
  `yootheme_builder_element_type_get_schema` returns an empty/sparse
729
730
  schema and the server accepts arbitrary `props`. Don't assume "no
730
- schema = no required fields" read the third-party element's
731
+ schema = no required fields". Read the third-party element's
731
732
  docs.
732
733
  - **Type name vs. label confusion.** The `name` field on the
733
734
  catalogue row is the machine identifier (e.g. `pro_slider`); the
@@ -740,17 +741,17 @@ an instance with a sensible default props payload.
740
741
  **Worked example (tool-call snippet):**
741
742
 
742
743
  ```jsonc
743
- // Step 2 narrow the catalogue with sparse-fields to save tokens.
744
+ // Step 2. Narrow the catalogue with sparse-fields to save tokens.
744
745
  yootheme_builder_element_types_list({
745
746
  fields: ["name", "label", "origin"]
746
747
  })
747
748
  // Rows: [{ name: "headline", label: "Headline", origin: "core" }, ...]
748
749
 
749
- // Step 3 fetch the schema (note: type_name, not name).
750
+ // Step 3. Fetch the schema (note: type_name, not name).
750
751
  yootheme_builder_element_type_get_schema({ type_name: "headline" })
751
752
  // Returns the field definitions for the headline's `props`.
752
753
 
753
- // Step 6 place the element.
754
+ // Step 6. Place the element.
754
755
  yootheme_builder_element_add({
755
756
  template_id: "home",
756
757
  parent_path: "/0/children/2", // row inside section
@@ -764,7 +765,7 @@ yootheme_builder_element_add({
764
765
  **Edge case:** A child theme can override a built-in element's
765
766
  schema in PHP. The `origin` field will read `child_theme` instead
766
767
  of `core`. If you see surprising required keys, that's the override
767
- talking surface this to the user so they know their theme is
768
+ talking. Surface this to the user so they know their theme is
768
769
  customising element defaults.
769
770
 
770
771
  **Success criterion:** After publish, the front-end shows the new
@@ -782,7 +783,7 @@ and the props payload you passed.
782
783
  re-creating.
783
784
  - **Delete an element**: use `yootheme_builder_element_delete({
784
785
  template_id, element_path, etag, confirm: true })`.
785
- Elicitation-aware confirms via the AI client prompt before
786
+ Elicitation-aware. Confirms via the AI client prompt before
786
787
  destroying state when `confirm` is omitted. On hosts without
787
788
  elicitation, it returns a preview-with-confirm-required response;
788
789
  call again with `confirm: true`.
@@ -793,7 +794,7 @@ and the props payload you passed.
793
794
  type without fetching the whole nested tree): call through the
794
795
  gateway: `yootheme_builder_advanced({ tool: "yootheme_builder_page_get_schema", input: { template_id } })`.
795
796
  - **Etag-only fetch** (e.g. polling for concurrent edits): use
796
- `yootheme_builder_get_etag()` (takes no arguments) cheaper than
797
+ `yootheme_builder_get_etag()` (takes no arguments) is cheaper than
797
798
  fetching the full layout.
798
799
  - **Find a public/front-end URL for a template** (404 test page,
799
800
  homepage URL, etc.): call
@@ -831,24 +832,24 @@ Joomla administrator access." Don't fabricate tool calls.
831
832
  | `yootheme_builder_element_clone` | mutating | `element_path`, `etag`, `site_id`, `template_id` | Clone an element as a sibling (same parent, immediately after the source). Returns the new element's path. Requires ETag. Operates on the default site unless site_id is provided. |
832
833
  | `yootheme_builder_element_delete` | destructive | `confirm`, `element_path`, `etag`, `site_id`, `template_id` | PERMANENTLY delete an element and all its children. Cannot be undone. Always ask the user to confirm first, then call again with `confirm: true`. Requires ETag. Operates on the default site unless site_id is provided. |
833
834
  | `yootheme_builder_element_get` | read+idempotent | `element_path`, `site_id`, `template_id` | Get the full element object at a specific JSON-Pointer path, including props and children. Use yootheme_builder_element_list to discover paths. Operates on the default site unless site_id is provided. |
834
- | `yootheme_builder_element_get_binding` | read+idempotent | `element_path`, `site_id`, `template_id` | Read the source binding attached to an element the bound source name, the field-mappings (which source field feeds which element prop) and the query arguments/directives. Returns the empty object if the element is not bound. Operates on the default site unless site_id is provided. |
835
+ | `yootheme_builder_element_get_binding` | read+idempotent | `element_path`, `site_id`, `template_id` | Read the source binding attached to an element: the bound source name, the field-mappings (which source field feeds which element prop) and the query arguments/directives. Returns the empty object if the element is not bound. Operates on the default site unless site_id is provided. |
835
836
  | `yootheme_builder_element_list` | read+idempotent | `cursor`, `depth`, `fields`, `limit`, `root_path`, `site_id`, `template_id` | List elements in a template as a flat array with JSON-Pointer paths + types. Scope with `root_path`/`depth` for a subtree, paginate with `limit`/`cursor` for large templates. `fields[]` narrows each row. Operates on the default site unless site_id is provided. |
836
837
  | `yootheme_builder_element_move` | idempotent | `element_path`, `etag`, `site_id`, `template_id`, `to_index`, `to_parent_path` | Move an element to a new parent + index in the tree. Useful for reordering or reparenting (e.g. moving a card from one grid column to another). Requires ETag. Operates on the default site unless site_id is provided. |
837
- | `yootheme_builder_element_type_get_schema` | read+idempotent | `element_type`, `site_id`, `type_name` | **Call before every `element_add` / `_update_settings`** unknown prop keys are silently dropped server-side, so guessing fails quietly. Returns `{name,type,label?}` field descriptors. Use `element_type`; `type_name` is DEPRECATED. Operates on the default site unless site_id is provided. |
838
+ | `yootheme_builder_element_type_get_schema` | read+idempotent | `element_type`, `site_id`, `type_name` | **Call before every `element_add` / `_update_settings`.** Unknown prop keys are silently dropped server-side, so guessing fails quietly. Returns `{name,type,label?}` field descriptors. Use `element_type`; `type_name` is DEPRECATED. Operates on the default site unless site_id is provided. |
838
839
  | `yootheme_builder_element_types_list` | read+idempotent | `fields`, `site_id` | List element types registered on this site (built-ins + YOOessentials/uEssentials extras). Names feed `element_type` of element_add. Pass `fields[]` to narrow each row. Operates on the default site unless site_id is provided. |
839
- | `yootheme_builder_element_unbind_source` | destructive | `confirm`, `element_path`, `etag`, `site_id`, `template_id` | Remove the source binding from an element. Clears `props.source`. Destructive in the sense that it may break dynamic-content rendering always ask the user to confirm. Requires ETag. Operates on the default site unless site_id is provided. |
840
- | `yootheme_builder_element_update_settings` | idempotent | `element_path`, `etag`, `merge`, `props`, `site_id`, `template_id` | Update `props` on an element. Default replaces all props; pass `merge:true` for server-side deep-merge (only request keys overwritten, others survive avoids read-modify-write races). Requires ETag. Operates on the default site unless site_id is provided. |
840
+ | `yootheme_builder_element_unbind_source` | destructive | `confirm`, `element_path`, `etag`, `site_id`, `template_id` | Remove the source binding from an element. Clears `props.source`. Destructive in the sense that it may break dynamic-content rendering, so always ask the user to confirm. Requires ETag. Operates on the default site unless site_id is provided. |
841
+ | `yootheme_builder_element_update_settings` | idempotent | `element_path`, `etag`, `merge`, `props`, `site_id`, `template_id` | Update `props` on an element. Default replaces all props; pass `merge:true` for server-side deep-merge (only request keys overwritten, others survive, which avoids read-modify-write races). Requires ETag. Operates on the default site unless site_id is provided. |
841
842
  | `yootheme_builder_get_etag` | read+idempotent | `site_id` | Get the current ETag (state revision) for the YOOtheme builder. Returns sha256+revision string used for optimistic locking on writes. Pass the returned value back as `etag` on any write tool (page_save, page_publish, element_add, element_update_settings, element_clone, element_move, element_delete). The server returns HTTP 412 if the ETag has changed since you read it. Keywords: get etag, current etag, state revision, optimistic lock, version stamp. Operates on the default site unless site_id is provided. |
842
843
  | `yootheme_builder_health` | read+idempotent | `site_id` | Check plugin installed/reachable. Returns plugin version, YT Pro version, REST endpoints. Authenticated payload adds site_url + home_url for deep-linking. See yootheme_builder_diagnose for Bearer-validity + connectivity summary. Operates on the default site unless site_id is provided. |
843
844
  | `yootheme_builder_inspect_multi_items_binding` | read+idempotent | `element_path`, `site_id`, `template_id` | Reports Multi-Items binding state: container/item pair (grid↔grid_item, slideshow↔slideshow_item, …), current binding level (none\|container\|item), and a recommended_fix when the binding sits on the container instead of the child. Operates on the default site unless site_id is provided. |
844
845
  | `yootheme_builder_page_get_layout` | read+idempotent | `fields`, `flat`, `site_id`, `template_id` | Get full layout tree for one template. Default nested `{layout, etag}`. Set `flat:true` for depth-first array `{elements:[...], etag}`; combine with `fields[]` to project per-element. Operates on the default site unless site_id is provided. |
845
- | `yootheme_builder_page_get_schema` | read+idempotent | `site_id`, `template_id` | Get the flat schema for a template a list of nodes with their JSON-Pointer paths and element types. Best entry-point for navigation: lighter than page_get_layout, sufficient to locate elements before editing. Operates on the default site unless site_id is provided. |
846
- | `yootheme_builder_page_publish` | idempotent | `etag`, `site_id`, `template_id` | Publish a template persist state, flush YT + WP caches, snapshot the published-state ETag. ETag optional when provided, 412 on conflict; when omitted, last-write-wins. Recommended for collaborative edits. Operates on the default site unless site_id is provided. |
847
- | `yootheme_builder_page_save` | idempotent | `etag`, `site_id`, `template_id` | Re-run save-transforms and persist. ETag optional when provided, 412 on conflict; when omitted, last-write-wins. Recommended for collaborative edits. No-op when state is byte-identical (returns `no_changes:true`, ETag unchanged). Operates on the default site unless site_id is provided. |
846
+ | `yootheme_builder_page_get_schema` | read+idempotent | `site_id`, `template_id` | Get the flat schema for a template: a list of nodes with their JSON-Pointer paths and element types. Best entry-point for navigation: lighter than page_get_layout, sufficient to locate elements before editing. Operates on the default site unless site_id is provided. |
847
+ | `yootheme_builder_page_publish` | idempotent | `etag`, `site_id`, `template_id` | Publish a template: persist state, flush YT + WP caches, snapshot the published-state ETag. ETag optional. When provided, 412 on conflict; when omitted, last-write-wins. Recommended for collaborative edits. Operates on the default site unless site_id is provided. |
848
+ | `yootheme_builder_page_save` | idempotent | `etag`, `site_id`, `template_id` | Re-run save-transforms and persist. ETag optional. When provided, 412 on conflict; when omitted, last-write-wins. Recommended for collaborative edits. No-op when state is byte-identical (returns `no_changes:true`, ETag unchanged). Operates on the default site unless site_id is provided. |
848
849
  | `yootheme_builder_pages_list` | read+idempotent | `fields`, `site_id` | List all pages, templates, and layouts in the YOOtheme Pro builder. Returns template_id, label, type, element count, and frontend_url per row. CALL THIS FIRST to discover available template IDs before any tool that needs a template_id (page_get_layout, element_list, page_get_schema, etc.). Keywords: list pages, list templates, list layouts, discover template_id, index, available templates, what pages exist. Pass `fields:["id","label"]` to slim. Returns ALL pages in one call (no pagination, typically <50 templates per site). Operates on the default site unless site_id is provided. |
849
850
  | `yootheme_builder_sites_list` | read+idempotent | `site_id` | List all sites configured in this multi-site MCP installation. Returns site_id + URL + platform (wordpress\|joomla) + default flag per row. CALL THIS FIRST when working with a fresh MCP connection to discover available site_ids before targeting one with any other tool. Read-only, no REST calls. Keywords: list sites, list connections, list installations, discover site_id, available sites, configured sites, what sites exist, multi-site index. (site_id is accepted for schema-uniformity but ignored by this tool.) |
850
851
  | `yootheme_builder_sites_test` | read+idempotent | `site_id` | Verify connectivity to ONE site: probes /health (no auth) + /etag (auth) in parallel; returns plugin_reachable + bearer_valid. `site_id` is REQUIRED. Use sites_list to find IDs. |
851
852
  | `yootheme_builder_sources_list` | read+idempotent | `fields`, `site_id` | List all data sources, feeds, and dynamic content sources available in the YOOtheme Pro builder. Returns name + label + origin (apimapper / wordpress / joomla / essentials) per source. CALL THIS BEFORE binding any element to a data source. Pick a source name from the list and pass it to `element_bind_source`. Keywords: list sources, list data sources, list feeds, list bindings, dynamic content, available data, what sources exist. Pass `fields[]` to narrow each row. Operates on the default site unless site_id is provided. |
852
- | `yootheme_builder_template_summary` | read+idempotent | `site_id`, `template_id` | Token-efficient template overview: element counts by type, binding count, max nesting depth, and named landmark sections computed server-side in one call. Use this to grasp a large template before pulling element_list or page_get_layout. Operates on the default site unless site_id is provided. |
853
+ | `yootheme_builder_template_summary` | read+idempotent | `site_id`, `template_id` | Token-efficient template overview: element counts by type, binding count, max nesting depth, and named landmark sections, computed server-side in one call. Use this to grasp a large template before pulling element_list or page_get_layout. Operates on the default site unless site_id is provided. |
853
854
 
854
855
  <!-- TOOL-CATALOG:END -->