@bettercms-ai/mcp 0.74.0 → 0.76.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.
@@ -43,7 +43,12 @@ Listing tools needs no sign-in; the first tool **call** does.
43
43
  4. **A refusal for access: call `whoami` first.** It names the principal, the workspace, the
44
44
  scope (project or workspace) and, where visible, the grants (publish, code and deploy,
45
45
  sidebar schema), so you can tell the user which one is missing.
46
- 5. **Unsure how a feature works: `search_docs` before guessing.** A tool that fails oddly, a
46
+ 5. **"Invalid tool parameters" is the client, not BetterCMS.** A client with tool search (Claude
47
+ Code) lists most of the 150 tools by name and loads a schema on demand; a call to a tool whose
48
+ schema it has not loaded is refused before it is sent. Load the tool with the client's tool
49
+ search, every tool the step needs in one search, then make the same call again. Never change
50
+ the arguments because of it. The tools a setup starts with are always loaded.
51
+ 6. **Unsure how a feature works: `search_docs` before guessing.** A tool that fails oddly, a
47
52
  capability you needed and did not have, or docs that misled you: `give_feedback`, and tell the
48
53
  user you sent it.
49
54
 
@@ -123,7 +128,7 @@ resources: `bettercms://skill/bettercms` for this file, and each reference under
123
128
  | Move content out of another CMS (Cosmic, Contentful, Sanity, Strapi, Prismic, WordPress…) | [external-content.md](references/external-content.md) | a CMS SDK in package.json; `envWarning` on import; pages that render empty without a third-party key | Contentful, Sanity, Strapi, envWarning, missing key, empty pages |
124
129
  | Read a source site before modelling it | [detection.md](references/detection.md) | converting from a URL or built HTML; deciding what a band, a repeat or a value is | detect, classify, section, repeat, global, carousel clone, hidden state |
125
130
  | Pages vs collections, folders, fields, schema changes | [content-modeling.md](references/content-modeling.md) | modelling a route family; a model write returns 409 | schema, model, collection, field, folder, rename, remove field, listing, filter, locked field |
126
- | Dock layout: groups, rows, tabs, icons, item names, showIf order | [editor-chrome.md](references/editor-chrome.md) | `get_next_steps` lists a `dock-*` rule; the `field-ui` prompt | dock, fieldset, tab, group, itemLabel, showIf, field-ui |
131
+ | Dock layout: groups, rows, tabs, icons, item names, showIf order | [editor-chrome.md](references/editor-chrome.md) | after any import, convert, componentize or extract (the gate's `dock` row); a `dock-*` rule; the `field-ui` prompt | dock, fieldset, tab, group, itemLabel, showIf, field-ui |
127
132
  | A custom input for one field in the dock: when, the user's approval, the contract | [dock-input.md](references/dock-input.md) | `get_next_steps` lists `dock-input-candidate`; a 409 `input_needs_confirmation` | custom input, ui.input, dock input, confirmed, swatch |
128
133
  | What the server does and does not check on a write | [write-limits.md](references/write-limits.md) | before relying on a limit; reading a refused write; a bulk load or re-run | validation, maxLength, unique, 400, refused write, dry run, externalKey, upsert, re-run |
129
134
  | Plan a site by business type | [site-blueprints.md](references/site-blueprints.md) | the IA of a known site type, with its collections, forms and structured data | new site, IA, portfolio, agency, corporate, SaaS, ecommerce, directory, blog, docs, restaurant, events, course, jobs, real estate, nonprofit, multi-brand |
@@ -75,9 +75,14 @@ Never let a component contain itself, directly or through a child.
75
75
  `set_component_source` per component is needed. Deploy. A page whose bands could not be
76
76
  lifted is wrapped where it stands instead (§5).
77
77
  7. Output validation, from step 3 of §6.
78
+ 8. Editor chrome, last and not optional: the components this lane made have bare props. Load
79
+ [editor-chrome.md](editor-chrome.md) and run step 8 of the repair order in
80
+ [finish-site.md](finish-site.md) for each one; `extract_component` ends the same way.
78
81
 
79
82
  ## 3. Names and groups
80
83
 
84
+ Name each component's closest kit entry as its `kitEntry` (`bettercms://kit/entry/{id}`) and take that entry's ui. When the match is wrong, override it; the `no-kit-match` exemption needs a note.
85
+
81
86
  Name a family by what it is (`Hero`, `CTA`, `Testimonials`) and each variant by how it looks
82
87
  (`Hero / Split`, `CTA / Centered`). Never put a page name in a reusable definition; which pages
83
88
  use it is a usage question (§8). The componentize lane files a section under its page's slug
@@ -69,6 +69,7 @@ line), which is what a script waiting on the setup reads.
69
69
  | `buttons` | every button field is one of the site's live Button looks, the Button family is the looks setup measured on this build (the same looks, not the same count), and no look is named by a number or a build's class | `blocking.rows`, `route: null` |
70
70
  | `components` | the authoring question is answered, and no section is left that a componentize run would place | `blocking.rows`, `route: null` |
71
71
  | `forms` | every form of the customer's has an address to notify; a form setup ignored (sign-in, add to basket) is not counted | `blocking.rows`, `route: null` |
72
+ | `dock` | every component with props has at least one prop carrying V2 `ui`, and every list prop (`table`, `array`, `multi-reference`) titles its rows with `ui.preview.title` or `ui.itemLabel`; and every component with props names the `bettercms://kit` entry its dock UI was built from (`update_component { kitEntry }`, `set-kit-entry`), or records `no-kit-match` with a note on `route: "component/<slug>/kit"`; one row per component per half, Button looks not counted | `blocking.rows`, `route: null`, the component, its props and the `bettercms://kit/entry/{id}` to read in `detail` |
72
73
 
73
74
  `pages` counts routes built, created and published. `coverage` sums `editable` of `total` across
74
75
  the site, `svg`, `number` and `attribute` included, and `open` counts the rows still open per
@@ -106,6 +107,7 @@ The other rows name their fix the same way:
106
107
  | `derive-buttons` | `editor_setup { force: true }` mints a Button for each look the build draws, retires one it no longer draws and maps each button to its look; rename a look with `update_component` ([components.md](components.md)) |
107
108
  | `componentize` | `set_authoring_preference` when nobody answered, then `get_componentize_plan` and `componentize_sections` ([componentize.md](componentize.md)) |
108
109
  | `set-form-recipient` | ask the user where the form's submissions go, then `update_form` with `notifyEmails`; `update_form { ignored: true }` when it is not one of their forms |
110
+ | `set-dock-ui` | the last step of the repair order below: `get_component`, then `update_component` with `propUi` and `propTab` for the props the row names ([editor-chrome.md](editor-chrome.md)) |
109
111
 
110
112
  A row nothing measured reads `unmeasured: true` with `run-setup`, and `gate.unmeasured` lists the
111
113
  checks that have one: a release older than a count, or a project set up before setup recorded
@@ -207,8 +209,9 @@ in a sentence a person can verify. `reason: null` withdraws one.
207
209
  | `decorative` | `text`, `image`, `svg` |
208
210
  | `duplicate-track` | `text`, `image`, `link`, `svg`, `number`, `attribute` (the cloned track of a marquee or slider) |
209
211
  | `client-only-island` | nothing: it lists an island the build cannot show, and the route still meets the bar outside it |
210
- | `user-declined` | `page`, `published`, `text`, `image`, `link`, `svg`, `number`, `attribute`, `seo`, `structuredData`, `collections`, and only with the user's own words quoted in `note` (`User: "leave pricing in code"`) |
212
+ | `user-declined` | `page`, `published`, `text`, `image`, `link`, `svg`, `number`, `attribute`, `seo`, `structuredData`, `collections`, `dock`, and only with the user's own words quoted in `note` (`User: "leave pricing in code"`) |
211
213
  | `document-body` | `sections`, and only on a route that places no section at all: a page that is one document (a markdown post, a legal page) |
214
+ | `default-controls` | `dock`, on `route: "component/<slug>"`: a component whose props read right with the dock's default controls (one short heading, a toggle); `note` says why |
212
215
 
213
216
  Nothing else excuses `sections`, and nothing excuses `style`, `twin`, `names`, `buttons`,
214
217
  `components` or `forms`: not the user's decision either. A name is fixed by renaming, and a form
@@ -284,6 +287,7 @@ and add the new result. Update the file as each row moves, so a reset loses at m
284
287
  | 5 | Bindings: the site reads BetterCMS data and each intended leaf or attribute is bound; build, preview and runtime agree | [bindings.md](bindings.md), [frameworks.md](frameworks.md) |
285
288
  | 6 | Behaviour: forms, links, menus, accordions, modals, consent, custom code | [forms-and-interactions.md](forms-and-interactions.md) |
286
289
  | 7 | Discoverability: native SEO, structured data, robots and sitemap, redirects, internal links | [seo.md](seo.md) |
290
+ | 8 | Editor chrome, MANDATORY and last, after any import, convert, componentize or extract: load the reference, and for every component set the V2 `ui` of each prop (control, tab, group, collapsed, layout, preview, itemLabel, icon, and `propHelpText`) by playbook §14 and the nearest `bettercms://kit` entry. The gate's `dock` row stays open until it is done | [editor-chrome.md](editor-chrome.md) |
287
291
 
288
292
  Load the step's reference when the step starts, and let it go when the step's rows are verified.
289
293
 
@@ -87,6 +87,8 @@ and `get_componentize_plan` proposes nothing more.
87
87
  5. Work the rest through [finish-site.md](finish-site.md) (gap ledger, repair order, proof loop).
88
88
  The gate's `sections` and `style` rows are part of it: a setup whose pages cannot take a new
89
89
  section, a new order or spacing is not finished.
90
+ 6. End Phase 3 on the editor chrome of every component (step 8 of finish-site.md's repair order,
91
+ [editor-chrome.md](editor-chrome.md)): the gate's `dock` row blocks until each has its V2 `ui`.
90
92
 
91
93
  ### Phase 4 — Publish and verify
92
94
 
@@ -92,7 +92,7 @@ Tags: global-synced, conditional, repeater, localized. Proves: Three stacked row
92
92
  - A rotating announcement (several messages cycling) is an array, not one string — switch `message` to an array of {message, link} rather than joining with ·.
93
93
  - Don't put the account/cart icons in utility links — those are app state; see `nav-ecommerce-header`.
94
94
 
95
- Not carried by a stored component: ai, category, document preview path, item openMode, kind:global.
95
+ Not carried by a stored component: ai, category, item openMode, kind:global.
96
96
 
97
97
  ### Mega menu with featured cards + promo slot (`nav-mega-featured-promo`)
98
98
 
@@ -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, reference target, slot allow, variants.
117
+ Not carried by a stored component: ai, category, kind:global, shopify reference, variants.
118
118
 
119
119
  ### Docs sidebar navigation (`nav-docs-sidebar`)
120
120
 
@@ -156,7 +156,7 @@ Tags: global-synced, commerce, references, repeater, conditional, media-heavy. P
156
156
  - Copying '(2)' from the cart badge into content is the most common converter mistake — it's session state.
157
157
  - Free-shipping thresholds belong to commerce settings, not the header; reference them from the renderer.
158
158
 
159
- Not carried by a stored component: category, kind:global, reference target, variants.
159
+ Not carried by a stored component: category, kind:global, shopify reference, variants.
160
160
 
161
161
  ### Multi-locale header with switchers (`nav-locale-header`)
162
162
 
@@ -196,7 +196,7 @@ Tags: responsive-layout, conditional, validation, commerce. Proves: A per-templa
196
196
  - 'Add to cart' is an ACTION, not a link — our button type only carries links (gap: action buttons).
197
197
  - A bar covering the cookie banner or chat launcher: the renderer must stack them; nothing to model.
198
198
 
199
- Not carried by a stored component: ai, category, document preview path.
199
+ Not carried by a stored component: ai, category.
200
200
 
201
201
  ### Announcement bar with countdown (`announcement-countdown`)
202
202
 
@@ -216,7 +216,7 @@ Tags: global-synced, conditional, validation, repeater, localized, a11y. Proves:
216
216
  - Storing the countdown as text ('2 days left') — it's wrong the next day. Always a datetime with offset.
217
217
  - Hide-after earlier than the countdown end can't be caught today (gap: cross-field validation).
218
218
 
219
- Not carried by a stored component: ai, category, document preview path, item openMode, kind:global.
219
+ Not carried by a stored component: ai, category, item openMode, kind:global.
220
220
 
221
221
  ### Cookie consent banner (`cookie-consent`)
222
222
 
@@ -338,7 +338,7 @@ Tags: variants, conditional, media-heavy, a11y, repeater. Proves: One media slot
338
338
  - A hero with BOTH a background video and a side image is a different section (full-bleed video) — don't merge.
339
339
  - Alt text on a decorative hero photo should still describe it when it shows the product.
340
340
 
341
- Not carried by a stored component: ai, category, item settings, variants.
341
+ Not carried by a stored component: ai, category, variants.
342
342
 
343
343
  ### Centered hero with gradient + screenshot (`hero-centered-gradient`)
344
344
 
@@ -359,7 +359,7 @@ Tags: variants, conditional, validation, media-heavy. Proves: Announcement chip
359
359
  - Editing the headline can orphan the highlight — the renderer must ignore a highlight that no longer matches (no cross-field validation yet).
360
360
  - Don't store raw CSS gradient strings — they can't be re-themed or validated.
361
361
 
362
- Not carried by a stored component: ai, category, document preview path, variants.
362
+ Not carried by a stored component: ai, category, variants.
363
363
 
364
364
  ### Full-bleed video hero with captions (`hero-video-fullbleed`)
365
365
 
@@ -400,7 +400,7 @@ Tags: repeater, media-heavy, conditional, validation, a11y. Proves: Slides array
400
400
  - Cloned slides doubling the count — dedupe by image URL + heading.
401
401
  - Slide schedules that leave fewer than 2 live slides: the renderer should fall back to a static hero (min can't be enforced over time).
402
402
 
403
- Not carried by a stored component: ai, category, document preview path, fieldset (derived).
403
+ Not carried by a stored component: ai, category, fieldset (derived).
404
404
 
405
405
  ### Product hero with variant picker (`hero-product`)
406
406
 
@@ -421,7 +421,7 @@ Tags: references, commerce, media-heavy, conditional, repeater. Proves: Live com
421
421
  - Hard-coding the price in the tagline ('Just $165!') — it goes stale; flag any currency in copy.
422
422
  - Picker options are a fixed list here; a product with a 'Handle wrap' option can't be picked until options come from the reference (gap).
423
423
 
424
- Not carried by a stored component: ai, category, document preview path, reference target, variants.
424
+ Not carried by a stored component: ai, category, shopify reference, variants.
425
425
 
426
426
  ### Search hero (`hero-search`)
427
427
 
@@ -460,7 +460,7 @@ Tags: form, references, conditional, validation, repeater. Proves: A form REFERE
460
460
  - Copying inputs into the hero's schema — the form then can't be reused or receive submissions properly.
461
461
  - Hidden values that contain personal data (an email from the URL) must not be stored in content.
462
462
 
463
- Not carried by a stored component: ai, category, item openMode, item settings, variants.
463
+ Not carried by a stored component: ai, category, item openMode, variants.
464
464
 
465
465
  ### App download hero (`hero-app-download`)
466
466
 
@@ -480,7 +480,7 @@ Tags: media-heavy, conditional, validation, global-synced, repeater. Proves: A f
480
480
  - Uploading badge or QR images — they can't be updated and the QR silently breaks when the link changes.
481
481
  - Ratings copied from the store go stale; the help text says so because there's no live source.
482
482
 
483
- Not carried by a stored component: ai, category, document preview path, item openMode.
483
+ Not carried by a stored component: ai, category, item openMode.
484
484
 
485
485
  ### Stats hero (`hero-stats`)
486
486
 
@@ -623,7 +623,7 @@ Tags: repeater, conditional, media-heavy, variants, rich-text. Proves: Per-row m
623
623
  - Storing `side` on every row breaks the zigzag the moment rows are reordered — store `auto` unless the source deliberately breaks the pattern.
624
624
  - Autoplay videos without a poster flash black; always extract or generate a poster.
625
625
 
626
- Not carried by a stored component: ai, category, group (nested), group unused (props), item settings, variants.
626
+ Not carried by a stored component: ai, category, variants.
627
627
 
628
628
  ### Feature bento (responsive spans) (`bento-feature-showcase`)
629
629
 
@@ -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, slot allow, variants.
647
+ Not carried by a stored component: ai, category, variants.
648
648
 
649
649
  ### Steps / how it works (`steps-how-it-works`)
650
650
 
@@ -683,7 +683,7 @@ Tags: repeater, conditional, media-heavy, validation, rich-text. Proves: Date pr
683
683
  - Storing “2014” in a date field becomes 2014-01-01 and later renders as “Jan 1, 2014”.
684
684
  - Two milestones with the same year keep their array order as the tie-breaker — keep the array roughly sorted.
685
685
 
686
- Not carried by a stored component: ai, category, group (nested), group unused (props), variants.
686
+ Not carried by a stored component: ai, category, variants.
687
687
 
688
688
  ### Tabs with media (`tabs-with-media`)
689
689
 
@@ -703,7 +703,7 @@ Tags: repeater, conditional, media-heavy, variants, a11y, localized. Proves: Fix
703
703
  - Auto-advancing tabs must stop on interaction and respect reduced motion — the renderer handles it; never model a “pause” field.
704
704
  - Tab labels longer than ~20 characters wrap on the top variant and break the underline.
705
705
 
706
- Not carried by a stored component: ai, category, group (nested), group unused (props), variants.
706
+ Not carried by a stored component: ai, category, variants.
707
707
 
708
708
  ### Accordion features with image swap (`accordion-feature-image-swap`)
709
709
 
@@ -722,7 +722,7 @@ Tags: repeater, media-heavy, a11y, variants, rich-text. Proves: One required ima
722
722
  - Images of different aspect ratios cause the layout to jump on every click — warn when the source images differ.
723
723
  - Do not tag these rows as FAQ structured data — they are not questions.
724
724
 
725
- Not carried by a stored component: ai, category, group (nested), group unused (props), variants.
725
+ Not carried by a stored component: ai, category, variants.
726
726
 
727
727
  ### Comparison vs competitors (`comparison-vs-competitors`)
728
728
 
@@ -783,7 +783,7 @@ Tags: conditional, rich-text, variants, localized. Proves: Mode select swaps an
783
783
  - Quotation marks typed into content double up with the design's quotes — strip them.
784
784
  - Lines split by `<br>` inside one paragraph are still separate lines.
785
785
 
786
- Not carried by a stored component: category, document preview path, item settings, variants.
786
+ Not carried by a stored component: category, variants.
787
787
 
788
788
  ### Problem → solution (`problem-solution`)
789
789
 
@@ -982,7 +982,7 @@ Tags: seo-structured, references, conditional, validation, a11y, commerce. Prove
982
982
  - Typed-in ratings drift from the real ones; prefer the connected source and show “Synced …” in the UI.
983
983
  - Distribution counts that don't sum to the total look fake; validate the sum.
984
984
 
985
- Not carried by a stored component: category, item openMode, itemNoun (derived), reference target, variants.
985
+ Not carried by a stored component: category, item openMode, itemNoun (derived), shopify reference, variants.
986
986
 
987
987
  ## Media & galleries
988
988
 
@@ -1005,7 +1005,7 @@ Tags: media-heavy, a11y, responsive-layout, repeater, validation, localized. Pro
1005
1005
  - Credits pasted into captions get translated; keep them in the credit object.
1006
1006
  - Empty alt is right for decorative photos but wrong for a portfolio — flag empties for review.
1007
1007
 
1008
- Not carried by a stored component: category, document preview path, validation.items, variants.
1008
+ Not carried by a stored component: category, variants.
1009
1009
 
1010
1010
  ### Gallery with category filters (`lightbox-gallery-filters`)
1011
1011
 
@@ -1024,7 +1024,7 @@ Tags: media-heavy, a11y, repeater, validation, localized. Proves: Filters define
1024
1024
  - A photo tagged with a key that no filter defines is invisible under every filter except All — validate keys against the filters.
1025
1025
  - Free-typed keys are error-prone; a select fed by the section's filters is the right control (schema gap).
1026
1026
 
1027
- Not carried by a stored component: category, document preview path, item openMode, validation.items, variants.
1027
+ Not carried by a stored component: category, item openMode, variants.
1028
1028
 
1029
1029
  ### Video section (YouTube · Vimeo · hosted) (`video-section`)
1030
1030
 
@@ -1064,7 +1064,7 @@ Tags: media-heavy, a11y, repeater, validation, variants, localized. Proves: Pair
1064
1064
  - Before and after with different crops make the slider useless — dimensions should match (not enforceable in our schema yet).
1065
1065
  - A slider built from a div with mouse events only is not keyboard accessible; the renderer must use a real range input.
1066
1066
 
1067
- Not carried by a stored component: category, document preview path, variants.
1067
+ Not carried by a stored component: category, variants.
1068
1068
 
1069
1069
  ### Image with hotspots (shop the look) (`image-hotspots`)
1070
1070
 
@@ -1084,7 +1084,7 @@ Tags: media-heavy, conditional, references, commerce, a11y, validation, variants
1084
1084
  - Copying product price into the note text goes stale; reference the product.
1085
1085
  - Re-cropping the image after placing pins moves every pin. A visual point picker would prevent this (schema gap).
1086
1086
 
1087
- Not carried by a stored component: category, reference target, variants.
1087
+ Not carried by a stored component: category, shopify reference, variants.
1088
1088
 
1089
1089
  ### 3D model / Lottie / 360° embed (`interactive-3d-lottie-embed`)
1090
1090
 
@@ -1124,7 +1124,7 @@ Tags: polymorphic-array, media-heavy, a11y, responsive-layout, references, condi
1124
1124
  - Loop mode clones slides in the DOM — import only originals.
1125
1125
  - Autoplaying carousels need a pause control and must stop on focus (WCAG 2.2.2); the renderer adds both.
1126
1126
 
1127
- Not carried by a stored component: category, group unused (props), reference target, variants.
1127
+ Not carried by a stored component: category, shopify reference, variants.
1128
1128
 
1129
1129
  ### Full-bleed parallax image with overlay text (`parallax-image-overlay`)
1130
1130
 
@@ -1164,7 +1164,7 @@ Tags: dynamic-query, embed, conditional, media-heavy, references, commerce, vali
1164
1164
  - Widget scripts from UGC vendors add 200–500 KB and third-party cookies — replace, don't import.
1165
1165
  - Never mark rightsGranted true on import; only a person can confirm permission.
1166
1166
 
1167
- Not carried by a stored component: category, reference target, variants.
1167
+ Not carried by a stored component: category, shopify reference, variants.
1168
1168
 
1169
1169
  ## Commerce
1170
1170
 
@@ -1213,7 +1213,7 @@ Tags: commerce, deep-nesting, polymorphic-array, conditional, references, media-
1213
1213
  - Variant combinations are typed strings; renaming an option value orphans gallery `forValues` and variant rows.
1214
1214
  - Video posters are required: autoplaying video without a poster hurts LCP on the product page.
1215
1215
 
1216
- Not carried by a stored component: ai, category, document preview path, kind:entry (props), reference target, validation.items.
1216
+ Not carried by a stored component: ai, category, kind:entry (props), shopify reference.
1217
1217
 
1218
1218
  ### Featured product spotlight (`commerce-featured-product`)
1219
1219
 
@@ -1336,7 +1336,7 @@ Tags: media-heavy, references, deep-nesting, repeater, commerce, a11y, validatio
1336
1336
  - Coordinates are raw numbers today — there's no visual point picker bound to the image yet (gap).
1337
1337
  - Dots without labels fail WCAG 4.1.2; the label is required for that reason.
1338
1338
 
1339
- Not carried by a stored component: ai, category, document preview path, variants.
1339
+ Not carried by a stored component: ai, category, variants.
1340
1340
 
1341
1341
  ### Size guide table (`commerce-size-guide`)
1342
1342
 
@@ -1425,7 +1425,7 @@ Tags: commerce, conditional, validation, repeater, variants. Proves: Both cycle
1425
1425
  - `inherits` is a free string, not a reference to a sibling plan — renaming a plan leaves stale 'Everything in' lines (gap: references within the same entry).
1426
1426
  - Per-seat prices must say 'per seat' near the number, not only in the footnote.
1427
1427
 
1428
- Not carried by a stored component: ai, category, document preview path, variants.
1428
+ Not carried by a stored component: ai, category, variants.
1429
1429
 
1430
1430
  ### Usage-based price calculator (`pricing-usage-calculator`)
1431
1431
 
@@ -1492,7 +1492,7 @@ Tags: commerce, repeater, conditional, validation, rich-text. Proves: One plan o
1492
1492
  - A minimum term hidden in small print is a trust killer — it has its own field on purpose.
1493
1493
  - Mixed units (per month + per session) can't be summed into one honest monthly number without an assumption; show the breakdown.
1494
1494
 
1495
- Not carried by a stored component: category, document preview path.
1495
+ Not carried by a stored component: category.
1496
1496
 
1497
1497
  ### Enterprise contact card (`pricing-enterprise-card`)
1498
1498
 
@@ -1765,7 +1765,7 @@ Tags: repeater, a11y, variants, conditional, validation, media-heavy. Proves: Ty
1765
1765
  - Payment icons for methods not enabled at checkout are a common trust-breaker.
1766
1766
  - Icon-only badges need text; the title is required.
1767
1767
 
1768
- Not carried by a stored component: category, document preview path, variants.
1768
+ Not carried by a stored component: category, variants.
1769
1769
 
1770
1770
  ## Listings & feeds
1771
1771
 
@@ -1903,7 +1903,7 @@ Tags: deep-nesting, repeater, conditional, rich-text, validation, dynamic-query,
1903
1903
  - Version strings with spaces or dates as versions collide as anchors.
1904
1904
  - 60+ releases inline makes the section slow to edit — move to the collection.
1905
1905
 
1906
- Not carried by a stored component: category, segmented>4, validation.items, variants.
1906
+ Not carried by a stored component: category, segmented fallback, variants.
1907
1907
 
1908
1908
  ### Public roadmap (`public-roadmap`)
1909
1909
 
@@ -1948,7 +1948,7 @@ Tags: dynamic-query, references, conditional, repeater, validation, a11y. Proves
1948
1948
  - A label-less search input fails WCAG 1.3.1 / 4.1.2 — label is required.
1949
1949
  - Search pages must be noindex — the platform does it natively; never add a field for it.
1950
1950
 
1951
- Not carried by a stored component: category, reference target, variants.
1951
+ Not carried by a stored component: category, shopify reference, variants.
1952
1952
 
1953
1953
  ## Long-form & docs
1954
1954
 
@@ -2042,7 +2042,7 @@ Tags: embed, repeater, validation, variants. Proves: One example in N languages
2042
2042
  - API keys in sample code — replace real-looking secrets with $ENV placeholders.
2043
2043
  - The `code` field's built-in language list (html/css/js/liquid/json) doesn't cover API languages — the select carries it.
2044
2044
 
2045
- Not carried by a stored component: category, openMode, variants.
2045
+ Not carried by a stored component: category, variants.
2046
2046
 
2047
2047
  ### Knowledge-base article (`kb-article`)
2048
2048
 
@@ -2086,7 +2086,7 @@ Tags: dynamic-query, repeater, conditional, references, seo-structured, a11y, va
2086
2086
  - 300 inline terms is the ceiling — beyond that, use the collection.
2087
2087
  - Localised term lists re-sort per language (Ä, Ø, Ł) — sort with the locale's collation.
2088
2088
 
2089
- Not carried by a stored component: category, validation.items, variants.
2089
+ Not carried by a stored component: category, variants.
2090
2090
 
2091
2091
  ### Recipe (`recipe`)
2092
2092
 
@@ -2110,7 +2110,7 @@ Tags: deep-nesting, repeater, seo-structured, media-heavy, conditional, referenc
2110
2110
  - Dietary claims set at recipe level while an optional ingredient breaks them.
2111
2111
  - Timer fields filled but hasTimer off — hidden values still ship unless cleared on save.
2112
2112
 
2113
- Not carried by a stored component: category, kind:entry (props), reference target.
2113
+ Not carried by a stored component: category, kind:entry (props), shopify reference.
2114
2114
 
2115
2115
  ### Course curriculum (`course-curriculum`)
2116
2116
 
@@ -2132,7 +2132,7 @@ Tags: deep-nesting, repeater, conditional, references, validation, media-heavy,
2132
2132
  - Live lesson times stored in local time without a zone.
2133
2133
  - Five levels inline (course → module → lesson → resource → file) — keep resources tiny and inline.
2134
2134
 
2135
- Not carried by a stored component: category, segmented>4, variants.
2135
+ Not carried by a stored component: category, segmented fallback, variants.
2136
2136
 
2137
2137
  ### Legal / policy page (`legal-policy`)
2138
2138
 
@@ -2268,7 +2268,7 @@ Tags: repeater, media-heavy, variants, validation, a11y. Proves: Values with a r
2268
2268
  - Perks with prices or policies that change — keep them short and dated in HR, not here.
2269
2269
  - Nine-value lists — validation caps at eight; past five, nobody remembers them.
2270
2270
 
2271
- Not carried by a stored component: ai, category, item settings, variants.
2271
+ Not carried by a stored component: ai, category, variants.
2272
2272
 
2273
2273
  ### Careers list (`careers-list`)
2274
2274
 
@@ -2313,7 +2313,7 @@ Tags: seo-structured, conditional, references, repeater, validation, form. Prove
2313
2313
  - Closed roles deleted instead of closed: their URLs 404 and lose links. Close them.
2314
2314
  - Benefits retyped on every job drift — use the shared block.
2315
2315
 
2316
- Not carried by a stored component: category, item settings, kind:entry (props).
2316
+ Not carried by a stored component: category, kind:entry (props).
2317
2317
 
2318
2318
  ### About & mission with timeline (`about-timeline`)
2319
2319
 
@@ -2356,7 +2356,7 @@ Tags: deep-nesting, repeater, media-heavy, conditional, validation, a11y. Proves
2356
2356
  - Photos without credits get printed uncredited — credit is required for photos.
2357
2357
  - A stale .zip that no longer matches the assets shown.
2358
2358
 
2359
- Not carried by a stored component: category, group unused (props), variants.
2359
+ Not carried by a stored component: category, variants.
2360
2360
 
2361
2361
  ## Events & places
2362
2362
 
@@ -2404,7 +2404,7 @@ Tags: deep-nesting, references, seo-structured, conditional, commerce, repeater,
2404
2404
  - Cancelled events deleted rather than marked — Google keeps showing the old date.
2405
2405
  - Sold-out early-bird tiers left 'On sale' after salesEnd — use the window, not the badge.
2406
2406
 
2407
- Not carried by a stored component: category, item settings, kind:entry (props).
2407
+ Not carried by a stored component: category, kind:entry (props).
2408
2408
 
2409
2409
  ### Webinar registration (`webinar-registration`)
2410
2410
 
@@ -2426,7 +2426,7 @@ Tags: form, conditional, references, embed, validation, variants. Proves: One se
2426
2426
  - Leaving stage 'live' after the event — the page shows a dead stream.
2427
2427
  - Gating on-demand recordings of public talks lowers reach; gate deliberately.
2428
2428
 
2429
- Not carried by a stored component: ai, category, group unused (props), item settings, variants.
2429
+ Not carried by a stored component: ai, category, variants.
2430
2430
 
2431
2431
  ### Locations directory (`locations-directory`)
2432
2432
 
@@ -2523,7 +2523,7 @@ Tags: repeater, conditional, validation, a11y. Proves: Typed columns · rows fro
2523
2523
  - Past ~60 rows, keep the data in CSV or a collection; the grid stays usable but the page gets heavy.
2524
2524
  - Do not model 'striped' or 'compact' as booleans — they are variants.
2525
2525
 
2526
- Not carried by a stored component: ai, category, document preview path, variants.
2526
+ Not carried by a stored component: ai, category, variants.
2527
2527
 
2528
2528
  ### Table (`table-comparison`)
2529
2529
 
@@ -2544,7 +2544,7 @@ Tags: validation, a11y, seo-structured, references, commerce. Proves: The `table
2544
2544
  - A blank cell in a yes/no column is 'Not included'; a blank cell anywhere else is 'No value'.
2545
2545
  - Don't retype units in cells — the column carries them.
2546
2546
 
2547
- Not carried by a stored component: ai, category, document preview path.
2547
+ Not carried by a stored component: ai, category.
2548
2548
 
2549
2549
  ### Chart with annotations (`chart-attrition`)
2550
2550
 
@@ -2614,7 +2614,7 @@ Tags: commerce, deep-nesting, repeater, conditional, references, validation. Pro
2614
2614
  - SCHEMA GAP: option keys need to be unique within their step only (scoped uniqueness) — `unique` is neither scoped nor enforced.
2615
2615
  - Price deltas drift from Shopify variant prices; prefer reading the variant price and keeping priceDelta only for non-Shopify add-ons.
2616
2616
 
2617
- Not carried by a stored component: ai, category, reference target, variants.
2617
+ Not carried by a stored component: ai, category, shopify reference, variants.
2618
2618
 
2619
2619
  ### Map with markers (`stockist-map`)
2620
2620
 
@@ -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, slot allow, variants.
2776
+ Not carried by a stored component: ai, category, variants.
2777
2777
 
2778
2778
  ### Any-block module list (`polymorphic-modules`)
2779
2779
 
@@ -2817,7 +2817,7 @@ Tags: conditional, references, dynamic-query, commerce, validation. Proves: Manu
2817
2817
  - SCHEMA GAP: required-if — `maxPrice` is required only when visible; that works because hidden fields skip validation, but 'required when price = between AND minPrice is set' can't be written.
2818
2818
  - minPrice < maxPrice can't be validated (cross-field).
2819
2819
 
2820
- Not carried by a stored component: ai, category, reference target, variants.
2820
+ Not carried by a stored component: ai, category, shopify reference, variants.
2821
2821
 
2822
2822
  ### Global block with per-page overrides (`global-announcement-overrides`)
2823
2823
 
@@ -2885,7 +2885,7 @@ Tags: personalization, deep-nesting, conditional, repeater, validation. Proves:
2885
2885
  - SCHEMA GAP: a variant's hidden `content` is still required-validated by its own rules if `isControl` flips — conditions hide but can't relax `required` declaratively.
2886
2886
  - Personalized copy must not change the H1 for SEO purposes; the native page title stays the default's.
2887
2887
 
2888
- Not carried by a stored component: ai, category, document preview path, variants.
2888
+ Not carried by a stored component: ai, category, variants.
2889
2889
 
2890
2890
  ### Responsive layout settings (`responsive-layout-settings`)
2891
2891
 
@@ -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, slot allow, variants.
2931
+ Not carried by a stored component: ai, category, variants.
2932
2932
 
2933
2933
  ### References web (`references-web`)
2934
2934
 
@@ -2951,7 +2951,7 @@ Tags: references, dynamic-query, conditional, repeater, validation. Proves: Prod
2951
2951
  - SCHEMA GAP: `unique` on reference arrays isn't enforced; the same story can be pinned twice.
2952
2952
  - Referencing pages by id survives slug changes; storing hrefs doesn't.
2953
2953
 
2954
- Not carried by a stored component: category, reference target.
2954
+ Not carried by a stored component: category, shopify reference.
2955
2955
 
2956
2956
  ### Changelog with nested validation (`changelog-nested-validation`)
2957
2957
 
@@ -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, slot allow.
3044
+ Not carried by a stored component: category.
3045
3045
 
3046
3046
  ### Sticky scroll story (`scrollytelling`)
3047
3047
 
@@ -3086,7 +3086,7 @@ Tags: a11y, media-heavy, form, validation, conditional. Proves: Captions per lan
3086
3086
  - SCHEMA GAP: the sign-up form is modelled inline because forms are a separate system; ideally the block only references the form and the form owns labels/errors.
3087
3087
  - Autoplay over 5 seconds without a pause control fails WCAG 2.2.2; the help warns, nothing blocks it.
3088
3088
 
3089
- Not carried by a stored component: category, document preview path.
3089
+ Not carried by a stored component: category.
3090
3090
 
3091
3091
  ### Section theme tokens (`section-theme-tokens`)
3092
3092
 
@@ -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, slot allow, variants.
3175
+ Not carried by a stored component: ai, category, 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, slot allow, variants.
3217
+ Not carried by a stored component: ai, category, variants.
3218
3218
 
3219
3219
  ### Journal story (`core-journalStory`)
3220
3220
 
@@ -3235,7 +3235,7 @@ Tags: rich-text, references, media-heavy, seo-structured, localized, validation,
3235
3235
  - Reading time is computed by the template; no field stores it today, so don't copy "7 min read" into readingTime.
3236
3236
  - Bind the body wrapper as kind `document`, never `richtext`, or a save repaints the article from plain text.
3237
3237
 
3238
- Not carried by a stored component: ai, kind:entry (props), reference target.
3238
+ Not carried by a stored component: ai, kind:entry (props), shopify reference.
3239
3239
 
3240
3240
  ### Hero (`core-hero`)
3241
3241
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bettercms-ai/mcp",
3
- "version": "0.74.0",
3
+ "version": "0.76.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": {
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@bettercms-ai/device-auth": "^0.2.0",
35
- "@bettercms-ai/sdk": "^1.31.0",
35
+ "@bettercms-ai/sdk": "^1.32.0",
36
36
  "@modelcontextprotocol/sdk": "^1.30.0",
37
37
  "zod": "^4.3.6"
38
38
  },