@bettercms-ai/mcp 0.76.6 → 0.78.0

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.
@@ -149,7 +149,7 @@ helpers rather than by hand.
149
149
  `display:contents` span, and `as` names a real wrapper. `path` is dotted keys with any
150
150
  number of `[n]` indices: `title`, `hero.title`, `columns[0].links[2].href`.
151
151
  - Rich text is addressed per paragraph: `<base>#<_key>`. No write tool takes an address:
152
- `update_content_entry` replaces the whole field (with `merge: true` it keeps the other
152
+ `update_content_entry` replaces the whole field (it merges by default, keeping the other
153
153
  top-level fields, never other blocks of the same field). The platform's own path writer refuses a
154
154
  `#<_key>` path (`KEYED_PATH_NOT_WRITABLE`), and only the editor patches one block. A `_key` is
155
155
  part of an address, so never regenerate keys of blocks that already exist.
@@ -337,3 +337,30 @@ asked for it. Refusals per item: `target-unknown`, `path-not-in-schema`, `owner-
337
337
  Until a convert that emits proposals has submitted its receipt, every id refuses `target-unknown`.
338
338
  `get_next_steps` `receipt.decisions` counts `stored`, `materialized`, `proven`, `pending` (open
339
339
  proposals) and `lost`; stop when `pending` is 0.
340
+
341
+ ### Archive (ZIP) sites
342
+
343
+ A project with no connected repository and no receipt carrying proposals is an ARCHIVE site: no
344
+ codemod runs, so each release scan mints the proposals itself. `target` is then
345
+ `template|owner|textHash` (owner `page`, `layout` or `entry:<collection>`; Layout copy has template
346
+ `*`, an entry route its collection's `/blog/*`), and translations of a page share one template.
347
+ Decisions are not written into source: every release stamps them into the built HTML wherever
348
+ their anchors (structure, text, nearest declared field) agree 2 of 3, else the row is `lost`
349
+ (`anchor-lost`). A `bind` stamps only when the element's text equals the field's stored value; an
350
+ uploaded copy change loses it (`anchor-text-changed`) and its copy is proposed again. An AI `code`
351
+ for `runtime`, `external`, `derived` or `stylesheet` refuses `evidence-missing` here (there is no
352
+ source to check); `decorative`, `embed` and `legal` are checked on the page, and a person may mark
353
+ any reason. Each such decision lives in BetterCMS, not in the site's code: recommend connecting a
354
+ repository.
355
+
356
+ Archive sites also take `{ op: "rule", template, match, then }`, one row for every element it
357
+ matches on every route of `template`:
358
+ - `template`: `/`-segments literal or `*`, a trailing `/**`, or `*` alone (every route). No regex.
359
+ - `match`: at least one of `struct` (a proposal's structure anchor), `cls` (one class token),
360
+ `text` (exact copy); `owner` (`page`, `layout`, `entry`) narrows.
361
+ - `then`: `{ op: "code", why }` or `{ op: "bind", path }`. A bind rule names a `layout` or `entry`
362
+ owner, and matching more than one element on a route is `ambiguous` there.
363
+ A person beats an AI, then a per-id decision beats a rule; two rules saying different things about
364
+ one element are `declaration-conflict`. On a git site a `rule` refuses `invalid-item`. A lane change
365
+ (a repository connected, or a convert's receipt arriving) loses the other lane's decisions
366
+ (`lane-changed`): decide again on the new proposals.
@@ -35,7 +35,7 @@ row has the field `key`, a `reason` and, for a look set by several props, the si
35
35
  merge into the stored `ui`:
36
36
  `update_content_model { modelId | pageId, fieldUi: { "<path>": { input: { name, writes } } }, ifMatch, confirmed: true }`,
37
37
  `update_component { componentId, propUi: { "<key>": { input: { name, writes } } }, ifMatch, confirmed: true }`.
38
- `update_field`'s `ui` REPLACES the field's whole `ui`: send every key you read with it.
38
+ `update_field`'s `ui` MERGES per key into the stored `ui`, as `fieldUi` does: send `null` for a key to clear it.
39
39
  4. On no: leave it. Nothing is broken.
40
40
 
41
41
  A write through the agent tools that sets or changes `ui.input` without `confirmed: true` is
@@ -114,7 +114,7 @@ Tags: deep-nesting, slots, global-synced, conditional, references, variants, com
114
114
  - If two menu items share the same panel content, that is still two panels in content; don't invent a shared-panel global for it.
115
115
  - Hover-only panels fail keyboard users — the converter should default `openOn` to click when the source has no aria-expanded handling.
116
116
 
117
- Not carried by a stored component: ai, category, kind:global, shopify reference, variants.
117
+ Not carried by a stored component: ai, category, kind:global, shopify reference, slot allow: ctaCard, imageBlock, productCard, videoBlock, variants.
118
118
 
119
119
  ### Docs sidebar navigation (`nav-docs-sidebar`)
120
120
 
@@ -644,7 +644,7 @@ Tags: slots, responsive-layout, conditional, media-heavy, variants. Proves: Slot
644
644
  - Phones stack cells; if the source reorders them with CSS `order`, capture it or the story reads out of order.
645
645
  - 6-column variants need spans up to 6; validate spans against the variant's column count.
646
646
 
647
- Not carried by a stored component: ai, category, variants.
647
+ Not carried by a stored component: ai, category, slot allow: featureBlock, statBlock, imageBlock, videoBlock, quoteBlock, ctaCard, textBlock, variants.
648
648
 
649
649
  ### Steps / how it works (`steps-how-it-works`)
650
650
 
@@ -922,7 +922,7 @@ Tags: repeater, variants, a11y, validation, conditional, media-heavy. Proves: Gr
922
922
  - Alt text like “logo” or empty alt on linked logos fails a11y; the required name fixes it.
923
923
  - Conditions on `_variant` work today because the variant is stored on the block value — this is a schema-language gap worth making official.
924
924
 
925
- Not carried by a stored component: category, item openMode, variants.
925
+ Not carried by a stored component: category, item openMode, showIf on _variant, variants.
926
926
 
927
927
  ### Press mentions (`press-mentions`)
928
928
 
@@ -1145,7 +1145,7 @@ Tags: media-heavy, a11y, responsive-layout, variants, conditional. Proves: Art-d
1145
1145
  - Text over a busy photo fails contrast; the overlay help gives a range and the renderer checks contrast.
1146
1146
  - A background-image has no alt — converting to an `<img>` with alt (or decorative) is part of the import.
1147
1147
 
1148
- Not carried by a stored component: ai, category, variants.
1148
+ Not carried by a stored component: ai, category, showIf on _variant, variants.
1149
1149
 
1150
1150
  ### Social photo feed (UGC) (`ugc-social-feed`)
1151
1151
 
@@ -2773,7 +2773,7 @@ Tags: deep-nesting, slots, repeater, variants, media-heavy. Proves: Guide › Ta
2773
2773
  - Breadcrumb at 7 drills (Guide / Seasoning / Steps and kit / Steps / Season over fire… / Heat it upside down / Card / Button) must fold into the Pathway chip on a 380px inspector — this entry is the test case.
2774
2774
  - Accordion item cards inside a 1/3 column are cramped; that's a variant decision, not a field.
2775
2775
 
2776
- Not carried by a stored component: ai, category, variants.
2776
+ Not carried by a stored component: ai, category, slot allow: layoutColumns, accordionBlock, textBlock, imageBlock, videoBlock, ctaCard, variants.
2777
2777
 
2778
2778
  ### Any-block module list (`polymorphic-modules`)
2779
2779
 
@@ -2928,7 +2928,7 @@ Tags: slots, variants, media-heavy, responsive-layout, commerce. Proves: Slot ce
2928
2928
  - SCHEMA GAP: slotSettings can't be conditional on the child's block type (e.g. padding 'none' only for images) and can't vary per breakpoint.
2929
2929
  - Dense packing changes the visual order but not the DOM order — screen readers follow the DOM.
2930
2930
 
2931
- Not carried by a stored component: ai, category, variants.
2931
+ Not carried by a stored component: ai, category, slot allow: imageBlock, productCard, quoteBlock, textBlock, ctaCard, statBlock, videoBlock, featureBlock, variants.
2932
2932
 
2933
2933
  ### References web (`references-web`)
2934
2934
 
@@ -3041,7 +3041,7 @@ Tags: slots, conditional, a11y, form, repeater, references. Proves: Overlays wit
3041
3041
  - Exit-intent doesn't exist on touch devices; the label says '(desktop)' because the schema can't scope a trigger per device.
3042
3042
  - Focus trap, Esc to close and focus return are renderer requirements, not fields — never make them toggles.
3043
3043
 
3044
- Not carried by a stored component: category.
3044
+ Not carried by a stored component: category, slot allow: textBlock, imageBlock, videoBlock, ctaCard, quoteBlock, featureBlock.
3045
3045
 
3046
3046
  ### Sticky scroll story (`scrollytelling`)
3047
3047
 
@@ -3172,7 +3172,7 @@ Tags: slots, polymorphic-array, repeater, variants. Proves: Array of tabs, each
3172
3172
  - Slot children are `{ componentId, overrides? }` with no `_variant`: a variant is its own component.
3173
3173
  - Give every block, tab and instance a stable `id`; changing one orphans the edits made against it.
3174
3174
 
3175
- Not carried by a stored component: ai, category, variants.
3175
+ Not carried by a stored component: ai, category, slot allow: textBlock, imageBlock, featureBlock, statBlock, quoteBlock, ctaCard, productCard, videoBlock, variants.
3176
3176
 
3177
3177
  ### Pricing (`core-pricing`)
3178
3178
 
@@ -3214,7 +3214,7 @@ Tags: slots, polymorphic-array, variants, responsive-layout, media-heavy. Proves
3214
3214
  - A slot child has no `_variant`: a variant is its own component.
3215
3215
  - slotSettings are leaf fields only; a cell's own copy stays in the cell component's props.
3216
3216
 
3217
- Not carried by a stored component: ai, category, variants.
3217
+ Not carried by a stored component: ai, category, slot allow: imageBlock, statBlock, quoteBlock, textBlock, ctaCard, productCard, videoBlock, variants.
3218
3218
 
3219
3219
  ### Journal story (`core-journalStory`)
3220
3220
 
@@ -27,11 +27,11 @@ The batch route reports steps 2, 4 and 5 as `code: "UNIQUE_CONFLICT"` or `"VALID
27
27
 
28
28
  Rule: read `errors` by field key, fix exactly those fields, write again once.
29
29
 
30
- `update_content_entry` `data` REPLACES the entry's whole value object: an optional field left out
31
- is deleted. Send `merge: true` to lay `data` over the stored value by top-level key (a group or
32
- repeater you send still replaces that whole key). Pass `ifMatch` (the `optimisticVersion` from
33
- `get_content_entry`) so a 409 tells you someone wrote since your read; with `merge` it defaults to
34
- the version the merge read.
30
+ `update_content_entry` merges `data` into the stored value by top-level key: a field left out is
31
+ kept, and a group or repeater you send still replaces that whole key. `merge: false` REPLACES the
32
+ whole value object instead, deleting every optional field left out. Pass `ifMatch` (the
33
+ `optimisticVersion` from `get_content_entry`) so a 409 tells you someone wrote since your read; a
34
+ merge defaults to the version it read.
35
35
 
36
36
  ## Value contract
37
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bettercms-ai/mcp",
3
- "version": "0.76.6",
3
+ "version": "0.78.0",
4
4
  "type": "module",
5
5
  "description": "BetterCMS MCP server — schema, content, forms + components authoring tools over the Management API, authed via OAuth device-code.",
6
6
  "bin": {