@bettercms-ai/mcp 0.78.1 → 0.79.1

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.
@@ -1,5 +1,152 @@
1
1
  {
2
2
  "$comment": "GENERATED from the dashboard's Kit Library (KIT_LIBRARY + EXAMPLES) by scripts/kit-export.ts. Do not edit. Regenerate (dashboard: bun run kit:export -- --backend <backend checkout>).",
3
+ "fieldConfig": {
4
+ "read": {
5
+ "*": [
6
+ "placeholder",
7
+ "zones",
8
+ "options",
9
+ "fields"
10
+ ],
11
+ "text": [
12
+ "minLength",
13
+ "maxLength",
14
+ "pattern",
15
+ "patternMessage",
16
+ "inputType"
17
+ ],
18
+ "longtext": [
19
+ "minLength",
20
+ "maxLength",
21
+ "pattern",
22
+ "patternMessage",
23
+ "inputType"
24
+ ],
25
+ "url": [
26
+ "minLength",
27
+ "maxLength",
28
+ "pattern",
29
+ "patternMessage",
30
+ "inputType"
31
+ ],
32
+ "richtext": [
33
+ "minLength",
34
+ "maxLength",
35
+ "pattern",
36
+ "patternMessage",
37
+ "inputType"
38
+ ],
39
+ "document": [
40
+ "minLength",
41
+ "maxLength",
42
+ "pattern",
43
+ "patternMessage",
44
+ "inputType"
45
+ ],
46
+ "number": [
47
+ "min",
48
+ "max",
49
+ "step",
50
+ "scale",
51
+ "unit",
52
+ "validation"
53
+ ],
54
+ "rating": [
55
+ "min",
56
+ "max",
57
+ "step",
58
+ "scale",
59
+ "unit",
60
+ "validation"
61
+ ],
62
+ "select": [
63
+ "multiSelect"
64
+ ],
65
+ "multiselect": [
66
+ "min",
67
+ "max",
68
+ "allowCustom"
69
+ ],
70
+ "tags": [
71
+ "min",
72
+ "max",
73
+ "allowCustom"
74
+ ],
75
+ "code": [
76
+ "language",
77
+ "languages"
78
+ ],
79
+ "date": [
80
+ "timezone",
81
+ "includeTime"
82
+ ],
83
+ "datetime": [
84
+ "timezone",
85
+ "includeTime"
86
+ ],
87
+ "reference": [
88
+ "contentModelId",
89
+ "polymorphic",
90
+ "allowedModelSlugs",
91
+ "targets",
92
+ "filter"
93
+ ],
94
+ "multi-reference": [
95
+ "contentModelId",
96
+ "polymorphic",
97
+ "allowedModelSlugs",
98
+ "targets",
99
+ "filter",
100
+ "min",
101
+ "max"
102
+ ],
103
+ "array": [
104
+ "itemType",
105
+ "minItems",
106
+ "maxItems",
107
+ "item"
108
+ ],
109
+ "image": [
110
+ "media"
111
+ ],
112
+ "modular": [
113
+ "blockSlugs",
114
+ "minItems",
115
+ "maxItems"
116
+ ]
117
+ },
118
+ "host": {
119
+ "any": [
120
+ "sectionLabel",
121
+ "sectionShape",
122
+ "sectionTitle",
123
+ "format"
124
+ ],
125
+ "richtext": [
126
+ "accept",
127
+ "allowMultipleParagraphs",
128
+ "inline",
129
+ "allowTargetBlank",
130
+ "components",
131
+ "hostTag",
132
+ "features"
133
+ ]
134
+ },
135
+ "server": [
136
+ "seeded",
137
+ "shared",
138
+ "sharedValue",
139
+ "attr",
140
+ "numeric",
141
+ "iconFont",
142
+ "htmlClasses",
143
+ "units",
144
+ "lead",
145
+ "band",
146
+ "family",
147
+ "shape"
148
+ ]
149
+ },
3
150
  "categories": [
4
151
  {
5
152
  "name": "Navigation & chrome",
@@ -57,8 +57,8 @@ Listing tools needs no sign-in; the first tool **call** does.
57
57
  These hold on every task. The reference in brackets has the detail and the codes.
58
58
 
59
59
  1. **Confirm the bound project before any write**: §9 of the schema playbook, then `get_project`.
60
- Its `authoringPreference` (components, fields, or null while owed) is asked once, can be
61
- re-answered, and is the user's answer, never yours.
60
+ Its `authoringPreference` defaults to components (recorded by a deploy, a promote or setup)
61
+ and is never asked; the owner can switch it to fields.
62
62
  2. **Never create SEO fields** (§5b). Page and entry meta are native columns. [seo.md]
63
63
  3. **A page is a list of sections**, never loose top-level blocks, and never a nav, footer or
64
64
  modal: chrome is the Layout. A call to action is one `button` field, never a text field
@@ -235,6 +235,11 @@ coverage as `help`. The platform writes a line only for the four reasons above a
235
235
  elements with none; clear the finding by running `editor_setup`, or by writing one of the four
236
236
  kinds yourself, never with filler.
237
237
 
238
+ **Config keys.** Write only the `config` keys a field type documents (`maxLength`, `min`/`max`,
239
+ `options`, `itemType`, `zones`, a rich text's `accept`/`inline`): any other key sends that field to
240
+ the old classic editor. The import's own keys (`attr`, `numeric`, `units`, `band`, `seeded`, …) are the
241
+ server's: both MCP surfaces drop them from what you write.
242
+
238
243
  ## 6. Changing a schema safely
239
244
 
240
245
  A schema write alone is not a release. Before one, read the model with `get_content_model`, a few
@@ -323,7 +328,7 @@ production cannot store it. Translate before the first write.
323
328
  | `boolean` | `boolean` | `boolean` |
324
329
  | `slug` | `slug` (an entry's own slug stays on the entry) | `text` |
325
330
  | `url`, `link` | `link` | `link`; `url` for a media or embed address |
326
- | `email`, `phone` | `email`, `phone` | `text` |
331
+ | `email`, `phone` | `email`; a phone number is `text` with `richText: false` (`phone` opens only in the classic editor) | `text` |
327
332
  | `date`, `datetime` | `date`, `datetime` | `date` (`YYYY-MM-DD`); a datetime stays `text` |
328
333
  | `color` | `color` | `color` |
329
334
  | `select` | `select` | `select` with `config.options` |
@@ -341,14 +346,14 @@ production cannot store it. Translate before the first write.
341
346
  | `object` | `group` | `group` |
342
347
  | `array` of objects | `repeater`; item limits in `config.minItems` / `config.maxItems` (the editor shows "max N") | `table` |
343
348
  | `array` of strings | `array` (`itemType: "text"`) | `table` |
344
- | `array` of several item shapes | `modular` with `config.blockSlugs` (create the block models first) | separate components |
345
- | `slot` | `sections` or `component-ref` | `slot` (one instance; a list with `config.multiple`) |
349
+ | `array` of several item shapes | one component per shape, placed as sections; on a model, a `repeater` whose rows carry each shape's fields (`modular` opens only in the classic editor) | separate components |
350
+ | `slot` | components placed on the page (componentize); never a `sections` or `component-ref` field, which the page form cannot edit | `slot` (one instance; a list with `config.multiple`) |
346
351
  | a form `reference` | a `form` block inside the section | `form` |
347
352
 
348
353
  V2 features with no production shape are dropped and reported, never faked: a per-cell table
349
354
  type, per-breakpoint values (only `style.hideOn` differs by breakpoint) and per-field
350
355
  localization. Two have a shape now: typed table columns are a `repeater` with one field per column
351
- and `ui.layout: "table"`, and a slot with several children is a `slot` prop with `config.multiple`
356
+ (never `ui.layout: "table"`, which the editor cannot draw), and a slot with several children is a `slot` prop with `config.multiple`
352
357
  ([components.md](components.md) §1).
353
358
 
354
359
  | The plan says | Production word |
@@ -362,7 +367,7 @@ and `ui.layout: "table"`, and a slot with several children is a `slot` prop with
362
367
  | Variant, layout | Components sharing one `sectionType` ([components.md](components.md)) |
363
368
  | Listing | `collection` block (§4) |
364
369
  | Picks | `multi-reference` |
365
- | Polymorphic array, modules | `modular` field |
370
+ | Polymorphic array, modules | one component per shape |
366
371
 
367
372
  Tools and reports use the production word. Labels and help an editor reads never say
368
373
  "document": the `document` field is labelled Body.
@@ -87,9 +87,11 @@ its number, a `fixCode` and a `fix`, the call that closes it.
87
87
  (`fixCode`, `count`, the `fix` of its first row, the first `routes`), two with the same count in a
88
88
  fixed order. Run it on every row that carries that `fixCode`, call `get_next_steps`, and repeat
89
89
  until `complete`: following it reaches `complete` with no step that changes nothing. A fix no
90
- tool can make is named only when nothing else is left. A `fix` of `null` means no tool closes that row (a collection's listing
91
- route, a URL that cannot be placed, two pages nobody but the owner can choose between): put it to
92
- the user and stop retrying. Treat a row that its fix did not move the same way.
90
+ tool can make is named only when nothing else is left. A `fix` of `null` means no tool closes that row by itself: its
91
+ `detail` names what to change in the site's code, so change it, commit, push and `rebuild_project`.
92
+ Only a collection's listing route, a URL that cannot be placed and two pages nobody but the owner
93
+ can choose between are left; record each as an exception with a true reason, never stop to ask. A
94
+ row its fix did not move twice is recorded the same way.
93
95
 
94
96
  A `sections` or `style` row is a page nobody can add a section to, reorder or space, however
95
97
  complete its copy is. Its `fixCode` names the one fix, and `fix` the call when a tool can make it:
@@ -97,8 +99,8 @@ complete its copy is. Its `fixCode` names the one fix, and `fix` the call when a
97
99
  | `fixCode` | The fix |
98
100
  |---|---|
99
101
  | `run-sections-conversion` | Only the site's code can draw this page's sections: its app renders the route, a framework hydrates the page whole (`PAGE_HYDRATED`), or the release could not map its bands. In a checkout run `npx @bettercms-ai/convert@latest --sections --root .` ([componentize.md](componentize.md) §5), or call `componentize_sections` with `codemod: true` and the plan's `digest`; `--upgrade-sections` for a `style` row. Then push and release |
100
- | `rebuild` | The build that serves is older than what makes the row pass: a published section, the wrap's commit (`wrap: "wrapped"` on a row that still fails), or the in-place switch. No tool starts one: ask the user to push and Rebuild |
101
- | `enable-in-place-structure` | A static page the release can write by itself, and the project's in-place structure switch is off. Setup switches it on for a project it creates; on an existing one it is the operator's call. No repository change |
102
+ | `rebuild` | The build that serves is older than what makes the row pass: a published section, the wrap's commit (`wrap: "wrapped"` on a row that still fails), or the in-place switch. Push what changed, then `rebuild_project` and `get_deploy_status { waitSeconds: 50 }` until it is live |
103
+ | `enable-in-place-structure` | A static page the release can write by itself, and the project's in-place structure switch is off. Setup switches it on for a project it creates; on an existing one, `update_project { structureInPlace: true }`. No repository change |
102
104
  | `run-setup` | Nothing measured what the row reads, or a page is still to register: `editor_setup { force: true }`, then read again |
103
105
 
104
106
  The other rows name their fix the same way:
@@ -11,11 +11,9 @@ for what it leaves out.
11
11
 
12
12
  ## Communication style
13
13
 
14
- Be succinct. Say what you did ("Converted 12 routes; 3 values still unmatched on /pricing"), ask
15
- direct questions, and skip narrating what you are about to do. Give numbers, not adjectives.
16
-
17
- Before starting, tell the user they can pause and resume anytime by saying
18
- **"Continue BetterCMS setup"**.
14
+ Be succinct. Say what you did ("Converted 12 routes; 3 values still unmatched on /pricing") and
15
+ skip narrating what you are about to do. Give numbers, not adjectives. Finish the setup in this
16
+ run: do not stop to ask anything the sections below give an answer for.
19
17
 
20
18
  **RESUME TRIGGER.** On "Continue BetterCMS setup", read `get_project`, `get_next_steps` and
21
19
  `get_binding_report` for the project and the gap ledger at `.bettercms/ledger.json` if it exists,
@@ -42,17 +40,16 @@ Check: the MCP answers for this project id, and this folder is its repo.
42
40
  added while you run loads only when the agent starts, and every step below works on that
43
41
  folder's source.
44
42
 
45
- ### Phase 2 — The questions the MCP requires, and no others
46
-
47
- Check: `get_project` shows `authoringPreference` set and the user has answered media delivery.
43
+ ### Phase 2 — No questions: the defaults are recorded
48
44
 
49
- Ask exactly these two, each through its tool, and never answer them yourself:
45
+ Nothing here is asked. Record and report:
50
46
 
51
- 1. **Authoring**: `set_authoring_preference` (components or fields). Recommend components for a
52
- marketing site. It is asked once per project and can be re-answered.
53
- 2. **Media delivery**: `set_media_delivery` (the BetterCMS CDN, recommended, or the API origin).
47
+ 1. **Authoring**: components. A deploy, a promote and every `editor_setup` record it when nothing
48
+ is set; call `set_authoring_preference` only if the prompt you were started with names `fields`.
49
+ 2. **Media delivery**: the BetterCMS CDN, the project's default. Leave it.
50
+ 3. **Git**: the prompt you were started with says whether you may push. Follow it; never ask.
54
51
 
55
- Everything else has a default. Do not ask about it; decide, then report what you decided:
52
+ Everything else has a default too. Do not ask about it; decide, then report what you decided:
56
53
 
57
54
  - **Scope is the whole site**: every page, section, heading, paragraph, list item, link and image
58
55
  the site renders. Not the home page first, not "the main copy".
@@ -85,8 +82,8 @@ convert the source, `submit_conversion_receipt` also returned complete.
85
82
  finish line. Run the `convert_site` prompt only when the job is to convert the source (the gate
86
83
  asks for it, the owner wants the code to declare its bindings, or the project is headless), and
87
84
  then to its own complete receipt, never a partial one.
88
- 4. When the answer was components: `get_componentize_plan`, confirm it with the user, apply it
89
- with `componentize_sections`, then the repository half (`componentize_sections { codemod: true }`
85
+ 4. With components recorded: `get_componentize_plan`, then apply it with
86
+ `componentize_sections` (the owner can undo it), then the repository half (`componentize_sections { codemod: true }`
90
87
  when there is no checkout) and `submit_componentize_receipt` ([componentize.md](componentize.md)).
91
88
  5. Work the rest through [finish-site.md](finish-site.md) (gap ledger, repair order, proof loop).
92
89
  The gate's `sections` and `style` rows are part of it: a setup whose pages cannot take a new
@@ -122,11 +122,11 @@ every entry and are not repeated in the tables. SEO fields are never listed.
122
122
  | Map pin | `location` (lat, lng, optional label). Never two text fields |
123
123
  | Tags, amenities, bullet lists | `array` with `itemType: "text"`. One choice from a fixed list is `select` |
124
124
  | Rows of the same shape (hours, facts, metrics, tickets) | `repeater` of `text`, `number`, `select`, `boolean` children |
125
- | Mixed ordered blocks in a case study | `modular` |
125
+ | Mixed ordered blocks in a case study | one component per block shape, placed as sections |
126
126
  | One or many other entries | `reference`, `multi-reference`. A missing target is refused on write |
127
- | Call to action | `button` (label and link in one value). A bare link is `link`; also `email`, `phone` |
127
+ | Call to action | `button` (label and link in one value). A bare link is `link`; also `email`; a phone number is `text` |
128
128
  | Date, date and time | `date`, `datetime`. Keep the zone as a `text` IANA name beside it when the site shows times |
129
- | A spec or comparison table | `repeater` with one field per column (any field type) and `ui.layout: "table"`. There is no separate table field type |
129
+ | A spec or comparison table | `repeater` with one field per column (any field type). There is no separate table field type |
130
130
 
131
131
  An external system's id (`"store_product_id"`, `"ats_job_id"`, `"feed_id"`, `"lms_course_id"`)
132
132
  is a `text` field kept as migration metadata and locked: `readOnly: "developer"` with a
@@ -261,7 +261,7 @@ Projects collection, `urlPattern` `/work/:slug` (or the established prefix):
261
261
  | `"year"` | `number` | |
262
262
  | `"services"` | `multi-reference` to Services, or `array` of text | References when service pages exist |
263
263
  | `"cover_image"`, `"excerpt"` | `image`, `longtext` | Words baked into a hero image move into fields |
264
- | `"modules"` or `"body"` | `modular`, or `document` | `modular` (text, image, gallery, quote, video, stats blocks) for image-led studies; `document` when mostly prose |
264
+ | `"modules"` or `"body"` | components, or `document` | one component per block (text, image, gallery, quote, video, stats) for image-led studies; `document` when mostly prose |
265
265
  | `"results"` | `repeater`: `"value"`, `"label"` | Only verified outcomes |
266
266
  | `"credits"` | `repeater`: `"role"`, `"name"` | |
267
267
  | `"testimonial"` | `reference` to Testimonials | |
@@ -207,7 +207,6 @@ write new rich text in that shape.
207
207
  | 409 `unique_conflict` | Another entry already holds this value in a unique field. `conflicts` names it | Match to that entry and update it; do not create a twin |
208
208
  | 409 `locale_conflict` | The translation group already has an entry in that locale. `errors` names `locale` or `translationOf` | Edit the existing translation |
209
209
  | 409 `Version conflict` (entries), `VERSION_CONFLICT` (sidebar, section zones) | Someone wrote since your read. The entry body carries `currentVersion` | Read again, re-apply your change to the fresh value, write with the new version |
210
- | 409 `AUTHORING_DECISION_REQUIRED` | Deploy or promote was called before a human chose components or fields. `message` is the question | Ask the user, then `set_authoring_preference`. Do not retry or route around it |
211
210
  | 409 `stale-plan` | The site changed after the componentize plan was read; `digest` is the current one | `get_componentize_plan` again, re-confirm, resubmit with the new digest |
212
211
  | 409 `style-edits` | The conversion receipt lists changed classes or styles. `styleEdits` holds up to 40 tokens | Restore every token, rerun `npx @bettercms-ai/convert --verify-styles`, resubmit the receipt |
213
212
  | 400 `digest-mismatch` | The receipt was built for a different brief | Read the brief again and rebuild the receipt against it |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bettercms-ai/mcp",
3
- "version": "0.78.1",
3
+ "version": "0.79.1",
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": {