@bettercms-ai/mcp 0.31.0 → 0.31.2
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/dist/index.js +49 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2965,7 +2965,7 @@ function buildToolDefs(deps) {
|
|
|
2965
2965
|
def(
|
|
2966
2966
|
"deploy_project",
|
|
2967
2967
|
"Deploy new source/build",
|
|
2968
|
-
"Deploy new source/build for the connected project and make it live at its <handle>.bettercms.site. Pass a .tgz or .zip of the project as a base64 string in `data`: SOURCE (has package.json) is built server-side in an isolated sandbox; a prebuilt static site is served as-is. Returns the release id + sha \u2014 then poll get_deploy_status until it is live. IMPORTANT \u2014 you MUST exclude node_modules, .git, and build output/caches (dist, build, .next, .astro, .cache) BEFORE creating the archive: a source deploy is reinstalled and built server-side, so those are never needed, and the upload has a hard size ceiling (~100 MB) enforced before the request reaches the server \u2014 an archive that includes node_modules is rejected in transit (a 413/502 with no server-side detail). Keep the archive to your own source files. Server-side stripping exists as a safety net, but it runs AFTER the upload and cannot rescue an over-limit body. For a LARGE archive (or if this returns a 413/502), use create_deploy_upload + deploy_from_upload instead \u2014 that path uploads straight to storage with no size ceiling.",
|
|
2968
|
+
"Deploy new source/build for the connected project and make it live at its <handle>.bettercms.site. Pass a .tgz or .zip of the project as a base64 string in `data`: SOURCE (has package.json) is built server-side in an isolated sandbox; a prebuilt static site is served as-is. Returns the release id + sha \u2014 then poll get_deploy_status until it is live. IMPORTANT \u2014 you MUST exclude node_modules, .git, and build output/caches (dist, build, .next, .astro, .cache) BEFORE creating the archive: a source deploy is reinstalled and built server-side, so those are never needed, and the upload has a hard size ceiling (~100 MB) enforced before the request reaches the server \u2014 an archive that includes node_modules is rejected in transit (a 413/502 with no server-side detail). Keep the archive to your own source files. Server-side stripping exists as a safety net, but it runs AFTER the upload and cannot rescue an over-limit body. For a LARGE archive (or if this returns a 413/502), use create_deploy_upload + deploy_from_upload instead \u2014 that path uploads straight to storage with no size ceiling. Returns `canvas.lane` \u2014 which live-preview lane the last release gave the editor (`bridge` / `draft-route` / `none`; see the playbook's section 11) \u2014 and `editorUrl`, the visual editor to hand the user.",
|
|
2969
2969
|
z.object({ data: z.string().min(1).describe("base64 .tgz/.zip of the project"), mimeType: z.string().optional() }).shape,
|
|
2970
2970
|
async (c, a) => ok("Deploy queued.", await raw(c, `/management/projects/deploy`, s(a.data), a.mimeType))
|
|
2971
2971
|
),
|
|
@@ -3008,7 +3008,7 @@ function buildToolDefs(deps) {
|
|
|
3008
3008
|
def(
|
|
3009
3009
|
"get_binding_report",
|
|
3010
3010
|
"Check what on the live site is editable",
|
|
3011
|
-
"The receipt for 'is this site actually EDITABLE?'. Every release scans the built HTML for the element that renders each CMS field value; this returns what that scan found, per slot: `mode` ('text-match' = bindings guessed from rendered text, 'declared' = the template declares them), `pagesInspected`, `bound` (elements carrying a binding), and `unmatched` \u2014 per page, each path with its kind and the reason it failed (not-declared / ambiguous-text / no-element). DEPLOY FIRST: before any release there is no report and this answers pages 0, mode null, refreshRequired true. It certifies exactly one thing \u2014 that every non-empty field of every page has SOME element carrying its path. It cannot see copy that was never modelled, so diff each route's visible text against its entry values yourself before calling a page done. Pass `slot` ('current' or 'staging') to read the other tree; the default is the slot this project's releases land in.",
|
|
3011
|
+
"The receipt for 'is this site actually EDITABLE?'. Every release scans the built HTML for the element that renders each CMS field value; this returns what that scan found, per slot: `mode` ('text-match' = bindings guessed from rendered text, 'declared' = the template declares them), `pagesInspected`, `bound` (elements carrying a binding), and `unmatched` \u2014 per page, each path with its kind and the reason it failed (not-declared / ambiguous-text / no-element). DEPLOY FIRST: before any release there is no report and this answers pages 0, mode null, refreshRequired true. It certifies exactly one thing \u2014 that every non-empty field of every page has SOME element carrying its path. It cannot see copy that was never modelled, so diff each route's visible text against its entry values yourself before calling a page done. `builtRoutes` lists the routes the live build has HTML for (null when unknown: runtime release, >500 routes, or a report older than this field). `canvas.lane` names the live-preview lane this build gives the editor \u2014 `bridge` (the build ships BcmsDraftBridge), `draft-route` (a node runtime rendering drafts server-side) or `none`, in which case get_next_steps carries the recipe (playbook section 11); null means the report predates the field. `unaddressable` counts visible text on the live site that no field owns, as the editor's x-ray measured it against the sha now serving \u2014 the one thing `unmatched` structurally cannot see; absent means nobody has turned that control on for this build. `unaddressable` is measured PER SLOT by the editor, which frames `current`; on a promote-gated project pass slot:'current' to read it. Pass `slot` ('current' or 'staging') to read the other tree; the default is the slot this project's releases land in.",
|
|
3012
3012
|
z.object({ slot: z.enum(["current", "staging"]).optional().describe("which release tree to read; defaults to the one this project deploys to") }).shape,
|
|
3013
3013
|
async (c, a) => ok("Binding report.", await data(c, "GET", `/management/projects/current/binding-report${q({ slot: a.slot })}`))
|
|
3014
3014
|
),
|
|
@@ -3218,7 +3218,7 @@ function buildToolDefs(deps) {
|
|
|
3218
3218
|
def(
|
|
3219
3219
|
"get_deploy_status",
|
|
3220
3220
|
"Get deploy/build status",
|
|
3221
|
-
"Get the connected project's deploy/build status: state (idle|queued|building|failed), whether it's publishing, the live commit sha, when it went live, and any build error. Poll this after deploy_project until state is idle with your sha live.",
|
|
3221
|
+
"Get the connected project's deploy/build status: state (idle|queued|building|failed), whether it's publishing, the live commit sha, when it went live, and any build error. Poll this after deploy_project until state is idle with your sha live. Also returns `canvas.lane` (the editor's live-preview lane for this site: `bridge` / `draft-route` / `none`) and `editorUrl`, the visual editor to hand the user.",
|
|
3222
3222
|
z.object({}).shape,
|
|
3223
3223
|
async (c) => ok("Deploy status.", await data(c, "GET", `/management/projects/deploy-status`))
|
|
3224
3224
|
)
|
|
@@ -3984,6 +3984,10 @@ in this order:
|
|
|
3984
3984
|
4. list_extraction_candidates / extract_component
|
|
3985
3985
|
now that blocks exist, fold any section repeated 3+ times
|
|
3986
3986
|
|
|
3987
|
+
Step 2 is not a formality: \`componentize_sections\` and \`create_component\` both land components
|
|
3988
|
+
as DRAFTS, so \`publish_component\` each one and publish the page \u2014 otherwise the canvas keeps
|
|
3989
|
+
painting the PUBLISHED copy and the editor reports N components unpublished.
|
|
3990
|
+
|
|
3987
3991
|
**Answering \`fields\` is a real answer, not a deferral.** A blog, a catalogue or a directory
|
|
3988
3992
|
is schema-first by design (\xA71) and should stay that way. Say so and move on.
|
|
3989
3993
|
|
|
@@ -3996,16 +4000,38 @@ the user rather than describing the choice in the abstract.
|
|
|
3996
4000
|
A deploy makes a site LIVE. It does not make it editable \u2014 those are different states, and the
|
|
3997
4001
|
gap between them is the single most common disappointment after an import.
|
|
3998
4002
|
|
|
3999
|
-
**The canvas is the real site
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4003
|
+
**The canvas is the real site.** A PUBLISHED page of a DEPLOYED site with DECLARED bindings
|
|
4004
|
+
frames the project's OWN build, with unpublished text painted over it, whether or not the draft
|
|
4005
|
+
has drifted from the published copy. STRUCTURAL drafts (new
|
|
4006
|
+
sections, reordering, a changed component definition) are the one thing that build cannot show,
|
|
4007
|
+
and there are four ways to see them: publish and redeploy; the editor's **Draft render** toggle,
|
|
4008
|
+
which swaps in the platform renderer on demand (approximate theme, one click back); live, through
|
|
4009
|
+
the draft bridge below (Next); or \u2014 for server-rendered sites \u2014 the node lane, coming.
|
|
4010
|
+
|
|
4011
|
+
Only FOUR states use the platform renderer by default: an UNPUBLISHED page, a page whose route
|
|
4012
|
+
the last build does not carry (\`get_binding_report.builtRoutes\`), a project with NO build at
|
|
4013
|
+
all, and a \`mode: "text-match"\` site whose draft has drifted (its elements are found by matching
|
|
4014
|
+
page text to stored values, so drifted text may be unclickable \u2014 declare the bindings, \xA713).
|
|
4015
|
+
Those are exactly where \`bcms-presentation.json\` matters \u2014 the renderer previews in a
|
|
4016
|
+
GENERIC theme unless the deploy artifact declares one at its root. Put the file in \`public/\`
|
|
4004
4017
|
(the build lands it at the artifact root) declaring the site's presentation \u2014 container width,
|
|
4005
4018
|
type scale, nav position and background, footer surface \u2014 as DTCG \`{"$type": ..., "$value": ...}\`
|
|
4006
4019
|
entries. Redeclare it on every deploy; absent means "declared nothing" and previews fall back
|
|
4007
4020
|
to platform defaults that will not look like this site.
|
|
4008
4021
|
|
|
4022
|
+
**Which live-preview lane THIS site has, and what it costs not to have one.**
|
|
4023
|
+
\`get_binding_report.canvas.lane\` names it: \`bridge\` (the build ships \`BcmsDraftBridge\` from
|
|
4024
|
+
\`@bettercms-ai/next/draft-bridge\`, so a structural draft re-renders inside the site's own
|
|
4025
|
+
build), \`draft-route\` (a node runtime whose app renders drafts server-side), or \`none\` \u2014 no
|
|
4026
|
+
lane, so every structural draft falls back to the platform renderer and its generic theme.
|
|
4027
|
+
\`null\` means the report predates the field; redeploy to learn. When it is \`none\`,
|
|
4028
|
+
\`get_next_steps\` names the recipe for this project's framework (\`canvas-lane-missing\`), and
|
|
4029
|
+
\xA713 step 5c has both. The same report carries \`unaddressable\`: how much VISIBLE text on the
|
|
4030
|
+
live site no field owns, counted against the sha now serving when an author turns the visual
|
|
4031
|
+
editor's **"Unbound text"** control on \u2014 \`unmatched\` cannot see it, because it only ever speaks
|
|
4032
|
+
about fields that already exist. Absent means nobody has turned that control on for this build,
|
|
4033
|
+
not that the site is clean.
|
|
4034
|
+
|
|
4009
4035
|
**A site built in the CMS with NO deployed build has only that renderer** \u2014 live and in the
|
|
4010
4036
|
editor \u2014 so the generic theme IS the site until you theme it. Theme it without a deploy:
|
|
4011
4037
|
\`update_project { presentation: { "page.maxWidth": { "$type": "dimension", "$value": 1200 },
|
|
@@ -4059,13 +4085,14 @@ renders. Three consequences, each load-bearing:
|
|
|
4059
4085
|
content. Div-built chrome outside \`<main>\` is still excluded; div-built chrome with no
|
|
4060
4086
|
\`<main>\` anywhere loses that protection.
|
|
4061
4087
|
|
|
4062
|
-
**Structural drafts can render on the real site too \u2014 the draft bridge.** Wrap your page's
|
|
4088
|
+
**Structural drafts can render on the real site too, LIVE \u2014 the draft bridge.** Wrap your page's
|
|
4063
4089
|
blocks in \`BcmsDraftBridge\` (\`@bettercms-ai/next/draft-bridge\`) instead of calling
|
|
4064
4090
|
\`BcmsBlocks\` directly: standalone it renders identically, and inside the visual editor it
|
|
4065
4091
|
receives the DRAFT block tree over a same-origin postMessage handshake and re-renders it with
|
|
4066
4092
|
the site's own components \u2014 so adding, removing or reordering sections previews in the site's
|
|
4067
|
-
real design
|
|
4068
|
-
|
|
4093
|
+
real design, with no publish and no Draft render detour. A bridge that answers wins over the
|
|
4094
|
+
toggle. Sites without one keep Draft render's approximate fallback, and a route the build does
|
|
4095
|
+
not carry falls back always (a static build has no file to frame).
|
|
4069
4096
|
|
|
4070
4097
|
**Hosting decides whether a canvas exists at all.** A site deployed here is framed through a
|
|
4071
4098
|
same-origin proxy \u2014 that is what the canvas requires. A site hosted elsewhere (your own Vercel,
|
|
@@ -4226,6 +4253,17 @@ conversion is yours to write.
|
|
|
4226
4253
|
and no network content step, by design. So the archive MUST SHIP its own
|
|
4227
4254
|
\`bcms-content.json\` \u2014 generate it locally with a delivery key and commit it. Without
|
|
4228
4255
|
one the site renders its fallbacks and the report says \`no-element\` for every path.
|
|
4256
|
+
5c. **Live preview lane.** Static HTML makes a page click-to-edit; it cannot show a STRUCTURAL
|
|
4257
|
+
draft \u2014 a new section, a reorder, a changed component \u2014 so those fall back to the platform
|
|
4258
|
+
renderer's generic theme unless the build can render drafts itself. Give it a lane:
|
|
4259
|
+
- NEXT: wrap the page's \`BcmsBlocks\` in \`BcmsDraftBridge\` from
|
|
4260
|
+
\`@bettercms-ai/next/draft-bridge\` and redeploy. The bridge marks its output
|
|
4261
|
+
\`data-bcms-canvas="bridge"\`, which is what the release scan records.
|
|
4262
|
+
- ASTRO: switch the pages to \`output: 'server'\` with the node adapter, mount
|
|
4263
|
+
\`@bettercms-ai/astro\`'s draft routes under \`src/pages/api/bcms/draft/\`, set
|
|
4264
|
+
\`BCMS_DRAFT_SECRET\`, redeploy, then switch the project to "Run as a server app" on the
|
|
4265
|
+
Hosting page. Never migrate a static site to SSR without asking the human first.
|
|
4266
|
+
Then \`get_binding_report.canvas.lane\` reads \`bridge\` or \`draft-route\` instead of \`none\`.
|
|
4229
4267
|
6. Push, or \`deploy_project\`; poll \`get_deploy_status\` until it is live. Then
|
|
4230
4268
|
\`get_binding_report\` \u2014 still \`text-match\`, and \`unmatched\` should be EMPTY because the
|
|
4231
4269
|
values are byte-equal to what the build renders. On a converted site read \`coverage\` too: it
|