@caelo-cms/mcp-server 0.10.61 → 0.10.64

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@caelo-cms/mcp-server",
3
3
  "mcpName": "io.github.caelo-cms/caelo",
4
- "version": "0.10.61",
4
+ "version": "0.10.64",
5
5
  "private": false,
6
6
  "license": "MPL-2.0",
7
7
  "description": "MCP servers for Caelo CMS: `caelo_chat` (talk to Caelo's own AI) and the admin-scoped Power-MCP (the full chat-runner tool catalogue, driven by your own agent). Lets Claude Code (or any MCP-aware client) drive a Caelo install from outside the browser.",
@@ -1,9 +1,9 @@
1
1
  {
2
- "version": "0.10.61",
2
+ "version": "0.10.64",
3
3
  "tools": [
4
4
  {
5
5
  "name": "edit_module",
6
- "description": "Edit ONE module's structure: HTML template, fields, CSS, JS, displayName, description, or kind. **AUTHOR EXPLICITLY (v0.12.0+):** pass `html` with `{{fieldName}}` placeholders + an explicit `fields[]` array with semantic snake_case names (`hero_title`, `primary_cta_href`, `nav_items`), NOT a literal-content fallback. The operator says 'fix the homepage hero copy'; YOU translate that to the right field names. Field names like `cta2label2` or `spanText` are wrong — they leak the extractor heuristic. **Field kinds (v0.12.0):** `text`, `richtext`, `url`, `image`, `number`, `boolean`, `link` (primitives); `text-list` (array of strings, slot `{{#field}}…{{.}}…{{/field}}`); `link-list` (array of `{label, href}`, slot `{{#field}}…{{label}}…{{href}}…{{/field}}` — use for menus, footer columns); `module` (single nested module, slot `{{>field}}`); `module-list` (array of nested modules, slot `{{#field}}…{{/field}}`). **Nested fields may declare `allowedModuleTypes`** — a whitelist of stable module `type`s (e.g. `[\"button\"]`), NOT slugs. It matches the referenced module's `type`; set it to constrain what can nest in a `module`/`module-list` slot, and widen it here if a valid module is being wrongly rejected. **Lists are lists, not numbered scalars.** A menu with 10 items is ONE `link-list` field with 10 elements — never `label1`, `label2`, …, `label10`. A tag cloud is ONE `text-list`. Cards with rich per-item structure use `module-list` pointing at a sub-module. **Update description + kind when the module's purpose drifts.** The `## Modules` block exposes them to your future self; stale descriptions hurt your own decision-making. **Legacy fallback only:** if you pass HTML with literal content and NO `fields[]`, a server-side extractor mints heuristic field names — useful for one-shot drafts but the result hurts the `## Modules` block. Treat it as a fallback, not the default path. **Scope module CSS under the module's own root class** - bare global selectors (`body`, `h1`, `.card`) bleed into every other module on the page (issue #158). **Module JS shares ONE page-level script** - no implicit `root`/`el` binding exists; wrap in an IIFE and query via document.querySelectorAll scoped to your module's root class (see the `js` input description). Edits are CHAT-BRANCHED until publish. **For a TARGETED change to existing html/css/js, PREFER `edit_content`** (surgical string-replace: far cheaper than re-emitting the whole body here, and the diff is reviewable). Use `edit_module` for a WHOLESALE rewrite, a brand-new module body, or `fields`/`displayName`/`kind`/`type`/`description` changes. Use this for structure, styling, fields list, or `description`/`kind` updates. DO NOT use this to change what one page shows — use `set_page_module_content` (per-page content) or `set_content_instance_values` (shared content) for that. Prefer `update_modules_many` when targeting > 1 module. DO NOT use for page metadata (`update_pages_many`) or template-level edits (`propose_update_template`). **Internal links** (`href`s in HTML, `url`/`link` fields, link-list and nav items): write the page's path, e.g. `/about` — it must be an EXISTING page (list_pages); a link to a page that does not exist yet is refused, so create the target first, or add the link after. Exception, a site import you are rebuilding in this chat: a link to a page of that import run is kept and resolved by resolve_import_links at the end. Images/files: their media URL (find_media). Other sites: the full https:// URL.",
6
+ "description": "Edit ONE module's structure: HTML template, fields, CSS, JS, displayName, description, or kind. **AUTHOR EXPLICITLY (v0.12.0+):** pass `html` with `{{fieldName}}` placeholders + an explicit `fields[]` array with semantic snake_case names (`hero_title`, `primary_cta_href`, `nav_items`), NOT a literal-content fallback. The operator says 'fix the homepage hero copy'; YOU translate that to the right field names. Field names like `cta2label2` or `spanText` are wrong — they leak the extractor heuristic. **Field kinds (v0.12.0):** `text`, `richtext`, `url`, `image`, `number`, `boolean`, `link` (primitives); `text-list` (array of strings, slot `{{#field}}…{{.}}…{{/field}}`); `link-list` (array of `{label, href}`, slot `{{#field}}…{{label}}…{{href}}…{{/field}}` — use for menus, footer columns); `module` (single nested module, slot `{{>field}}`); `module-list` (array of nested modules, slot `{{#field}}…{{/field}}`). **Nested fields may declare `allowedModuleTypes`** — a whitelist of stable module `type`s (e.g. `[\"button\"]`), NOT slugs. It matches the referenced module's `type`; set it to constrain what can nest in a `module`/`module-list` slot, and widen it here if a valid module is being wrongly rejected. **Lists are lists, not numbered scalars.** A menu with 10 items is ONE `link-list` field with 10 elements — never `label1`, `label2`, …, `label10`. A tag cloud is ONE `text-list`. Cards with rich per-item structure use `module-list` pointing at a sub-module. **Update description + kind when the module's purpose drifts.** The `## Modules` block exposes them to your future self; stale descriptions hurt your own decision-making. **Legacy fallback only:** if you pass HTML with literal content and NO `fields[]`, a server-side extractor mints heuristic field names — useful for one-shot drafts but the result hurts the `## Modules` block. Treat it as a fallback, not the default path. **Scope module CSS under the module's own root class** - bare global selectors (`body`, `h1`, `.card`) bleed into every other module on the page (issue #158); the tool result flags unscoped selectors. **Module JS shares ONE page-level script** - no implicit `root`/`el` binding exists; wrap in an IIFE and query via document.querySelectorAll scoped to your module's root class (see the `js` input description). **Accordion, tabs, carousel need NO module JS** - mark the markup with `data-caelo-ui=\"accordion|tabs|carousel\"` and Caelo ships vetted, accessible behaviour (markup contract in the `js` input description). Edits are CHAT-BRANCHED until publish. **For a TARGETED change to existing html/css/js, PREFER `edit_content`** (surgical string-replace: far cheaper than re-emitting the whole body here, and the diff is reviewable). Use `edit_module` for a WHOLESALE rewrite, a brand-new module body, or `fields`/`displayName`/`kind`/`type`/`description` changes. Use this for structure, styling, fields list, or `description`/`kind` updates. DO NOT use this to change what one page shows — use `set_page_module_content` (per-page content) or `set_content_instance_values` (shared content) for that. Prefer `update_modules_many` when targeting > 1 module. DO NOT use for page metadata (`update_pages_many`) or template-level edits (`propose_update_template`). **Internal links** (`href`s in HTML, `url`/`link` fields, link-list and nav items): write the page's path, e.g. `/about` — it must be an EXISTING page (list_pages); a link to a page that does not exist yet is refused, so create the target first, or add the link after. Exception, a site import you are rebuilding in this chat: a link to a page of that import run is kept and resolved by resolve_import_links at the end. Images/files: their media URL (find_media). Other sites: the full https:// URL.",
7
7
  "inputSchema": {
8
8
  "type": "object",
9
9
  "additionalProperties": false,
@@ -48,7 +48,7 @@
48
48
  },
49
49
  "js": {
50
50
  "type": "string",
51
- "description": "Vanilla JS. Emitted ONCE per page into a single shared <script defer> concatenated with every other module's JS — top-level scope is SHARED and there is NO implicit binding: `root`, `el`, `module`, and `this` are NOT defined. Wrap everything in an IIFE, select elements with document.querySelectorAll('.your-module-root-class …'), and iterate the matches so multiple placements of the module on one page all work. Omit entirely for purely presentational modules."
51
+ "description": "Vanilla JS. Emitted ONCE per page into a single shared <script defer> concatenated with every other module's JS — top-level scope is SHARED and there is NO implicit binding: `root`, `el`, `module`, and `this` are NOT defined. Wrap everything in an IIFE, select elements with document.querySelectorAll('.your-module-root-class …'), and iterate the matches so multiple placements of the module on one page all work. Omit entirely for purely presentational modules. **Vetted interactions - use these instead of writing JS for them.** Add `data-caelo-ui=\"<id>\"` to the markup and Caelo ships accessible, dependency-free behaviour once per page; style it freely in the module CSS. `accordion` (FAQ, collapsible sections): `<div data-caelo-ui=\"accordion\" data-single>` containing `<details id=\"...\"><summary>Question</summary><div>Answer</div></details>` items - `data-single` keeps one open; a link to `#<details id>` opens it. `tabs`: `<div data-caelo-ui=\"tabs\"><div role=\"tablist\" aria-label=\"...\"><button type=\"button\" role=\"tab\" id=\"t1\" aria-controls=\"p1\" aria-selected=\"true\">...</button><button type=\"button\" role=\"tab\" id=\"t2\" aria-controls=\"p2\" aria-selected=\"false\" tabindex=\"-1\">...</button></div><div role=\"tabpanel\" id=\"p1\" aria-labelledby=\"t1\">...</div><div role=\"tabpanel\" id=\"p2\" aria-labelledby=\"t2\" hidden>...</div></div>` - ids must be unique on the page. `carousel` (slider, testimonials): `<section data-caelo-ui=\"carousel\" aria-roledescription=\"carousel\" aria-label=\"...\"><div data-caelo-carousel-track tabindex=\"0\"><div role=\"group\" aria-roledescription=\"slide\" aria-label=\"1 of 3\">...</div>...</div><button type=\"button\" data-caelo-carousel-prev aria-label=\"Previous slide\"><span aria-hidden=\"true\">&lsaquo;</span></button><button type=\"button\" data-caelo-carousel-next aria-label=\"Next slide\"><span aria-hidden=\"true\">&rsaquo;</span></button></section>` (an icon button keeps its visible content aria-hidden; a text button needs no aria-label) - one slide per view by default; set the slides' `flex-basis` in module CSS to show more. `mobile-nav` is applied by the built-in nav-menu renderer; never add it by hand. Write module JS only for behaviour the kit does not cover."
52
52
  },
53
53
  "fields": {
54
54
  "type": "array",
@@ -555,7 +555,7 @@
555
555
  "js": {
556
556
  "type": "string",
557
557
  "maxLength": 50000,
558
- "description": "Vanilla JS. Emitted ONCE per page into a single shared <script defer> concatenated with every other module's JS — top-level scope is SHARED and there is NO implicit binding: `root`, `el`, `module`, and `this` are NOT defined. Wrap everything in an IIFE, select elements with document.querySelectorAll('.your-module-root-class …'), and iterate the matches so multiple placements of the module on one page all work. Omit entirely for purely presentational modules."
558
+ "description": "Vanilla JS. Emitted ONCE per page into a single shared <script defer> concatenated with every other module's JS — top-level scope is SHARED and there is NO implicit binding: `root`, `el`, `module`, and `this` are NOT defined. Wrap everything in an IIFE, select elements with document.querySelectorAll('.your-module-root-class …'), and iterate the matches so multiple placements of the module on one page all work. Omit entirely for purely presentational modules. **Vetted interactions - use these instead of writing JS for them.** Add `data-caelo-ui=\"<id>\"` to the markup and Caelo ships accessible, dependency-free behaviour once per page; style it freely in the module CSS. `accordion` (FAQ, collapsible sections): `<div data-caelo-ui=\"accordion\" data-single>` containing `<details id=\"...\"><summary>Question</summary><div>Answer</div></details>` items - `data-single` keeps one open; a link to `#<details id>` opens it. `tabs`: `<div data-caelo-ui=\"tabs\"><div role=\"tablist\" aria-label=\"...\"><button type=\"button\" role=\"tab\" id=\"t1\" aria-controls=\"p1\" aria-selected=\"true\">...</button><button type=\"button\" role=\"tab\" id=\"t2\" aria-controls=\"p2\" aria-selected=\"false\" tabindex=\"-1\">...</button></div><div role=\"tabpanel\" id=\"p1\" aria-labelledby=\"t1\">...</div><div role=\"tabpanel\" id=\"p2\" aria-labelledby=\"t2\" hidden>...</div></div>` - ids must be unique on the page. `carousel` (slider, testimonials): `<section data-caelo-ui=\"carousel\" aria-roledescription=\"carousel\" aria-label=\"...\"><div data-caelo-carousel-track tabindex=\"0\"><div role=\"group\" aria-roledescription=\"slide\" aria-label=\"1 of 3\">...</div>...</div><button type=\"button\" data-caelo-carousel-prev aria-label=\"Previous slide\"><span aria-hidden=\"true\">&lsaquo;</span></button><button type=\"button\" data-caelo-carousel-next aria-label=\"Next slide\"><span aria-hidden=\"true\">&rsaquo;</span></button></section>` (an icon button keeps its visible content aria-hidden; a text button needs no aria-label) - one slide per view by default; set the slides' `flex-basis` in module CSS to show more. `mobile-nav` is applied by the built-in nav-menu renderer; never add it by hand. Write module JS only for behaviour the kit does not cover."
559
559
  },
560
560
  "fields": {
561
561
  "type": "array",
@@ -1034,7 +1034,7 @@
1034
1034
  },
1035
1035
  {
1036
1036
  "name": "delete_content_instance",
1037
- "description": "Soft-delete a content_instance. Only allowed when ZERO placements still bind to it (orphan instance). When placements exist, the op returns an error pointing you at fork_placement_content for each referencing placement. Use list_content_instances to find orphan instances (placementCount=0) and prune them. Prefer `delete_content_instances` over multiple `delete_content_instance` calls when deleting more than one.",
1037
+ "description": "Soft-delete a content_instance. Only allowed when ZERO placements still bind to it (orphan instance). When placements exist, the op returns an error naming the affected pages: list the placements with get_content_instance, detach each via fork_placement_content (the page keeps its content as a private copy), then retry. Use list_content_instances to find orphan instances (placementCount=0) and prune them. Prefer `delete_content_instances` over multiple `delete_content_instance` calls when deleting more than one.",
1038
1038
  "inputSchema": {
1039
1039
  "type": "object",
1040
1040
  "additionalProperties": false,
@@ -2575,7 +2575,7 @@
2575
2575
  "js": {
2576
2576
  "type": "string",
2577
2577
  "maxLength": 50000,
2578
- "description": "Vanilla JS. Emitted ONCE per page into a single shared <script defer> concatenated with every other module's JS — top-level scope is SHARED and there is NO implicit binding: `root`, `el`, `module`, and `this` are NOT defined. Wrap everything in an IIFE, select elements with document.querySelectorAll('.your-module-root-class …'), and iterate the matches so multiple placements of the module on one page all work. Omit entirely for purely presentational modules."
2578
+ "description": "Vanilla JS. Emitted ONCE per page into a single shared <script defer> concatenated with every other module's JS — top-level scope is SHARED and there is NO implicit binding: `root`, `el`, `module`, and `this` are NOT defined. Wrap everything in an IIFE, select elements with document.querySelectorAll('.your-module-root-class …'), and iterate the matches so multiple placements of the module on one page all work. Omit entirely for purely presentational modules. **Vetted interactions - use these instead of writing JS for them.** Add `data-caelo-ui=\"<id>\"` to the markup and Caelo ships accessible, dependency-free behaviour once per page; style it freely in the module CSS. `accordion` (FAQ, collapsible sections): `<div data-caelo-ui=\"accordion\" data-single>` containing `<details id=\"...\"><summary>Question</summary><div>Answer</div></details>` items - `data-single` keeps one open; a link to `#<details id>` opens it. `tabs`: `<div data-caelo-ui=\"tabs\"><div role=\"tablist\" aria-label=\"...\"><button type=\"button\" role=\"tab\" id=\"t1\" aria-controls=\"p1\" aria-selected=\"true\">...</button><button type=\"button\" role=\"tab\" id=\"t2\" aria-controls=\"p2\" aria-selected=\"false\" tabindex=\"-1\">...</button></div><div role=\"tabpanel\" id=\"p1\" aria-labelledby=\"t1\">...</div><div role=\"tabpanel\" id=\"p2\" aria-labelledby=\"t2\" hidden>...</div></div>` - ids must be unique on the page. `carousel` (slider, testimonials): `<section data-caelo-ui=\"carousel\" aria-roledescription=\"carousel\" aria-label=\"...\"><div data-caelo-carousel-track tabindex=\"0\"><div role=\"group\" aria-roledescription=\"slide\" aria-label=\"1 of 3\">...</div>...</div><button type=\"button\" data-caelo-carousel-prev aria-label=\"Previous slide\"><span aria-hidden=\"true\">&lsaquo;</span></button><button type=\"button\" data-caelo-carousel-next aria-label=\"Next slide\"><span aria-hidden=\"true\">&rsaquo;</span></button></section>` (an icon button keeps its visible content aria-hidden; a text button needs no aria-label) - one slide per view by default; set the slides' `flex-basis` in module CSS to show more. `mobile-nav` is applied by the built-in nav-menu renderer; never add it by hand. Write module JS only for behaviour the kit does not cover."
2579
2579
  },
2580
2580
  "bindThemeLiterals": {
2581
2581
  "type": "boolean",
@@ -5080,7 +5080,7 @@
5080
5080
  },
5081
5081
  "js": {
5082
5082
  "type": "string",
5083
- "description": "Vanilla JS. Emitted ONCE per page into a single shared <script defer> concatenated with every other module's JS — top-level scope is SHARED and there is NO implicit binding: `root`, `el`, `module`, and `this` are NOT defined. Wrap everything in an IIFE, select elements with document.querySelectorAll('.your-module-root-class …'), and iterate the matches so multiple placements of the module on one page all work. Omit entirely for purely presentational modules."
5083
+ "description": "Vanilla JS. Emitted ONCE per page into a single shared <script defer> concatenated with every other module's JS — top-level scope is SHARED and there is NO implicit binding: `root`, `el`, `module`, and `this` are NOT defined. Wrap everything in an IIFE, select elements with document.querySelectorAll('.your-module-root-class …'), and iterate the matches so multiple placements of the module on one page all work. Omit entirely for purely presentational modules. **Vetted interactions - use these instead of writing JS for them.** Add `data-caelo-ui=\"<id>\"` to the markup and Caelo ships accessible, dependency-free behaviour once per page; style it freely in the module CSS. `accordion` (FAQ, collapsible sections): `<div data-caelo-ui=\"accordion\" data-single>` containing `<details id=\"...\"><summary>Question</summary><div>Answer</div></details>` items - `data-single` keeps one open; a link to `#<details id>` opens it. `tabs`: `<div data-caelo-ui=\"tabs\"><div role=\"tablist\" aria-label=\"...\"><button type=\"button\" role=\"tab\" id=\"t1\" aria-controls=\"p1\" aria-selected=\"true\">...</button><button type=\"button\" role=\"tab\" id=\"t2\" aria-controls=\"p2\" aria-selected=\"false\" tabindex=\"-1\">...</button></div><div role=\"tabpanel\" id=\"p1\" aria-labelledby=\"t1\">...</div><div role=\"tabpanel\" id=\"p2\" aria-labelledby=\"t2\" hidden>...</div></div>` - ids must be unique on the page. `carousel` (slider, testimonials): `<section data-caelo-ui=\"carousel\" aria-roledescription=\"carousel\" aria-label=\"...\"><div data-caelo-carousel-track tabindex=\"0\"><div role=\"group\" aria-roledescription=\"slide\" aria-label=\"1 of 3\">...</div>...</div><button type=\"button\" data-caelo-carousel-prev aria-label=\"Previous slide\"><span aria-hidden=\"true\">&lsaquo;</span></button><button type=\"button\" data-caelo-carousel-next aria-label=\"Next slide\"><span aria-hidden=\"true\">&rsaquo;</span></button></section>` (an icon button keeps its visible content aria-hidden; a text button needs no aria-label) - one slide per view by default; set the slides' `flex-basis` in module CSS to show more. `mobile-nav` is applied by the built-in nav-menu renderer; never add it by hand. Write module JS only for behaviour the kit does not cover."
5084
5084
  },
5085
5085
  "fields": {
5086
5086
  "type": "array",
@@ -7738,7 +7738,7 @@
7738
7738
  },
7739
7739
  {
7740
7740
  "name": "list_bug_reports",
7741
- "description": "List the defect reports already filed against Caelo (by you via bug_report, or auto-captured by the chat), newest first. Call BEFORE bug_report to see whether the problem is already reported; filter by status (new / triaged / fixed / invalid). The forwarding column says where each report went: local_only = stored on this site only, the Caelo team has NOT seen it; queued = will be sent to the Caelo team; sent = the Caelo team received it; failed = sending failed, stored here only. Never tell the operator the Caelo team knows about a report unless its forwarding is sent.",
7741
+ "description": "List the defect reports already filed against Caelo (by you via bug_report, or auto-captured by the chat), newest first. Call BEFORE bug_report to see whether the problem is already reported; filter by status (new / triaged / fixed / invalid). The forwarding column says where each report went: local_only = stored on this site only, the Caelo team has NOT seen it; queued = will be sent to the Caelo team; sent = the Caelo team received it; failed = sending failed, stored here only. local_only and failed reports reach the Caelo team only when the Owner clicks \"Send unsent reports\" on Settings → Detected bugs (with sending turned on); you cannot send them yourself. Never tell the operator the Caelo team knows about a report unless its forwarding is sent.",
7742
7742
  "inputSchema": {
7743
7743
  "$schema": "https://json-schema.org/draft/2020-12/schema",
7744
7744
  "type": "object",