@bettercms-ai/mcp 0.67.1 → 0.68.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.
- package/dist/index.js +18 -11
- package/dist/index.js.map +1 -1
- package/dist/skills/bettercms/references/bindings.md +3 -0
- package/dist/skills/bettercms/references/componentize.md +4 -3
- package/dist/skills/bettercms/references/components.md +3 -0
- package/dist/skills/bettercms/references/content-modeling.md +30 -3
- package/dist/skills/bettercms/references/dock-input.md +3 -0
- package/dist/skills/bettercms/references/finish-site.md +1 -1
- package/dist/skills/bettercms/references/site-review.md +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2694,6 +2694,8 @@ var NEW_TOOL_TEXT = {
|
|
|
2694
2694
|
};
|
|
2695
2695
|
var DELETE_PAGE_RUNTIME_BUNDLE = " Or, with no pageId, `runtimeBundle`: 'report' lists the duplicate pages derived from a server app's own bundle (`app/` folders); 'apply' retires them and their empty folders.";
|
|
2696
2696
|
var PARAM_TEXT = {
|
|
2697
|
+
helpText: "shown under the field: its purpose, where it shows, any constraint; never its label or value. Omitted: written for you.",
|
|
2698
|
+
describes: "for editors: what it is and holds; omitted: written for you",
|
|
2697
2699
|
runtimeBundle: "instead of pageId: the server-app bundle cleanup",
|
|
2698
2700
|
pageRef: "page id or path ('/de/about'); a bare slug only when one page has it",
|
|
2699
2701
|
editorSetupForce: "re-run a setup already ready for the live build",
|
|
@@ -2962,9 +2964,7 @@ var fieldShape = {
|
|
|
2962
2964
|
// builder. They were unreachable from MCP for ONE reason: the OutField/toField whitelist
|
|
2963
2965
|
// below did not model them, so they were stripped after the model had gone to the trouble of
|
|
2964
2966
|
// sending them. Declaring them here is what makes the existing panel agent-writable.
|
|
2965
|
-
helpText: z.string().max(500).optional().describe(
|
|
2966
|
-
"one line of guidance shown UNDER this field in the editor \u2014 what to write here, not what the field is. Write it for the person typing ('Roughly 60 characters; it becomes the browser tab title'), not for a developer."
|
|
2967
|
-
),
|
|
2967
|
+
helpText: z.string().max(500).optional().describe(PARAM_TEXT.helpText),
|
|
2968
2968
|
showIf: z.object({
|
|
2969
2969
|
match: z.enum(["all", "any"]),
|
|
2970
2970
|
rules: z.array(
|
|
@@ -3281,6 +3281,7 @@ var withProjectId = (def) => ({
|
|
|
3281
3281
|
return currentProject.run(arg("projectId"), () => currentBranch.run(arg("branchId"), () => def.handler(args)));
|
|
3282
3282
|
}
|
|
3283
3283
|
});
|
|
3284
|
+
var autoHelpNote = (args) => typeof args.helpText === "string" && args.helpText.trim() ? "" : " No helpText was sent, so the platform wrote it (helpSource: auto); send helpText with update_field to write your own.";
|
|
3284
3285
|
function buildToolDefs(deps) {
|
|
3285
3286
|
async function withClient(fn) {
|
|
3286
3287
|
const token = await deps.auth.getAccessToken();
|
|
@@ -3382,7 +3383,7 @@ function buildToolDefs(deps) {
|
|
|
3382
3383
|
const createModelInput = z.object({
|
|
3383
3384
|
name: z.string().min(1).describe("human model name, e.g. 'Blog Post'"),
|
|
3384
3385
|
slug: slug.describe("url-safe unique slug, e.g. 'blog-post'"),
|
|
3385
|
-
description: z.string().optional(),
|
|
3386
|
+
description: z.string().optional().describe(PARAM_TEXT.describes),
|
|
3386
3387
|
urlPattern: urlPatternArg,
|
|
3387
3388
|
kind: z.enum(["model", "block"]).optional().describe(
|
|
3388
3389
|
"'model' (default) = a collection with its own entries. 'block' = a type that exists only to be stacked inside another model's 'modular' field \u2014 it holds no entries, and create_content_entry against it is refused. Create blocks FIRST, then the model whose modular field lists their slugs. Cannot be changed later."
|
|
@@ -3614,7 +3615,7 @@ function buildToolDefs(deps) {
|
|
|
3614
3615
|
z.object({ type: z.literal("set-section-state"), ...sectionTarget, state: z.enum(["inherit", "override-content", "customize-structure", "disable", "reset"]) }),
|
|
3615
3616
|
z.object({ type: z.literal("add-section"), name: z.string().min(1), icon: layoutIcon, zone: z.enum(["before_page", "after_page"]) }),
|
|
3616
3617
|
z.object({ type: z.literal("restore-section"), section: z.object({ id: z.string().min(1) }).passthrough(), data: z.object({ fields: z.record(z.string(), z.unknown()) }), placement: z.object({ zone: z.enum(["above-page-content", "below-page-content"]), localOrderKey: z.string().min(1), afterSectionId: z.string().optional(), beforeSectionId: z.string().optional() }).optional() }),
|
|
3617
|
-
z.object({ type: z.literal("update-section"), ...sectionTarget, name: z.string().min(1).optional(), icon: layoutIcon.optional(), slug: z.string().min(1).optional(), zone: z.enum(["above-page-content", "below-page-content"]).optional(), orderKey: z.string().min(1).optional() }),
|
|
3618
|
+
z.object({ type: z.literal("update-section"), ...sectionTarget, name: z.string().min(1).optional(), icon: layoutIcon.optional(), slug: z.string().min(1).optional(), zone: z.enum(["above-page-content", "below-page-content"]).optional(), orderKey: z.string().min(1).optional(), description: z.string().optional() }),
|
|
3618
3619
|
z.object({ type: z.literal("remove-section"), ...sectionTarget }),
|
|
3619
3620
|
z.object({ type: z.literal("move-section"), ...sectionTarget, afterId: z.string().nullable().optional(), beforeId: z.string().nullable().optional() }),
|
|
3620
3621
|
z.object({ type: z.literal("add-field"), ...sectionTarget, parentFieldId: z.string().optional(), fieldType: z.enum(["text", "longtext", "richtext", "number", "toggle", "date", "image", "file", "link", "email", "phone", "select", "color", "json", "reference", "multi-reference", "group", "repeater"]).optional(), field: z.object({ id: z.string(), slug: z.string(), label: z.string(), type: z.string() }).passthrough().optional() }),
|
|
@@ -3653,19 +3654,19 @@ function buildToolDefs(deps) {
|
|
|
3653
3654
|
"conversion"
|
|
3654
3655
|
]);
|
|
3655
3656
|
const sectionType = z.string().min(1).max(64).describe(
|
|
3656
|
-
"section family, e.g. 'Hero' \u2014 set this with a library category to make the component selectable in the page editor's 'Add a section' picker. Components sharing
|
|
3657
|
+
"section family, e.g. 'Hero' \u2014 set this with a library category to make the component selectable in the page editor's 'Add a section' picker. Components sharing one are layout variants of one section."
|
|
3657
3658
|
);
|
|
3658
3659
|
const allowedOn = z.array(z.string().regex(/^(\*|slug:[a-z0-9-]+|type:(singleton|dynamic|template))$/)).max(100).describe("placement allowlist: *, slug:<page-slug>, and/or type:singleton|dynamic|template");
|
|
3659
3660
|
const createComponentInput = z.object({
|
|
3660
3661
|
name: z.string().min(1),
|
|
3661
3662
|
slug: slug.describe("url-safe unique slug (lowercase letters/numbers/hyphens)"),
|
|
3662
3663
|
category: componentCategory.optional().describe("defaults to 'custom'"),
|
|
3663
|
-
group: z.string().min(1).max(100).optional().describe("the folder editors see in the dashboard's Components tab,
|
|
3664
|
+
group: z.string().min(1).max(100).optional().describe("the folder editors see in the dashboard's Components tab, by NAME (e.g. 'Sections', 'Forms'); CREATED when missing. Separate from `category`, the picker tab."),
|
|
3664
3665
|
sectionType: sectionType.optional(),
|
|
3665
3666
|
variantOf: z.string().min(1).max(255).optional().describe("id/slug of the component this is a VARIANT of: joins or starts its family (422 if its shared inputs are missing)"),
|
|
3666
3667
|
projectId: z.string().nullable().optional().describe("owning project id; null creates a workspace-wide global component"),
|
|
3667
3668
|
allowedOn: allowedOn.optional(),
|
|
3668
|
-
description: z.string().optional(),
|
|
3669
|
+
description: z.string().optional().describe(PARAM_TEXT.describes),
|
|
3669
3670
|
blockJson: z.array(blockObject).default([]).describe("the component's block tree"),
|
|
3670
3671
|
props: z.array(componentPropObject).default([]).describe(
|
|
3671
3672
|
"overridable fields. DECLARE A PROP \u2014 WITH A `target` \u2014 for every string, link and image a marketer will ever touch: only the leaves a prop targets are click-to-edit. Each one may carry `ui` to say how its control presents in the inspector \u2014 a collapsed group, what titles and thumbnails a table's rows, whether that table's rows can be dragged at all."
|
|
@@ -5179,7 +5180,7 @@ ${notes.join("\n")}` : summary, created);
|
|
|
5179
5180
|
body: JSON.stringify(input2),
|
|
5180
5181
|
headers: confirmedHeaders(true)
|
|
5181
5182
|
})).data : await client.addPageFields(args.pageId, input2);
|
|
5182
|
-
return ok(`Added field '${args.key}' to page '${page.title}'. Page now has ${page.fields.length} field(s)
|
|
5183
|
+
return ok(`Added field '${args.key}' to page '${page.title}'. Page now has ${page.fields.length} field(s).${autoHelpNote(args)}`, page);
|
|
5183
5184
|
}
|
|
5184
5185
|
const modelId = args.modelId;
|
|
5185
5186
|
const model = await client.getModel(modelId);
|
|
@@ -5208,7 +5209,7 @@ ${notes.join("\n")}` : summary, created);
|
|
|
5208
5209
|
headers: { ...opts ? { "If-Match": `W/"${opts.ifMatch}"` } : {}, ...confirmedHeaders(true) }
|
|
5209
5210
|
})).data : opts ? await client.updateModel(modelId, input, opts) : await client.updateModel(modelId, input);
|
|
5210
5211
|
return ok(
|
|
5211
|
-
`Added field '${args.key}' to '${updated.name}'${args.after ? ` after '${args.after}'` : ""}. Model now has ${updated.fields.length} field(s)
|
|
5212
|
+
`Added field '${args.key}' to '${updated.name}'${args.after ? ` after '${args.after}'` : ""}. Model now has ${updated.fields.length} field(s).${autoHelpNote(args)}`,
|
|
5212
5213
|
updated
|
|
5213
5214
|
);
|
|
5214
5215
|
})
|
|
@@ -7031,7 +7032,13 @@ Do not stop at the plan or at a partial receipt \u2014 finish the whole site, ne
|
|
|
7031
7032
|
8. \`get_binding_report\`: \`unmatched\` 0, \`unaddressable\` under 2% per route; fix the SOURCE, deploy, re-read (playbook \xA711).
|
|
7032
7033
|
9. \`set_binding_mode { declaredBindings: true }\`, deploy AGAIN and poll, then confirm \`get_binding_report\`
|
|
7033
7034
|
reads mode "declared", unmatched 0, bound above 0, \`coverage.pending\` empty. Send me that report.
|
|
7034
|
-
10.
|
|
7035
|
+
10. \`get_next_steps\`: if it lists \`upgrade-section-roots\` (section spacing and style handles), in the repo run
|
|
7036
|
+
\`npx @bettercms-ai/convert@latest --upgrade-sections --root . --dry-run\`, read the plan, then run it for real. For every
|
|
7037
|
+
root its receipt lists as \`skipped\`, pass the block down by hand: \`{...sectionRootAttrs(block)}\` on the section root, or
|
|
7038
|
+
\`data-bcms-style=""\` plus \`style={...}\` from \`block.style\`. Run \`--verify-styles\` again and restore what it lists (the
|
|
7039
|
+
marker and the inline style from \`block.style\` are allowed; changing a class or an existing style is not). Deploy,
|
|
7040
|
+
poll, call \`get_next_steps\` again and tell me what it still lists. Not listed: say so and move on; invent no work.
|
|
7041
|
+
11. Ask me whether to commit and push to my repository, commit only, or leave it uncommitted (unpushed, the
|
|
7035
7042
|
next rebuild from my repo drops it). Touch git only as I answer.`;
|
|
7036
7043
|
var FIELD_UI_PROMPT = {
|
|
7037
7044
|
title: "Declare how fields LOOK in the editor (guided)",
|