@bettercms-ai/mcp 0.81.0 → 0.83.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 +56 -6
- package/dist/index.js.map +1 -1
- package/dist/skills/bettercms/SKILL.md +5 -4
- package/dist/skills/bettercms/references/frameworks.md +5 -2
- package/dist/skills/bettercms/references/getting-started.md +38 -1
- package/dist/skills/bettercms/references/next.md +10 -7
- package/dist/skills/bettercms/references/other-frameworks.md +24 -5
- package/dist/skills/bettercms/references/publishing.md +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2546,6 +2546,7 @@ var NO_QUESTIONS_INSTRUCTION = "Never stop a setup to ask the user: authoring (c
|
|
|
2546
2546
|
var NEXT_STEPS_DESCRIPTION = `Call this FIRST on a project. Returns \`receipt\` \u2014 \`done\` (live release, bound elements, conversion coverage, composed pages, published components and Layout), \`missing\`, \`nextAction\` and \`notes\` (unjudged: unknown, not done) \u2014 plus \`data\`, the unfinished items by \`ruleId\` (skill finish-site lists them). Each item cites its count and may carry \`payload\` {rows, total}, at most 20 rows. \`receipt.complete\` is the setup gate's verdict and \`receipt.gate\` its numbers per built route. Run \`receipt.gate.nextAction\`, call it again after each batch; you are finished only when \`complete\` is true. \`organise-content\`: pages and collections are in no folder \u2014 read ${STRUCTURE_PLAYBOOK_URI}, call suggest_content_structure and, once the user agrees, set_content_structure.`;
|
|
2547
2547
|
var LAYOUT_CHROME_INSTRUCTION = 'When the user asks to make the navigation, footer or other site chrome editable, or get_next_steps lists a `layout-*` or `chrome-duplicated` item: this is playbook \xA711 item 3. Chrome is the project Layout, never page fields: in the source, wrap each Section in `data-bcms-layout-section` (the slot, its base slug) and mark each value `data-bcms-layout-field="layout:<sections[slug].id>:<fieldId>"`, never `data-bcms-field` inside it, then push; the strip removes the page copies, never delete them by hand. On a site BetterCMS serves, publish_layout writes Layout VALUES into the live pages; a structure change waits for a Rebuild. Never place nav, footer or modal blocks or fields on a page: the Layout (or the site\'s own layout) draws chrome, so a page copy either duplicates it or renders nowhere (get_componentize_plan reports one as LAYOUT_CHROME).';
|
|
2548
2548
|
var CTA_BUTTON_INSTRUCTION = "A call to action is ONE `button` field (value {label, href, variant?, size?, arrow?, icon?, newTab?}), rendered with BcmsButton from @bettercms-ai/astro or @bettercms-ai/next: never a text field beside a link field. A page that already holds such a pair (primaryCtaText + primaryCtaHref) becomes one button with update_field `mergeHref`. Inside a component a CTA is a `button` block whose text and href two props target.";
|
|
2549
|
+
var NAMING_INSTRUCTION = "Names are 1-2 words of meaning per part: playbook \xA72 Naming.";
|
|
2549
2550
|
var STRUCTURE_EXAMPLE_PAYLOAD = {
|
|
2550
2551
|
version: 0,
|
|
2551
2552
|
doc: {
|
|
@@ -3115,6 +3116,18 @@ var SLOT_MULTIPLE_NOTE = "'slot' with config.multiple holds a list [{componentId
|
|
|
3115
3116
|
var PROP_V2_NOTE = "Props take the fields' V2 keys (\xA714): 'object' = ONE {child: value} from config.fields, \u226410 levels (field_depth_exceeded); datetime|slug|email|phone|json|location|tags|rating|code|reference|multi-reference as that field (a reference names contentModelId, or polymorphic + allowedModelSlugs; page reads hydrate its entries); helpMore, advanced, recommendedMax, openMode, config.scale, ui.layout rows|chips|gallery, ui.preview.fallback, showIf notEmpty|empty. Send helpText: null for a prop whose /kit schema has no description (omitted, the platform writes one).";
|
|
3116
3117
|
var LAYOUT_LOCK_NOTE = "A Global field with `overridable:false` + `lockReason` (add-field `field`, update-field `patch`) refuses page overrides (LAYOUT_FIELD_NOT_OVERRIDABLE); get_layout scope page lists stored ones as `shadowed`.";
|
|
3117
3118
|
var AUTHORING_DESCRIPTION = "Record which authoring architecture this site uses: 'components' (the default: reusable section components placed as blocks, which editors add, reorder and swap; on a site whose pages were DERIVED it keeps every field, value and binding, then run the componentize lane) or 'fields' (a typed field schema per page, for a blog, catalogue or directory). A deploy, a promote and every editor_setup record 'components' when nothing is set, so call this only to change it. Never ask the user: record it, say so in your final report, and tell them they can switch it in the dashboard.";
|
|
3119
|
+
var DELIVERY_KEY_DESCRIPTION = "Create a read-only delivery key for this project's own front end and return it once (it is never shown again: write it straight into the front end's .env under the name its SDK config reads, e.g. BCMS_API_KEY or BETTERCMS_API_KEY, never into chat or a commit). Published content needs no key (the SDK reads it by BCMS_PROJECT_ID), so create one only when the front end's config asks for a key. `scope: \"published\"` = content:read, no expiry; `scope: \"draft\"` also reads drafts and expires within the hour (a preview build's credential; editors' previews use the dashboard's preview link instead). Listed and revocable in Project \u2192 Settings \u2192 API keys like any other key. Requires artifact:write.";
|
|
3120
|
+
var DELIVERY_KEY_PARAMS = {
|
|
3121
|
+
name: "what it is for, shown in the key list (e.g. 'Front end (Vercel)')",
|
|
3122
|
+
scope: "published (content:read, the default) or draft (also drafts; expires within the hour)"
|
|
3123
|
+
};
|
|
3124
|
+
var FRONT_END_DESCRIPTION = 'Record where this project\'s own front end lives, so editors open drafts on it ("Preview on site") and a publish reaches it: `siteUrl` (its deployed origin), `framework` (next or astro: which preview route the SDK mounts), `draftPath` (Next only, when not /api/draft) and `revalidation` (a front end that revalidates instead of rebuilding). Call it after the front end is deployed; `npx @bettercms-ai/cli@latest deploy --to <host>` already registers the rebuild hook. Read the current values from get_project. Fields you omit are left as they are; null clears one. Requires artifact:write.';
|
|
3125
|
+
var FRONT_END_PARAMS = {
|
|
3126
|
+
siteUrl: "the deployed front end's origin, https://\u2026 (null clears it)",
|
|
3127
|
+
framework: "next, astro, react-ts, sveltekit or nuxt: picks the draft route (astro: /api/bcms/draft/enable; the rest: draftPath or /api/draft)",
|
|
3128
|
+
draftPath: "Next only: the draft-mode route when not /api/draft (null clears it)",
|
|
3129
|
+
revalidation: "a front end that revalidates instead of rebuilding: { webhookUrl (https), webhookSecret (16+ chars, also stored as BETTERCMS_WEBHOOK_SECRET on the front end) } (null clears it)"
|
|
3130
|
+
};
|
|
3118
3131
|
var MEDIA_DEFAULT_NOTE = "Leave the default (the CDN) unless the owner asked otherwise; never ask.";
|
|
3119
3132
|
var REBUILD_DESCRIPTION = "Rebuild from the connected repository, as the dashboard's Rebuild does. Use it when a get_next_steps fix names it, or after a push that started no build; then get_deploy_status { waitSeconds: 50 } until live, and editor_setup. 409 NOT_QUEUED: no repository (deploy_project the working tree) or publishing held.";
|
|
3120
3133
|
var withWait = (path, waitSeconds) => typeof waitSeconds === "number" && waitSeconds > 0 ? `${path}?wait=${Math.min(Math.round(waitSeconds), 50)}` : path;
|
|
@@ -3694,7 +3707,7 @@ var GIT_TEXT = {
|
|
|
3694
3707
|
var HOSTING_TEXT = {
|
|
3695
3708
|
list_env_vars: "The project's environment variables by NAME and scope (never a value), and `missing`: the ones the repository's .env.example declares that the project does not set. A site missing them builds and serves, then renders empty or crashes in the browser. Resolve `missing` by running `npx @bettercms-ai/cli@latest env push` in the repository: it uploads those values from the user's own .env files straight to BetterCMS, so they never pass through this conversation. Never read, print or ask the user to paste a value. When the values do not exist locally because the site reads its content from another CMS, move that content into BetterCMS instead (the bettercms skill's external-content reference). BetterCMS's own BCMS_* identifiers are supplied to every build and never need setting.",
|
|
3696
3709
|
list_hosting_connections: "The Vercel, Netlify and Cloudflare accounts connected to this workspace (id, provider, accountLabel, status; never a token), plus `connectUrl`, the dashboard page where a person connects one. Call it before deploy_to_host. If the provider the user wants has no connection with status `ok`, give the user `connectUrl` to connect it in their browser and stop until they have: you never handle OAuth or a host token yourself.",
|
|
3697
|
-
deploy_to_host: "Deploy this project to the user's own Vercel or Netlify account through their connection. BetterCMS builds the site and the host serves that build (skill publishing). The first call creates the site on the host and makes it the project's host; a later call for the same provider redeploys that site (`redeployed: true`). `connectionId` (from list_hosting_connections) defaults to the newest working one, `siteName` to the project's handle. A refusal carries a `code` and a `fixUrl` (not_connected, reconnect, pick_existing_site, grant_required, ADMIN_REQUIRED): each is fixed by the user at `fixUrl`, so relay it and stop. `deploymentQueued: false` means the project has no live build yet: deploy_project first, and that release reaches the host on its own. Never run the Vercel or Netlify CLI while a connection exists. Then poll get_host_deploy_status. Needs artifact:write, like deploy_project.",
|
|
3710
|
+
deploy_to_host: "Deploy this project to the user's own Vercel or Netlify account through their connection. BetterCMS builds the site and the host serves that build (skill publishing). The first call creates the site on the host and makes it the project's host; a later call for the same provider redeploys that site (`redeployed: true`). `connectionId` (from list_hosting_connections) defaults to the newest working one, `siteName` to the project's handle. A refusal carries a `code` and a `fixUrl` (not_connected, reconnect, pick_existing_site, grant_required, ADMIN_REQUIRED): each is fixed by the user at `fixUrl`, so relay it and stop. `deploymentQueued: false` means the project has no live build yet: deploy_project first, and that release reaches the host on its own. Never run the Vercel or Netlify CLI while a connection exists. A headless project is not deployed here: its own front end deploys with `npx @bettercms-ai/cli@latest deploy --to <host>`. Then poll get_host_deploy_status. Needs artifact:write, like deploy_project.",
|
|
3698
3711
|
get_host_deploy_status: "The connected project's recent deployments to Vercel, Netlify or Cloudflare, newest first: state (queued|deploying|live|failed), providerUrl, error, sha and targetName. Poll it after deploy_to_host until the newest one is `live`, whose `providerUrl` is the live URL to hand the user, or `failed`, whose `error` you read back to them."
|
|
3699
3712
|
};
|
|
3700
3713
|
async function builtinCopyId(client, builtinId) {
|
|
@@ -4279,7 +4292,7 @@ function buildToolDefs(deps) {
|
|
|
4279
4292
|
propUi: z.record(z.string(), z.record(z.string(), z.unknown()).nullable()).optional().describe(PROP_UI_ARG_NOTE),
|
|
4280
4293
|
propGroup: z.record(z.string(), z.record(z.string(), z.unknown()).nullable()).optional().describe("prop key \u2192 its ui.group ({id, label?, kind?, icon?, collapsed?}), null takes it out"),
|
|
4281
4294
|
propTab: z.record(z.string(), z.record(z.string(), z.unknown()).nullable()).optional().describe("prop key \u2192 its ui.tab ({id, label?, icon?, order?}), the V2 schema group it sits in. The FIRST top-level prop in a tab defines {id, label, icon?, order?}, later ones send {id}; \u22648 tabs; one group's members share one tab. null takes it out"),
|
|
4282
|
-
propLabel: z.record(z.string(), z.string().min(1).max(255)).optional().describe("prop key \u2192 label"),
|
|
4295
|
+
propLabel: z.record(z.string(), z.string().min(1).max(255)).optional().describe("prop key or dotted sub-field path \u2192 label"),
|
|
4283
4296
|
propHelpText: z.record(z.string(), z.string().max(200).nullable()).optional().describe("prop key \u2192 help text; null = no help on purpose (stays empty, never refilled)"),
|
|
4284
4297
|
override: z.boolean().optional().describe(OVERRIDE_NOTE),
|
|
4285
4298
|
ifMatch: z.number().int().min(0).optional().describe(COMPONENT_IF_MATCH_NOTE),
|
|
@@ -4798,6 +4811,25 @@ ${d.outline}` : "Proposed Content structure.", d);
|
|
|
4798
4811
|
z.object({ preference: z.enum(AUTHORING_CHOICES).describe("components or fields") }).shape,
|
|
4799
4812
|
async (c, a) => ok("Recorded the authoring architecture.", await data(c, "PATCH", `/management/projects/current/authoring-preference`, { preference: a.preference }))
|
|
4800
4813
|
),
|
|
4814
|
+
def(
|
|
4815
|
+
"create_delivery_key",
|
|
4816
|
+
"Create a read-only delivery key for the front end",
|
|
4817
|
+
DELIVERY_KEY_DESCRIPTION,
|
|
4818
|
+
z.object({ name: z.string().min(1).describe(DELIVERY_KEY_PARAMS.name), scope: z.enum(["published", "draft"]).optional().describe(DELIVERY_KEY_PARAMS.scope) }).shape,
|
|
4819
|
+
async (c, a) => ok("Created the delivery key. It is shown once: write it into the front end's .env now.", await data(c, "POST", `/management/projects/current/delivery-keys`, a))
|
|
4820
|
+
),
|
|
4821
|
+
def(
|
|
4822
|
+
"set_front_end",
|
|
4823
|
+
"Record where the project's own front end lives",
|
|
4824
|
+
FRONT_END_DESCRIPTION,
|
|
4825
|
+
z.object({
|
|
4826
|
+
siteUrl: z.string().nullable().optional().describe(FRONT_END_PARAMS.siteUrl),
|
|
4827
|
+
framework: z.enum(["next", "astro", "react-ts", "sveltekit", "nuxt"]).optional().describe(FRONT_END_PARAMS.framework),
|
|
4828
|
+
draftPath: z.string().nullable().optional().describe(FRONT_END_PARAMS.draftPath),
|
|
4829
|
+
revalidation: z.object({ webhookUrl: z.string(), webhookSecret: z.string() }).nullable().optional().describe(FRONT_END_PARAMS.revalidation)
|
|
4830
|
+
}).shape,
|
|
4831
|
+
async (c, a) => ok("Recorded the front end.", await data(c, "PATCH", `/management/projects/current/front-end`, a))
|
|
4832
|
+
),
|
|
4801
4833
|
def(
|
|
4802
4834
|
"set_binding_mode",
|
|
4803
4835
|
"Set how the site's bindings are resolved",
|
|
@@ -4859,7 +4891,7 @@ ${d.outline}` : "Proposed Content structure.", d);
|
|
|
4859
4891
|
fieldUi: z.record(z.string(), z.record(z.string(), z.unknown()).nullable()).optional().describe(FIELD_UI_ARG_NOTE),
|
|
4860
4892
|
fieldFieldset: z.record(z.string(), z.string().min(1).nullable()).optional().describe("path \u2192 fieldset id, null takes it out"),
|
|
4861
4893
|
fieldOrder: z.strictObject({ parentPath: z.string().min(1).optional(), order: z.array(z.string().min(1)).min(1).max(200) }).optional().describe("the full new order of one parent's child keys (top level without parentPath). An array with both zones needs 'KEY.zones.nonRepeatable' or 'KEY.zones.repeatable'; its bare key is a 400"),
|
|
4862
|
-
fieldLabel: z.record(z.string(), z.string().min(1).max(255)).optional().describe(
|
|
4894
|
+
fieldLabel: z.record(z.string(), z.string().min(1).max(255)).optional().describe('path or "<family>#section" \u2192 label'),
|
|
4863
4895
|
fieldHelpText: z.record(z.string(), z.string().max(500).nullable()).optional().describe("path \u2192 help text, null clears it"),
|
|
4864
4896
|
override: z.boolean().optional().describe(OVERRIDE_NOTE),
|
|
4865
4897
|
ifMatch: z.number().int().min(0).optional().describe(MODEL_IF_MATCH_NOTE),
|
|
@@ -6210,7 +6242,7 @@ ${notes.join("\n")}` : summary, created);
|
|
|
6210
6242
|
name: "create_form",
|
|
6211
6243
|
config: {
|
|
6212
6244
|
title: "Create a form",
|
|
6213
|
-
description: "Create a form in the connected project from a field schema. Confirm the fields with the user first. Field types: text, email, textarea, select (needs options), radio (needs options), checkboxes (needs options), checkbox, number, phone, date, url, consent, hidden, step (a divider: the fields after it are one page). Returns the new form's id. It
|
|
6245
|
+
description: "Create a form in the connected project from a field schema. Confirm the fields with the user first. Field types: text, email, textarea, select (needs options), radio (needs options), checkboxes (needs options), checkbox, number, phone, date, url, consent, hidden, step (a divider: the fields after it are one page). Returns the new form's id. It is created PUBLISHED when this connection may publish; otherwise it lands as a DRAFT (a draft form returns 403 on submit) \u2014 check `status` and call publish_form, or let the user publish it. A draft form placed on a page also goes live when that page is published. Embed it with `<BcmsForm form={getForm('Name')} />` from @bettercms-ai/next.",
|
|
6214
6246
|
inputSchema: createFormInput.shape
|
|
6215
6247
|
},
|
|
6216
6248
|
handler: guard(
|
|
@@ -6239,7 +6271,7 @@ ${notes.join("\n")}` : summary, created);
|
|
|
6239
6271
|
name: "publish_form",
|
|
6240
6272
|
config: {
|
|
6241
6273
|
title: "Publish a form",
|
|
6242
|
-
description: "Publish a form by id so it accepts submissions. create_form
|
|
6274
|
+
description: "Publish a form by id so it accepts submissions. A form create_form made without the publish right is a DRAFT, and a draft form answers every submit with 403 \u2014 call this before embedding it with `<BcmsForm form={getForm('Name')} />`. It re-bakes the project's site; `meta.rebuildQueued` says whether a rebuild was actually queued (false for a project with no connected source). 403 PUBLISH_NOT_GRANTED means this connection may author but not publish: say so and let the user publish from the dashboard Forms tab. 404 means the form is not in this connection's project.",
|
|
6243
6275
|
inputSchema: getFormInput.shape
|
|
6244
6276
|
},
|
|
6245
6277
|
handler: guard(
|
|
@@ -7362,6 +7394,24 @@ from the builtin blueprints \`list_components\` returns (\`builtin:*\`) instead
|
|
|
7362
7394
|
JSON. On an IMPORTED site, never materialize a builtin: read the repo's own components first
|
|
7363
7395
|
(\`src/components\`, its sections folder) and make ONE CMS component per source component, named
|
|
7364
7396
|
as the source names it \u2014 the site's Pricing section is "Pricing", not "Section 2" or "Simple".
|
|
7397
|
+
|
|
7398
|
+
**Naming: one or two words of MEANING, BEM-shaped, in Portable Text's words.** You choose every
|
|
7399
|
+
name, from what the page holds. The BLOCK is the section: what it IS (Hero, Pricing, FAQ), else
|
|
7400
|
+
the meaning words of its own heading ("We've spent years learning three timbers" \u2192 "Three
|
|
7401
|
+
Timbers", "Get in touch" \u2192 "Get In Touch"). A LIST is named by its own title, the heading or
|
|
7402
|
+
caption over it ("Our services" \u2192 "Services"), else by what its rows are (Plans, Questions,
|
|
7403
|
+
Steps, Links), never by its first row's copy. A list with its own title is a block inside the
|
|
7404
|
+
block: "About \u203A Services", its columns bare roles read under it (Title, Description). A field is
|
|
7405
|
+
its block plus its ELEMENT, said the way Portable Text titles its types (heading, paragraph,
|
|
7406
|
+
quote, list item, link, image, button) with a modifier only to tell two apart ("Hero headline",
|
|
7407
|
+
"Footer link 2 URL"). Never body copy, never a sentence. Rename anything to say its meaning better
|
|
7408
|
+
\u2014 \`propLabel\` (a table's sub-field by dotted path, \`plans.features\`), \`fieldLabel\` (a section by
|
|
7409
|
+
\`"<family>#section"\`), or \`data-bcms-section-label\` / \`data-bcms-label\` in the source \u2014 within
|
|
7410
|
+
the bound; a name you give is yours and is never re-derived. It is ENFORCED: a name outside the bound
|
|
7411
|
+
is refused with \`NAME_NOT_A_NAME\`, naming the rule and a \`suggested\` name per path (send it, or a
|
|
7412
|
+
better one), and a section the import could only call "Section N" holds \`get_next_steps\` until you
|
|
7413
|
+
name it. \`nameSource\` on a field says whose name it is: \`auto\` the platform's guess, \`human\` yours.
|
|
7414
|
+
|
|
7365
7415
|
On a DERIVED site run \`get_componentize_plan\` \u2192 \`componentize_sections\` FIRST \u2014 it does most
|
|
7366
7416
|
of this in one call, and once \`components\` is recorded each \`editor_setup\` of a derived site
|
|
7367
7417
|
runs it in bind mode and publishes the components, so expect ALREADY_COMPONENTIZED \u2014 the placements it wrote are
|
|
@@ -8663,7 +8713,7 @@ function buildServer(deps) {
|
|
|
8663
8713
|
// 🔴 The plain-language ask, routed — the stdio twin of the hosted connector's line
|
|
8664
8714
|
// (src/routes/mcp/index.ts MCP_INSTRUCTIONS). "Make my site editable" has one recipe and
|
|
8665
8715
|
// one definition of done; without this an agent converts the page it landed on and stops.
|
|
8666
|
-
instructions: RECEIPT_FIRST_INSTRUCTION + " " + NO_QUESTIONS_INSTRUCTION + " " + TOOL_LOADING_INSTRUCTION + " When the user asks to make a site or all of its pages editable and they were DERIVED at import: editor_setup, then get_next_steps until `receipt.gate.complete`. To convert its source or bind its fields: this is playbook \xA713. Read `bettercms://playbook/schema` \xA713, call get_binding_report and get_conversion_brief { complete: true }, convert EVERY route the brief lists, and finish only when get_binding_report shows coverage.pending empty on every route \u2014 not when the first page works. On a workspace-wide connection pass projectId on every call; never ask the user to re-scope the connection. " + LAYOUT_CHROME_INSTRUCTION + " " + CTA_BUTTON_INSTRUCTION + " When the user asks to componentize the whole site, to turn every section into a component, or to build a component library from the site: this is playbook \xA712. Read `bettercms://playbook/schema` \xA712, start with get_site_composition, and use the batch tools \u2014 componentize_sections, compose_pages, update_layout with `commands`, publish_components \u2014 rather than one call per component. Finish with get_site_composition and tell the user what the platform does not model (cookie banners, modals, breadcrumbs, pagination) and which components still need the owner's approval in the dashboard before they can be published. " + // The default after authoring (the structure standard): organise what you made. Same
|
|
8716
|
+
instructions: RECEIPT_FIRST_INSTRUCTION + " " + NO_QUESTIONS_INSTRUCTION + " " + TOOL_LOADING_INSTRUCTION + " When the user asks to make a site or all of its pages editable and they were DERIVED at import: editor_setup, then get_next_steps until `receipt.gate.complete`. To convert its source or bind its fields: this is playbook \xA713. Read `bettercms://playbook/schema` \xA713, call get_binding_report and get_conversion_brief { complete: true }, convert EVERY route the brief lists, and finish only when get_binding_report shows coverage.pending empty on every route \u2014 not when the first page works. On a workspace-wide connection pass projectId on every call; never ask the user to re-scope the connection. " + LAYOUT_CHROME_INSTRUCTION + " " + CTA_BUTTON_INSTRUCTION + " " + NAMING_INSTRUCTION + " When the user asks to componentize the whole site, to turn every section into a component, or to build a component library from the site: this is playbook \xA712. Read `bettercms://playbook/schema` \xA712, start with get_site_composition, and use the batch tools \u2014 componentize_sections, compose_pages, update_layout with `commands`, publish_components \u2014 rather than one call per component. Finish with get_site_composition and tell the user what the platform does not model (cookie banners, modals, breadcrumbs, pagination) and which components still need the owner's approval in the dashboard before they can be published. " + // The default after authoring (the structure standard): organise what you made. Same
|
|
8667
8717
|
// sentence as the hosted connector's MCP_INSTRUCTIONS.
|
|
8668
8718
|
STRUCTURE_DEFAULT_INSTRUCTION + " " + SKILLS_ROUTING_INSTRUCTION + " " + DOCK_UI_ROUTING_INSTRUCTION + " " + PUBLISH_HOLD_INSTRUCTION
|
|
8669
8719
|
}
|