@bettercms-ai/mcp 0.25.2 → 0.26.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.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/token-store.ts","../src/device-auth.ts","../src/server.ts","../src/tools.ts","../../types/src/component.ts","../../types/src/layout-lucide-icons.ts","../src/prompts.ts","../src/playbook.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { loadConfig } from \"./config.js\";\nimport { FileTokenStore } from \"./token-store.js\";\nimport { DeviceAuthClient } from \"./device-auth.js\";\nimport { buildServer } from \"./server.js\";\n\nexport { buildServer } from \"./server.js\";\nexport { DeviceAuthClient } from \"./device-auth.js\";\nexport { loadConfig } from \"./config.js\";\n\n/** Entrypoint for the `bettercms-mcp` stdio server. */\nasync function main(): Promise<void> {\n const config = loadConfig();\n const store = new FileTokenStore(config.credentialsPath, config.apiUrl);\n const auth = new DeviceAuthClient(config, store);\n const server = buildServer({ auth, managementBaseUrl: config.managementBaseUrl });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n process.stderr.write(`[bettercms-mcp] ready on stdio (api: ${config.apiUrl})\\n`);\n}\n\n// Only run when executed as the entry (not when imported, e.g. in tests).\n// Compare realpaths so symlinked launch paths still detect the entrypoint:\n// `import.meta.url` is realpath-resolved by Node, but `process.argv[1]` is not,\n// so the old `file://${argv[1]}` check silently failed under npx `.bin`\n// symlinks, global installs, and macOS /var→/private/var — the server would\n// exit 0 without starting.\nfunction isMainModule(): boolean {\n const argv1 = process.argv[1];\n if (!argv1) return false;\n try {\n return realpathSync(argv1) === fileURLToPath(import.meta.url);\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n main().catch((err) => {\n process.stderr.write(`[bettercms-mcp] fatal: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n });\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/**\n * Resolved configuration for the BetterCMS MCP server.\n *\n * A single `BETTERCMS_API_URL` (origin, no path) drives both the device-auth\n * endpoints and the Management API base the SDK targets:\n * device: {apiUrl}/api/v1/auth/device/*\n * management: {apiUrl}/api/v1 (SDK appends /management/content/*)\n */\nexport interface McpConfig {\n apiUrl: string;\n deviceBaseUrl: string;\n managementBaseUrl: string;\n credentialsPath: string;\n clientName: string;\n}\n\nconst DEFAULT_API_URL = \"https://api.bettercms.ai\";\n\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): McpConfig {\n const apiUrl = (env.BETTERCMS_API_URL?.trim() || DEFAULT_API_URL).replace(/\\/+$/, \"\");\n return {\n apiUrl,\n deviceBaseUrl: `${apiUrl}/api/v1/auth/device`,\n managementBaseUrl: `${apiUrl}/api/v1`,\n credentialsPath:\n env.BETTERCMS_MCP_CREDENTIALS?.trim() ||\n join(homedir(), \".bettercms\", \"mcp-credentials.json\"),\n clientName: env.BETTERCMS_MCP_CLIENT_NAME?.trim() || \"BetterCMS MCP\",\n };\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\n/** Credentials cached between runs so the device flow runs only once per env. */\nexport interface StoredCredentials {\n accessToken: string;\n refreshToken: string;\n /** Epoch ms when the access token expires. */\n accessTokenExpiresAt: number;\n workspaceId: string | null;\n projectId: string | null;\n}\n\n/**\n * An authorization the user has been sent off to approve but hasn't yet.\n * Persisted so a later tool call can *resume* polling that same code instead of\n * minting a fresh one — this is what lets the flow survive across the\n * \"return the link → user approves → retry\" round-trip in clients (VS Code)\n * that never surface the server's stderr prompt.\n */\nexport interface PendingDevice {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n /** verification_uri with `?code=` prefilled — the link we hand the user. */\n verificationUriComplete: string;\n intervalSeconds: number;\n /** Epoch ms when the device code expires. */\n expiresAt: number;\n}\n\n/** Persistence boundary for credentials (file-backed in prod, in-memory in tests). */\nexport interface TokenStore {\n read(): Promise<StoredCredentials | null>;\n write(creds: StoredCredentials): Promise<void>;\n clear(): Promise<void>;\n /** In-progress device authorization awaiting approval, if any. */\n readPending(): Promise<PendingDevice | null>;\n writePending(pending: PendingDevice): Promise<void>;\n clearPending(): Promise<void>;\n}\n\n/**\n * File-backed token store. Credentials are namespaced by `key` (the API origin)\n * so pointing the server at a different environment doesn't reuse a stale token.\n * The file is written 0600 (owner-only) since it holds bearer credentials.\n */\nexport class FileTokenStore implements TokenStore {\n /** Pending authorizations live under a sibling key so they never shadow creds. */\n private readonly pendingKey: string;\n\n constructor(\n private readonly path: string,\n private readonly key: string,\n ) {\n this.pendingKey = `${key}::pending`;\n }\n\n private async readAll(): Promise<Record<string, unknown>> {\n try {\n const raw = await readFile(this.path, \"utf-8\");\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n return parsed && typeof parsed === \"object\" ? parsed : {};\n } catch {\n return {};\n }\n }\n\n private async writeAll(all: Record<string, unknown>): Promise<void> {\n await mkdir(dirname(this.path), { recursive: true });\n await writeFile(this.path, JSON.stringify(all, null, 2), { mode: 0o600 });\n }\n\n async read(): Promise<StoredCredentials | null> {\n const all = await this.readAll();\n return (all[this.key] as StoredCredentials | undefined) ?? null;\n }\n\n async write(creds: StoredCredentials): Promise<void> {\n const all = await this.readAll();\n all[this.key] = creds;\n await this.writeAll(all);\n }\n\n async clear(): Promise<void> {\n const all = await this.readAll();\n delete all[this.key];\n await this.writeAll(all);\n }\n\n async readPending(): Promise<PendingDevice | null> {\n const all = await this.readAll();\n return (all[this.pendingKey] as PendingDevice | undefined) ?? null;\n }\n\n async writePending(pending: PendingDevice): Promise<void> {\n const all = await this.readAll();\n all[this.pendingKey] = pending;\n await this.writeAll(all);\n }\n\n async clearPending(): Promise<void> {\n const all = await this.readAll();\n delete all[this.pendingKey];\n await this.writeAll(all);\n }\n}\n","import type { McpConfig } from \"./config.js\";\nimport type { PendingDevice, StoredCredentials, TokenStore } from \"./token-store.js\";\n\n/** Skew applied when deciding if a cached access token is still usable. */\nconst EXPIRY_SKEW_MS = 60_000;\n\n/**\n * How long a single tool call waits inline for the user to approve before it\n * gives up and hands the activation link back to the caller. Fast approvals\n * complete in the *same* call; slow ones resume on the next tool call.\n */\nconst GRACE_POLL_MS = 25_000;\n\ninterface TokenSuccess {\n access_token: string;\n token_type: string;\n expires_in: number;\n refresh_token: string;\n scope: string;\n workspace_id: string | null;\n project_id: string | null;\n}\n\ninterface DeviceCodeResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete?: string;\n expires_in: number;\n interval: number;\n}\n\n/** Injectable seams so tests can run without real timers / network / stderr. */\nexport interface DeviceAuthDeps {\n fetch?: typeof fetch;\n sleep?: (ms: number) => Promise<void>;\n log?: (message: string) => void;\n now?: () => number;\n}\n\n/** Thrown when the device flow cannot complete (denied / expired / unexpected). */\nexport class DeviceAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DeviceAuthError\";\n }\n}\n\n/**\n * Thrown when authorization is *legitimately still pending* after the inline\n * grace window. Carries the activation link so the caller (a tool handler) can\n * surface it in the visible tool result — the device flow is persisted, so the\n * next tool call resumes it and completes the user's original request.\n */\nexport class DeviceAuthPendingError extends Error {\n readonly verificationUri: string;\n readonly verificationUriComplete: string;\n readonly userCode: string;\n readonly expiresAt: number;\n\n constructor(pending: PendingDevice) {\n super(\"Authorization pending — approve in the browser, then retry.\");\n this.name = \"DeviceAuthPendingError\";\n this.verificationUri = pending.verificationUri;\n this.verificationUriComplete = pending.verificationUriComplete;\n this.userCode = pending.userCode;\n this.expiresAt = pending.expiresAt;\n }\n}\n\n/**\n * Drives the OAuth 2.0 Device Authorization Grant (RFC 8628) against the\n * BetterCMS backend and hands the SDK a valid `content:manage` access token.\n *\n * - `getAccessToken()` returns a usable token: cached if fresh, refreshed if\n * expired, or freshly minted via the full device flow if there's nothing valid.\n * - All human-facing output goes to stderr — stdout is the MCP JSON-RPC channel.\n */\nexport class DeviceAuthClient {\n private readonly fetchImpl: typeof fetch;\n private readonly sleep: (ms: number) => Promise<void>;\n private readonly log: (message: string) => void;\n private readonly now: () => number;\n private inFlight: Promise<string> | null = null;\n private refreshInFlight: Promise<string | null> | null = null;\n /** The single live poller for the current device code (see runDeviceFlow). */\n private pollTask: Promise<string | null> | null = null;\n\n constructor(\n private readonly config: McpConfig,\n private readonly store: TokenStore,\n deps: DeviceAuthDeps = {},\n ) {\n this.fetchImpl = deps.fetch ?? globalThis.fetch;\n this.sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));\n this.log = deps.log ?? ((m) => process.stderr.write(`${m}\\n`));\n this.now = deps.now ?? (() => Date.now());\n }\n\n /** Return a valid access token, doing the least work necessary. Single-flighted. */\n async getAccessToken(): Promise<string> {\n if (this.inFlight) return this.inFlight;\n this.inFlight = this.resolveToken().finally(() => {\n this.inFlight = null;\n });\n return this.inFlight;\n }\n\n private async resolveToken(): Promise<string> {\n const creds = await this.store.read();\n if (creds && creds.accessTokenExpiresAt - this.now() > EXPIRY_SKEW_MS) {\n return creds.accessToken;\n }\n if (creds?.refreshToken) {\n const refreshed = await this.refresh();\n if (refreshed) return refreshed;\n }\n return this.runDeviceFlow();\n }\n\n /**\n * Resume a still-live authorization if one is persisted, otherwise start a\n * fresh one; then grace-poll. Throws {@link DeviceAuthPendingError} (carrying\n * the activation link) if the user hasn't approved within the grace window.\n */\n private async runDeviceFlow(): Promise<string> {\n let pending = await this.store.readPending();\n if (pending && pending.expiresAt - this.now() <= EXPIRY_SKEW_MS) {\n await this.store.clearPending(); // stale — don't resume an expired code\n pending = null;\n }\n if (!pending) {\n pending = await this.startDeviceFlow();\n }\n\n const graceDeadline = Math.min(this.now() + GRACE_POLL_MS, pending.expiresAt);\n // A detached poller may already own this code (handed off by an earlier tool call).\n // Never poll it concurrently: the code is single-use, so the loser of the claim race\n // gets invalid_grant — wait on the existing poller instead of starting a second one.\n const token = this.pollTask\n ? await Promise.race([this.pollTask, this.sleep(GRACE_POLL_MS).then(() => null)])\n : await this.pollForApproval(pending, graceDeadline);\n if (token) return token;\n\n // Still pending after the grace window — hand the link to the caller so it lands in the\n // visible tool result, and keep polling in the background so a later approval is still\n // redeemed. Polling used to stop dead right here, which is how an approval that landed\n // 30s later got stranded: the grant sat at \"approved\" server-side forever, the browser\n // said \"approved ✓ — your terminal will finish connecting automatically\" with nothing\n // listening, and Settings → Connected agents stayed empty (it lists CLAIMED grants only).\n this.pollInBackground(pending);\n throw new DeviceAuthPendingError(pending);\n }\n\n /** Keep redeeming this code until it expires, detached from any tool call. One per code. */\n private pollInBackground(pending: PendingDevice): void {\n if (this.pollTask) return;\n const task = this.pollForApproval(pending, pending.expiresAt);\n this.pollTask = task;\n // Detached settle handler: swallows a terminal rejection (denied/expired) so it is never\n // an unhandled rejection, while leaving `task` itself awaitable by runDeviceFlow.\n void task.catch(() => {}).finally(() => {\n if (this.pollTask === task) this.pollTask = null;\n });\n }\n\n /** Request a fresh device code, persist it as pending, and log a breadcrumb. */\n private async startDeviceFlow(): Promise<PendingDevice> {\n const start = await this.fetchImpl(`${this.config.deviceBaseUrl}/code`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ client_name: this.config.clientName }),\n });\n if (!start.ok) {\n throw new DeviceAuthError(\n `Failed to start device authorization (HTTP ${start.status}).`,\n );\n }\n const code = (await start.json()) as DeviceCodeResponse;\n const pending: PendingDevice = {\n deviceCode: code.device_code,\n userCode: code.user_code,\n verificationUri: code.verification_uri,\n verificationUriComplete:\n code.verification_uri_complete ??\n `${code.verification_uri}?code=${encodeURIComponent(code.user_code)}`,\n intervalSeconds: code.interval,\n expiresAt: this.now() + code.expires_in * 1000,\n };\n await this.store.writePending(pending);\n // A fresh code retires any poller still chasing the previous one (which will simply\n // 400 expired_token and settle). Without this, runDeviceFlow would race the OLD task\n // and never poll the code the user is actually being shown.\n this.pollTask = null;\n\n // Breadcrumb for terminal/non-VS-Code clients that DO surface stderr.\n this.log(\"\");\n this.log(\"┌─ BetterCMS authorization required ─────────────────────────\");\n this.log(`│ Visit: ${pending.verificationUri}`);\n this.log(`│ Enter code: ${pending.userCode}`);\n this.log(`│ Or open: ${pending.verificationUriComplete}`);\n this.log(\"└────────────────────────────────────────────────────────────\");\n return pending;\n }\n\n /**\n * Poll the token endpoint until `deadline`. Returns the access token on\n * approval, or null if the deadline passes while still pending. Throws\n * {@link DeviceAuthError} on a terminal outcome (denied / expired).\n */\n private async pollForApproval(\n pending: PendingDevice,\n deadline: number,\n ): Promise<string | null> {\n let intervalMs = pending.intervalSeconds * 1000;\n\n while (this.now() < deadline) {\n await this.sleep(intervalMs);\n if (this.now() >= deadline) break; // don't poll once past the window\n\n const res = await this.fetchImpl(`${this.config.deviceBaseUrl}/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n device_code: pending.deviceCode,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n });\n\n if (res.ok) {\n const body = (await res.json()) as TokenSuccess;\n await this.store.clearPending();\n this.log(\"[bettercms-mcp] authorized ✓\");\n return this.persist(body);\n }\n\n const err = (await res.json().catch(() => ({}))) as { error?: string };\n switch (err.error) {\n case \"authorization_pending\":\n continue;\n case \"slow_down\":\n intervalMs += 5_000; // RFC 8628 §3.5\n continue;\n case \"access_denied\":\n await this.store.clearPending();\n throw new DeviceAuthError(\"Authorization was denied.\");\n case \"expired_token\":\n await this.store.clearPending();\n throw new DeviceAuthError(\"The device code expired before approval. Try again.\");\n default:\n throw new DeviceAuthError(\n `Device authorization failed: ${err.error ?? `HTTP ${res.status}`}.`,\n );\n }\n }\n return null; // still pending — caller surfaces the activation link\n }\n\n /**\n * Exchange the stored refresh token for a new access token. Single-flighted:\n * the device `/refresh` endpoint is single-use (it rotates the refresh token\n * and revokes the prior access key), so a burst of concurrent 401s must NOT\n * each fire their own refresh — the first would rotate, and the rest would\n * send the now-stale token, get `invalid_grant`, and wipe the freshly-minted\n * credentials. Collapsing them into one in-flight rotation keeps the session\n * alive without a needless re-auth.\n */\n async refresh(): Promise<string | null> {\n if (this.refreshInFlight) return this.refreshInFlight;\n this.refreshInFlight = this.doRefresh().finally(() => {\n this.refreshInFlight = null;\n });\n return this.refreshInFlight;\n }\n\n /**\n * Forget the cached credentials and start a fresh device flow. Called when the\n * bound project was deleted server-side (a key bound to a dead project can never\n * succeed again) — clearing lets the user re-authorize against a LIVE project.\n * Returns a new token if approval is fast, else throws {@link DeviceAuthPendingError}\n * carrying the activation link (the next tool call resumes into the new project).\n */\n async resetAndReauthorize(): Promise<string> {\n await this.store.clear();\n await this.store.clearPending();\n return this.getAccessToken();\n }\n\n private async doRefresh(): Promise<string | null> {\n const creds = await this.store.read();\n if (!creds?.refreshToken) return null;\n\n let res: Response;\n try {\n res = await this.fetchImpl(`${this.config.deviceBaseUrl}/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: creds.refreshToken }),\n });\n } catch {\n // Network/transport error — transient. Keep the (still-valid, 30-day)\n // refresh token so a later call can retry instead of forcing a re-auth.\n return null;\n }\n\n if (res.ok) {\n const body = (await res.json()) as TokenSuccess;\n return this.persist(body);\n }\n\n // Clear only on a definitive auth rejection: the OAuth `invalid_grant` signal\n // (the backend's \"this refresh token is dead\", sent as 400 invalid_grant) or a\n // hard 401/403. A bare 400 WITHOUT that signal (request-validation error, or a\n // WAF/infra page with an unparseable body → err={}) is treated as transient —\n // keep the refresh token so a later call can retry instead of forcing re-auth.\n const err = (await res.json().catch(() => ({}))) as { error?: string };\n if (err.error === \"invalid_grant\" || res.status === 401 || res.status === 403) {\n await this.store.clear();\n }\n return null;\n }\n\n private async persist(body: TokenSuccess): Promise<string> {\n const creds: StoredCredentials = {\n accessToken: body.access_token,\n refreshToken: body.refresh_token,\n accessTokenExpiresAt: this.now() + body.expires_in * 1000,\n workspaceId: body.workspace_id,\n projectId: body.project_id,\n };\n await this.store.write(creds);\n return creds.accessToken;\n }\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { BetterCMS } from \"@bettercms-ai/sdk\";\nimport { registerTools } from \"./tools.js\";\nimport { registerPrompts } from \"./prompts.js\";\nimport { PLAYBOOK_URI, SCHEMA_PLAYBOOK } from \"./playbook.js\";\nimport type { DeviceAuthClient } from \"./device-auth.js\";\n\nexport const SERVER_NAME = \"bettercms\";\n// Tracks the shared MCP tool-catalog version (kept in sync with the remote /mcp\n// SERVER_INFO in src/routes/mcp/index.ts) so both surfaces report the same version.\nexport const SERVER_VERSION = \"1.4.0\";\n\n/**\n * Display identity, mirroring the remote host's SERVER_INFO (src/lib/brand.ts). Not\n * imported from it: this package is published to npm and must not depend on backend\n * internals — same deliberate duplication as SERVER_VERSION above, so keep both in sync.\n *\n * The URLs are absolute and hardcoded because a published stdio server has no env to\n * derive an origin from. `title`/`websiteUrl`/`icons` are additive 2025-11-25\n * Implementation fields; older clients ignore them.\n */\nconst SERVER_DISPLAY = {\n title: \"BetterCMS\",\n websiteUrl: \"https://bettercms.ai\",\n icons: [\n { src: \"https://api.bettercms.ai/brand/mark-512.png\", mimeType: \"image/png\", sizes: [\"512x512\"] },\n { src: \"https://api.bettercms.ai/brand/mark.svg\", mimeType: \"image/svg+xml\", sizes: [\"any\"] },\n ],\n};\n\nexport interface BuildServerDeps {\n auth: DeviceAuthClient;\n managementBaseUrl: string;\n}\n\n/**\n * Build the BetterCMS MCP server with its tools registered. Auth is lazy — the\n * device flow runs on the first tool call, not at connect time, so the MCP\n * handshake/tool-listing never blocks on user approval.\n */\nexport function buildServer(deps: BuildServerDeps): McpServer {\n const server = new McpServer(\n { name: SERVER_NAME, version: SERVER_VERSION, ...SERVER_DISPLAY },\n {\n capabilities: { tools: {}, prompts: {}, resources: {} },\n instructions:\n \"BetterCMS never executes a customer's Section renderer or app code. An ordinary MCP connection is not a push runner: explicitly poll list_section_validation_requests, claim one request at an exact git commit, run implementation and responsive checks inside the user's own repository and real app shell, then submit manifest + validation with that requestId and complete it—or truthfully fail it when implementation/evidence is missing. Never invent a manifest, a passing validation, or visual evidence; these tools cannot grant the separate human Visual Approval required for publication.\",\n },\n );\n\n // The playbook is a RESOURCE, not a tool description: it is fetched once by a client\n // that wants it, rather than riding in the prompt on every turn. Mirrors the hosted\n // /mcp PLAYBOOK_RESOURCE (src/routes/mcp/index.ts) — same URI, name and mime, so the\n // `bettercms://playbook/schema` that prompts and tool descriptions point at resolves\n // on stdio too. Without this, `import-site`'s \"read section 11 first\" is a dead link.\n server.registerResource(\n \"schema-playbook\",\n PLAYBOOK_URI,\n {\n title: \"BetterCMS schema & components playbook\",\n description:\n \"How to design a components-first BetterCMS project: components vs collections, section anatomy, sectionType variants, kind:'block' + modular fields, the 'document' article body, the draft->publish order, and what makes an imported site editable.\",\n mimeType: \"text/markdown\",\n },\n () => ({\n contents: [{ uri: PLAYBOOK_URI, mimeType: \"text/markdown\", text: SCHEMA_PLAYBOOK }],\n }),\n );\n\n registerTools(server, {\n auth: deps.auth,\n createClient: (apiKey) =>\n BetterCMS.management({ apiKey, baseUrl: deps.managementBaseUrl }),\n });\n\n // Guided slash-command prompts ship with the server (auto-available as\n // /mcp__bettercms__studio and /mcp__bettercms__new_page when the MCP is added).\n registerPrompts(server);\n\n return server;\n}\n","import { z } from \"zod\";\nimport { SECTION_DOCTRINE as DOCTRINE } from \"@bettercms-ai/types\";\nimport { BetterCMSError } from \"@bettercms-ai/sdk\";\nimport { LAYOUT_SECTION_ICON_SET } from \"@bettercms-ai/types\";\nimport { DeviceAuthPendingError } from \"./device-auth.js\";\nimport type {\n ManagedContentModel,\n ManagedContentEntry,\n ManagedPage,\n ManagedForm,\n ManagedFormInput,\n ManagedComponent,\n ManagedComponentInput,\n ExtractionCandidate,\n CreateModelInput,\n UpdateModelInput,\n CreateEntryInput,\n UpdateEntryInput,\n CreateManagedPageInput,\n UploadAssetInput,\n UploadedAsset,\n WriteContentInput,\n SeoMetaInput,\n SeoMeta,\n} from \"@bettercms-ai/sdk\";\nimport type {\n LayoutDataDocument,\n LayoutStructureDocument,\n ManagementLayoutCommand,\n PageLayoutOverrideDocument,\n} from \"@bettercms-ai/types\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\n/** Subset of the management SDK client the tools use (kept narrow for testability). */\nexport interface ManagementApi {\n listPages(): Promise<ManagedPage[]>;\n getPage(id: string): Promise<ManagedPage>;\n getModel(id: string): Promise<ManagedContentModel>;\n createModel(input: CreateModelInput): Promise<ManagedContentModel>;\n updateModel(id: string, input: UpdateModelInput): Promise<ManagedContentModel>;\n createPage(input: CreateManagedPageInput): Promise<ManagedPage>;\n addPageFields(\n id: string,\n input: { addFields: OutField[] },\n ): Promise<ManagedPage>;\n setPageContent(\n id: string,\n input: { data: Record<string, unknown>; status?: \"draft\" | \"published\" },\n ): Promise<ManagedContentEntry>;\n createEntry(input: CreateEntryInput): Promise<ManagedContentEntry>;\n updateEntry(\n id: string,\n input: UpdateEntryInput,\n opts?: { ifMatch?: number },\n ): Promise<ManagedContentEntry>;\n listEntries(filter?: {\n modelId?: string;\n pageId?: string;\n status?: \"draft\" | \"published\";\n }): Promise<ManagedContentEntry[]>;\n getEntry(id: string): Promise<ManagedContentEntry>;\n uploadAsset(input: UploadAssetInput): Promise<UploadedAsset>;\n deletePage(id: string): Promise<{ id: string }>;\n deleteEntry(id: string): Promise<{ id: string }>;\n deleteModel(id: string): Promise<{ id: string }>;\n listForms(): Promise<ManagedForm[]>;\n getForm(id: string): Promise<ManagedForm>;\n createForm(input: ManagedFormInput): Promise<ManagedForm>;\n updateForm(id: string, input: ManagedFormInput): Promise<ManagedForm>;\n listComponents(): Promise<ManagedComponent[]>;\n getComponent(id: string): Promise<ManagedComponent>;\n createComponent(input: ManagedComponentInput): Promise<ManagedComponent>;\n updateComponent(id: string, input: ManagedComponentInput): Promise<ManagedComponent>;\n listExtractionCandidates(projectId?: string): Promise<ExtractionCandidate[]>;\n extractComponent(input: {\n hash: string;\n name: string;\n slug: string;\n projectId?: string;\n }): Promise<{ component: ManagedComponent; replaced: number }>;\n getManagedLayout(opts?: { scope?: \"global\" | \"page\"; pageId?: string; copy?: \"draft\" | \"published\"; projectId?: string }): Promise<ManagedLayoutDocument>;\n commandManagedLayout(input: { scope?: \"global\" | \"page\"; pageId?: string; projectId?: string; command: ManagementLayoutCommand; ifMatch: number }): Promise<ManagedLayoutDocument>;\n writeContent(input: WriteContentInput): Promise<string>;\n generateSeoMeta(input: SeoMetaInput): Promise<SeoMeta>;\n // Generic escape hatch for the lifecycle tools (media mgmt, submissions, redirects,\n // SEO, site-files, promote, versions). These management endpoints have no bespoke SDK\n // method; the MCP tools call them straight through the client's public request plumbing,\n // so parity with the remote /mcp surface needs no per-endpoint SDK code (DRY).\n url(path: string): string;\n fetchJSON<T>(url: string, init?: RequestInit): Promise<T>;\n}\n\ntype ManagedLayoutDocument =\n | { scope: \"global\"; revision: number; etag: string; status: string; structure: LayoutStructureDocument; data: LayoutDataDocument }\n | { scope: \"page\"; pageId: string; pageSlug: string; revision: number; etag: string; status: string; globalStructure: LayoutStructureDocument; globalData: LayoutDataDocument; override: PageLayoutOverrideDocument };\n\nexport interface ToolDeps {\n auth: {\n getAccessToken(): Promise<string>;\n refresh(): Promise<string | null>;\n /** Forget cached creds + re-run device flow (used when the bound project was deleted). */\n resetAndReauthorize(): Promise<string>;\n };\n /** Build a management client bound to the given access token. */\n createClient: (apiKey: string) => ManagementApi;\n /**\n * Ask the HUMAN a question mid-tool-call (MCP elicitation). Optional because plenty of\n * clients don't implement it — every caller must degrade to telling the model to ask in\n * chat instead. Wired from the McpServer in registerTools.\n */\n elicit?: (params: {\n message: string;\n requestedSchema: { type: \"object\"; properties: Record<string, unknown>; required?: string[] };\n }) => Promise<{ action: string; content?: Record<string, unknown> }>;\n}\n\n// ── The framework question ────────────────────────────────────────────────────\n// Mirrors src/lib/projects/framework-choice.ts in the backend. Deliberately duplicated\n// rather than imported: this package is published to npm and must not depend on backend\n// internals (same reasoning as SERVER_VERSION in server.ts). Keep the two in sync.\n\n/** The one sentence every page-building surface states. Shared so the surfaces cannot drift apart. */\nexport { SECTION_DOCTRINE } from \"@bettercms-ai/types\";\n\nexport const FRAMEWORK_CHOICES = [\"astro\", \"next\", \"react-ts\", \"other\"] as const;\n\nconst FRAMEWORK_LABELS: Record<(typeof FRAMEWORK_CHOICES)[number], string> = {\n astro: \"Astro — recommended default, static by default and fastest to publish\",\n next: \"Next.js\",\n \"react-ts\": \"React + TypeScript (Vite, prerendered)\",\n other: \"Other — headless project: content and API only, bring your own frontend\",\n};\n\n/** What the model must read out when it cannot ask the user through the client UI. */\nexport const FRAMEWORK_PROMPT = [\n \"Ask the user which technology this site should be built with, then call create_project again with their answer as `framework`:\",\n ...FRAMEWORK_CHOICES.map((c, i) => ` ${i + 1}. ${c} — ${FRAMEWORK_LABELS[c]}`),\n \"\",\n \"Do not choose on their behalf. Sites cannot be built as plain HTML/CSS — every project is backed by one of these starters, which is what keeps its content editable in the CMS.\",\n].join(\"\\n\");\n\n/**\n * Resolve `framework` by ASKING, never by defaulting.\n *\n * Prefers a real client-side prompt (elicitation) so the human picks from a list instead of\n * the model inventing an answer. When the client can't elicit — or the person dismisses the\n * prompt — we return the question as text for the model to put in chat. Either way the one\n * outcome that never happens is a silent default, which is the whole point: a guessed\n * framework means a forked starter and seeded content pointing at the wrong stack, and\n * nobody notices until the site is half-built.\n */\nasync function askFramework(\n deps: ToolDeps,\n): Promise<{ framework: string } | { prompt: string }> {\n if (!deps.elicit) return { prompt: FRAMEWORK_PROMPT };\n try {\n const res = await deps.elicit({\n message: \"Which technology should this site be built with?\",\n requestedSchema: {\n type: \"object\",\n properties: {\n framework: {\n type: \"string\",\n title: \"Technology\",\n description: \"The frontend stack this project's starter is based on.\",\n enum: [...FRAMEWORK_CHOICES],\n enumNames: FRAMEWORK_CHOICES.map((c) => FRAMEWORK_LABELS[c]),\n },\n },\n required: [\"framework\"],\n },\n });\n const picked = res.action === \"accept\" ? res.content?.framework : undefined;\n if (typeof picked === \"string\" && (FRAMEWORK_CHOICES as readonly string[]).includes(picked)) {\n return { framework: picked };\n }\n } catch {\n // Client advertised elicitation but couldn't serve it. Fall through to asking in chat.\n }\n return { prompt: FRAMEWORK_PROMPT };\n}\n\n// ── The authoring-architecture question ───────────────────────────────────────\n// Mirrors src/lib/projects/authoring-choice.ts in the backend, duplicated for the same\n// reason as the framework question above: this package ships to npm and must not import\n// backend internals. Keep the two in sync.\n//\n// The backend is where the ENFORCEMENT lives — deploy/promote answer 409\n// AUTHORING_DECISION_REQUIRED until this is set — and its refusal quotes the project's real\n// page counts, which this surface has no way to know at ask time. So the prompt here is the\n// generic question; the grounded one arrives in the 409.\n\nexport const AUTHORING_CHOICES = [\"components\", \"fields\"] as const;\n\nconst AUTHORING_LABELS: Record<(typeof AUTHORING_CHOICES)[number], string> = {\n components:\n \"Components — reusable section components placed as blocks; editors add, reorder and swap sections without touching a schema. Best for marketing and landing sites\",\n fields:\n \"Fields — a typed field schema per page. Best for blogs, catalogues and directories, where many rows share one shape\",\n};\n\n/** What the model must read out when it cannot ask the user through the client UI. */\nexport const AUTHORING_PROMPT = [\n \"Ask the user which authoring architecture this site should use, then call set_authoring_preference again with their answer as `preference`:\",\n ...AUTHORING_CHOICES.map((c, i) => ` ${i + 1}. ${c} — ${AUTHORING_LABELS[c]}`),\n \"\",\n \"Answering 'components' does not convert anything — there is no field-to-block converter. It means you author the sections yourself: create_component, then publish_component (an unpublished component renders as NOTHING on the live site), then set_page_content placing `component` blocks. Once a page has blocks, list_extraction_candidates and extract_component fold the repeats.\",\n \"\",\n \"Do not choose on their behalf. This is asked once per project.\",\n].join(\"\\n\");\n\n/** Resolve `preference` by ASKING, never by defaulting. Same shape as askFramework. */\nasync function askAuthoring(\n deps: ToolDeps,\n): Promise<{ preference: string } | { prompt: string }> {\n if (!deps.elicit) return { prompt: AUTHORING_PROMPT };\n try {\n const res = await deps.elicit({\n message: \"Which authoring architecture should this site use?\",\n requestedSchema: {\n type: \"object\",\n properties: {\n preference: {\n type: \"string\",\n title: \"Authoring architecture\",\n description: \"How this site's pages are composed. Asked once per project.\",\n enum: [...AUTHORING_CHOICES],\n enumNames: AUTHORING_CHOICES.map((c) => AUTHORING_LABELS[c]),\n },\n },\n required: [\"preference\"],\n },\n });\n const picked = res.action === \"accept\" ? res.content?.preference : undefined;\n if (typeof picked === \"string\" && (AUTHORING_CHOICES as readonly string[]).includes(picked)) {\n return { preference: picked };\n }\n } catch {\n // Client advertised elicitation but couldn't serve it. Fall through to asking in chat.\n }\n return { prompt: AUTHORING_PROMPT };\n}\n\n/** MCP tool result shape (text content + optional error flag). */\nexport interface ToolResult {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}\n\nexport interface ToolDef {\n name: string;\n config: { title: string; description: string; inputSchema: z.ZodRawShape };\n handler: (args: Record<string, unknown>) => Promise<ToolResult>;\n}\n\n// ── Shared schema pieces ──────────────────────────────────────────────────────\n\nconst fieldType = z.enum([\n \"text\",\n \"richtext\",\n \"image\",\n \"boolean\",\n \"number\",\n \"select\",\n \"reference\",\n \"multi-reference\",\n \"array\",\n \"date\",\n \"datetime\",\n \"group\", // Non-Repeatable Zone: one nested object of fields\n \"repeater\", // Repeatable Zone: an array of nested field-objects\n // A slot holding one component instance. This enum is a SECOND, narrower copy of the\n // field-type union, and `toField`/`OutField` below strip anything not modelled here —\n // which is why showIf/helpText/searchable/placement are all unreachable from MCP today.\n // Adding the type here without also carrying its `config` through `toField` would let an\n // agent create the field and silently lose its component allowlist.\n \"component-ref\",\n // Migration 0188. Both are LEAF types, so `toField`'s pass-through branch carries their\n // `config` verbatim — which is what the warning above demands before adding a type here.\n // `modular` needs config.blockSlugs; `location` takes no config.\n \"modular\",\n \"location\",\n // All LEAF types, so the pass-through branch above covers them. `document` is THE article\n // body — the rich document canvas, collections only, at most one per model, top level\n // only. It was the conspicuous omission: the dashboard shipped an editor for it while no\n // agent could create the field. `sections` is a page-section zone composed in the Visual\n // Editor, so it has no inline control.\n \"document\",\n \"longtext\",\n \"slug\",\n \"email\",\n \"phone\",\n \"link\",\n \"color\",\n \"json\",\n \"file\",\n \"sections\",\n]);\n\nconst slug = z\n .string()\n .regex(/^[a-z0-9-]+$/, \"lowercase letters, numbers, and hyphens only\");\n\nconst fieldKey = z\n .string()\n .regex(/^[a-zA-Z0-9_]+$/, \"letters, numbers, and underscores only\");\n\n// Recursive field schema. The MCP SDK serialises this Zod shape to the JSON\n// Schema the LLM sees — on SDK >= 1.29 (the floor pinned in package.json) the\n// `z.lazy()` below emits a proper `$ref`/`$defs` recursion so nested\n// group/repeater fields are VISIBLE. A stale older SDK collapsed it to an\n// opaque {} (the historic \"nested fields not created\" bug). The same recursive\n// shape is hand-written as JSON Schema in the remote proxy — keep the two in\n// sync: see bettercms-backend/src/routes/mcp/index.ts (FIELD_DEF).\n/** A field definition. Recursive: `group`/`repeater` nest more fields. */\nexport type FieldInput = {\n key: string;\n label: string;\n type: z.infer<typeof fieldType>;\n required?: boolean;\n /** Opt OUT of the rich-text default for a non-prose string (href, slug, id). */\n richText?: boolean;\n options?: string[];\n config?: Record<string, unknown>;\n fields?: FieldInput[];\n};\n\nconst fieldShape = {\n key: fieldKey.describe(\n \"machine field key. 🔴 UNIQUE ACROSS THE WHOLE MODEL — API IDs share ONE FLAT NAMESPACE, so a field nested inside a group must NOT reuse a key used by another field or group. Every section's heading cannot be 'title'. Prefix with the section: 'hero_title', 'pricing_title', 'faq_title'. Reusing a key is refused, and if it slips through it leaves permanent errors in the editor and breaks conditional-visibility rules, which reference fields by bare key.\",\n ),\n label: z.string().min(1).describe(\"human label shown in the editor\"),\n type: fieldType,\n required: z.boolean().optional(),\n richText: z\n .boolean()\n .optional()\n .describe(\n \"prose formatting. DEFAULTS TO TRUE for 'text': the field is created as rich text so editors can bold, link and format it on the canvas, and the API returns rich text (render with rich() from @bettercms-ai/sdk; plain() for titles and meta). Pass false for a value that is NOT prose and must stay a bare string — a URL/href, a slug, an id, an email, a phone number, a CSS class, an icon name. A link stored as rich text will not work as an href.\",\n ),\n options: z.array(z.string()).optional().describe(\"choices when type is 'select'\"),\n config: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"per-type config: reference {contentModelId}, multi-reference {contentModelId,min,max}, array {itemType: 'text'|'number'|'date'}, date {includeTime}, modular {blockSlugs: ['quote','gallery'], minItems?, maxItems?} — blockSlugs is REQUIRED, non-empty, and each slug must name an existing kind:'block' model\",\n ),\n fields: z\n .array(z.lazy(() => fieldObject))\n .optional()\n .describe(\n \"NESTED child fields — REQUIRED for type 'group' (one nested object, a Non-Repeatable Zone like blog_hero → heading, description, hero_image) and type 'repeater' (a repeatable array of such objects, a Repeatable Zone / section-list like testimonials → quote, author). A section with repeating items is a 'repeater'; a fixed grouped block is a 'group'. Recurse to any depth — do NOT flatten zones into separate top-level fields.\",\n ),\n};\nconst fieldObject: z.ZodType<FieldInput> = z.object(fieldShape);\n\n/**\n * Output field shape persisted by the API. Canonical: nesting lives on `array` via\n * `config.zones`. The LLM may still speak `group`/`repeater` (kept in the input schema\n * because it's intuitive) — toField() maps those into the canonical array.zones shape\n * here, so the backend, dashboard, codegen, and delivery all see one model.\n */\ntype OutField = {\n key: string;\n label: string;\n type: Exclude<FieldInput[\"type\"], \"group\" | \"repeater\">;\n required?: boolean;\n options?: string[];\n config?: Record<string, unknown>;\n};\n\n\n/**\n * API IDs share ONE FLAT NAMESPACE across a model — a field inside a group must not reuse a key\n * used by any other field or group. Checked here, before the write, because the failure it\n * prevents is silent: the schema saves, and the author is left with permanent red error rows in\n * the builder plus `showIf` rules that reference a bare key and therefore cannot resolve.\n *\n * This is the shape `create_page` produces by default — its own description tells the agent to\n * build a nested tree where every visual section becomes a group, and the natural key for each\n * section's heading is `title`. The marketing page came out with `title` and `subtitle` in three\n * groups. The rule was never written down anywhere the model could read it, so this is both a\n * guard and the place it gets taught.\n *\n * Depth is ONE LEVEL, matching the dashboard's own `walk` — checking deeper here would refuse\n * schemas the builder renders as clean.\n *\n * Reads BOTH dialects: `fields` (what an agent sends) and `config.zones` (what the API returns).\n */\nfunction flatFieldKeys(fields: unknown): string[] {\n const out: string[] = [];\n const childrenOf = (f: Record<string, unknown>): unknown[] => {\n const zones = (f.config as { zones?: { nonRepeatable?: unknown[]; repeatable?: { fields?: unknown[] } } } | undefined)?.zones;\n if (zones?.nonRepeatable) return zones.nonRepeatable;\n if (zones?.repeatable?.fields) return zones.repeatable.fields;\n return (f.fields as unknown[]) ?? [];\n };\n for (const raw of (Array.isArray(fields) ? fields : [])) {\n const f = raw as Record<string, unknown>;\n if (typeof f?.key === \"string\" && f.key.trim()) out.push(f.key.trim());\n for (const raw2 of childrenOf(f)) {\n const c = raw2 as Record<string, unknown>;\n if (typeof c?.key === \"string\" && c.key.trim()) out.push(c.key.trim());\n }\n }\n return out;\n}\n\n/** Keys used more than once, first-seen order. */\nfunction duplicateKeys(keys: string[]): string[] {\n const seen = new Map<string, number>();\n for (const k of keys) seen.set(k, (seen.get(k) ?? 0) + 1);\n return [...new Set(keys)].filter((k) => (seen.get(k) ?? 0) > 1);\n}\n\n/** The refusal an AGENT has to be able to act on — names the keys, the rule, the remediation. */\nfunction duplicateKeyFailure(dupes: string[]): string {\n return (\n `Duplicate API ID${dupes.length === 1 ? \"\" : \"s\"}: ${dupes.map((k) => `'${k}'`).join(\", \")}. ` +\n `API IDs share ONE flat namespace across the whole model — a field inside a group must not ` +\n `reuse a key used by another field or group. Prefix each key with its section and retry ` +\n `(e.g. 'hero_title' and 'pricing_title', never 'title' in both).`\n );\n}\n\nfunction toFields(fs: FieldInput[] | undefined): OutField[] {\n return (fs ?? []).map(toField);\n}\n\n/**\n * Prose fields are RICH TEXT unless the caller opts out.\n *\n * The default is inverted from what the type name suggests, deliberately: an agent asked for a\n * headline says `type: 'text'` because that is the word for it, and the author then finds a\n * heading they cannot bold or link on the canvas — the toolbar's marks render disabled with\n * \"enable rich text formatting to use this\", and the only route out is a schema edit.\n *\n * 🔴 The opt-out is NOT cosmetic. A richtext field's API value is an ENVELOPE, not a string, so\n * an href, slug, id, email or class name created as rich text is broken the moment a template\n * interpolates it — that is the shape that renders \"[object Object]\". `richText: false` is the\n * required answer for every non-prose string, and the input schema says so.\n */\nfunction proseType(f: FieldInput): FieldInput[\"type\"] {\n // `text` is the only prose leaf this enum carries — `longtext` is not in it, so there is\n // nothing else to widen to. Stated because \"why only text?\" is the obvious next question.\n if (f.type !== \"text\") return f.type;\n return f.richText === false ? \"text\" : \"richtext\";\n}\n\nfunction toField(f: FieldInput): OutField {\n const base = {\n key: f.key,\n label: f.label,\n ...(f.required !== undefined ? { required: f.required } : {}),\n };\n\n // group → array with a non-repeatable zone (a fixed block).\n if (f.type === \"group\") {\n return { ...base, type: \"array\", config: { zones: { nonRepeatable: toFields(f.fields) } } };\n }\n // repeater → array with a repeatable zone (a list of blocks).\n if (f.type === \"repeater\") {\n return { ...base, type: \"array\", config: { zones: { repeatable: { fields: toFields(f.fields) } } } };\n }\n // Already-canonical zoned array (the LLM emitted config.zones directly) → recurse.\n if (f.type === \"array\" && f.config && typeof f.config === \"object\" && \"zones\" in f.config) {\n const zones = (f.config as { zones?: { nonRepeatable?: FieldInput[]; repeatable?: { fields?: FieldInput[]; minItems?: number; maxItems?: number } } }).zones ?? {};\n return {\n ...base,\n type: \"array\",\n config: {\n zones: {\n ...(zones.nonRepeatable ? { nonRepeatable: toFields(zones.nonRepeatable) } : {}),\n ...(zones.repeatable\n ? {\n repeatable: {\n fields: toFields(zones.repeatable.fields),\n ...(zones.repeatable.minItems !== undefined ? { minItems: zones.repeatable.minItems } : {}),\n ...(zones.repeatable.maxItems !== undefined ? { maxItems: zones.repeatable.maxItems } : {}),\n },\n }\n : {}),\n },\n },\n };\n }\n\n // Leaf field or primitive array (config.itemType) — pass through, with the prose default\n // applied here so EVERY field-creating tool (create_page, create_content_model, add_field,\n // add_page_field) inherits it from one place rather than four that can drift.\n return {\n ...base,\n type: proseType(f) as OutField[\"type\"],\n ...(f.options ? { options: f.options } : {}),\n ...(f.config ? { config: f.config } : {}),\n };\n}\n\n// ── Result helpers ────────────────────────────────────────────────────────────\n\nfunction ok(summary: string, data: unknown): ToolResult {\n return {\n content: [\n { type: \"text\", text: summary },\n { type: \"text\", text: JSON.stringify(data, null, 2) },\n ],\n };\n}\n\nfunction fail(message: string): ToolResult {\n return { content: [{ type: \"text\", text: message }], isError: true };\n}\n\n/**\n * Authorization isn't done yet. Surface the clickable activation link *in the\n * tool result* (the one channel every MCP client renders — unlike the server's\n * stderr, which VS Code hides). The device flow is persisted, so simply\n * re-running this tool after approval resumes it and completes the request.\n */\nfunction authPrompt(err: DeviceAuthPendingError): ToolResult {\n const text = [\n \"🔐 BetterCMS authorization required — you're not signed in yet.\",\n \"\",\n `1. Open this link and approve: ${err.verificationUriComplete}`,\n ` (or visit ${err.verificationUri} and enter code ${err.userCode})`,\n \"2. Once approved, run this tool again — it resumes automatically and completes your request.\",\n ].join(\"\\n\");\n return { content: [{ type: \"text\", text }], isError: true };\n}\n\n// ── Tool definitions ──────────────────────────────────────────────────────────\n\nexport function buildToolDefs(deps: ToolDeps): ToolDef[] {\n /** Run with a token, retrying once on 401 after a refresh / re-auth. */\n async function withClient<T>(fn: (client: ManagementApi) => Promise<T>): Promise<T> {\n const token = await deps.auth.getAccessToken();\n try {\n return await fn(deps.createClient(token));\n } catch (err) {\n if (err instanceof BetterCMSError && err.status === 401) {\n const next = (await deps.auth.refresh()) ?? (await deps.auth.getAccessToken());\n return await fn(deps.createClient(next));\n }\n // The key is bound to a project that was deleted server-side (L1: 409\n // PROJECT_DELETED). It can never succeed again — clear creds and re-authorize\n // so the user picks a LIVE project, then retry the original call into it.\n // (resetAndReauthorize throws DeviceAuthPendingError if approval isn't instant,\n // which guard() turns into the clickable activation prompt.)\n if (err instanceof BetterCMSError && err.status === 409 && err.bodyCode === \"PROJECT_DELETED\") {\n const next = await deps.auth.resetAndReauthorize();\n return await fn(deps.createClient(next));\n }\n throw err;\n }\n }\n\n /** Wrap a handler with uniform error → ToolResult conversion. */\n function guard<A>(fn: (args: A) => Promise<ToolResult>) {\n return async (args: A): Promise<ToolResult> => {\n try {\n return await fn(args);\n } catch (err) {\n if (err instanceof DeviceAuthPendingError) {\n return authPrompt(err);\n }\n if (err instanceof BetterCMSError) {\n return fail(`BetterCMS error (${err.status} ${err.code}): ${err.message}`);\n }\n return fail(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);\n }\n };\n }\n\n // ── Component authoring schemas ──\n // blockJson is a recursive ContentBlock tree; props is the override allowlist. The\n // backend validates the exact block union, so blocks are typed loosely here.\n // Declared BEFORE createPageInput/createComponentInput — both reference it.\n interface BlockInput { type: string; id: string; props: Record<string, unknown>; style?: Record<string, unknown> }\n const blockObject: z.ZodType<BlockInput> = z.object({\n type: z\n .enum([\n \"heading\", \"text\", \"richtext\", \"image\", \"button\", \"spacer\", \"video\",\n \"columns\", \"section\", \"slider\", \"tabs\", \"navbar\", \"footer\", \"form\", \"component\",\n \"collection\",\n ])\n .describe(\"block type; section/slider/tabs/columns nest child blocks\"),\n id: z.string().min(1).describe(\"stable unique block id\"),\n props: z\n .record(z.string(), z.unknown())\n .describe(\n \"per-type props: heading {text, level}; text/richtext {html} (NOT {text}); image {src, alt}; button {text, href}; spacer {height}; video {url}; form {formId}; component {componentId, overrides?}; navbar {links:[{label,href}], logo?, cta?}; footer {columns, copyright?}; section {children: block[]}; columns {columns: block[][], gap} — a column may NOT hold columns/section/slider/tabs; slider {slides:[{id,children}]}; tabs {tabs:[{id,label,children}]}; collection {cardComponentId?, detailComponentId?, titleField?, excerptField?, limit?, order?, emptyText?} — lists this page's published entries as cards, and renders ONE entry on /<page>/<entrySlug>\",\n ),\n style: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"design tokens: theme, bg (none|surface|muted|accent|dark|custom), bgCustom hex, paddingTop/paddingBottom/paddingSides px, contentWidth (narrow|default|wide|full), align, corner, shadow, borderTop/borderBottom. A real marketing band is a `section` block carrying bg + padding + contentWidth.\",\n ),\n });\n\n const createPageInput = z.object({\n title: z.string().min(1).describe(\"display title of the page, e.g. 'Home'\"),\n slug: slug.describe(\"URL-safe path segment, unique per project, e.g. 'home'\"),\n pageType: z\n .enum([\"singleton\", \"dynamic\"])\n .default(\"singleton\")\n .describe(\n \"'singleton' = exactly one entry (Home, About, Contact); 'dynamic' = many entries sharing this schema (Blog posts, Products). Defaults to singleton.\",\n ),\n blockJson: z\n .array(blockObject)\n .optional()\n .describe(\n \"the page's VISUAL composition — how a components-first page is built. Place one `component` block per section: {type:'component', id:'<stable>', props:{componentId:'<id from create_component>'}}. The component must be PUBLISHED (publish_component) or it renders as nothing on the live site. Independent of `fields`, which is a typed schema for a site's own code to read.\",\n ),\n fields: z.array(fieldObject).optional().describe(\"the page's typed schema fields\"),\n metaTitle: z.string().optional().describe(\"SEO meta title\"),\n metaDescription: z.string().optional().describe(\"SEO meta description\"),\n });\n\n const writeContentInput = z.object({\n action: z\n .enum([\"write\", \"rewrite\", \"translate\"])\n .describe(\"'write' = draft from a brief, 'rewrite' = improve existing copy, 'translate' = needs targetLang\"),\n text: z.string().min(1).describe(\"the source text (a brief for 'write', the copy to change otherwise)\"),\n instructions: z.string().optional().describe(\"optional extra guidance, e.g. 'make it punchier'\"),\n targetLang: z.string().optional().describe(\"required for 'translate', e.g. 'Spanish'\"),\n context: z.string().optional().describe(\"optional surrounding context, e.g. the page title\"),\n });\n\n const generateSeoMetaInput = z.object({\n text: z.string().min(1).describe(\"the content to derive SEO metadata from\"),\n context: z.string().optional().describe(\"optional surrounding context, e.g. the page slug\"),\n });\n\n const createModelInput = z.object({\n name: z.string().min(1).describe(\"human model name, e.g. 'Blog Post'\"),\n slug: slug.describe(\"url-safe unique slug, e.g. 'blog-post'\"),\n description: z.string().optional(),\n kind: z\n .enum([\"model\", \"block\"])\n .optional()\n .describe(\n \"'model' (default) = a collection with its own entries. 'block' = a type that exists only to be stacked inside another model's 'modular' field — 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.\",\n ),\n fields: z\n .array(fieldObject)\n .optional()\n .describe(\n \"the model's typed schema fields. 'group'/'repeater' NEST their child fields (any depth) — don't flatten zones into top-level fields.\",\n ),\n });\n\n const addFieldInput = z.object({\n modelId: z.string().min(1).describe(\"id of the content model to extend\"),\n ...fieldShape,\n });\n\n const addPageFieldInput = z.object({\n pageId: z.string().min(1).describe(\"id of the page to extend (from list_pages / create_page)\"),\n ...fieldShape,\n });\n\n // Exactly one of localPath/url (enforced by the SDK + backend route, documented here).\n const uploadAssetInput = z.object({\n localPath: z\n .string()\n .min(1)\n .optional()\n .describe(\"absolute path to a local file (e.g. a repo image); provide this OR url\"),\n url: z\n .string()\n .url()\n .optional()\n .describe(\"remote image URL to ingest; provide this OR localPath\"),\n filename: z.string().optional().describe(\"override the stored filename\"),\n altText: z.string().optional().describe(\"accessibility alt text\"),\n caption: z.string().optional(),\n folderId: z.string().optional().describe(\"target Media Library folder (defaults to project root)\"),\n });\n\n const createEntryInput = z.object({\n contentModelId: z.string().min(1).describe(\"id of the model this entry belongs to\"),\n slug: slug.optional(),\n status: z.enum([\"draft\", \"published\"]).optional().describe(\"defaults to draft\"),\n data: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\"field values keyed by field key\"),\n });\n\n const getPageInput = z.object({\n pageId: z.string().min(1).describe(\"page id (from list_pages / create_page)\"),\n });\n\n const setPageContentInput = z.object({\n pageId: z.string().min(1).describe(\"id of the page to write values to\"),\n data: z\n .record(z.string(), z.unknown())\n .describe(\n \"field values keyed by field key. A nested 'array' (zone) value is an OBJECT { nonRepeatable: { childKey: value, … }, repeatable: [ { childKey: value }, … ] } — nonRepeatable holds the fixed-block values, repeatable is the list of item objects (omit a zone you didn't define). A primitive 'array' (itemType) is a plain list. An 'image' value is an asset URL or asset id (from upload_asset) — the server resolves it to { id, url, name, altText }. Read get_page first to see each field's zones.\",\n ),\n status: z.enum([\"draft\", \"published\"]).optional().describe(\"omit to leave status unchanged\"),\n });\n\n const getEntryInput = z.object({\n entryId: z.string().min(1).describe(\"content entry id\"),\n });\n\n const listEntriesInput = z.object({\n modelId: z.string().optional().describe(\"filter by content model id\"),\n pageId: z.string().optional().describe(\"filter by page id (a singleton page has one entry)\"),\n status: z.enum([\"draft\", \"published\"]).optional(),\n });\n\n const updateEntryInput = z.object({\n entryId: z.string().min(1).describe(\"content entry id\"),\n data: z.record(z.string(), z.unknown()).optional().describe(\"field values keyed by field key\"),\n status: z.enum([\"draft\", \"published\"]).optional(),\n slug: slug.optional(),\n });\n\n const deletePageInput = z.object({\n pageId: z.string().min(1).describe(\"id of the page to delete (from list_pages)\"),\n });\n const deleteEntryInput = z.object({\n entryId: z.string().min(1).describe(\"id of the content entry to delete (from list_content_entries)\"),\n });\n const deleteModelInput = z.object({\n modelId: z.string().min(1).describe(\"id of the content model to delete (from list_content_models)\"),\n });\n\n const getFormInput = z.object({\n formId: z.string().min(1).describe(\"form id (from list_forms)\"),\n });\n\n // ── Form authoring schemas ──\n // MUST stay at parity with the server's field vocabulary (packages/db FormField + the\n // route's Zod). `update_form` REPLACES the whole `fields` array, so a type this schema\n // omits cannot be echoed back: an agent that reads a form and writes it back DESTROYS\n // every human-authored field of that type. `radio`/`checkboxes` were exactly that gap.\n // Guarded by src/__tests__/mcp/mcp-parity.test.ts.\n const formFieldObject = z.object({\n key: z.string().min(1).describe(\"machine key for the submitted value, e.g. 'email'\"),\n label: z.string().min(1).describe(\"field label shown to the visitor\"),\n type: z.enum([\n \"text\", \"email\", \"textarea\", \"select\",\n \"checkbox\", // single boolean; predates `checkboxes`\n \"checkboxes\", // pick-many, value is a string[] of chosen option labels\n \"radio\", // pick-one, rendered inline rather than in a dropdown\n \"number\", \"phone\", \"date\", \"url\", \"consent\", \"hidden\",\n ]),\n placeholder: z.string().optional(),\n helpText: z.string().optional().describe(\"hint shown under the control, muted\"),\n required: z.boolean().optional(),\n options: z.array(z.string()).optional().describe(\"choices when type is 'select', 'radio' or 'checkboxes'\"),\n hidden: z.boolean().optional().describe(\"not rendered; pairs with defaultValue to capture context\"),\n defaultValue: z.string().optional(),\n showIf: z\n .object({ field: z.string(), equals: z.string() })\n .optional()\n .describe(\"show this field only when another field equals a value\"),\n validation: z\n .object({\n emailPolicy: z.enum([\"any\", \"business\"]).optional().describe(\"'email' fields only\"),\n min: z.number().optional().describe(\"'number' fields only — inclusive floor\"),\n max: z.number().optional().describe(\"'number' fields only — inclusive ceiling\"),\n phoneFormat: z.enum([\"any\", \"e164\"]).optional().describe(\"'phone' fields only\"),\n pattern: z.string().optional().describe(\"'text' / 'textarea' / 'url' fields only — a regex\"),\n })\n .optional()\n .describe(\"per-field rules the API enforces on submit; each key is only valid on the field types listed\"),\n });\n const formSettingsShape = {\n description: z.string().optional(),\n submitLabel: z.string().optional().describe(\"submit button label (default 'Submit')\"),\n successMessage: z.string().optional(),\n redirectUrl: z.string().url().optional().describe(\"URL to redirect to on success\"),\n };\n const createFormInput = z.object({\n name: z.string().min(1).describe(\"human form name (used by getForm('Name'))\"),\n fields: z.array(formFieldObject).default([]).describe(\"the form's fields\"),\n ...formSettingsShape,\n });\n const updateFormInput = z.object({\n formId: z.string().min(1).describe(\"form id (from list_forms)\"),\n name: z.string().optional(),\n fields: z.array(formFieldObject).optional().describe(\"REPLACES the field array — include all fields to keep\"),\n ...formSettingsShape,\n });\n\n const componentPropObject = z.object({\n key: z.string().min(1),\n label: z.string().min(1),\n target: z.object({ blockId: z.string().min(1), path: z.string().min(1) }),\n // MUST stay at parity with componentPropDefSchema on the server. `update_component`\n // REPLACES the whole `props` array, so a type this enum omits cannot be echoed back: an\n // agent that reads a component and writes it back DESTROYS every prop of that type.\n type: z.enum([\"text\", \"richtext\", \"image\", \"url\", \"boolean\", \"number\", \"select\", \"group\", \"table\", \"slot\"]),\n // 'slot' holds ONE nested component instance; config.componentIds restricts what may\n // fill it. Absent here until now, so a slot allowlist was unreachable from stdio even\n // once the enum allowed the type.\n config: z\n .object({\n componentIds: z.array(z.string()).optional(), // 'slot' allowlist\n options: z.array(z.string()).optional(), // 'select' — required, choices\n // 'group'/'table' sub-shape. Typed loosely here (the server validates the full\n // recursive shape) so a 3-level tree does not need a 3-level Zod mirror in the client.\n fields: z.array(z.record(z.string(), z.unknown())).optional(),\n min: z.number().optional(), // 'number'\n max: z.number().optional(),\n step: z.number().optional(),\n })\n .passthrough()\n .optional(),\n defaultValue: z.unknown().optional(),\n });\n const getLayoutInput = z.object({\n scope: z.enum([\"global\", \"page\"]).default(\"global\"),\n pageId: z.string().min(1).optional().describe(\"page id or slug; required for page scope\"),\n copy: z.enum([\"draft\", \"published\"]).optional().describe(\"which copy to read; default draft. Verifying a publish MUST read copy:'published' and check the response's copy echo — the draft is never a publish receipt (FLO-1188).\"),\n projectId: z.string().min(1).optional().describe(\"required only for a workspace-scoped grant\"),\n });\n const layoutBinding = z.object({ inputId: z.string().min(1), fieldId: z.string().min(1) });\n const layoutIcon = z.string().min(1).max(80)\n .regex(/^(?:[a-z0-9]+(?:-[a-z0-9]+)*|[A-Z][A-Za-z0-9]+)$/)\n .refine((value) => LAYOUT_SECTION_ICON_SET.has(value), \"Select a supported Lucide icon\")\n .describe(\"Lucide icon name in canonical kebab-case; legacy CamelCase Layout icon names remain accepted\");\n const sectionTarget = { sectionId: z.string().min(1) };\n const layoutCommand = z.discriminatedUnion(\"type\", [\n z.object({ type: z.literal(\"set-section-values\"), ...sectionTarget, values: z.record(z.string(), z.unknown()) }),\n z.object({ type: z.literal(\"set-field-value\"), ...sectionTarget, fieldId: z.string().min(1), value: z.unknown() }),\n z.object({ type: z.literal(\"add-component\"), ...sectionTarget, componentId: z.string().min(1), variantGroupId: z.string().min(1).optional(), bindings: z.array(layoutBinding).optional(), literalValues: z.record(z.string(), z.unknown()).optional() }),\n z.object({ type: z.literal(\"remove-item\"), ...sectionTarget, itemId: z.string().min(1) }),\n z.object({ type: z.literal(\"move-component\"), ...sectionTarget, itemId: z.string().min(1), index: z.number().int().nonnegative() }),\n z.object({ type: z.literal(\"move-item\"), ...sectionTarget, itemId: z.string().min(1), index: z.number().int().nonnegative() }),\n z.object({ type: z.literal(\"swap-component-variant\"), ...sectionTarget, itemId: z.string().min(1), componentId: z.string().min(1) }),\n z.object({ type: z.literal(\"set-page-state\"), ...sectionTarget, state: z.enum([\"inherit\", \"override-content\", \"customize-structure\", \"disable\", \"reset\"]) }),\n z.object({ type: z.literal(\"set-section-state\"), ...sectionTarget, state: z.enum([\"inherit\", \"override-content\", \"customize-structure\", \"disable\", \"reset\"]) }),\n z.object({ type: z.literal(\"add-section\"), name: z.string().min(1), icon: layoutIcon, zone: z.enum([\"before_page\", \"after_page\"]) }),\n 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() }),\n 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() }),\n z.object({ type: z.literal(\"remove-section\"), ...sectionTarget }),\n z.object({ type: z.literal(\"move-section\"), ...sectionTarget, afterId: z.string().nullable().optional(), beforeId: z.string().nullable().optional() }),\n 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() }),\n z.object({ type: z.literal(\"update-field\"), ...sectionTarget, fieldId: z.string().min(1), patch: z.object({}).passthrough() }),\n z.object({ type: z.literal(\"remove-field\"), ...sectionTarget, fieldId: z.string().min(1) }),\n z.object({ type: z.literal(\"move-field\"), ...sectionTarget, itemId: z.string().min(1), index: z.number().int().nonnegative() }),\n z.object({ type: z.literal(\"set-bindings\"), ...sectionTarget, itemId: z.string().min(1), bindings: z.array(layoutBinding), literalValues: z.record(z.string(), z.unknown()).optional() }),\n ]);\n const commandLayoutInput = z.object({\n scope: z.enum([\"global\", \"page\"]).default(\"global\"),\n pageId: z.string().min(1).optional(),\n projectId: z.string().min(1).optional().describe(\"required only for a workspace-scoped grant\"),\n command: layoutCommand.describe(\"one canonical discriminated Layout command; authority is derived from type\"),\n ifMatch: z.number().int().nonnegative().describe(\"revision returned by get_layout\"),\n });\n // Eight structural categories (what the component IS) + the four \"Add a section\" library\n // tabs (where it appears). Keep in step with componentCategorySchema in\n // src/lib/validation/schemas/components.ts — the library four were missing here, so an\n // agent could not file a component under a library tab.\n const componentCategory = z.enum([\n \"navbar\", \"footer\", \"button\", \"section\", \"slider\", \"tabs\", \"form\", \"custom\",\n \"hero\", \"content\", \"social-proof\", \"conversion\",\n ]);\n const sectionType = z\n .string()\n .min(1)\n .max(64)\n .describe(\n \"section family, e.g. 'Hero' — set this with a library category to make the component selectable in the page editor's 'Add a section' picker. Components sharing a sectionType are layout variants of one section.\",\n );\n const allowedOn = z\n .array(z.string().regex(/^(\\*|slug:[a-z0-9-]+|type:(singleton|dynamic|template))$/))\n .max(100)\n .describe(\"placement allowlist: *, slug:<page-slug>, and/or type:singleton|dynamic|template\");\n const createComponentInput = z.object({\n name: z.string().min(1),\n slug: slug.describe(\"url-safe unique slug (lowercase letters/numbers/hyphens)\"),\n category: componentCategory.optional().describe(\"defaults to 'custom'\"),\n sectionType: sectionType.optional(),\n projectId: z.string().nullable().optional().describe(\"owning project id; null creates a workspace-wide global component\"),\n allowedOn: allowedOn.optional(),\n description: z.string().optional(),\n blockJson: z.array(blockObject).default([]).describe(\"the component's block tree\"),\n props: z.array(componentPropObject).default([]).describe(\"overridable fields\"),\n });\n const updateComponentInput = z.object({\n componentId: z.string().min(1).describe(\"component id (from list_components)\"),\n name: z.string().optional(),\n category: componentCategory.optional(),\n sectionType: sectionType\n .nullable()\n .optional()\n .describe(\n \"null demotes it to an ordinary component — it disappears from the 'Add a section' picker, and instances already placed keep rendering but lose their section chrome and variant switcher\",\n ),\n allowedOn: allowedOn.optional().describe(\"REPLACES the placement allowlist\"),\n description: z.string().optional(),\n blockJson: z.array(blockObject).optional().describe(\"REPLACES the block tree\"),\n props: z.array(componentPropObject).optional(),\n });\n const getComponentInput = z.object({\n componentId: z.string().min(1).describe(\"component id (from list_components)\"),\n });\n const listExtractionCandidatesInput = z.object({\n projectId: z.string().min(1).optional().describe(\"only needed for a workspace-wide key\"),\n });\n const extractComponentInput = z.object({\n hash: z.string().min(1).describe(\"candidate hash from list_extraction_candidates\"),\n name: z.string().min(1).describe(\"name for the new component\"),\n slug: slug.describe(\"url-safe unique slug (lowercase letters/numbers/hyphens)\"),\n projectId: z.string().min(1).optional().describe(\"only needed for a workspace-wide key\"),\n });\n const sectionEvidenceProjectId = z\n .string()\n .min(1)\n .max(64)\n .describe(\"exact project id from get_project (not a slug); Section evidence is project-local and never reusable across projects\");\n const sectionId = z.string().uuid().describe(\"Section definition id from Section Studio\");\n const sectionVersion = z.number().int().positive().describe(\"exact Section schema version implemented or tested\");\n const sha256 = z.string().regex(/^[0-9a-f]{64}$/i, \"Expected a SHA-256 hex digest\");\n const sectionViewport = z.object({\n name: z.string().trim().min(1).max(64),\n width: z.number().int().min(240).max(7680),\n height: z.number().int().min(240).max(7680),\n });\n const sectionEvidenceDigest = z.string()\n .regex(/^(?:sha256:)?[0-9a-f]{64}$/i, \"Expected a SHA-256 digest\");\n const nonEmptyDescriptor = z.record(z.string(), z.unknown())\n .refine((value) => Object.keys(value).length > 0, \"Descriptor cannot be empty\");\n const sectionRequestId = z.string().uuid().describe(\"durable Section validation request id returned by list_section_validation_requests or the dashboard\");\n const sectionHttpUrl = z.string().url().max(2048).refine((value) => {\n try {\n const protocol = new URL(value).protocol;\n return protocol === \"http:\" || protocol === \"https:\";\n } catch {\n return false;\n }\n }, \"Expected an HTTP or HTTPS URL\");\n const sectionValidationViewport = sectionViewport.extend({\n status: z.enum([\"passed\", \"failed\"]),\n evidenceDigest: sectionEvidenceDigest,\n });\n const submitSectionManifestInput = z.object({\n projectId: sectionEvidenceProjectId,\n requestId: sectionRequestId.optional().describe(\"include when fulfilling a claimed dashboard request so the evidence is bound to that exact run\"),\n sectionId,\n version: sectionVersion,\n apiId: z.string().regex(/^[a-z][A-Za-z0-9]*$/, \"Use lower camelCase\").max(100),\n schemaHash: sha256.describe(\"exact SHA-256 hex hash shown for this Section version\"),\n commitSha: z.string().regex(/^[0-9a-f]{7,64}$/i).describe(\"git commit containing the implementation\"),\n loader: nonEmptyDescriptor.describe(\"non-empty serializable loader descriptor emitted by the repo build; never executable code\"),\n previewAdapter: nonEmptyDescriptor.describe(\"non-empty serializable adapter descriptor for the customer's real app shell; never executable code\"),\n nativeViewports: z\n .array(sectionViewport)\n .max(20)\n .optional()\n .describe(\"the customer's named responsive viewports; BetterCMS also enforces Desktop 1440x900, Tablet 768x1024, and Mobile 390x844\"),\n });\n const submitSectionValidationInput = z.object({\n projectId: sectionEvidenceProjectId.describe(\"exact project id from get_project (not a slug); must match the manifest's project\"),\n requestId: sectionRequestId.optional().describe(\"same claimed request id used for the manifest; binds and terminalizes that run\"),\n sectionId: sectionId.describe(\"exact Section definition id\"),\n version: sectionVersion,\n manifestId: z.string().uuid().describe(\"manifest id returned by submit_section_manifest; it pins the schema hash and commit SHA\"),\n status: z.enum([\"passed\", \"failed\"]).describe(\"the actual result of the external repo/app-shell validation\"),\n fixtureHash: sha256.describe(\"SHA-256 hex hash of the canonical preview dataset and stress fixtures used\"),\n evidenceDigest: sectionEvidenceDigest\n .describe(\"SHA-256 digest of the immutable validation evidence bundle (screenshots/report/results)\"),\n appShell: z.object({\n kind: z.literal(\"actual-app\"),\n identifier: z.string().trim().min(1).max(255),\n url: sectionHttpUrl.optional(),\n }).describe(\"the real customer application shell used for the validation run\"),\n viewportResults: z.array(sectionValidationViewport).min(1).max(23)\n .describe(\"one signed result for every required and native manifest viewport\"),\n });\n const listSectionValidationRequestsInput = z.object({\n projectId: sectionEvidenceProjectId,\n limit: z.number().int().min(1).max(100).optional(),\n });\n const claimSectionValidationRequestInput = z.object({\n projectId: sectionEvidenceProjectId,\n requestId: sectionRequestId,\n commitSha: z.string().regex(/^[0-9a-f]{7,64}$/i)\n .describe(\"exact git commit the agent will inspect and validate; evidence must use this same commit\"),\n providerRunId: z.string().trim().min(1).max(255).optional(),\n providerRunUrl: sectionHttpUrl.optional().describe(\"optional HTTP(S) link to the user's external agent run\"),\n });\n const completeSectionValidationRequestInput = z.object({\n projectId: sectionEvidenceProjectId,\n requestId: sectionRequestId,\n manifestId: z.string().uuid().optional(),\n validationRunId: z.string().uuid().optional(),\n });\n const failSectionValidationRequestInput = z.object({\n projectId: sectionEvidenceProjectId,\n requestId: sectionRequestId,\n errorCode: z.string().trim().regex(/^[A-Z][A-Z0-9_]*$/).max(100),\n errorMessage: z.string().trim().min(1).max(2_000),\n providerRunId: z.string().trim().min(1).max(255).optional(),\n providerRunUrl: sectionHttpUrl.optional().describe(\"optional HTTP(S) link to the user's external agent run\"),\n });\n\n /**\n * The content-lifecycle tools, in parity with the remote /mcp catalog. Each is a thin\n * call to an authenticated API route through the client's public request plumbing — no\n * bespoke SDK method per endpoint (DRY). Most target Management; Section evidence targets\n * the project-scoped ingest lane. `def`/`data` collapse the shared boilerplate.\n */\n function lifecycleTools(): ToolDef[] {\n const def = (\n name: string,\n title: string,\n description: string,\n shape: z.ZodRawShape,\n run: (client: ManagementApi, args: Record<string, unknown>) => Promise<ToolResult>,\n ): ToolDef => ({\n name,\n config: { title, description, inputSchema: shape },\n handler: guard(async (args: Record<string, unknown>) => withClient((client) => run(client, args))) as ToolDef[\"handler\"],\n });\n const q = (obj: Record<string, unknown>): string => {\n const p = new URLSearchParams();\n for (const [k, v] of Object.entries(obj)) if (v !== undefined && v !== null) p.set(k, String(v));\n const s = p.toString();\n return s ? `?${s}` : \"\";\n };\n /**\n * Call a management endpoint and return its `data` payload.\n *\n * 🔴 Do NOT set a content-type here. `ManagementApi.headers()` already sends\n * `Content-Type: application/json`, and `fetchJSON` merges headers as a PLAIN OBJECT —\n * so a lowercase `content-type` is a DIFFERENT key, both survive the spread, and the\n * Headers constructor then APPENDS them into `application/json, application/json`.\n * Hono's zValidator does not recognise that as JSON, reads the body as absent, and every\n * write here failed with a validation error naming a field the caller did send. It cost\n * all 16 body-carrying tools on this surface, silently, because the request looked\n * perfect from the client side and the server's complaint pointed at the body's contents.\n */\n const data = async (client: ManagementApi, method: string, path: string, body?: unknown): Promise<unknown> =>\n (await client.fetchJSON<{ data?: unknown }>(client.url(path), {\n method,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n })).data;\n const s = (v: unknown) => v as string;\n /** POST raw bytes (base64 → binary) for the binary deploy tool; returns `data`. */\n const raw = async (client: ManagementApi, path: string, base64: string, mimeType?: string): Promise<unknown> =>\n (await client.fetchJSON<{ data?: unknown }>(client.url(path), {\n method: \"POST\",\n body: Buffer.from(base64, \"base64\"),\n headers: { \"content-type\": mimeType ?? \"application/octet-stream\" },\n })).data;\n\n return [\n def(\"create_media_upload\", \"Get a presigned media-upload URL\",\n \"PREFERRED way to add an image — get a presigned URL and upload the file DIRECTLY to storage, so the bytes never pass through the conversation. Flow: (1) call this with filename, mimeType and sizeBytes (the file's exact byte length); (2) PUT the file to `uploadUrl`, e.g. `curl -X PUT -H 'Content-Type: image/jpeg' --data-binary @photo.jpg \\\"<uploadUrl>\\\"` — the url pins both headers, so they must match exactly; (3) call attach_media_upload with the `assetId` + `uploadKey`. URL expires in 10 minutes.\",\n z.object({\n filename: z.string().min(1).describe(\"file name incl. extension, e.g. 'hero.png'\"),\n mimeType: z.string().min(1).describe(\"MIME type, e.g. 'image/png'\"),\n sizeBytes: z.number().describe(\"the file's exact size in bytes (e.g. from `stat`/`wc -c`) — the presigned url pins it\"),\n }).shape,\n async (c, a) => ok(\"Upload URL.\", await data(c, \"POST\", `/management/media/upload-url`, { filename: a.filename, mimeType: a.mimeType, sizeBytes: a.sizeBytes }))),\n def(\"attach_media_upload\", \"Attach a presigned media upload\",\n \"Register a file you already uploaded via create_media_upload (step 3) into the Media Library and get back its CDN url. Pass the `assetId` + `uploadKey` from step 1, plus the filename and any alt text/caption.\",\n z.object({\n assetId: z.string().min(1).describe(\"the assetId from create_media_upload\"),\n uploadKey: z.string().min(1).describe(\"the uploadKey from create_media_upload, after the PUT succeeded\"),\n filename: z.string().min(1).describe(\"file name incl. extension\"),\n altText: z.string().optional(),\n caption: z.string().optional(),\n folderId: z.string().optional(),\n }).shape,\n async (c, a) => ok(\"Media asset.\", await data(c, \"POST\", `/management/media/from-upload`, { assetId: a.assetId, uploadKey: a.uploadKey, filename: a.filename, altText: a.altText, caption: a.caption, folderId: a.folderId }))),\n def(\"list_media\", \"List media assets\",\n \"List the images/assets already in the connected project's Media Library (id, url, filename, mimeType, size, alt/caption). Reuse an existing asset instead of re-uploading. Filter with `search` or `type` ('image'|'video'|…).\",\n z.object({ search: z.string().optional(), type: z.string().optional(), limit: z.number().optional(), page: z.number().optional() }).shape,\n async (c, a) => ok(\"Media assets.\", await data(c, \"GET\", `/management/media${q({ search: a.search, type: a.type, limit: a.limit, page: a.page })}`))),\n def(\"get_media\", \"Get a media asset\",\n \"Get one media asset by id — its CDN url, filename, MIME type, size, and alt/caption. Use the url as the value of an 'image' field.\",\n z.object({ assetId: z.string().min(1).describe(\"media asset id (from list_media / upload_asset)\") }).shape,\n async (c, a) => ok(\"Media asset.\", await data(c, \"GET\", `/management/media/${s(a.assetId)}`))),\n def(\"delete_media\", \"Delete a media asset\",\n \"Delete a media asset from the Media Library (soft delete — reversible from the dashboard trash). Provide assetId.\",\n z.object({ assetId: z.string().min(1).describe(\"media asset id (from list_media)\") }).shape,\n async (c, a) => ok(\"Deleted media asset.\", await data(c, \"DELETE\", `/management/media/${s(a.assetId)}`))),\n\n def(\"delete_form\", \"Delete a form\",\n \"Delete a form by id. Soft delete — the form stops rendering and accepting submissions, but leads already collected against it are preserved. Use it to clean up forms created by mistake.\",\n z.object({ formId: z.string().min(1).describe(\"form id (from list_forms)\") }).shape,\n async (c, a) => ok(\"Deleted form.\", await data(c, \"DELETE\", `/management/forms/${s(a.formId)}`))),\n\n def(\"list_form_submissions\", \"List a form's submissions (leads)\",\n \"List the SUBMISSIONS (leads) a form has received — each with its submitted field values. Filter with status ('inbox'|'spam') and paginate with limit/page.\",\n z.object({ formId: z.string().min(1), status: z.enum([\"inbox\", \"spam\"]).optional(), limit: z.number().optional(), page: z.number().optional() }).shape,\n async (c, a) => ok(\"Form submissions.\", await data(c, \"GET\", `/management/forms/${s(a.formId)}/submissions${q({ status: a.status, limit: a.limit, page: a.page })}`))),\n def(\"delete_form_submission\", \"Delete a form submission\",\n \"Delete one form submission (lead) — e.g. to clear spam. Provide formId and submissionId (from list_form_submissions).\",\n z.object({ formId: z.string().min(1), submissionId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Deleted submission.\", await data(c, \"DELETE\", `/management/forms/${s(a.formId)}/submissions/${s(a.submissionId)}`))),\n\n def(\"list_redirects\", \"List redirects\",\n \"List the URL redirects configured for the connected project (source path → destination, type).\",\n z.object({}).shape,\n async (c) => ok(\"Redirects.\", await data(c, \"GET\", `/management/redirects`))),\n def(\"update_redirect\", \"Update a redirect\",\n \"Update an existing redirect in place — change where it points, its HTTP status, or disable it without deleting. Prefer this over delete+create: it keeps the redirect's id and preserves the chain-collapse rewrites of other rules pointing at it. Only provided fields change. Loops 422, duplicate sources 409.\",\n z.object({ redirectId: z.string().min(1).describe(\"redirect id (from list_redirects)\"), sourcePath: z.string().min(1).optional(), destination: z.string().min(1).optional(), redirectType: z.enum([\"301\", \"302\", \"307\", \"308\"]).optional(), isActive: z.boolean().optional().describe(\"set false to disable without deleting\") }).shape,\n async (c, a) => ok(\"Updated redirect.\", await data(c, \"PATCH\", `/management/redirects/${s(a.redirectId)}`, { sourcePath: a.sourcePath, destination: a.destination, redirectType: a.redirectType, isActive: a.isActive }))),\n def(\"create_redirect\", \"Create a redirect\",\n \"Create a URL redirect — e.g. a 301 after renaming a page's slug. `sourcePath` is the path to redirect FROM ('/old-page'), `destination` the path/url TO ('/new-page'). Chains collapse; loops/dupes rejected. Defaults to 301.\",\n z.object({ sourcePath: z.string().min(1), destination: z.string().min(1), redirectType: z.enum([\"301\", \"302\", \"307\", \"308\"]).optional() }).shape,\n async (c, a) => ok(\"Created redirect.\", await data(c, \"POST\", `/management/redirects`, { sourcePath: a.sourcePath, destination: a.destination, redirectType: a.redirectType }))),\n def(\"delete_redirect\", \"Delete a redirect\",\n \"Delete a URL redirect by id (from list_redirects). Provide redirectId.\",\n z.object({ redirectId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Deleted redirect.\", await data(c, \"DELETE\", `/management/redirects/${s(a.redirectId)}`))),\n\n def(\"get_seo\", \"Get site SEO\",\n \"Get the connected project's site-wide SEO settings — default meta (title/description/ogImage), JSON-LD siteSchema, and robots/sitemap/rss config.\",\n z.object({}).shape,\n async (c) => ok(\"SEO settings.\", await data(c, \"GET\", `/management/seo`))),\n def(\"update_seo\", \"Update site SEO\",\n \"Set site-wide SEO defaults. `seoDefaults` { metaTitle, metaDescription, ogImage, twitterHandle } applies to every page unless overridden. Optionally robotsConfig / sitemapConfig / rssConfig. Each field is REPLACED whole. Rebuilds the site.\",\n z.object({ seoDefaults: z.record(z.string(), z.unknown()).optional(), siteSchema: z.record(z.string(), z.unknown()).optional(), robotsConfig: z.record(z.string(), z.unknown()).optional(), sitemapConfig: z.record(z.string(), z.unknown()).optional(), rssConfig: z.record(z.string(), z.unknown()).optional() }).shape,\n async (c, a) => ok(\"Updated SEO.\", await data(c, \"PATCH\", `/management/seo`, a))),\n\n def(\"get_site_files\", \"List site files\",\n \"List the AI-crawler files installed on the connected project (llms.txt / llms-full.txt) — metadata only.\",\n z.object({}).shape,\n async (c) => ok(\"Site files.\", await data(c, \"GET\", `/management/site-files`))),\n def(\"set_site_file\", \"Set a site file\",\n \"Create or replace an AI-crawler file served at the site root — `kind` 'llms.txt' or 'llms-full.txt' — with `content` (plain text, max 5 MB). Rebuilds the site.\",\n z.object({ kind: z.enum([\"llms.txt\", \"llms-full.txt\"]), content: z.string() }).shape,\n async (c, a) => ok(\"Saved site file.\", await data(c, \"PUT\", `/management/site-files/${s(a.kind)}`, { content: a.content }))),\n def(\"delete_site_file\", \"Delete a site file\",\n \"Remove an AI-crawler file (llms.txt / llms-full.txt) from the connected project. Provide kind.\",\n z.object({ kind: z.enum([\"llms.txt\", \"llms-full.txt\"]) }).shape,\n async (c, a) => ok(\"Deleted site file.\", await data(c, \"DELETE\", `/management/site-files/${s(a.kind)}`))),\n\n // ── Editorial board ──\n // Publishing is two decisions: may the KEY publish (content:publish, granted at\n // consent) and may the ITEM publish (it must sit in the board's gate stage). These\n // tools are the second one. Without them a publish-enabled connection still dead-ends\n // on a 409 the moment a project uses review columns.\n def(\"get_workflow_board\", \"List editorial workflow stages\",\n \"List the connected project's editorial board columns in order — each stage's `key`, name, and whether it is the `publishGate` (the one stage content may go live from). Read this BEFORE move_entry_stage / move_page_stage: stage keys are per-project and not guessable, because a project can rename or replace every column.\",\n z.object({}).shape,\n async (c) => ok(\"Workflow stages.\", await data(c, \"GET\", `/management/workflow/stages`))),\n def(\"move_entry_stage\", \"Move a content entry across the board\",\n \"Move a content entry to another editorial stage — this is how you get an entry OUT of review so it can be published. `workflowStage` is a stage key from get_workflow_board (null clears it). Optionally set `workflowAssigneeIds` / `workflowDueDate`, or pass `fromStage` to fail with 409 if someone moved it first. Moving into the publish-gate stage is an approval and needs a publish-enabled connection. Publish afterwards with update_content_entry status:'published' — approving and publishing are deliberately two separate calls.\",\n z.object({ entryId: z.string().min(1), workflowStage: z.string().max(64).describe(\"stage key from get_workflow_board\"), fromStage: z.string().max(64).optional().describe(\"the stage you believe it is in — 409s if it has moved\") }).shape,\n async (c, a) => ok(\"Moved entry.\", await data(c, \"PATCH\", `/management/content/entries/${s(a.entryId)}/workflow`, { workflowStage: a.workflowStage, fromStage: a.fromStage }))),\n def(\"move_page_stage\", \"Move a page across the board\",\n \"Move a page to another editorial stage — the page twin of move_entry_stage, and the only way to take a page out of review so update_page (status:'published') can go live. `workflowStage` is a stage key from get_workflow_board. Moving into the publish-gate stage is an approval and needs a publish-enabled connection.\",\n z.object({ pageId: z.string().min(1), workflowStage: z.string().max(64).describe(\"stage key from get_workflow_board\"), fromStage: z.string().max(64).optional().describe(\"the stage you believe it is in — 409s if it has moved\") }).shape,\n async (c, a) => ok(\"Moved page.\", await data(c, \"PATCH\", `/management/pages/${s(a.pageId)}/workflow`, { workflowStage: a.workflowStage, fromStage: a.fromStage }))),\n\n def(\"promote_project\", \"Promote staging → production\",\n \"Promote the connected project's STAGED build to PRODUCTION — the one-click publish. Flips prod to the newest staged release (no rebuild) after the QA scan passes. Managed hosting only; needs a publish-enabled connection.\",\n z.object({}).shape,\n async (c) => ok(\"Promoted to production.\", await data(c, \"POST\", `/management/projects/promote`))),\n\n def(\"list_entry_versions\", \"List a content entry's versions\",\n \"List a content entry's version history (newest first) — each version's number, data snapshot, and when it was saved. Use it to find a past state to restore.\",\n z.object({ entryId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Entry versions.\", await data(c, \"GET\", `/management/content/entries/${s(a.entryId)}/versions`))),\n def(\"restore_entry_version\", \"Restore a content entry to a past version\",\n \"Restore a content entry to a past version (undo). Copies that version's data back as the current DRAFT (non-destructive). Publish afterwards to take it live. Provide entryId and the version number (from list_entry_versions).\",\n z.object({ entryId: z.string().min(1), version: z.number().int().positive() }).shape,\n async (c, a) => ok(\"Restored entry version.\", await data(c, \"POST\", `/management/content/entries/${s(a.entryId)}/versions/${a.version}/restore`))),\n\n // ── Project / workspace (parity with remote /mcp) ──\n def(\"get_project\", \"Get the connected project\",\n \"Get the connected project's info — id, name, slug, subdomain, and its live URL (https://<handle>.bettercms.site). Use it to tell the user where their site is published / link the result.\",\n z.object({}).shape,\n async (c) => ok(\"Project.\", await data(c, \"GET\", `/management/projects/current`))),\n def(\"list_projects\", \"List projects\",\n \"List the projects this key can see — id, name, slug, and live URL each. A project-scoped key sees only its own project; a workspace-level key sees every project in the workspace. Use it to find a project you created earlier, or to confirm which sites exist before acting.\",\n z.object({}).shape,\n async (c) => ok(\"Projects.\", await data(c, \"GET\", `/management/projects`))),\n def(\"update_project\", \"Update the connected project\",\n \"Update the connected project's settings — rename it, change its slug/description, SEO defaults, or visibility. Only the provided fields change.\",\n z.object({ name: z.string().optional(), slug: z.string().optional(), description: z.string().optional(), visibility: z.string().optional(), seoDefaults: z.record(z.string(), z.unknown()).optional() }).shape,\n async (c, a) => ok(\"Updated project.\", await data(c, \"PATCH\", `/management/projects/current`, a))),\n def(\"create_project\", \"Create a new project\",\n \"Create a NEW project (site) in the connected workspace. ASK THE USER WHICH TECHNOLOGY TO BUILD WITH FIRST and pass it as `framework` — 'astro' (recommended default), 'next', 'react-ts' (React + TypeScript), or 'other' for a headless project with no generated frontend. Do not pick for them: called without it, this tool asks them directly (or hands you the question to ask). Sites cannot be created as plain HTML/CSS — every project is backed by one of these starters, which is what makes its content editable in the CMS. Optionally pass templateId to seed curated content. Returns the new project's id and slug. (Use clone_project instead to duplicate an existing project.)\",\n // `framework` is OPTIONAL in the schema on purpose, even though it is required in\n // effect: a required arg is rejected by the SDK before the handler runs, which would\n // kill the elicitation below and leave the model guessing on its own. Optional here,\n // answered by a human there. The backend rejects a create with no framework regardless.\n z.object({ name: z.string().min(1), slug: z.string().optional(), description: z.string().optional(), templateId: z.string().optional(), framework: z.enum(FRAMEWORK_CHOICES).optional().describe(\"REQUIRED in effect — the technology the USER chose. Ask them; never default it.\") }).shape,\n async (c, a) => {\n let framework = a.framework;\n if (framework === undefined) {\n const asked = await askFramework(deps);\n if (\"prompt\" in asked) return fail(asked.prompt);\n framework = asked.framework;\n }\n return ok(\"Created project.\", await data(c, \"POST\", `/management/projects`, { ...a, framework }));\n }),\n def(\"set_authoring_preference\", \"Set the site's authoring architecture\",\n \"Record which authoring architecture this site uses — 'components' (reusable section components placed as blocks; editors add, reorder and swap sections without touching a schema — best for marketing and landing sites) or 'fields' (a typed field schema per page — best for blogs, catalogues and directories). ASK THE USER; do not pick for them. Called without `preference`, this tool asks them directly (or hands you the question to ask). deploy_project, deploy_from_upload and promote_project all refuse with 409 AUTHORING_DECISION_REQUIRED until it is set, and that refusal carries this project's real page counts to show the user. Answering 'components' does NOT convert anything — there is no field-to-block converter; it means you author the sections yourself: create_component, then publish_component (an unpublished component renders as NOTHING on the live site), then set_page_content placing `component` blocks. Asked once per project; re-callable if the user changes their mind.\",\n // Optional in the schema for exactly the reason `framework` is above: a required arg is\n // rejected by the SDK before the handler runs, which would kill the elicitation below\n // and leave the model guessing. Optional here, answered by a human there. The backend\n // gate refuses the deploy regardless, so nothing ships on a guess.\n z.object({ preference: z.enum(AUTHORING_CHOICES).optional().describe(\"REQUIRED in effect — the architecture the USER chose. Ask them; never default it.\") }).shape,\n async (c, a) => {\n let preference = a.preference;\n if (preference === undefined) {\n const asked = await askAuthoring(deps);\n if (\"prompt\" in asked) return fail(asked.prompt);\n preference = asked.preference;\n }\n return ok(\"Recorded the authoring architecture.\", await data(c, \"PATCH\", `/management/projects/current/authoring-preference`, { preference }));\n }),\n def(\"set_binding_mode\", \"Set how the site's bindings are resolved\",\n \"Switch this project between the two binding resolvers, from the NEXT release on. `declaredBindings: true` makes the annotator trust the template's own data-bcms-field / data-bcms-props and never guess from rendered text — the durable state; `false` returns to text-matching, which works once (at import, when the CMS values equal the built copy) and breaks the first time anyone edits a value. Call it ONLY after every page's copy is declared in the template: undeclared fields stop being editable. The order is push → release → get_binding_report shows mode 'text-match' with 0 unmatched → set_binding_mode → release again → get_binding_report shows mode 'declared'. Flipping back is the same call. REQUIRES a project-scoped connection carrying the artifact:write scope — the same authority that deploys the site — because this decides what every future release does to every page; a workspace-wide grant is refused with 403. See section 13 of the bettercms://playbook/schema resource.\",\n z.object({ declaredBindings: z.boolean().describe(\"true = trust the template's declared bindings; false = text-match (the default)\") }).shape,\n async (c, a) => ok(\"Recorded the binding mode.\", await data(c, \"PATCH\", `/management/projects/current/binding-mode`, { declaredBindings: a.declaredBindings }))),\n def(\"clone_project\", \"Clone a project\",\n \"Clone (duplicate) a project as a reusable template into the connected workspace. Copies pages, content models + entries, components, media, forms, and SEO/custom-code settings; excludes submissions, analytics, domains, and secrets. Returns the new project's id and slug. Omit sourceProjectId to clone the connected project.\",\n z.object({ sourceProjectId: z.string().optional(), name: z.string().optional(), slug: z.string().optional() }).shape,\n async (c, a) => ok(\"Cloned project.\", await data(c, \"POST\", `/management/projects/clone`, a))),\n def(\"create_template\", \"Save a project/page as a template\",\n \"Save a project (or one page) as a REUSABLE template — a frozen snapshot of its content models, pages, entries, components, and forms (secrets/domains/analytics excluded). Later seed a new project from it with create_project { templateId }. Set visibility 'public' to list it in the cross-workspace gallery. Returns the new template's id.\",\n z.object({ sourceProjectId: z.string().min(1), name: z.string().min(1), scope: z.string().optional(), sourcePageId: z.string().optional(), description: z.string().optional(), visibility: z.string().optional() }).shape,\n async (c, a) => ok(\"Created template.\", await data(c, \"POST\", `/management/templates`, a))),\n def(\"list_templates\", \"List saved templates\",\n \"List your workspace's saved templates (id, name, scope, visibility). Use a template's id as create_project { templateId } to seed a new project from it.\",\n z.object({}).shape,\n async (c) => ok(\"Templates.\", await data(c, \"GET\", `/management/templates`))),\n\n // ── Content models (read/metadata; parity with remote /mcp) ──\n def(\"list_content_models\", \"List content models\",\n \"List the content models (reusable schemas for dynamic collections like Blog/Products) in the connected project.\",\n z.object({}).shape,\n async (c) => ok(\"Content models.\", await data(c, \"GET\", `/management/content/models`))),\n def(\"get_content_model\", \"Get a content model\",\n \"Get one content model by id INCLUDING its full field schema (keys, types, nested group/repeater children). Read this before add_field so you know the existing keys.\",\n z.object({ modelId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Content model.\", await data(c, \"GET\", `/management/content/models/${s(a.modelId)}`))),\n def(\"update_content_model\", \"Update a content model's metadata\",\n \"Rename a content model or edit its description/slug (metadata only — does NOT touch fields; use add_field to extend the schema). Provide modelId plus the fields to change.\",\n z.object({ modelId: z.string().min(1), name: z.string().optional(), slug: z.string().optional(), description: z.string().optional() }).shape,\n async (c, a) => ok(\"Updated content model.\", await data(c, \"PATCH\", `/management/content/models/${s(a.modelId)}`, { name: a.name, slug: a.slug, description: a.description }))),\n def(\"get_content_types\", \"Get generated TypeScript types\",\n \"Get the auto-generated TypeScript types for the connected project's content models/pages. Pull these to write correctly-typed code against the BetterCMS delivery SDK in the user's site.\",\n z.object({}).shape,\n async (c) => ok(\"Content types.\", await data(c, \"GET\", `/management/content/types`))),\n\n // ── Pages (metadata edit; parity with remote /mcp) ──\n def(\"update_page\", \"Edit a page\",\n \"Edit a page: title, slug, SEO metaTitle/metaDescription, publish status (draft|published), and `blockJson` (its block composition — passing it REPLACES the whole array, so read get_page first). It does NOT change the field SCHEMA — use add_page_field / set_page_content for that. Renaming the slug keeps content intact. Publishing copies the draft blocks live in the same call. \" +\n DOCTRINE,\n z.object({ pageId: z.string().min(1), title: z.string().optional(), slug: z.string().optional(), blockJson: z.array(blockObject).optional().describe(\"REPLACES the page's block composition\"), metaTitle: z.string().optional(), metaDescription: z.string().optional(), status: z.enum([\"draft\", \"published\"]).optional() }).shape,\n async (c, a) => ok(\"Updated page.\", await data(c, \"PATCH\", `/management/pages/${s(a.pageId)}/meta`, { title: a.title, slug: a.slug, blockJson: a.blockJson, metaTitle: a.metaTitle, metaDescription: a.metaDescription, status: a.status }))),\n\n // ── Code + deploy (parity with remote /mcp; needs artifact:write) ──\n def(\"pull_project_source\", \"Pull the project's live source\",\n \"Get the connected project's CURRENT live source/build so you can edit it locally. Returns a presigned tarball download url (1h) + the live commit sha — download it, extract, edit the files, then call deploy_project. If the project is connected to a GitHub repo, returns `github: {owner, repo}` so you can `git clone` that instead.\",\n z.object({}).shape,\n async (c) => ok(\"Project source.\", await data(c, \"GET\", `/management/projects/source`))),\n def(\"deploy_project\", \"Deploy new source/build\",\n \"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 — then poll get_deploy_status until it is live. IMPORTANT — 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 — 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 — that path uploads straight to storage with no size ceiling.\",\n z.object({ data: z.string().min(1).describe(\"base64 .tgz/.zip of the project\"), mimeType: z.string().optional() }).shape,\n async (c, a) => ok(\"Deploy queued.\", await raw(c, `/management/projects/deploy`, s(a.data), a.mimeType as string | undefined))),\n def(\"create_deploy_upload\", \"Get a presigned deploy-upload URL\",\n \"Get a presigned URL to upload a LARGE deploy archive directly to storage, bypassing the ~100 MB body limit deploy_project's inline `data` hits. Flow: (1) call this for `uploadUrl` + `uploadKey`; (2) PUT your .tgz/.zip to `uploadUrl` (e.g. `curl -X PUT --data-binary @archive.tgz \\\"<uploadUrl>\\\"`) — straight to storage, no size ceiling; (3) call deploy_from_upload with `uploadKey`. Still exclude node_modules/.git/build caches. URL expires in 10 minutes.\",\n z.object({}).shape,\n async (c) => ok(\"Upload URL.\", await data(c, \"POST\", `/management/projects/deploy/upload-url`))),\n def(\"deploy_from_upload\", \"Deploy from a staged upload\",\n \"Deploy from an archive already uploaded via create_deploy_upload (step 3). Pass the `uploadKey` you received. Builds SOURCE server-side or serves a prebuilt site — then poll get_deploy_status until live.\",\n z.object({ uploadKey: z.string().min(1).describe(\"the uploadKey from create_deploy_upload, after PUTting the archive to its uploadUrl\") }).shape,\n async (c, a) => ok(\"Deploy queued.\", await data(c, \"POST\", `/management/projects/deploy/from-upload`, { uploadKey: a.uploadKey }))),\n // ── Insight: what happened, what's working, what's broken ─────────────────\n def(\"list_activity\", \"List project activity\",\n \"Recent activity in the connected project — who changed what, and when. Filter by `category` (comma-separated: content, pages, media, forms, deployment, settings, members), `actorId`, or a `since`/`until` ISO window.\",\n z.object({ category: z.string().optional(), actorId: z.string().optional(), since: z.string().optional(), until: z.string().optional(), limit: z.number().optional() }).shape,\n async (c, a) => ok(\"Project activity.\", await data(c, \"GET\", `/management/insights/activity${q({ category: a.category, actorId: a.actorId, since: a.since, until: a.until, limit: a.limit })}`))),\n def(\"get_changes\", \"Get changes since a timestamp\",\n \"Read the durable project change feed since an ISO timestamp. Call this at the start of a new turn to notice dashboard or agent edits made since your previous observation.\",\n z.object({ since: z.string().datetime(), limit: z.number().int().min(1).max(100).optional() }).shape,\n async (c, a) => ok(\"Project changes.\", await data(c, \"GET\", `/management/insights/activity${q({ since: a.since, limit: a.limit ?? 100 })}`))),\n def(\"get_next_steps\", \"Get what to do next\",\n \"What is still unfinished in the connected project, as the platform sees it — pages you created without a meta description, drafts never published, collections with no entries, forms nobody is notified about, writes waiting for human approval. Each item cites the count it reacted to. Call it AFTER a batch of edits to catch what you left behind, and before telling the user you are done.\",\n z.object({}).shape,\n async (c) => ok(\"Next steps.\", await data(c, \"GET\", `/management/insights/next-steps`))),\n def(\"get_binding_report\", \"Check what on the live site is editable\",\n \"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` — 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 — 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.\",\n z.object({ slot: z.enum([\"current\", \"staging\"]).optional().describe(\"which release tree to read; defaults to the one this project deploys to\") }).shape,\n async (c, a) => ok(\"Binding report.\", await data(c, \"GET\", `/management/projects/current/binding-report${q({ slot: a.slot })}`))),\n def(\"get_conversion_brief\", \"Get the brief for making this site's bindings durable\",\n \"The per-project brief for making this site's bindings DURABLE — read it before you touch the templates. Returns what already exists in the CMS: every live page with its route, and every bindable field path with its `label`, `kind`, the value the CMS holds now (`current`) and the copy the repo renders today (`original`, the field's defaultValue) — plus the exact attributes to declare, and the ordered steps. Call it for any site whose pages were DERIVED at import, and whenever get_next_steps reports `bindings-not-declared`. It REPLACES re-registering a schema: these pages, fields and values exist already, so create_page / add_page_field / create_content_model would build a second schema over the first — edit values with set_page_content instead. `lane` says how to get the source ('git-connected' = pull_project_source returns a repo; 'archive' = a tarball). The full recipe is section 13 of the bettercms://playbook/schema resource; get_binding_report is the receipt that says you finished.\",\n z.object({}).shape,\n async (c) => ok(\"Conversion brief.\", await data(c, \"GET\", `/management/projects/current/conversion-brief`))),\n def(\"get_analytics_overview\", \"Get traffic overview\",\n \"Traffic totals and the daily series for the connected project — views, unique visitors, bytes, sessions and bounces. Defaults to the last 30 days; pass `from`/`to` as YYYY-MM-DD.\",\n z.object({ from: z.string().optional(), to: z.string().optional() }).shape,\n async (c, a) => ok(\"Analytics overview.\", await data(c, \"GET\", `/management/insights/analytics/overview${q({ from: a.from, to: a.to })}`))),\n def(\"get_analytics_top_pages\", \"Get top pages\",\n \"The most-viewed paths on the live site, with views and bytes. Defaults to the last 30 days; pass `from`/`to` (YYYY-MM-DD) and `limit`.\",\n z.object({ from: z.string().optional(), to: z.string().optional(), limit: z.number().optional() }).shape,\n async (c, a) => ok(\"Top pages.\", await data(c, \"GET\", `/management/insights/analytics/top-pages${q({ from: a.from, to: a.to, limit: a.limit })}`))),\n def(\"list_seo_issues\", \"List SEO issues\",\n \"Scan every published page for SEO problems (missing or over-long titles and descriptions, missing OG image, noindex, absent schema) and return them with severities. Computed live — nothing is stored.\",\n z.object({}).shape,\n async (c) => ok(\"SEO issues.\", await data(c, \"GET\", `/management/insights/seo-issues`))),\n def(\"list_ai_reports\", \"List AI report runs\",\n \"Past AI report runs for the connected project — `kind` is 'links' (internal linking) or 'aeo' (AI-answer readiness). Read-only history; starting a run stays a dashboard action.\",\n z.object({ kind: z.enum([\"links\", \"aeo\"]), limit: z.number().optional() }).shape,\n async (c, a) => ok(\"AI reports.\", await data(c, \"GET\", `/management/insights/ai-reports${q({ kind: a.kind, limit: a.limit })}`))),\n\n // ── Bulk: one dataset → many pages ────────────────────────────────────────\n def(\"generate_pages_from_dataset\", \"Generate many pages from a dataset\",\n \"Turn a dataset into many pages at once (programmatic SEO from a keyword list, or ABM pages from an account list). Give a template `pageId`, a `mapping` (contentModelId, a slugTemplate like 'for-{{company}}', and per-field values that are either a column name or {ai:{prompt}}), and `rows`. ALWAYS call with dryRun:true first and show the sample — a real run parks for approval and must be released with approve_ai_job.\",\n z.object({\n pageId: z.string().min(1),\n mapping: z.record(z.string(), z.unknown()),\n rows: z.array(z.record(z.string(), z.string())).min(1),\n dryRun: z.boolean().optional(),\n }).shape,\n async (c, a) => ok(\"Generation queued.\", await data(c, \"POST\", `/management/bulk/generate`, { pageId: a.pageId, mapping: a.mapping, rows: a.rows, dryRun: a.dryRun }))),\n def(\"list_ai_jobs\", \"List bulk jobs\",\n \"Recent bulk jobs for the connected project with status and progress. Use it to report how a generation is going.\",\n z.object({}).shape,\n async (c) => ok(\"Bulk jobs.\", await data(c, \"GET\", `/management/bulk/jobs`))),\n def(\"get_ai_job\", \"Get a bulk job\",\n \"One bulk job — status, rows processed, rows created, conflicts, and the approval plan if it is still parked.\",\n z.object({ jobId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Bulk job.\", await data(c, \"GET\", `/management/bulk/jobs/${s(a.jobId)}`))),\n def(\"approve_ai_job\", \"Approve a bulk job\",\n \"Release a job that is awaiting approval so the queue can run it. Only call this when the USER has said yes — never approve your own plan unprompted.\",\n z.object({ jobId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Job approved.\", await data(c, \"POST\", `/management/bulk/jobs/${s(a.jobId)}/approve`))),\n def(\"reject_ai_job\", \"Reject a bulk job\",\n \"Discard a job awaiting approval. Nothing was charged and nothing was written.\",\n z.object({ jobId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Job rejected.\", await data(c, \"POST\", `/management/bulk/jobs/${s(a.jobId)}/reject`))),\n\n def(\"list_section_validation_requests\", \"List queued Section validation requests\",\n \"Poll for user-agent Section implementation-validation requests in this exact project. BetterCMS cannot push work into an ordinary MCP client: call this explicitly, claim one request, inspect and run the customer's real repository/app shell, then submit request-bound evidence and complete it. Returns only unclaimed user-agent requests; it never exposes another project.\",\n listSectionValidationRequestsInput.shape,\n async (c, a) => ok(\"Queued user-agent Section validation requests.\", await data(\n c,\n \"GET\",\n `/projects/${s(a.projectId)}/section-evidence/implementation-requests${q({ limit: a.limit })}`,\n ))),\n def(\"claim_section_validation_request\", \"Claim a Section validation request\",\n \"Atomically claim one queued user-agent request and pin the exact git commit you will inspect. Claim BEFORE submitting evidence. BetterCMS records coordination only; all customer code and responsive checks must run in the user's repository and real app shell.\",\n claimSectionValidationRequestInput.shape,\n async (c, a) => ok(\"Section validation request claimed.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/implementation-requests/${s(a.requestId)}/claim`,\n {\n commitSha: a.commitSha,\n providerRunId: a.providerRunId,\n providerRunUrl: a.providerRunUrl,\n },\n ))),\n def(\"complete_section_validation_request\", \"Complete a Section validation request\",\n \"Complete a claimed request only after submit_section_manifest and submit_section_validation have bound exact, passed evidence to the same requestId and pinned commit. This cannot grant the separate human Visual Approval.\",\n completeSectionValidationRequestInput.shape,\n async (c, a) => ok(\"Section validation request completed.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/implementation-requests/${s(a.requestId)}/complete`,\n { manifestId: a.manifestId, validationRunId: a.validationRunId },\n ))),\n def(\"fail_section_validation_request\", \"Fail a Section validation request\",\n \"Truthfully close a claimed request when the renderer, validation command, app shell, or required evidence is missing or fails. This path intentionally works without a manifest so 'not implemented' is representable instead of being reported as passed or left queued forever.\",\n failSectionValidationRequestInput.shape,\n async (c, a) => ok(\"Section validation request failed.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/implementation-requests/${s(a.requestId)}/fail`,\n {\n errorCode: a.errorCode,\n errorMessage: a.errorMessage,\n providerRunId: a.providerRunId,\n providerRunUrl: a.providerRunUrl,\n },\n ))),\n\n def(\"submit_section_manifest\", \"Submit a Section implementation manifest\",\n \"Record the implementation manifest produced for one exact Section schema version by CI or an agent running INSIDE the user's repository. BetterCMS does not execute customer code: inspect/build the real renderer in the user's app shell first, then submit its exact API ID, schema hash, commit SHA, loader, preview adapter, and native responsive viewports. Requires a project-scoped artifact:write credential. This records evidence only; it does not validate the implementation and cannot create human Visual Approval.\",\n submitSectionManifestInput.shape,\n async (c, a) => ok(\"Section implementation manifest recorded.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/sections/${s(a.sectionId)}/versions/${a.version}/manifests`,\n {\n requestId: a.requestId,\n apiId: a.apiId,\n schemaHash: a.schemaHash,\n commitSha: a.commitSha,\n loader: a.loader,\n previewAdapter: a.previewAdapter,\n nativeViewports: a.nativeViewports,\n },\n ))),\n def(\"submit_section_validation\", \"Submit a Section validation result\",\n \"Record a real validation result for one exact Section schema version and manifest. Run the component in the user's repository and real app shell across the canonical preview dataset, AI stress fixtures, and required/native viewports BEFORE calling this tool; BetterCMS never runs that customer code. Pass status 'passed' only when those checks actually passed, otherwise 'failed'. The manifest pins schemaHash and commitSha; fixtureHash and evidenceDigest pin the tested data and immutable evidence bundle. Requires project-scoped artifact:write and cannot create the separate human Visual Approval required for publication.\",\n submitSectionValidationInput.shape,\n async (c, a) => ok(\"Section validation result recorded.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/sections/${s(a.sectionId)}/versions/${a.version}/validations`,\n {\n requestId: a.requestId,\n manifestId: a.manifestId,\n status: a.status,\n fixtureHash: a.fixtureHash,\n evidenceDigest: a.evidenceDigest,\n appShell: a.appShell,\n viewportResults: a.viewportResults,\n },\n ))),\n\n def(\"get_deploy_status\", \"Get deploy/build status\",\n \"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.\",\n z.object({}).shape,\n async (c) => ok(\"Deploy status.\", await data(c, \"GET\", `/management/projects/deploy-status`))),\n ];\n }\n\n const defs: ToolDef[] = [\n {\n name: \"list_pages\",\n config: {\n title: \"List pages in the current project\",\n description:\n \"List the pages in the project this MCP key is bound to, each with its full field SCHEMA, pageType (singleton|dynamic), and status. Use it to verify WHERE content lands and to read field keys/types before set_page_content / add_page_field.\",\n inputSchema: {},\n },\n handler: guard(async () =>\n withClient(async (client) => {\n const pages = await client.listPages();\n return ok(\n `${pages.length} page(s) in the bound project.`,\n pages.map((p) => ({\n id: p.id,\n title: p.title,\n slug: p.slug,\n pageType: p.pageType,\n status: p.status,\n fields: p.fields,\n })),\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"get_page\",\n config: {\n title: \"Get a page (with its field schema)\",\n description:\n \"Get one page by id INCLUDING its full field schema (keys, types, nested group/repeater children) and pageType. Read this before set_page_content so you write correctly-keyed values, or before add_page_field so you know the existing keys.\",\n inputSchema: getPageInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getPageInput>) =>\n withClient(async (client) => {\n const page = await client.getPage(args.pageId);\n return ok(\n `Page '${page.title}' (${page.pageType ?? \"page\"}, ${page.fields.length} field(s)).`,\n page,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_page\",\n config: {\n title: \"Create a page\",\n description:\n \"Create a page with its own typed schema. Supports pageType 'singleton' (exactly one entry — Home, About, Contact) and 'dynamic' (many entries sharing the schema — Blog posts, Products). Project-scoped from the key. Additive — does not delete or overwrite existing pages. FIRST read the page's real markup and DECOMPOSE it into a destructured tree: each visual section becomes a nested field — a fixed grouped block → type 'group', a repeating list of items (cards, testimonials, features, FAQs) → type 'repeater' — each carrying its own child `fields`. Do NOT flatten sections into many flat top-level fields. Build the full nested tree, then call this once. 🔴 Every field key must be UNIQUE ACROSS THE WHOLE TREE — the namespace is flat, so 'title' cannot appear in two sections; prefix each with its section ('hero_title', 'faq_title'). Prose fields (headings, body copy, descriptions) are created as RICH TEXT by default; pass richText:false for values that must stay bare strings — hrefs, slugs, ids, emails. That tree is the page's SCHEMA — what it holds. \" +\n DOCTRINE,\n inputSchema: createPageInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createPageInput>) =>\n withClient(async (client) => {\n // A create has no \"before\", so any collision is new. This is THE path that produced the\n // marketing page's six duplicate rows.\n const dupes = duplicateKeys(flatFieldKeys(args.fields));\n if (dupes.length > 0) return fail(duplicateKeyFailure(dupes));\n const page = await client.createPage({\n title: args.title,\n slug: args.slug,\n pageType: args.pageType ?? \"singleton\",\n ...(args.blockJson ? { blockJson: args.blockJson } : {}),\n ...(args.fields ? { fields: args.fields.map(toField) } : {}),\n ...(args.metaTitle !== undefined ? { metaTitle: args.metaTitle } : {}),\n ...(args.metaDescription !== undefined ? { metaDescription: args.metaDescription } : {}),\n });\n return ok(\n `Created ${page.pageType ?? \"page\"} page '${page.title}' (id ${page.id}, slug ${page.slug}) with ${page.fields.length} field(s).`,\n page,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_content_model\",\n config: {\n title: \"Create a content model (reusable schema)\",\n description:\n \"Create a content model — a reusable schema for a dynamic collection (Blog, Products, Testimonials). `fields` may NEST: type 'group' = one nested object of child fields; type 'repeater' = a repeatable array of child objects. Put child fields in each group/repeater's own `fields` (any depth). Pass kind:'block' to create a BLOCK type instead — see that argument.\",\n inputSchema: createModelInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createModelInput>) =>\n withClient(async (client) => {\n const modelDupes = duplicateKeys(flatFieldKeys(args.fields));\n if (modelDupes.length > 0) return fail(duplicateKeyFailure(modelDupes));\n const model = await client.createModel({\n name: args.name,\n slug: args.slug,\n ...(args.description !== undefined ? { description: args.description } : {}),\n ...(args.kind !== undefined ? { kind: args.kind } : {}),\n fields: toFields(args.fields),\n });\n return ok(\n `Created content model '${model.name}' (${model.fields.length} field(s)).`,\n model,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"add_field\",\n config: {\n title: \"Add a field to a content model\",\n description:\n \"Append a field to an existing content model. Reads the model's current fields and adds yours (read-modify-write) — never removes existing fields. For a section/zone, add ONE 'group' (fixed block) or 'repeater' (repeating list) field carrying its child `fields` — don't add the zone's inner fields as separate top-level fields.\",\n inputSchema: addFieldInput.shape,\n },\n handler: guard(async (args: z.infer<typeof addFieldInput>) =>\n withClient(async (client) => {\n const model = await client.getModel(args.modelId);\n // 🔴 Was `model.fields.some(...)` — TOP LEVEL ONLY, so a key colliding with a group's\n // child sailed through. The namespace is flat; the check has to be too.\n const dupes = duplicateKeys([...flatFieldKeys(model.fields), args.key]);\n if (dupes.length > 0) return fail(duplicateKeyFailure(dupes));\n const updated = await client.updateModel(args.modelId, {\n fields: [...model.fields, toField(args)],\n });\n return ok(\n `Added field '${args.key}' to '${updated.name}'. Model now has ${updated.fields.length} field(s).`,\n updated,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"add_page_field\",\n config: {\n title: \"Add a field to a page\",\n description:\n \"Append a field to an existing page's schema (Home, About, a blog template, etc.). Additive — the API rejects a key that already exists and never overwrites or retypes existing fields. Use this when the target is a page (singleton or dynamic); use add_field when the target is a content model. For a section/zone, add ONE 'group' (fixed block) or 'repeater' (repeating list) field carrying its child `fields` — don't add the zone's inner fields as separate top-level fields.\",\n inputSchema: addPageFieldInput.shape,\n },\n handler: guard(async (args: z.infer<typeof addPageFieldInput>) =>\n withClient(async (client) => {\n // No client-side preflight here on purpose. `addPageFields` is an additive PATCH onto\n // the page-fields route, which now refuses a NEW flat-namespace collision itself — so a\n // check here would be a second authority AND an extra round-trip, and the two could\n // drift. `add_field` keeps its check only because it already fetches the model.\n const page = await client.addPageFields(args.pageId, { addFields: [toField(args)] });\n return ok(\n `Added field '${args.key}' to page '${page.title}'. Page now has ${page.fields.length} field(s).`,\n page,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_content_entry\",\n config: {\n title: \"Create a content entry\",\n description:\n \"Create a content entry under a model. Pass its field VALUES in `data`, keyed by field key — INCLUDE ALL REQUIRED FIELDS (create validates them). New entries are drafts; pass status:'published' to take it live. Read get_content_model first for the field keys and which are required.\",\n inputSchema: createEntryInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createEntryInput>) =>\n withClient(async (client) => {\n // One-shot create WITH data — the create route validates required fields, so\n // splitting into create-empty-then-update 400s for any model with a required\n // field. Status is draft-only on create server-side, so publishing needs a\n // follow-up update.\n const created = await client.createEntry({\n contentModelId: args.contentModelId,\n ...(args.slug !== undefined ? { slug: args.slug } : {}),\n ...(args.data !== undefined ? { data: args.data } : {}),\n });\n const entry =\n args.status !== undefined && args.status !== \"draft\"\n ? await client.updateEntry(created.id, { status: args.status })\n : created;\n return ok(\n `Created entry '${entry.slug}' (id ${entry.id}, status ${entry.status}).`,\n entry,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"set_page_content\",\n config: {\n title: \"Set a page's field values (content)\",\n description:\n \"Set a page's field VALUES — the actual content. For a SINGLETON page (Home, About, Site Settings) this creates or updates its one entry, so call it again to edit. `data` is keyed by field key: a nested 'array' (zone) value is an OBJECT { nonRepeatable: { childKey: value }, repeatable: [ { childKey: value } ] }; a primitive 'array' is a plain list; an 'image' value is an asset URL. Read the schema first with get_page. This is how you populate Home/About/Settings — create_content_entry is for dynamic collections only.\",\n inputSchema: setPageContentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof setPageContentInput>) =>\n withClient(async (client) => {\n const entry = await client.setPageContent(args.pageId, {\n data: args.data,\n ...(args.status !== undefined ? { status: args.status } : {}),\n });\n return ok(\n `Set content on page ${args.pageId} (entry ${entry.id}, status ${entry.status}).`,\n entry,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"list_content_entries\",\n config: {\n title: \"List content entries (incl. drafts)\",\n description:\n \"List content entries — including drafts — filtered by model and/or page. Use it to SEE existing content before editing. For a singleton page, pass its pageId to get its single entry.\",\n inputSchema: listEntriesInput.shape,\n },\n handler: guard(async (args: z.infer<typeof listEntriesInput>) =>\n withClient(async (client) => {\n const entries = await client.listEntries({\n ...(args.modelId ? { modelId: args.modelId } : {}),\n ...(args.pageId ? { pageId: args.pageId } : {}),\n ...(args.status ? { status: args.status } : {}),\n });\n return ok(`${entries.length} entr(y/ies).`, entries);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"get_content_entry\",\n config: {\n title: \"Get a content entry (with its values)\",\n description: \"Get one content entry by id INCLUDING its `data` (field values), even when draft.\",\n inputSchema: getEntryInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getEntryInput>) =>\n withClient(async (client) => {\n const entry = await client.getEntry(args.entryId);\n return ok(`Entry '${entry.slug}' (id ${entry.id}, status ${entry.status}).`, entry);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"update_content_entry\",\n config: {\n title: \"Update a content entry's values\",\n description:\n \"Update a content entry's `data` (field values) and/or status by id. `data` is keyed by field key; a nested 'array' (zone) value is an object { nonRepeatable: {…}, repeatable: [{…}] }, a primitive 'array' is a plain list. Use this to edit an existing entry; for a singleton page prefer set_page_content.\",\n inputSchema: updateEntryInput.shape,\n },\n handler: guard(async (args: z.infer<typeof updateEntryInput>) =>\n withClient(async (client) => {\n const entry = await client.updateEntry(args.entryId, {\n ...(args.data !== undefined ? { data: args.data } : {}),\n ...(args.status !== undefined ? { status: args.status } : {}),\n ...(args.slug !== undefined ? { slug: args.slug } : {}),\n });\n return ok(`Updated entry '${entry.slug}' (id ${entry.id}, status ${entry.status}).`, entry);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"upload_asset\",\n config: {\n title: \"Upload an asset to the Media Library\",\n description:\n \"Upload an image/asset from a local file path or a remote URL into the project's Media Library. Returns the asset's stable CDN URL — put that URL into a content entry's image field. Use this BEFORE creating entries that reference images.\",\n inputSchema: uploadAssetInput.shape,\n },\n handler: guard(async (args: z.infer<typeof uploadAssetInput>) =>\n withClient(async (client) => {\n const asset = await client.uploadAsset(args);\n return ok(\n `Uploaded '${asset.filename}' (id ${asset.id}). Put this URL (or the id ${asset.id}) into an image field to attach it: ${asset.url}`,\n asset,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"delete_page\",\n config: {\n title: \"Delete a page\",\n description:\n \"DELETE a page and its content. Destructive but REVERSIBLE — it soft-deletes (can be restored from the dashboard) and is audit-logged. Use it to remove a page you created by mistake. Confirm with the user before deleting content they may want.\",\n inputSchema: deletePageInput.shape,\n },\n handler: guard(async (args: z.infer<typeof deletePageInput>) =>\n withClient(async (client) => {\n const res = await client.deletePage(args.pageId);\n return ok(`Deleted page ${res.id} (soft-delete — restorable from the dashboard).`, res);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"delete_content_entry\",\n config: {\n title: \"Delete a content entry\",\n description:\n \"DELETE a single content entry. Destructive but REVERSIBLE (soft-delete, restorable from the dashboard) and audit-logged. Use it to remove content created by mistake.\",\n inputSchema: deleteEntryInput.shape,\n },\n handler: guard(async (args: z.infer<typeof deleteEntryInput>) =>\n withClient(async (client) => {\n const res = await client.deleteEntry(args.entryId);\n return ok(`Deleted entry ${res.id} (soft-delete — restorable from the dashboard).`, res);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"delete_content_model\",\n config: {\n title: \"Delete a content model\",\n description:\n \"DELETE a content model and its entries. Destructive but REVERSIBLE (soft-delete, restorable from the dashboard) and audit-logged. Confirm with the user first — this removes all content under the model.\",\n inputSchema: deleteModelInput.shape,\n },\n handler: guard(async (args: z.infer<typeof deleteModelInput>) =>\n withClient(async (client) => {\n const res = await client.deleteModel(args.modelId);\n return ok(`Deleted content model ${res.id} and its entries (soft-delete — restorable from the dashboard).`, res);\n }),\n ) as ToolDef[\"handler\"],\n },\n // ── Forms (read-only — discover dashboard forms to embed into the site) ──\n {\n name: \"list_forms\",\n config: {\n title: \"List forms in the current project\",\n description:\n \"List the forms built in the dashboard for the bound project — each with its id, name, and field schema. Use it to find a form to add to the user's site: read it, then write `<BcmsForm form={getForm('Name')} />` (from @bettercms-ai/next) into the page/component where the user wants it.\",\n inputSchema: {},\n },\n handler: guard(async () =>\n withClient(async (client) => {\n const forms = await client.listForms();\n return ok(\n `${forms.length} form(s) in the bound project.`,\n forms.map((f) => ({ id: f.id, name: f.name, fields: f.fields })),\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"get_form\",\n config: {\n title: \"Get a form (with its field schema)\",\n description:\n \"Get one form by id INCLUDING its fields (keys, types, required, options, showIf) and settings (submitLabel, successMessage, redirectUrl, turnstileEnabled, honeypotField). Read this before wiring `<BcmsForm>` so you render the right fields.\",\n inputSchema: getFormInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getFormInput>) =>\n withClient(async (client) => {\n const form = await client.getForm(args.formId);\n return ok(`Form '${form.name}' (${form.fields.length} field(s)).`, form);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_form\",\n config: {\n title: \"Create a form\",\n description:\n \"Create a form (fields + settings) in the bound project. CONFIRM the fields with the user first. Returns the new form's id — then embed it with `<BcmsForm form={getForm('Name')} />` from @bettercms-ai/next. Field types: text,email,textarea,select(needs options),radio(needs options),checkboxes(needs options),checkbox,number,phone,date,url,consent,hidden.\",\n inputSchema: createFormInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createFormInput>) =>\n withClient(async (client) => {\n const form = await client.createForm(args as ManagedFormInput);\n return ok(`Created form '${form.name}' (id ${form.id}). Embed with <BcmsForm form={getForm('${form.name}')} />.`, form);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"update_form\",\n config: {\n title: \"Update a form\",\n description:\n \"Update a form by id — name, fields, or settings. Read get_form first. Passing `fields` REPLACES the array (include all fields to keep).\",\n inputSchema: updateFormInput.shape,\n },\n handler: guard(async (args: z.infer<typeof updateFormInput>) =>\n withClient(async (client) => {\n const { formId, ...input } = args;\n const form = await client.updateForm(formId, input as ManagedFormInput);\n return ok(`Updated form '${form.name}' (id ${form.id}).`, form);\n }),\n ) as ToolDef[\"handler\"],\n },\n // ── Project/page Layout (draft-only; publish remains dashboard-gated) ──\n {\n name: \"get_layout\",\n config: {\n title: \"Get the project or page Layout\",\n description: \"Read the Global Layout or one page's Layout override, including its optimistic revision. Always read this before update_layout. copy:'published' reads the published copy — the only honest receipt for a publish claim.\",\n inputSchema: getLayoutInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getLayoutInput>) => withClient(async (client) => {\n const layout = await client.getManagedLayout(args);\n return ok(`${layout.scope === \"global\" ? \"Global\" : `Page ${layout.pageSlug}`} Layout ${args.copy === \"published\" ? \"PUBLISHED copy\" : \"draft\"} at revision ${layout.revision}.`, layout);\n })) as ToolDef[\"handler\"],\n },\n {\n name: \"update_layout\",\n config: {\n title: \"Apply one Layout draft command\",\n description: \"Apply one permission-shaped values/composition/schema command to the Global Layout or a page override. Draft-only: this never publishes. Pass the revision from get_layout as ifMatch.\",\n inputSchema: commandLayoutInput.shape,\n },\n handler: guard(async (args: z.infer<typeof commandLayoutInput>) => withClient(async (client) => {\n const layout = await client.commandManagedLayout({ ...args, command: args.command as ManagementLayoutCommand });\n return ok(`Updated ${layout.scope === \"global\" ? \"Global\" : `Page ${layout.pageSlug}`} Layout draft to revision ${layout.revision}.`, layout);\n })) as ToolDef[\"handler\"],\n },\n // ── Components (discover + author reusable symbols) ──\n {\n name: \"list_components\",\n config: {\n title: \"List reusable components\",\n description:\n \"List the reusable components in the bound project — each with id, name, slug, category, blockJson, and props. Use it to find a component to render with `<BcmsBlocks>` from @bettercms-ai/next.\",\n inputSchema: {},\n },\n handler: guard(async () =>\n withClient(async (client) => {\n const list = await client.listComponents();\n return ok(\n `${list.length} component(s) in the bound project.`,\n list.map((cmp) => ({ id: cmp.id, name: cmp.name, slug: cmp.slug, category: cmp.category })),\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"get_component\",\n config: {\n title: \"Get a component (with its blockJson)\",\n description:\n \"Get one component by id INCLUDING its blockJson tree and props. Read this before update_component so you keep the existing blocks.\",\n inputSchema: getComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getComponentInput>) =>\n withClient(async (client) => {\n const cmp = await client.getComponent(args.componentId);\n return ok(`Component '${cmp.name}' (${cmp.blockJson.length} block(s)).`, cmp);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_component\",\n config: {\n title: \"Create a reusable component\",\n description:\n \"Create a reusable component from a blockJson tree. THIS IS ALSO HOW A PAGE GETS ITS SECTIONS: set `sectionType` (e.g. 'Hero') and the component becomes a placeable section, selectable in the editor's 'Add a section' picker. Components sharing a `sectionType` are its layout VARIANTS — one Hero with a 'Centered' and a 'Two-column' variant, same prop keys, so a swap keeps the content. CONFIRM the structure with the user first. blockJson is an array of blocks — the same set create_page accepts (heading, text/richtext, image, button, spacer, video, columns, section, slider, tabs, navbar, footer, form, component, collection), NOT a narrower one; `section` nests child blocks in props.children and `columns` in props.columns. `props` declares overridable fields. Returns the new id — render with `<BcmsBlocks>`. Always lands as a DRAFT: it is not on the live site until someone publishes it from the dashboard. \" +\n DOCTRINE,\n inputSchema: createComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createComponentInput>) =>\n withClient(async (client) => {\n const cmp = await client.createComponent(args as ManagedComponentInput);\n return ok(`Created component '${cmp.name}' (id ${cmp.id}, slug ${cmp.slug}).`, cmp);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"list_extraction_candidates\",\n config: {\n title: \"Find sections that repeat across pages\",\n description:\n \"Find sections that appear IDENTICALLY (same structure and styling, different wording) on 3+ places across this project's pages, each proposed as one reusable component. Read-only — nothing changes. Returns a `hash` per candidate to pass to extract_component, plus how many places it appears, which fields differ between copies, and the exact pages involved. Use this before hand-building a component with create_component: if a section already repeats, extracting it is better than adding a 4th copy.\",\n inputSchema: listExtractionCandidatesInput.shape,\n },\n handler: guard(async (args: z.infer<typeof listExtractionCandidatesInput>) =>\n withClient(async (client) => {\n const found = await client.listExtractionCandidates(args.projectId);\n if (found.length === 0) {\n return ok(\"No section repeats on 3 or more pages in this project.\", found);\n }\n const lines = found.map(\n (c) => `- ${c.suggestedName} (hash ${c.hash}) — ${c.uses} places, ${c.props.length} varying field(s)`,\n );\n return ok(`${found.length} repeated section(s):\\n${lines.join(\"\\n\")}`, found);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"extract_component\",\n config: {\n title: \"Extract a repeated section into one component\",\n description:\n \"Fold one candidate from list_extraction_candidates into a single reusable component and repoint EVERY occurrence at it. CONFIRM WITH THE USER FIRST — this rewrites blocks on several pages at once, and name the pages from the candidate's `sites` when you ask. Only page DRAFTS change: the live site is untouched until those pages are published, and the component itself lands as a DRAFT. Fields that differ between copies become component props, so each page keeps its own wording. 409 means the sections were edited since you listed them — re-run list_extraction_candidates and ask again.\",\n inputSchema: extractComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof extractComponentInput>) =>\n withClient(async (client) => {\n const { component, replaced } = await client.extractComponent(args);\n return ok(\n `Created component '${component.name}' (id ${component.id}) and repointed ${replaced} sections to it. Page drafts changed; publish those pages to make it live.`,\n component,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"update_component\",\n config: {\n title: \"Update a reusable component\",\n description:\n \"Update a component by id — blockJson, props, name, or category. Read get_component first. Passing `blockJson`/`props` REPLACES them. This writes the DRAFT: the change does NOT appear on the live site until someone publishes the component from the dashboard.\",\n inputSchema: updateComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof updateComponentInput>) =>\n withClient(async (client) => {\n const { componentId, ...input } = args;\n const cmp = await client.updateComponent(componentId, input as ManagedComponentInput);\n return ok(`Updated component '${cmp.name}' (id ${cmp.id}).`, cmp);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"publish_component\",\n config: {\n title: \"Publish a component\",\n description:\n \"Publish a component: copy its DRAFT definition to the live copy and re-bake every published page that embeds it. This is the ONLY way a component reaches the live site — create_component and update_component write drafts, and an unpublished component renders as NOTHING on the live site, with no error. Publish every component you place on a page. 403 PUBLISH_NOT_GRANTED means this connection may author but not publish: say so and let the user publish from the dashboard. 422 means publishing would break a Layout that uses it — the response names which.\",\n inputSchema: getComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getComponentInput>) =>\n withClient(async (client) => {\n const res = await client.fetchJSON<{ data?: unknown }>(\n client.url(`/management/components/${args.componentId}/publish`),\n { method: \"POST\" },\n );\n return ok(\"Published component.\", res.data);\n }),\n ) as ToolDef[\"handler\"],\n },\n\n // ── AI content + SEO actions (Option B) ────────────────────────────────────\n {\n name: \"write_content\",\n config: {\n title: \"Write, rewrite, or translate content\",\n description:\n \"AI-write a piece of copy: action 'write' (draft from a brief), 'rewrite' (improve existing copy), or 'translate' (needs targetLang). Returns the suggested text — apply it with set_page_content or update_content_entry. Uses the workspace's own Anthropic key (BYOK, unmetered) or platform AI credits.\",\n inputSchema: writeContentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof writeContentInput>) =>\n withClient(async (client) => {\n const suggestion = await client.writeContent(args);\n return ok(`Generated ${args.action} suggestion (${suggestion.length} chars).`, { suggestion });\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"generate_seo_meta\",\n config: {\n title: \"Generate SEO metadata\",\n description:\n \"Generate SEO metadata (metaTitle, metaDescription, keywords, optional JSON-LD) for a piece of content. Pass the page/entry content as `text`. Returns a suggestion to apply via update_page or the entry SEO fields.\",\n inputSchema: generateSeoMetaInput.shape,\n },\n handler: guard(async (args: z.infer<typeof generateSeoMetaInput>) =>\n withClient(async (client) => {\n const meta = await client.generateSeoMeta(args);\n return ok(`Generated SEO metadata: \"${meta.metaTitle}\".`, meta);\n }),\n ) as ToolDef[\"handler\"],\n },\n\n // ── Lifecycle tools (parity with the remote /mcp surface) ──────────────────\n // Media management, form submissions (leads), redirects, SEO, AEO site-files,\n // promote, and entry version history. These call the management endpoints straight\n // through the client's request plumbing — no bespoke SDK method per endpoint.\n ...lifecycleTools(),\n ];\n\n return defs;\n}\n\n/** Register all BetterCMS tools on an MCP server. */\nexport function registerTools(server: McpServer, deps: ToolDeps): void {\n // Give the tools a way to ask the human directly. Threaded here rather than taken as a\n // dep by the caller so buildToolDefs stays server-free for the tests.\n const withElicit: ToolDeps = {\n ...deps,\n elicit: deps.elicit ?? ((params) => server.server.elicitInput(params as never)),\n };\n for (const def of buildToolDefs(withElicit)) {\n server.registerTool(def.name, def.config, def.handler as never);\n }\n}\n","/**\n * Component — a reusable, Webflow-style block tree (a \"symbol\").\n *\n * A component is authored once and placed across pages via `component` blocks\n * (see `ComponentBlock` in `./block.ts`). Its definition lives in `blockJson`;\n * `props` declares a flat allowlist of values an instance may override.\n */\nimport type { ContentBlock } from \"./block.js\";\nimport type { VariantInputMapping } from \"./layout.js\";\n\n/**\n * The category a component belongs to (drives library grouping + icons). The first eight\n * are structural (what the component IS); the last four are the \"Add a section\" library\n * tabs (where it appears). One varchar column, not a PG enum — widening is code-only.\n */\n/**\n * 🔴 THE STRUCTURE DOCTRINE — one sentence, one home, spliced into every surface that builds a page.\n *\n * It lives HERE, beside the component contract it describes, because there are THREE places that teach\n * an agent how to build a page and they drifted apart:\n * • `packages/mcp/src/tools.ts` — the MCP tool descriptions (external agents)\n * • `src/lib/ai/agent.ts` — the in-product Studio Agent's system prompt\n * • `packages/mcp/src/prompts.ts` — the authoring playbook, which a tool call does not carry\n *\n * Only the playbook explained sections. `create_page` taught the SCHEMA axis in detail (\"each visual\n * section becomes a nested field\") and said nothing about STRUCTURE; the Studio Agent's prompt named\n * \"pages & reusable components (structure/layout)\" without ever mentioning `sectionType`.\n *\n * Measured consequence, production 2026-08-18: project `acme` has three components, ALL with\n * `section_type = (none)`, and its home page is 18 loose top-level blocks with ZERO sections. Every\n * generated page came out flat, so the visual editor's section lane — outline, name, move, duplicate,\n * delete, variant swap — had nothing to attach to. The editor was faithfully showing pages that were\n * never built out of sections.\n *\n * A constant rather than three paraphrases, because updating some of them is exactly how this happened.\n */\nexport const SECTION_DOCTRINE =\n \"STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks — they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` — see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: a component's children render WITHOUT field bindings, so their text is NOT click-to-edit on the canvas — it is edited through the component's declared `props` in the section dock. A `section` block's children stay click-to-edit. So when you choose a component, DECLARE A PROP for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. Do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId — hero-centered, hero-split, feature-grid-three, cta-banner and nine more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize the blueprint with create_component so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section — never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.\";\n\nexport type ComponentCategory =\n | \"navbar\"\n | \"footer\"\n | \"button\"\n | \"section\"\n | \"slider\"\n | \"tabs\"\n | \"form\"\n | \"custom\"\n | \"hero\"\n | \"content\"\n | \"social-proof\"\n | \"conversion\";\n\n/**\n * A single overridable field on a component. `target` points at the block + JSON\n * path inside `blockJson` the override writes to (e.g. blockId \"cta\", path\n * \"props.text\"). Keeping overrides a declared allowlist (not arbitrary nested\n * rewrites) keeps instance data small and the contract explicit.\n */\nexport interface ComponentPropDef {\n key: string;\n label: string;\n target: { blockId: string; path: string };\n /**\n * `slot` holds ONE nested component instance — the component-level twin of the\n * content-model field type `component-ref` (see content-model.ts), named differently for\n * the same reason that one is: `component` already means a BLOCK type. Its value is\n * `{ componentId, overrides }` and its `target.path` is `props`, so filling a slot writes\n * that object over an empty `component` block's props.\n *\n * On a PAGE a slot fill is a LIVE reference; a published ENTRY freezes it (resolveDeep).\n */\n /**\n * The EDITOR contract, not a storage one: `applyOverrides` writes the value at\n * `target.path` whatever its shape, so `type` decides which control the inspector renders\n * and what shape that control produces (FLO-1020).\n *\n * number → a number (heading.level, columns.count)\n * select → one string from `config.options`\n * group → an object keyed by `config.fields`\n * table → an array of such objects (slider.slides)\n *\n * `reference` is absent on purpose: nothing resolves a content-entry id at component render\n * time, so such a prop would save cleanly and render as nothing.\n */\n type: \"text\" | \"richtext\" | \"image\" | \"url\" | \"boolean\" | \"number\" | \"select\" | \"group\" | \"table\" | \"slot\";\n defaultValue?: unknown;\n /** Per-type settings; the save schema enforces that each is present on the type needing it. */\n config?: {\n /** `slot` — a pick allowlist. */\n componentIds?: string[];\n /** `select` — the choices. Required, and a default must be one of them. */\n options?: string[];\n /** `group` / `table` — the sub-shape, nestable to 3 levels. */\n fields?: ComponentSubField[];\n /** `number` — bounds for the control. */\n min?: number;\n max?: number;\n step?: number;\n } & Record<string, unknown>;\n}\n\n/** One field inside a `group` prop or a `table` row. Recursive, capped at 3 levels deep. */\nexport interface ComponentSubField {\n key: string;\n label: string;\n /** No `slot`: a nested component instance belongs on the prop itself, not inside a row. */\n type: Exclude<ComponentPropDef[\"type\"], \"slot\">;\n defaultValue?: unknown;\n options?: string[];\n fields?: ComponentSubField[];\n}\n\n/** The value a `slot` prop holds — the draft half of a `component-ref`, deliberately. */\nexport interface SlotValue {\n componentId: string;\n overrides?: Record<string, unknown>;\n}\n\n/**\n * A component is a DRAFT until published; only the published copy reaches a visitor.\n * Mirrors pages and entries. See migration 0186_component_draft_live_split.sql.\n */\nexport type ComponentStatus = \"draft\" | \"published\";\n\n/**\n * Archive state (FLO-1012), deliberately SEPARATE from `ComponentStatus`.\n *\n * Archive takes a component out of the working set — hidden from the components list by\n * default, not offered in the visual editor's insert surfaces — while every existing usage\n * keeps serving. It is not unpublish (which pulls the live copy and re-bakes every page that\n * embeds it) and it is not delete.\n *\n * It is a timestamp rather than a third `status` value because a component can be published\n * AND archived; collapsing the two would lose the bit restore has to put back.\n */\n\nexport interface Component {\n id: string;\n workspaceId: string;\n projectId?: string | null;\n name: string;\n slug: string;\n category: ComponentCategory;\n /**\n * Section library: the family this component is a LAYOUT of, e.g. \"Hero\". `name` is the\n * layout label (\"Centered\"), so components sharing a sectionType are selectable variants\n * of one section. Null/absent = an ordinary component, not shown in the section library.\n */\n sectionType?: string | null;\n /** First-class variant family membership; exact workspace/project scope is enforced in DB. */\n variantGroupId?: string | null;\n variantInputMappings?: VariantInputMapping[];\n /** Placement governance: `*`, `slug:<page-slug>`, and/or `type:<page-type>`. */\n allowedOn: string[];\n description?: string | null;\n /** The DRAFT definition. Every builder/autosave/import write path targets these two. */\n blockJson: ContentBlock[];\n props: ComponentPropDef[];\n status: ComponentStatus;\n /** When it left the working set, or null/absent while active. @see ComponentStatus */\n archivedAt?: string | Date | null;\n /** Derived from `archivedAt`, so a client never has to know the column. */\n archived?: boolean;\n /**\n * The LIVE snapshot get_components_by_handle() serves. Null until the first publish.\n * Returned by GET-one (the Compare view needs it), omitted from list rows for payload.\n */\n publishedBlockJson?: ContentBlock[] | null;\n publishedProps?: ComponentPropDef[] | null;\n publishedAt?: string | null; // ISO 8601\n /**\n * Computed in SQL on list/get, never stored:\n * status='published' AND (blockJson or props has diverged from its published copy).\n * An exact jsonb compare, so it self-clears when an edit is reverted.\n */\n pendingChanges?: boolean;\n thumbnail?: string | null;\n createdAt: string; // ISO 8601\n updatedAt: string; // ISO 8601\n}\n\n/**\n * Public/delivery projection — the fields a renderer needs to resolve instances.\n *\n * DELIBERATELY UNCHANGED by the 0186 draft/live split: delivery aliases\n * publishedBlockJson -> blockJson, so every already-deployed site and every\n * bcms-content.json on disk keeps a byte-identical wire shape. Do not add `status` here —\n * delivery only ever returns published rows, so it would always be the same constant.\n */\nexport interface DeliveryComponent {\n id: string;\n name: string;\n slug: string;\n category: ComponentCategory;\n sectionType?: string | null;\n blockJson: ContentBlock[];\n props: ComponentPropDef[];\n}\n","/**\n * Generated from lucide-react@1.8.0 dynamic icon names.\n * Legacy CamelCase identifiers remain valid for existing Layout documents.\n */\nexport const LAYOUT_SECTION_ICONS: readonly string[] = Object.freeze([\n \"LayoutPanelTop\",\n \"PanelTop\",\n \"PanelBottom\",\n \"Menu\",\n \"Navigation\",\n \"Megaphone\",\n \"GalleryHorizontal\",\n \"Rows3\",\n \"Grid2X2\",\n \"FileText\",\n \"Link\",\n \"Contact\",\n \"BadgeInfo\",\n \"Sparkles\",\n \"a-arrow-down\",\n \"a-arrow-up\",\n \"a-large-small\",\n \"accessibility\",\n \"activity\",\n \"air-vent\",\n \"airplay\",\n \"alarm-clock-check\",\n \"alarm-check\",\n \"alarm-clock-minus\",\n \"alarm-minus\",\n \"alarm-clock-off\",\n \"alarm-clock-plus\",\n \"alarm-plus\",\n \"alarm-clock\",\n \"alarm-smoke\",\n \"album\",\n \"align-center-horizontal\",\n \"align-center-vertical\",\n \"align-end-horizontal\",\n \"align-end-vertical\",\n \"align-horizontal-distribute-center\",\n \"align-horizontal-distribute-end\",\n \"align-horizontal-distribute-start\",\n \"align-horizontal-justify-center\",\n \"align-horizontal-justify-end\",\n \"align-horizontal-justify-start\",\n \"align-horizontal-space-around\",\n \"align-horizontal-space-between\",\n \"align-start-horizontal\",\n \"align-start-vertical\",\n \"align-vertical-distribute-center\",\n \"align-vertical-distribute-end\",\n \"align-vertical-distribute-start\",\n \"align-vertical-justify-center\",\n \"align-vertical-justify-end\",\n \"align-vertical-justify-start\",\n \"align-vertical-space-around\",\n \"align-vertical-space-between\",\n \"ambulance\",\n \"ampersand\",\n \"ampersands\",\n \"amphora\",\n \"anchor\",\n \"angry\",\n \"annoyed\",\n \"antenna\",\n \"anvil\",\n \"aperture\",\n \"app-window-mac\",\n \"app-window\",\n \"apple\",\n \"archive-restore\",\n \"archive-x\",\n \"archive\",\n \"armchair\",\n \"arrow-big-down-dash\",\n \"arrow-big-down\",\n \"arrow-big-left-dash\",\n \"arrow-big-left\",\n \"arrow-big-right-dash\",\n \"arrow-big-right\",\n \"arrow-big-up-dash\",\n \"arrow-big-up\",\n \"arrow-down-0-1\",\n \"arrow-down-01\",\n \"arrow-down-1-0\",\n \"arrow-down-10\",\n \"arrow-down-a-z\",\n \"arrow-down-az\",\n \"arrow-down-from-line\",\n \"arrow-down-left\",\n \"arrow-down-narrow-wide\",\n \"arrow-down-right\",\n \"arrow-down-to-dot\",\n \"arrow-down-to-line\",\n \"arrow-down-up\",\n \"arrow-down-wide-narrow\",\n \"sort-desc\",\n \"arrow-down-z-a\",\n \"arrow-down-za\",\n \"arrow-down\",\n \"arrow-left-from-line\",\n \"arrow-left-right\",\n \"arrow-left-to-line\",\n \"arrow-left\",\n \"arrow-right-from-line\",\n \"arrow-right-left\",\n \"arrow-right-to-line\",\n \"arrow-right\",\n \"arrow-up-0-1\",\n \"arrow-up-01\",\n \"arrow-up-1-0\",\n \"arrow-up-10\",\n \"arrow-up-a-z\",\n \"arrow-up-az\",\n \"arrow-up-down\",\n \"arrow-up-from-dot\",\n \"arrow-up-from-line\",\n \"arrow-up-left\",\n \"arrow-up-narrow-wide\",\n \"sort-asc\",\n \"arrow-up-right\",\n \"arrow-up-to-line\",\n \"arrow-up-wide-narrow\",\n \"arrow-up-z-a\",\n \"arrow-up-za\",\n \"arrow-up\",\n \"arrows-up-from-line\",\n \"asterisk\",\n \"at-sign\",\n \"atom\",\n \"audio-lines\",\n \"audio-waveform\",\n \"award\",\n \"axe\",\n \"axis-3d\",\n \"axis-3-d\",\n \"baby\",\n \"backpack\",\n \"badge-alert\",\n \"badge-cent\",\n \"badge-check\",\n \"verified\",\n \"badge-dollar-sign\",\n \"badge-euro\",\n \"badge-indian-rupee\",\n \"badge-info\",\n \"badge-japanese-yen\",\n \"badge-minus\",\n \"badge-percent\",\n \"badge-plus\",\n \"badge-pound-sterling\",\n \"badge-question-mark\",\n \"badge-help\",\n \"badge-russian-ruble\",\n \"badge-swiss-franc\",\n \"badge-turkish-lira\",\n \"badge-x\",\n \"badge\",\n \"baggage-claim\",\n \"balloon\",\n \"ban\",\n \"banana\",\n \"bandage\",\n \"banknote-arrow-down\",\n \"banknote-arrow-up\",\n \"banknote-x\",\n \"banknote\",\n \"barcode\",\n \"barrel\",\n \"baseline\",\n \"bath\",\n \"battery-charging\",\n \"battery-full\",\n \"battery-low\",\n \"battery-medium\",\n \"battery-plus\",\n \"battery-warning\",\n \"battery\",\n \"beaker\",\n \"bean-off\",\n \"bean\",\n \"bed-double\",\n \"bed-single\",\n \"bed\",\n \"beef-off\",\n \"beef\",\n \"beer-off\",\n \"beer\",\n \"bell-dot\",\n \"bell-electric\",\n \"bell-minus\",\n \"bell-off\",\n \"bell-plus\",\n \"bell-ring\",\n \"bell\",\n \"between-horizontal-end\",\n \"between-horizonal-end\",\n \"between-horizontal-start\",\n \"between-horizonal-start\",\n \"between-vertical-end\",\n \"between-vertical-start\",\n \"biceps-flexed\",\n \"bike\",\n \"binary\",\n \"binoculars\",\n \"biohazard\",\n \"bird\",\n \"birdhouse\",\n \"bitcoin\",\n \"blend\",\n \"blinds\",\n \"blocks\",\n \"bluetooth-connected\",\n \"bluetooth-off\",\n \"bluetooth-searching\",\n \"bluetooth\",\n \"bold\",\n \"bolt\",\n \"bomb\",\n \"bone\",\n \"book-a\",\n \"book-alert\",\n \"book-audio\",\n \"book-check\",\n \"book-copy\",\n \"book-dashed\",\n \"book-template\",\n \"book-down\",\n \"book-headphones\",\n \"book-heart\",\n \"book-image\",\n \"book-key\",\n \"book-lock\",\n \"book-marked\",\n \"book-minus\",\n \"book-open-check\",\n \"book-open-text\",\n \"book-open\",\n \"book-plus\",\n \"book-search\",\n \"book-text\",\n \"book-type\",\n \"book-up-2\",\n \"book-up\",\n \"book-user\",\n \"book-x\",\n \"book\",\n \"bookmark-check\",\n \"bookmark-minus\",\n \"bookmark-off\",\n \"bookmark-plus\",\n \"bookmark-x\",\n \"bookmark\",\n \"boom-box\",\n \"bot-message-square\",\n \"bot-off\",\n \"bot\",\n \"bottle-wine\",\n \"bow-arrow\",\n \"box\",\n \"boxes\",\n \"braces\",\n \"curly-braces\",\n \"brackets\",\n \"brain-circuit\",\n \"brain-cog\",\n \"brain\",\n \"brick-wall-fire\",\n \"brick-wall-shield\",\n \"brick-wall\",\n \"briefcase-business\",\n \"briefcase-conveyor-belt\",\n \"briefcase-medical\",\n \"briefcase\",\n \"bring-to-front\",\n \"brush-cleaning\",\n \"brush\",\n \"bubbles\",\n \"bug-off\",\n \"bug-play\",\n \"bug\",\n \"building-2\",\n \"building\",\n \"bus-front\",\n \"bus\",\n \"cable-car\",\n \"cable\",\n \"cake-slice\",\n \"cake\",\n \"calculator\",\n \"calendar-1\",\n \"calendar-arrow-down\",\n \"calendar-arrow-up\",\n \"calendar-check-2\",\n \"calendar-check\",\n \"calendar-clock\",\n \"calendar-cog\",\n \"calendar-days\",\n \"calendar-fold\",\n \"calendar-heart\",\n \"calendar-minus-2\",\n \"calendar-minus\",\n \"calendar-off\",\n \"calendar-plus-2\",\n \"calendar-plus\",\n \"calendar-range\",\n \"calendar-search\",\n \"calendar-sync\",\n \"calendar-x-2\",\n \"calendar-x\",\n \"calendar\",\n \"calendars\",\n \"camera-off\",\n \"camera\",\n \"candy-cane\",\n \"candy-off\",\n \"candy\",\n \"cannabis-off\",\n \"cannabis\",\n \"captions-off\",\n \"captions\",\n \"subtitles\",\n \"car-front\",\n \"car-taxi-front\",\n \"car\",\n \"caravan\",\n \"card-sim\",\n \"carrot\",\n \"case-lower\",\n \"case-sensitive\",\n \"case-upper\",\n \"cassette-tape\",\n \"cast\",\n \"castle\",\n \"cat\",\n \"cctv-off\",\n \"cctv\",\n \"chart-area\",\n \"area-chart\",\n \"chart-bar-big\",\n \"bar-chart-horizontal-big\",\n \"chart-bar-decreasing\",\n \"chart-bar-increasing\",\n \"chart-bar-stacked\",\n \"chart-bar\",\n \"bar-chart-horizontal\",\n \"chart-candlestick\",\n \"candlestick-chart\",\n \"chart-column-big\",\n \"bar-chart-big\",\n \"chart-column-decreasing\",\n \"chart-column-increasing\",\n \"bar-chart-4\",\n \"chart-column-stacked\",\n \"chart-column\",\n \"bar-chart-3\",\n \"chart-gantt\",\n \"chart-line\",\n \"line-chart\",\n \"chart-network\",\n \"chart-no-axes-column-decreasing\",\n \"chart-no-axes-column-increasing\",\n \"bar-chart\",\n \"chart-no-axes-column\",\n \"bar-chart-2\",\n \"chart-no-axes-combined\",\n \"chart-no-axes-gantt\",\n \"gantt-chart\",\n \"chart-pie\",\n \"pie-chart\",\n \"chart-scatter\",\n \"scatter-chart\",\n \"chart-spline\",\n \"check-check\",\n \"check-line\",\n \"check\",\n \"chef-hat\",\n \"cherry\",\n \"chess-bishop\",\n \"chess-king\",\n \"chess-knight\",\n \"chess-pawn\",\n \"chess-queen\",\n \"chess-rook\",\n \"chevron-down\",\n \"chevron-first\",\n \"chevron-last\",\n \"chevron-left\",\n \"chevron-right\",\n \"chevron-up\",\n \"chevrons-down-up\",\n \"chevrons-down\",\n \"chevrons-left-right-ellipsis\",\n \"chevrons-left-right\",\n \"chevrons-left\",\n \"chevrons-right-left\",\n \"chevrons-right\",\n \"chevrons-up-down\",\n \"chevrons-up\",\n \"church\",\n \"cigarette-off\",\n \"cigarette\",\n \"circle-alert\",\n \"alert-circle\",\n \"circle-arrow-down\",\n \"arrow-down-circle\",\n \"circle-arrow-left\",\n \"arrow-left-circle\",\n \"circle-arrow-out-down-left\",\n \"arrow-down-left-from-circle\",\n \"circle-arrow-out-down-right\",\n \"arrow-down-right-from-circle\",\n \"circle-arrow-out-up-left\",\n \"arrow-up-left-from-circle\",\n \"circle-arrow-out-up-right\",\n \"arrow-up-right-from-circle\",\n \"circle-arrow-right\",\n \"arrow-right-circle\",\n \"circle-arrow-up\",\n \"arrow-up-circle\",\n \"circle-check-big\",\n \"check-circle\",\n \"circle-check\",\n \"check-circle-2\",\n \"circle-chevron-down\",\n \"chevron-down-circle\",\n \"circle-chevron-left\",\n \"chevron-left-circle\",\n \"circle-chevron-right\",\n \"chevron-right-circle\",\n \"circle-chevron-up\",\n \"chevron-up-circle\",\n \"circle-dashed\",\n \"circle-divide\",\n \"divide-circle\",\n \"circle-dollar-sign\",\n \"circle-dot-dashed\",\n \"circle-dot\",\n \"circle-ellipsis\",\n \"circle-equal\",\n \"circle-fading-arrow-up\",\n \"circle-fading-plus\",\n \"circle-gauge\",\n \"gauge-circle\",\n \"circle-minus\",\n \"minus-circle\",\n \"circle-off\",\n \"circle-parking-off\",\n \"parking-circle-off\",\n \"circle-parking\",\n \"parking-circle\",\n \"circle-pause\",\n \"pause-circle\",\n \"circle-percent\",\n \"percent-circle\",\n \"circle-pile\",\n \"circle-play\",\n \"play-circle\",\n \"circle-plus\",\n \"plus-circle\",\n \"circle-pound-sterling\",\n \"circle-power\",\n \"power-circle\",\n \"circle-question-mark\",\n \"help-circle\",\n \"circle-help\",\n \"circle-slash-2\",\n \"circle-slashed\",\n \"circle-slash\",\n \"circle-small\",\n \"circle-star\",\n \"circle-stop\",\n \"stop-circle\",\n \"circle-user-round\",\n \"user-circle-2\",\n \"circle-user\",\n \"user-circle\",\n \"circle-x\",\n \"x-circle\",\n \"circle\",\n \"circuit-board\",\n \"citrus\",\n \"clapperboard\",\n \"clipboard-check\",\n \"clipboard-clock\",\n \"clipboard-copy\",\n \"clipboard-list\",\n \"clipboard-minus\",\n \"clipboard-paste\",\n \"clipboard-pen-line\",\n \"clipboard-signature\",\n \"clipboard-pen\",\n \"clipboard-edit\",\n \"clipboard-plus\",\n \"clipboard-type\",\n \"clipboard-x\",\n \"clipboard\",\n \"clock-1\",\n \"clock-10\",\n \"clock-11\",\n \"clock-12\",\n \"clock-2\",\n \"clock-3\",\n \"clock-4\",\n \"clock-5\",\n \"clock-6\",\n \"clock-7\",\n \"clock-8\",\n \"clock-9\",\n \"clock-alert\",\n \"clock-arrow-down\",\n \"clock-arrow-up\",\n \"clock-check\",\n \"clock-fading\",\n \"clock-plus\",\n \"clock\",\n \"closed-caption\",\n \"cloud-alert\",\n \"cloud-backup\",\n \"cloud-check\",\n \"cloud-cog\",\n \"cloud-download\",\n \"download-cloud\",\n \"cloud-drizzle\",\n \"cloud-fog\",\n \"cloud-hail\",\n \"cloud-lightning\",\n \"cloud-moon-rain\",\n \"cloud-moon\",\n \"cloud-off\",\n \"cloud-rain-wind\",\n \"cloud-rain\",\n \"cloud-snow\",\n \"cloud-sun-rain\",\n \"cloud-sun\",\n \"cloud-sync\",\n \"cloud-upload\",\n \"upload-cloud\",\n \"cloud\",\n \"cloudy\",\n \"clover\",\n \"club\",\n \"code-xml\",\n \"code-2\",\n \"code\",\n \"coffee\",\n \"cog\",\n \"coins\",\n \"columns-2\",\n \"columns\",\n \"columns-3-cog\",\n \"columns-settings\",\n \"table-config\",\n \"columns-3\",\n \"panels-left-right\",\n \"columns-4\",\n \"combine\",\n \"command\",\n \"compass\",\n \"component\",\n \"computer\",\n \"concierge-bell\",\n \"cone\",\n \"construction\",\n \"contact-round\",\n \"contact-2\",\n \"contact\",\n \"container\",\n \"contrast\",\n \"cookie\",\n \"cooking-pot\",\n \"copy-check\",\n \"copy-minus\",\n \"copy-plus\",\n \"copy-slash\",\n \"copy-x\",\n \"copy\",\n \"copyleft\",\n \"copyright\",\n \"corner-down-left\",\n \"corner-down-right\",\n \"corner-left-down\",\n \"corner-left-up\",\n \"corner-right-down\",\n \"corner-right-up\",\n \"corner-up-left\",\n \"corner-up-right\",\n \"cpu\",\n \"creative-commons\",\n \"credit-card\",\n \"croissant\",\n \"crop\",\n \"cross\",\n \"crosshair\",\n \"crown\",\n \"cuboid\",\n \"cup-soda\",\n \"currency\",\n \"cylinder\",\n \"dam\",\n \"database-backup\",\n \"database-search\",\n \"database-zap\",\n \"database\",\n \"decimals-arrow-left\",\n \"decimals-arrow-right\",\n \"delete\",\n \"dessert\",\n \"diameter\",\n \"diamond-minus\",\n \"diamond-percent\",\n \"percent-diamond\",\n \"diamond-plus\",\n \"diamond\",\n \"dice-1\",\n \"dice-2\",\n \"dice-3\",\n \"dice-4\",\n \"dice-5\",\n \"dice-6\",\n \"dices\",\n \"diff\",\n \"disc-2\",\n \"disc-3\",\n \"disc-album\",\n \"disc\",\n \"divide\",\n \"dna-off\",\n \"dna\",\n \"dock\",\n \"dog\",\n \"dollar-sign\",\n \"donut\",\n \"door-closed-locked\",\n \"door-closed\",\n \"door-open\",\n \"dot\",\n \"download\",\n \"drafting-compass\",\n \"drama\",\n \"drill\",\n \"drone\",\n \"droplet-off\",\n \"droplet\",\n \"droplets\",\n \"drum\",\n \"drumstick\",\n \"dumbbell\",\n \"ear-off\",\n \"ear\",\n \"earth-lock\",\n \"earth\",\n \"globe-2\",\n \"eclipse\",\n \"egg-fried\",\n \"egg-off\",\n \"egg\",\n \"ellipse\",\n \"ellipsis-vertical\",\n \"more-vertical\",\n \"ellipsis\",\n \"more-horizontal\",\n \"equal-approximately\",\n \"equal-not\",\n \"equal\",\n \"eraser\",\n \"ethernet-port\",\n \"euro\",\n \"ev-charger\",\n \"expand\",\n \"external-link\",\n \"eye-closed\",\n \"eye-off\",\n \"eye\",\n \"factory\",\n \"fan\",\n \"fast-forward\",\n \"feather\",\n \"fence\",\n \"ferris-wheel\",\n \"file-archive\",\n \"file-axis-3d\",\n \"file-axis-3-d\",\n \"file-badge\",\n \"file-badge-2\",\n \"file-box\",\n \"file-braces-corner\",\n \"file-json-2\",\n \"file-braces\",\n \"file-json\",\n \"file-chart-column-increasing\",\n \"file-bar-chart\",\n \"file-chart-column\",\n \"file-bar-chart-2\",\n \"file-chart-line\",\n \"file-line-chart\",\n \"file-chart-pie\",\n \"file-pie-chart\",\n \"file-check-corner\",\n \"file-check-2\",\n \"file-check\",\n \"file-clock\",\n \"file-code-corner\",\n \"file-code-2\",\n \"file-code\",\n \"file-cog\",\n \"file-cog-2\",\n \"file-diff\",\n \"file-digit\",\n \"file-down\",\n \"file-exclamation-point\",\n \"file-warning\",\n \"file-headphone\",\n \"file-audio\",\n \"file-audio-2\",\n \"file-heart\",\n \"file-image\",\n \"file-input\",\n \"file-key\",\n \"file-key-2\",\n \"file-lock\",\n \"file-lock-2\",\n \"file-minus-corner\",\n \"file-minus-2\",\n \"file-minus\",\n \"file-music\",\n \"file-output\",\n \"file-pen-line\",\n \"file-signature\",\n \"file-pen\",\n \"file-edit\",\n \"file-play\",\n \"file-video\",\n \"file-plus-corner\",\n \"file-plus-2\",\n \"file-plus\",\n \"file-question-mark\",\n \"file-question\",\n \"file-scan\",\n \"file-search-corner\",\n \"file-search-2\",\n \"file-search\",\n \"file-signal\",\n \"file-volume-2\",\n \"file-sliders\",\n \"file-spreadsheet\",\n \"file-stack\",\n \"file-symlink\",\n \"file-terminal\",\n \"file-text\",\n \"file-type-corner\",\n \"file-type-2\",\n \"file-type\",\n \"file-up\",\n \"file-user\",\n \"file-video-camera\",\n \"file-video-2\",\n \"file-volume\",\n \"file-x-corner\",\n \"file-x-2\",\n \"file-x\",\n \"file\",\n \"files\",\n \"film\",\n \"fingerprint-pattern\",\n \"fingerprint\",\n \"fire-extinguisher\",\n \"fish-off\",\n \"fish-symbol\",\n \"fish\",\n \"fishing-hook\",\n \"fishing-rod\",\n \"flag-off\",\n \"flag-triangle-left\",\n \"flag-triangle-right\",\n \"flag\",\n \"flame-kindling\",\n \"flame\",\n \"flashlight-off\",\n \"flashlight\",\n \"flask-conical-off\",\n \"flask-conical\",\n \"flask-round\",\n \"flip-horizontal-2\",\n \"flip-vertical-2\",\n \"flower-2\",\n \"flower\",\n \"focus\",\n \"fold-horizontal\",\n \"fold-vertical\",\n \"folder-archive\",\n \"folder-check\",\n \"folder-clock\",\n \"folder-closed\",\n \"folder-code\",\n \"folder-cog\",\n \"folder-cog-2\",\n \"folder-dot\",\n \"folder-down\",\n \"folder-git-2\",\n \"folder-git\",\n \"folder-heart\",\n \"folder-input\",\n \"folder-kanban\",\n \"folder-key\",\n \"folder-lock\",\n \"folder-minus\",\n \"folder-open-dot\",\n \"folder-open\",\n \"folder-output\",\n \"folder-pen\",\n \"folder-edit\",\n \"folder-plus\",\n \"folder-root\",\n \"folder-search-2\",\n \"folder-search\",\n \"folder-symlink\",\n \"folder-sync\",\n \"folder-tree\",\n \"folder-up\",\n \"folder-x\",\n \"folder\",\n \"folders\",\n \"footprints\",\n \"forklift\",\n \"form\",\n \"forward\",\n \"frame\",\n \"frown\",\n \"fuel\",\n \"fullscreen\",\n \"funnel-plus\",\n \"funnel-x\",\n \"filter-x\",\n \"funnel\",\n \"filter\",\n \"gallery-horizontal-end\",\n \"gallery-horizontal\",\n \"gallery-thumbnails\",\n \"gallery-vertical-end\",\n \"gallery-vertical\",\n \"gamepad-2\",\n \"gamepad-directional\",\n \"gamepad\",\n \"gauge\",\n \"gavel\",\n \"gem\",\n \"georgian-lari\",\n \"ghost\",\n \"gift\",\n \"git-branch-minus\",\n \"git-branch-plus\",\n \"git-branch\",\n \"git-commit-horizontal\",\n \"git-commit\",\n \"git-commit-vertical\",\n \"git-compare-arrows\",\n \"git-compare\",\n \"git-fork\",\n \"git-graph\",\n \"git-merge-conflict\",\n \"git-merge\",\n \"git-pull-request-arrow\",\n \"git-pull-request-closed\",\n \"git-pull-request-create-arrow\",\n \"git-pull-request-create\",\n \"git-pull-request-draft\",\n \"git-pull-request\",\n \"glass-water\",\n \"glasses\",\n \"globe-lock\",\n \"globe-off\",\n \"globe-x\",\n \"globe\",\n \"goal\",\n \"gpu\",\n \"graduation-cap\",\n \"grape\",\n \"grid-2x2-check\",\n \"grid-2-x-2-check\",\n \"grid-2x2-plus\",\n \"grid-2-x-2-plus\",\n \"grid-2x2-x\",\n \"grid-2-x-2-x\",\n \"grid-2x2\",\n \"grid-2-x-2\",\n \"grid-3x2\",\n \"grid-3x3\",\n \"grid\",\n \"grid-3-x-3\",\n \"grip-horizontal\",\n \"grip-vertical\",\n \"grip\",\n \"group\",\n \"guitar\",\n \"ham\",\n \"hamburger\",\n \"hammer\",\n \"hand-coins\",\n \"hand-fist\",\n \"hand-grab\",\n \"grab\",\n \"hand-heart\",\n \"hand-helping\",\n \"helping-hand\",\n \"hand-metal\",\n \"hand-platter\",\n \"hand\",\n \"handbag\",\n \"handshake\",\n \"hard-drive-download\",\n \"hard-drive-upload\",\n \"hard-drive\",\n \"hard-hat\",\n \"hash\",\n \"hat-glasses\",\n \"haze\",\n \"hd\",\n \"hdmi-port\",\n \"heading-1\",\n \"heading-2\",\n \"heading-3\",\n \"heading-4\",\n \"heading-5\",\n \"heading-6\",\n \"heading\",\n \"headphone-off\",\n \"headphones\",\n \"headset\",\n \"heart-crack\",\n \"heart-handshake\",\n \"heart-minus\",\n \"heart-off\",\n \"heart-plus\",\n \"heart-pulse\",\n \"heart\",\n \"heater\",\n \"helicopter\",\n \"hexagon\",\n \"highlighter\",\n \"history\",\n \"hop-off\",\n \"hop\",\n \"hospital\",\n \"hotel\",\n \"hourglass\",\n \"house-heart\",\n \"house-plug\",\n \"house-plus\",\n \"house-wifi\",\n \"house\",\n \"home\",\n \"ice-cream-bowl\",\n \"ice-cream-2\",\n \"ice-cream-cone\",\n \"ice-cream\",\n \"id-card-lanyard\",\n \"id-card\",\n \"image-down\",\n \"image-minus\",\n \"image-off\",\n \"image-play\",\n \"image-plus\",\n \"image-up\",\n \"image-upscale\",\n \"image\",\n \"images\",\n \"import\",\n \"inbox\",\n \"indian-rupee\",\n \"infinity\",\n \"info\",\n \"inspection-panel\",\n \"italic\",\n \"iteration-ccw\",\n \"iteration-cw\",\n \"japanese-yen\",\n \"joystick\",\n \"kanban\",\n \"kayak\",\n \"key-round\",\n \"key-square\",\n \"key\",\n \"keyboard-music\",\n \"keyboard-off\",\n \"keyboard\",\n \"lamp-ceiling\",\n \"lamp-desk\",\n \"lamp-floor\",\n \"lamp-wall-down\",\n \"lamp-wall-up\",\n \"lamp\",\n \"land-plot\",\n \"landmark\",\n \"languages\",\n \"laptop-minimal-check\",\n \"laptop-minimal\",\n \"laptop-2\",\n \"laptop\",\n \"lasso-select\",\n \"lasso\",\n \"laugh\",\n \"layers-2\",\n \"layers-plus\",\n \"layers\",\n \"layers-3\",\n \"layout-dashboard\",\n \"layout-grid\",\n \"layout-list\",\n \"layout-panel-left\",\n \"layout-panel-top\",\n \"layout-template\",\n \"leaf\",\n \"leafy-green\",\n \"lectern\",\n \"lens-concave\",\n \"lens-convex\",\n \"library-big\",\n \"library\",\n \"life-buoy\",\n \"ligature\",\n \"lightbulb-off\",\n \"lightbulb\",\n \"line-dot-right-horizontal\",\n \"line-squiggle\",\n \"line-style\",\n \"link-2-off\",\n \"link-2\",\n \"link\",\n \"list-check\",\n \"list-checks\",\n \"list-chevrons-down-up\",\n \"list-chevrons-up-down\",\n \"list-collapse\",\n \"list-end\",\n \"list-filter-plus\",\n \"list-filter\",\n \"list-indent-decrease\",\n \"outdent\",\n \"indent-decrease\",\n \"list-indent-increase\",\n \"indent\",\n \"indent-increase\",\n \"list-minus\",\n \"list-music\",\n \"list-ordered\",\n \"list-plus\",\n \"list-restart\",\n \"list-start\",\n \"list-todo\",\n \"list-tree\",\n \"list-video\",\n \"list-x\",\n \"list\",\n \"loader-circle\",\n \"loader-2\",\n \"loader-pinwheel\",\n \"loader\",\n \"locate-fixed\",\n \"locate-off\",\n \"locate\",\n \"lock-keyhole-open\",\n \"unlock-keyhole\",\n \"lock-keyhole\",\n \"lock-open\",\n \"unlock\",\n \"lock\",\n \"log-in\",\n \"log-out\",\n \"logs\",\n \"lollipop\",\n \"luggage\",\n \"magnet\",\n \"mail-check\",\n \"mail-minus\",\n \"mail-open\",\n \"mail-plus\",\n \"mail-question-mark\",\n \"mail-question\",\n \"mail-search\",\n \"mail-warning\",\n \"mail-x\",\n \"mail\",\n \"mailbox\",\n \"mails\",\n \"map-minus\",\n \"map-pin-check-inside\",\n \"map-pin-check\",\n \"map-pin-house\",\n \"map-pin-minus-inside\",\n \"map-pin-minus\",\n \"map-pin-off\",\n \"map-pin-pen\",\n \"location-edit\",\n \"map-pin-plus-inside\",\n \"map-pin-plus\",\n \"map-pin-search\",\n \"map-pin-x-inside\",\n \"map-pin-x\",\n \"map-pin\",\n \"map-pinned\",\n \"map-plus\",\n \"map\",\n \"mars-stroke\",\n \"mars\",\n \"martini\",\n \"maximize-2\",\n \"maximize\",\n \"medal\",\n \"megaphone-off\",\n \"megaphone\",\n \"meh\",\n \"memory-stick\",\n \"menu\",\n \"merge\",\n \"message-circle-check\",\n \"message-circle-code\",\n \"message-circle-dashed\",\n \"message-circle-heart\",\n \"message-circle-more\",\n \"message-circle-off\",\n \"message-circle-plus\",\n \"message-circle-question-mark\",\n \"message-circle-question\",\n \"message-circle-reply\",\n \"message-circle-warning\",\n \"message-circle-x\",\n \"message-circle\",\n \"message-square-check\",\n \"message-square-code\",\n \"message-square-dashed\",\n \"message-square-diff\",\n \"message-square-dot\",\n \"message-square-heart\",\n \"message-square-lock\",\n \"message-square-more\",\n \"message-square-off\",\n \"message-square-plus\",\n \"message-square-quote\",\n \"message-square-reply\",\n \"message-square-share\",\n \"message-square-text\",\n \"message-square-warning\",\n \"message-square-x\",\n \"message-square\",\n \"messages-square\",\n \"metronome\",\n \"mic-off\",\n \"mic-vocal\",\n \"mic-2\",\n \"mic\",\n \"microchip\",\n \"microscope\",\n \"microwave\",\n \"milestone\",\n \"milk-off\",\n \"milk\",\n \"minimize-2\",\n \"minimize\",\n \"minus\",\n \"mirror-rectangular\",\n \"mirror-round\",\n \"monitor-check\",\n \"monitor-cloud\",\n \"monitor-cog\",\n \"monitor-dot\",\n \"monitor-down\",\n \"monitor-off\",\n \"monitor-pause\",\n \"monitor-play\",\n \"monitor-smartphone\",\n \"monitor-speaker\",\n \"monitor-stop\",\n \"monitor-up\",\n \"monitor-x\",\n \"monitor\",\n \"moon-star\",\n \"moon\",\n \"motorbike\",\n \"mountain-snow\",\n \"mountain\",\n \"mouse-left\",\n \"mouse-off\",\n \"mouse-pointer-2-off\",\n \"mouse-pointer-2\",\n \"mouse-pointer-ban\",\n \"mouse-pointer-click\",\n \"mouse-pointer\",\n \"mouse-right\",\n \"mouse\",\n \"move-3d\",\n \"move-3-d\",\n \"move-diagonal-2\",\n \"move-diagonal\",\n \"move-down-left\",\n \"move-down-right\",\n \"move-down\",\n \"move-horizontal\",\n \"move-left\",\n \"move-right\",\n \"move-up-left\",\n \"move-up-right\",\n \"move-up\",\n \"move-vertical\",\n \"move\",\n \"music-2\",\n \"music-3\",\n \"music-4\",\n \"music\",\n \"navigation-2-off\",\n \"navigation-2\",\n \"navigation-off\",\n \"navigation\",\n \"network\",\n \"newspaper\",\n \"nfc\",\n \"non-binary\",\n \"notebook-pen\",\n \"notebook-tabs\",\n \"notebook-text\",\n \"notebook\",\n \"notepad-text-dashed\",\n \"notepad-text\",\n \"nut-off\",\n \"nut\",\n \"octagon-alert\",\n \"alert-octagon\",\n \"octagon-minus\",\n \"octagon-pause\",\n \"pause-octagon\",\n \"octagon-x\",\n \"x-octagon\",\n \"octagon\",\n \"omega\",\n \"option\",\n \"orbit\",\n \"origami\",\n \"package-2\",\n \"package-check\",\n \"package-minus\",\n \"package-open\",\n \"package-plus\",\n \"package-search\",\n \"package-x\",\n \"package\",\n \"paint-bucket\",\n \"paint-roller\",\n \"paintbrush-vertical\",\n \"paintbrush-2\",\n \"paintbrush\",\n \"palette\",\n \"panda\",\n \"panel-bottom-close\",\n \"panel-bottom-dashed\",\n \"panel-bottom-inactive\",\n \"panel-bottom-open\",\n \"panel-bottom\",\n \"panel-left-close\",\n \"sidebar-close\",\n \"panel-left-dashed\",\n \"panel-left-inactive\",\n \"panel-left-open\",\n \"sidebar-open\",\n \"panel-left-right-dashed\",\n \"panel-left\",\n \"sidebar\",\n \"panel-right-close\",\n \"panel-right-dashed\",\n \"panel-right-inactive\",\n \"panel-right-open\",\n \"panel-right\",\n \"panel-top-bottom-dashed\",\n \"panel-top-close\",\n \"panel-top-dashed\",\n \"panel-top-inactive\",\n \"panel-top-open\",\n \"panel-top\",\n \"panels-left-bottom\",\n \"panels-right-bottom\",\n \"panels-top-left\",\n \"layout\",\n \"paperclip\",\n \"parentheses\",\n \"parking-meter\",\n \"party-popper\",\n \"pause\",\n \"paw-print\",\n \"pc-case\",\n \"pen-line\",\n \"edit-3\",\n \"pen-off\",\n \"pen-tool\",\n \"pen\",\n \"edit-2\",\n \"pencil-line\",\n \"pencil-off\",\n \"pencil-ruler\",\n \"pencil\",\n \"pentagon\",\n \"percent\",\n \"person-standing\",\n \"philippine-peso\",\n \"phone-call\",\n \"phone-forwarded\",\n \"phone-incoming\",\n \"phone-missed\",\n \"phone-off\",\n \"phone-outgoing\",\n \"phone\",\n \"pi\",\n \"piano\",\n \"pickaxe\",\n \"picture-in-picture-2\",\n \"picture-in-picture\",\n \"piggy-bank\",\n \"pilcrow-left\",\n \"pilcrow-right\",\n \"pilcrow\",\n \"pill-bottle\",\n \"pill\",\n \"pin-off\",\n \"pin\",\n \"pipette\",\n \"pizza\",\n \"plane-landing\",\n \"plane-takeoff\",\n \"plane\",\n \"play\",\n \"plug-2\",\n \"plug-zap\",\n \"plug-zap-2\",\n \"plug\",\n \"plus\",\n \"pocket-knife\",\n \"podcast\",\n \"pointer-off\",\n \"pointer\",\n \"popcorn\",\n \"popsicle\",\n \"pound-sterling\",\n \"power-off\",\n \"power\",\n \"presentation\",\n \"printer-check\",\n \"printer-x\",\n \"printer\",\n \"projector\",\n \"proportions\",\n \"puzzle\",\n \"pyramid\",\n \"qr-code\",\n \"quote\",\n \"rabbit\",\n \"radar\",\n \"radiation\",\n \"radical\",\n \"radio-off\",\n \"radio-receiver\",\n \"radio-tower\",\n \"radio\",\n \"radius\",\n \"rainbow\",\n \"rat\",\n \"ratio\",\n \"receipt-cent\",\n \"receipt-euro\",\n \"receipt-indian-rupee\",\n \"receipt-japanese-yen\",\n \"receipt-pound-sterling\",\n \"receipt-russian-ruble\",\n \"receipt-swiss-franc\",\n \"receipt-text\",\n \"receipt-turkish-lira\",\n \"receipt\",\n \"rectangle-circle\",\n \"rectangle-ellipsis\",\n \"form-input\",\n \"rectangle-goggles\",\n \"rectangle-horizontal\",\n \"rectangle-vertical\",\n \"recycle\",\n \"redo-2\",\n \"redo-dot\",\n \"redo\",\n \"refresh-ccw-dot\",\n \"refresh-ccw\",\n \"refresh-cw-off\",\n \"refresh-cw\",\n \"refrigerator\",\n \"regex\",\n \"remove-formatting\",\n \"repeat-1\",\n \"repeat-2\",\n \"repeat\",\n \"replace-all\",\n \"replace\",\n \"reply-all\",\n \"reply\",\n \"rewind\",\n \"ribbon\",\n \"road\",\n \"rocket\",\n \"rocking-chair\",\n \"roller-coaster\",\n \"rose\",\n \"rotate-3d\",\n \"rotate-3-d\",\n \"rotate-ccw-key\",\n \"rotate-ccw-square\",\n \"rotate-ccw\",\n \"rotate-cw-square\",\n \"rotate-cw\",\n \"route-off\",\n \"route\",\n \"router\",\n \"rows-2\",\n \"rows\",\n \"rows-3\",\n \"panels-top-bottom\",\n \"rows-4\",\n \"rss\",\n \"ruler-dimension-line\",\n \"ruler\",\n \"russian-ruble\",\n \"sailboat\",\n \"salad\",\n \"sandwich\",\n \"satellite-dish\",\n \"satellite\",\n \"saudi-riyal\",\n \"save-all\",\n \"save-off\",\n \"save\",\n \"scale-3d\",\n \"scale-3-d\",\n \"scale\",\n \"scaling\",\n \"scan-barcode\",\n \"scan-eye\",\n \"scan-face\",\n \"scan-heart\",\n \"scan-line\",\n \"scan-qr-code\",\n \"scan-search\",\n \"scan-text\",\n \"scan\",\n \"school\",\n \"scissors-line-dashed\",\n \"scissors\",\n \"scooter\",\n \"screen-share-off\",\n \"screen-share\",\n \"scroll-text\",\n \"scroll\",\n \"search-alert\",\n \"search-check\",\n \"search-code\",\n \"search-slash\",\n \"search-x\",\n \"search\",\n \"section\",\n \"send-horizontal\",\n \"send-horizonal\",\n \"send-to-back\",\n \"send\",\n \"separator-horizontal\",\n \"separator-vertical\",\n \"server-cog\",\n \"server-crash\",\n \"server-off\",\n \"server\",\n \"settings-2\",\n \"settings\",\n \"shapes\",\n \"share-2\",\n \"share\",\n \"sheet\",\n \"shell\",\n \"shelving-unit\",\n \"shield-alert\",\n \"shield-ban\",\n \"shield-check\",\n \"shield-cog-corner\",\n \"shield-cog\",\n \"shield-ellipsis\",\n \"shield-half\",\n \"shield-minus\",\n \"shield-off\",\n \"shield-plus\",\n \"shield-question-mark\",\n \"shield-question\",\n \"shield-user\",\n \"shield-x\",\n \"shield-close\",\n \"shield\",\n \"ship-wheel\",\n \"ship\",\n \"shirt\",\n \"shopping-bag\",\n \"shopping-basket\",\n \"shopping-cart\",\n \"shovel\",\n \"shower-head\",\n \"shredder\",\n \"shrimp\",\n \"shrink\",\n \"shrub\",\n \"shuffle\",\n \"sigma\",\n \"signal-high\",\n \"signal-low\",\n \"signal-medium\",\n \"signal-zero\",\n \"signal\",\n \"signature\",\n \"signpost-big\",\n \"signpost\",\n \"siren\",\n \"skip-back\",\n \"skip-forward\",\n \"skull\",\n \"slash\",\n \"slice\",\n \"sliders-horizontal\",\n \"sliders-vertical\",\n \"sliders\",\n \"smartphone-charging\",\n \"smartphone-nfc\",\n \"smartphone\",\n \"smile-plus\",\n \"smile\",\n \"snail\",\n \"snowflake\",\n \"soap-dispenser-droplet\",\n \"sofa\",\n \"solar-panel\",\n \"soup\",\n \"space\",\n \"spade\",\n \"sparkle\",\n \"sparkles\",\n \"stars\",\n \"speaker\",\n \"speech\",\n \"spell-check-2\",\n \"spell-check\",\n \"spline-pointer\",\n \"spline\",\n \"split\",\n \"spool\",\n \"sport-shoe\",\n \"spotlight\",\n \"spray-can\",\n \"sprout\",\n \"square-activity\",\n \"activity-square\",\n \"square-arrow-down-left\",\n \"arrow-down-left-square\",\n \"square-arrow-down-right\",\n \"arrow-down-right-square\",\n \"square-arrow-down\",\n \"arrow-down-square\",\n \"square-arrow-left\",\n \"arrow-left-square\",\n \"square-arrow-out-down-left\",\n \"arrow-down-left-from-square\",\n \"square-arrow-out-down-right\",\n \"arrow-down-right-from-square\",\n \"square-arrow-out-up-left\",\n \"arrow-up-left-from-square\",\n \"square-arrow-out-up-right\",\n \"arrow-up-right-from-square\",\n \"square-arrow-right-enter\",\n \"square-arrow-right-exit\",\n \"square-arrow-right\",\n \"arrow-right-square\",\n \"square-arrow-up-left\",\n \"arrow-up-left-square\",\n \"square-arrow-up-right\",\n \"arrow-up-right-square\",\n \"square-arrow-up\",\n \"arrow-up-square\",\n \"square-asterisk\",\n \"asterisk-square\",\n \"square-bottom-dashed-scissors\",\n \"scissors-square-dashed-bottom\",\n \"square-centerline-dashed-horizontal\",\n \"flip-horizontal\",\n \"square-centerline-dashed-vertical\",\n \"flip-vertical\",\n \"square-chart-gantt\",\n \"gantt-chart-square\",\n \"square-gantt-chart\",\n \"square-check-big\",\n \"check-square\",\n \"square-check\",\n \"check-square-2\",\n \"square-chevron-down\",\n \"chevron-down-square\",\n \"square-chevron-left\",\n \"chevron-left-square\",\n \"square-chevron-right\",\n \"chevron-right-square\",\n \"square-chevron-up\",\n \"chevron-up-square\",\n \"square-code\",\n \"code-square\",\n \"square-dashed-bottom-code\",\n \"square-dashed-bottom\",\n \"square-dashed-kanban\",\n \"kanban-square-dashed\",\n \"square-dashed-mouse-pointer\",\n \"mouse-pointer-square-dashed\",\n \"square-dashed-text\",\n \"text-selection\",\n \"text-select\",\n \"square-dashed-top-solid\",\n \"square-dashed\",\n \"box-select\",\n \"square-divide\",\n \"divide-square\",\n \"square-dot\",\n \"dot-square\",\n \"square-equal\",\n \"equal-square\",\n \"square-function\",\n \"function-square\",\n \"square-kanban\",\n \"kanban-square\",\n \"square-library\",\n \"library-square\",\n \"square-m\",\n \"m-square\",\n \"square-menu\",\n \"menu-square\",\n \"square-minus\",\n \"minus-square\",\n \"square-mouse-pointer\",\n \"inspect\",\n \"square-parking-off\",\n \"parking-square-off\",\n \"square-parking\",\n \"parking-square\",\n \"square-pause\",\n \"square-pen\",\n \"pen-box\",\n \"edit\",\n \"pen-square\",\n \"square-percent\",\n \"percent-square\",\n \"square-pi\",\n \"pi-square\",\n \"square-pilcrow\",\n \"pilcrow-square\",\n \"square-play\",\n \"play-square\",\n \"square-plus\",\n \"plus-square\",\n \"square-power\",\n \"power-square\",\n \"square-radical\",\n \"square-round-corner\",\n \"square-scissors\",\n \"scissors-square\",\n \"square-sigma\",\n \"sigma-square\",\n \"square-slash\",\n \"slash-square\",\n \"square-split-horizontal\",\n \"split-square-horizontal\",\n \"square-split-vertical\",\n \"split-square-vertical\",\n \"square-square\",\n \"square-stack\",\n \"square-star\",\n \"square-stop\",\n \"square-terminal\",\n \"terminal-square\",\n \"square-user-round\",\n \"user-square-2\",\n \"square-user\",\n \"user-square\",\n \"square-x\",\n \"x-square\",\n \"square\",\n \"squares-exclude\",\n \"squares-intersect\",\n \"squares-subtract\",\n \"squares-unite\",\n \"squircle-dashed\",\n \"squircle\",\n \"squirrel\",\n \"stamp\",\n \"star-half\",\n \"star-off\",\n \"star\",\n \"step-back\",\n \"step-forward\",\n \"stethoscope\",\n \"sticker\",\n \"sticky-note\",\n \"stone\",\n \"store\",\n \"stretch-horizontal\",\n \"stretch-vertical\",\n \"strikethrough\",\n \"subscript\",\n \"sun-dim\",\n \"sun-medium\",\n \"sun-moon\",\n \"sun-snow\",\n \"sun\",\n \"sunrise\",\n \"sunset\",\n \"superscript\",\n \"swatch-book\",\n \"swiss-franc\",\n \"switch-camera\",\n \"sword\",\n \"swords\",\n \"syringe\",\n \"table-2\",\n \"table-cells-merge\",\n \"table-cells-split\",\n \"table-columns-split\",\n \"table-of-contents\",\n \"table-properties\",\n \"table-rows-split\",\n \"table\",\n \"tablet-smartphone\",\n \"tablet\",\n \"tablets\",\n \"tag\",\n \"tags\",\n \"tally-1\",\n \"tally-2\",\n \"tally-3\",\n \"tally-4\",\n \"tally-5\",\n \"tangent\",\n \"target\",\n \"telescope\",\n \"tent-tree\",\n \"tent\",\n \"terminal\",\n \"test-tube-diagonal\",\n \"test-tube-2\",\n \"test-tube\",\n \"test-tubes\",\n \"text-align-center\",\n \"align-center\",\n \"text-align-end\",\n \"align-right\",\n \"text-align-justify\",\n \"align-justify\",\n \"text-align-start\",\n \"text\",\n \"align-left\",\n \"text-cursor-input\",\n \"text-cursor\",\n \"text-initial\",\n \"letter-text\",\n \"text-quote\",\n \"text-search\",\n \"text-wrap\",\n \"wrap-text\",\n \"theater\",\n \"thermometer-snowflake\",\n \"thermometer-sun\",\n \"thermometer\",\n \"thumbs-down\",\n \"thumbs-up\",\n \"ticket-check\",\n \"ticket-minus\",\n \"ticket-percent\",\n \"ticket-plus\",\n \"ticket-slash\",\n \"ticket-x\",\n \"ticket\",\n \"tickets-plane\",\n \"tickets\",\n \"timer-off\",\n \"timer-reset\",\n \"timer\",\n \"toggle-left\",\n \"toggle-right\",\n \"toilet\",\n \"tool-case\",\n \"toolbox\",\n \"tornado\",\n \"torus\",\n \"touchpad-off\",\n \"touchpad\",\n \"towel-rack\",\n \"tower-control\",\n \"toy-brick\",\n \"tractor\",\n \"traffic-cone\",\n \"train-front-tunnel\",\n \"train-front\",\n \"train-track\",\n \"tram-front\",\n \"train\",\n \"transgender\",\n \"trash-2\",\n \"trash\",\n \"tree-deciduous\",\n \"tree-palm\",\n \"palmtree\",\n \"tree-pine\",\n \"trees\",\n \"trending-down\",\n \"trending-up-down\",\n \"trending-up\",\n \"triangle-alert\",\n \"alert-triangle\",\n \"triangle-dashed\",\n \"triangle-right\",\n \"triangle\",\n \"trophy\",\n \"truck-electric\",\n \"truck\",\n \"turkish-lira\",\n \"turntable\",\n \"turtle\",\n \"tv-minimal-play\",\n \"tv-minimal\",\n \"tv-2\",\n \"tv\",\n \"type-outline\",\n \"type\",\n \"umbrella-off\",\n \"umbrella\",\n \"underline\",\n \"undo-2\",\n \"undo-dot\",\n \"undo\",\n \"unfold-horizontal\",\n \"unfold-vertical\",\n \"ungroup\",\n \"university\",\n \"school-2\",\n \"unlink-2\",\n \"unlink\",\n \"unplug\",\n \"upload\",\n \"usb\",\n \"user-check\",\n \"user-cog\",\n \"user-key\",\n \"user-lock\",\n \"user-minus\",\n \"user-pen\",\n \"user-plus\",\n \"user-round-check\",\n \"user-check-2\",\n \"user-round-cog\",\n \"user-cog-2\",\n \"user-round-key\",\n \"user-round-minus\",\n \"user-minus-2\",\n \"user-round-pen\",\n \"user-round-plus\",\n \"user-plus-2\",\n \"user-round-search\",\n \"user-round-x\",\n \"user-x-2\",\n \"user-round\",\n \"user-2\",\n \"user-search\",\n \"user-star\",\n \"user-x\",\n \"user\",\n \"users-round\",\n \"users-2\",\n \"users\",\n \"utensils-crossed\",\n \"fork-knife-crossed\",\n \"utensils\",\n \"fork-knife\",\n \"utility-pole\",\n \"van\",\n \"variable\",\n \"vault\",\n \"vector-square\",\n \"vegan\",\n \"venetian-mask\",\n \"venus-and-mars\",\n \"venus\",\n \"vibrate-off\",\n \"vibrate\",\n \"video-off\",\n \"video\",\n \"videotape\",\n \"view\",\n \"voicemail\",\n \"volleyball\",\n \"volume-1\",\n \"volume-2\",\n \"volume-off\",\n \"volume-x\",\n \"volume\",\n \"vote\",\n \"wallet-cards\",\n \"wallet-minimal\",\n \"wallet-2\",\n \"wallet\",\n \"wallpaper\",\n \"wand-sparkles\",\n \"wand-2\",\n \"wand\",\n \"warehouse\",\n \"washing-machine\",\n \"watch\",\n \"waves-arrow-down\",\n \"waves-arrow-up\",\n \"waves-ladder\",\n \"waves\",\n \"waypoints\",\n \"webcam\",\n \"webhook-off\",\n \"webhook\",\n \"weight-tilde\",\n \"weight\",\n \"wheat-off\",\n \"wheat\",\n \"whole-word\",\n \"wifi-cog\",\n \"wifi-high\",\n \"wifi-low\",\n \"wifi-off\",\n \"wifi-pen\",\n \"wifi-sync\",\n \"wifi-zero\",\n \"wifi\",\n \"wind-arrow-down\",\n \"wind\",\n \"wine-off\",\n \"wine\",\n \"workflow\",\n \"worm\",\n \"wrench\",\n \"x-line-top\",\n \"x\",\n \"zap-off\",\n \"zap\",\n \"zodiac-aquarius\",\n \"zodiac-aries\",\n \"zodiac-cancer\",\n \"zodiac-capricorn\",\n \"zodiac-gemini\",\n \"zodiac-leo\",\n \"zodiac-libra\",\n \"zodiac-ophiuchus\",\n \"zodiac-pisces\",\n \"zodiac-sagittarius\",\n \"zodiac-scorpio\",\n \"zodiac-taurus\",\n \"zodiac-virgo\",\n \"zoom-in\",\n \"zoom-out\",\n]);\n\nexport const LAYOUT_SECTION_ICON_SET: ReadonlySet<string> = new Set(LAYOUT_SECTION_ICONS);\nexport type LayoutSectionIcon = string;\n","import { z } from \"zod\";\nimport { SCHEMA_PLAYBOOK } from \"./playbook.js\";\nimport { SECTION_DOCTRINE } from \"@bettercms-ai/types\";\n\n/**\n * The one rule that decides whether a generated page is editable at all, injected into every\n * prompt that can end in a block tree.\n *\n * Only `studio` and `propose_schema` carried the playbook, and the playbook is where the\n * section rules lived — so `new_page`, `build_site` and `generate_landing_pages` could each\n * author a page with no idea that a page is a list of sections. A page authored as loose\n * top-level blocks gets one editor section per block: a hero of headline + lede + two CTAs\n * arrives as four sections, and the two CTAs stack instead of sitting side by side.\n */\nconst STRUCTURE_RULE = `### Page structure (non-negotiable)\n${SECTION_DOCTRINE}`;\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\n/**\n * Guided slash-command prompts that ship WITH the MCP. Claude Code (and other\n * hosts) surface server prompts automatically as `/mcp__bettercms__<name>`, so\n * adding the MCP is all it takes — no per-machine skill files.\n *\n * Design: one **generous parent** (`studio`) that reads the user's intent and\n * routes to the right sub-flow, plus thin direct entry points (`new_page`, ...)\n * for the individual flows. New BetterCMS tools get a new sub-flow section here.\n */\n\n// ── Reusable sub-flows ──────────────────────────────────────────────────────\n\nconst SCHEMA_PROPOSAL_FLOW = `### Whole-project design (confirm-first) → \\`create_component\\` / \\`create_page\\` / \\`create_content_model\\`\nDesign the WHOLE project from its brief or its code, and **confirm the shape with the user\nBEFORE creating anything**. Never silently guess.\n\n1. **Read the source** — the connected repo, or the uploaded project in your working\n directory. For each page, identify the repeated visual regions and the list-shaped data.\n2. **Classify every part** using the decision tree in the playbook below. The two mistakes\n that matter: flattening a marketing page into loose page fields when its sections should\n be COMPONENTS, and giving a blog a \\`richtext\\` field when its body should be \\`document\\`.\n3. **Present the proposal (REQUIRED gate).** Show the component library (with each section's\n family and variants), the collections and their fields, and the pages that place them.\n Ask the user (AskUserQuestion) to confirm or adjust. Do not create anything before this.\n4. **Build it in the playbook's order** — blocks, collections, components, PUBLISH the\n components, pages, content, publish. Skipping the publish step ships a blank site.\n\n${SCHEMA_PLAYBOOK}\n`;\n\nconst PAGE_FLOW = `### Page authoring → \\`create_page\\` tool\nAuthor a page (the page-first schema). Ask, in order, via AskUserQuestion:\n1. **Page type** — singleton (exactly one entry: Home, About, Contact) vs dynamic\n (many entries sharing the schema: Blog posts, Products).\n2. **Identity** — title; derive a slug (lowercase, a–z 0–9 -) and confirm; optional\n metaTitle/metaDescription.\n3. **Fields (loop until done)** — for each: key (^[a-zA-Z0-9_]+$), label, type,\n required?. Types (13): text, richtext, image, boolean, number, select (needs\n \\`options: string[]\\`), reference / multi-reference (\\`config.contentModelId\\`,\n multi adds min/max), array (primitives — \\`config.itemType\\`: text|number|date),\n date (\\`config.includeTime\\`?), datetime, **group** (Non-Repeatable Zone: ONE\n nested object — recurse to collect its \\`fields\\`, e.g. blog_hero → heading,\n description, hero_image), **repeater** (Repeatable Zone: an ARRAY of such objects\n — recurse to collect item \\`fields\\`, e.g. testimonials → quote, author). Nesting\n may go several levels deep.\n4. **Review** the assembled tree, then call \\`create_page\\` with\n { title, slug, pageType, fields, metaTitle?, metaDescription? }. Field object:\n { key, label, type, required?, options?, config?, fields? }.`;\n\nconst FIELD_FLOW = `### Add a field → \\`add_field\\` (models) / \\`add_page_field\\` (pages)\nAppend a field to an existing schema. First decide the target: a **content model**\nor a **page** (Home, About, a blog template). Ask: which target (id — use\n\\`list_pages\\` to find a page id), then the field (key, label, type — any of the 13\nabove, including nested group/repeater), required?. Confirm, then call:\n- a model → \\`add_field\\` { modelId, key, label, type, ... }\n- a page → \\`add_page_field\\` { pageId, key, label, type, ... }\nBoth are additive: they reject a key that already exists and never retype/overwrite\nan existing field (edit those in the dashboard).`;\n\nconst ENTRY_FLOW = `### Create an entry → \\`create_content_entry\\` tool\nCreate a content entry under a model. Ask: which model (id), the field values (data),\nstatus (draft/published). Then call \\`create_content_entry\\` { contentModelId, data?, status?, slug? }.`;\n\nconst FORM_FLOW = `### Form authoring → \\`create_form\\` / \\`update_form\\` tools\nAuthor a form (then the user embeds it with \\`<BcmsForm form={getForm('Name')} />\\` from\n@bettercms-ai/next). Confirm the fields with the user BEFORE creating. Never guess fields.\n1. **Discover** — \\`list_forms\\` to see existing forms; \\`get_form\\` to read one before editing.\n2. **Collect fields (loop)** — for each: key (machine key for the value), label, type. Types:\n text, email, textarea, select (needs \\`options: string[]\\`), checkbox, number, phone, date,\n url, consent, hidden. Optional per field: required?, placeholder?, defaultValue?, and\n \\`showIf: { field, equals }\\` for conditional display.\n3. **Settings** — name (used by getForm('Name')), submitLabel?, successMessage?, redirectUrl?.\n4. **Confirm**, then \\`create_form\\` { name, fields, ... } (returns the new id), or\n \\`update_form\\` { formId, ... } to edit (passing \\`fields\\` REPLACES the array — include all).\n5. Offer to wire \\`<BcmsForm>\\` into the page/component where the user wants it.`;\n\nconst COMPONENT_FLOW = `### Component authoring → \\`create_component\\` / \\`publish_component\\`\nAuthor a reusable section. blockJson is the visual definition; authoring it blind is\nerror-prone, so go slow and confirm. Never guess the layout.\n1. **Discover** — \\`list_components\\` / \\`get_component\\` (read before update; keep existing blocks).\n2. **Design the tree** — wrap the section in a \\`section\\` block carrying \\`style\\`\n (bg + paddingTop/paddingBottom + contentWidth) and nest content in props.children. See\n \"Anatomy of a real section component\" in the playbook. Give every block a stable id.\n3. **sectionType + category** — set both, or the component never appears in the editor's\n \"Add a section\" picker. Components sharing a sectionType are swappable VARIANTS, so reuse\n the same prop keys across a family or a swap drops content.\n4. **Props** — declare only what should really be editable:\n { key, label, target: { blockId, path }, type: text|richtext|image|url|boolean|slot }.\n5. **Confirm the structure** (AskUserQuestion: show the block tree), then \\`create_component\\`.\n6. **\\`publish_component\\`.** It lands as a DRAFT, and a draft component renders as NOTHING on\n the live site — no error, no placeholder. This step is not optional.\n`;\n\nconst LAYOUT_FLOW = `### Project/page Layout authoring → \\`get_layout\\` / \\`update_layout\\`\nEdit the project's draft Global Layout or one page's draft override. Layout publishing stays\nin the dashboard; these tools never change the live site.\n1. **Read first** — call \\`get_layout\\` with scope \\`global\\`, or scope \\`page\\` + pageId.\n Keep the returned \\`revision\\`; every write must pass it as \\`ifMatch\\`.\n2. **Choose one discriminated command type** — the server derives its authority family;\n callers cannot claim a weaker family for a schema or composition mutation.\n3. **Apply one canonical command** with \\`update_layout\\`, then use the returned revision for\n the next command. A 409 means somebody else edited it: re-read; never blindly retry.\n4. Direct fields are headless data. Only Component items render markup. Navigation/Footer\n are reserved Sections and cannot be deleted or moved; page overrides may inherit,\n override content, customize structure, or disable them.\n5. Read Component/Variant identities before attaching or swapping. Required values and\n bindings must be complete before a human publishes from the dashboard.`;\n\nconst BUILD_SITE_FLOW = `### Build a whole site (schema → pages → AI copy) → composes the flows below\nEnd-to-end authoring from a repo or a brief. Confirm-first at every stage.\n1. **Schema** — run the whole-project schema design above: propose the page/zone/field tree,\n get the user's approval, then \\`create_page\\` per page.\n2. **Copy** — for each page/entry, draft the real text with \\`write_content\\` (action 'write',\n pass the section as the brief + the page title as \\`context\\`). Review with the user, then\n apply via \\`set_page_content\\` / \\`create_content_entry\\` / \\`update_content_entry\\`.\n3. **SEO** — run the SEO flow to fill metaTitle/metaDescription for each page.\nNever invent brand facts — ask the user for anything the repo/brief doesn't state.`;\n\nconst LANDING_PAGES_FLOW = `### Generate landing pages (programmatic SEO / ABM) → \\`write_content\\` + \\`create_content_entry\\` + \\`generate_seo_meta\\`\nSpin up many pages sharing one template, each personalized per row (company, keyword, persona).\n1. **Template** — ensure a dynamic page or content model exists for the template\n (\\`create_page\\` pageType 'dynamic' / \\`create_content_model\\`); its fields are the per-page slots.\n2. **Dataset** — get the list of targets from the user (rows of variables, e.g. company + industry).\n3. **Per row (loop)** — draft each slot with \\`write_content\\` (the row's variables as the brief/\n \\`context\\`), pick a unique slug, then \\`create_content_entry\\` { contentModelId, data, slug, status }.\n Add SEO with \\`generate_seo_meta\\` on the drafted copy and store it on the entry.\nConfirm the first 1–2 rows with the user before generating the rest. For hundreds of rows,\nthe dashboard AI Page Builder bulk-imports a CSV — mention it.`;\n\nconst SEO_FLOW = `### Optimize SEO → \\`generate_seo_meta\\` + the page/entry update tools\nFill or refresh SEO metadata across the site.\n1. **Target** — pick the pages/entries (\\`list_pages\\` / \\`list_content_entries\\`); confirm scope with the user.\n2. **Per target** — read its content (\\`get_page\\` / \\`get_content_entry\\`), call \\`generate_seo_meta\\` with that\n content as \\`text\\`, review the suggested metaTitle/metaDescription/keywords, then apply it via\n the page/entry update tools (or the dashboard SEO fields).\nKeep titles ~60 chars and descriptions ~155; don't overwrite good existing meta without asking.`;\n\n// ── Registration ─────────────────────────────────────────────────────────────\n\nexport function registerPrompts(server: McpServer): void {\n // Parent router — the generous entry point.\n server.registerPrompt(\n \"studio\",\n {\n title: \"BetterCMS Studio (guided)\",\n description:\n \"One command to author in BetterCMS. Detects what you want — create a page, add a field, create an entry — and runs the matching guided flow, then calls the right tool.\",\n argsSchema: {\n request: z\n .string()\n .optional()\n .describe(\"what you want to do, e.g. 'a blog page with a hero zone'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are the BetterCMS authoring assistant (via the bettercms MCP).\n${request ? `The user's request: \"${request}\".\\n` : \"\"}\nFirst, **preflight**: confirm the bettercms tools are loaded (\\`create_page\\`, \\`add_field\\`,\n\\`create_content_entry\\`). If \\`create_page\\` is missing and only \\`create_model\\` shows, the host has a\nstale cached MCP — tell the user to run \\`rm -rf ~/.npm/_npx\\` and restart, then stop.\n\nThen **route** to the matching sub-flow below based on the request and conversation\ncontext. DEFAULT: when setting up a project or designing its schema from the repo (or\nwhen intent is unclear), run the **whole-repo schema design** flow — it proposes the\nstructure and confirms with the user before creating anything. Use the single-page or\nsingle-field flows only for targeted follow-ups. If still unsure, ask the user\n(AskUserQuestion: \"Design the schema from my project\" / \"Create one page\" / \"Add a field\" /\n\"Create an entry\" / \"Build a form\" / \"Build a component\"). Run flows by asking ONE step at\na time, pre-filling sensible defaults from the request but never inventing fields the user\ndidn't imply. Whatever the page/zone/form/component is scoped to follows the MCP key's project.\n\n${SCHEMA_PROPOSAL_FLOW}\n\n${PAGE_FLOW}\n\n${FIELD_FLOW}\n\n${ENTRY_FLOW}\n\n${FORM_FLOW}\n\n${COMPONENT_FLOW}\n\n${LAYOUT_FLOW}\n\n${BUILD_SITE_FLOW}\n\n${LANDING_PAGES_FLOW}\n\n${SEO_FLOW}\n\nThis assistant is extensible: when new BetterCMS tools are added, a new sub-flow appears\nhere — route to it the same way.`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"edit_layout\",\n {\n title: \"Edit project or page Layout (guided)\",\n description:\n \"Safely edit a draft Global Layout or page override with optimistic locking. Publishing remains in the dashboard.\",\n argsSchema: {\n request: z.string().optional().describe(\"what to change, e.g. 'disable the footer on the pricing page'\"),\n },\n },\n ({ request }) => ({\n messages: [{\n role: \"user\",\n content: {\n type: \"text\",\n text: `Edit the BetterCMS Layout draft.${request ? ` The user wants: \"${request}\".` : \"\"}\n\n${LAYOUT_FLOW}\n\nReport which scope changed and the new revision. Remind the user that publishing is a separate dashboard action.`,\n },\n }],\n }),\n );\n\n // Direct entry point for whole-repo schema design (the confirm-first default).\n server.registerPrompt(\n \"propose_schema\",\n {\n title: \"Design schema from repo (confirm-first)\",\n description:\n \"Read the repository, propose a destructured content schema (pages → group/repeater zones → nested fields), confirm it with you, then create it via create_page. Use this to set up a project's schema.\",\n argsSchema: {\n request: z\n .string()\n .optional()\n .describe(\"optional focus, e.g. 'just the marketing pages' or 'the whole site'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Design the BetterCMS content schema for this repository.${\n request ? ` Focus: \"${request}\".` : \"\"\n }\n\nPreflight: if \\`create_page\\` isn't available (only create_model/add_field/create_content_entry),\nthe host has a stale cached MCP — tell the user to \\`rm -rf ~/.npm/_npx\\` and restart, then stop.\n\n${SCHEMA_PROPOSAL_FLOW}\n\nAfter creating, report each page's id, slug, type, and field count, and the project it\nlanded in. On 409 slug_taken, offer an alternative slug; on 401/403, the MCP key needs\n(re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for the page flow (parent can also dispatch here).\n server.registerPrompt(\n \"new_page\",\n {\n title: \"New page (guided)\",\n description:\n \"Guided creation of a BetterCMS page (singleton or dynamic) with fields, including nested group (Non-Repeatable Zone) and repeater (Repeatable Zone) fields. Calls create_page.\",\n argsSchema: {\n request: z\n .string()\n .optional()\n .describe(\"what the page is, e.g. 'a blog page with a hero'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Create a BetterCMS page via the \\`create_page\\` tool.${\n request ? ` The user wants: \"${request}\".` : \"\"\n }\n\nPreflight: if \\`create_page\\` isn't available (only create_model/add_field/create_content_entry),\nthe host has a stale cached MCP — tell the user to \\`rm -rf ~/.npm/_npx\\` and restart, then stop.\n\n${PAGE_FLOW}\n\n${STRUCTURE_RULE}\n\nAfter creating, report the page id, slug, type, field count, and the project it landed in.\nOn 409 slug_taken, offer an alternative slug; on 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for form authoring.\n server.registerPrompt(\n \"new_form\",\n {\n title: \"New form (guided)\",\n description:\n \"Guided creation of a BetterCMS form (fields + settings) you can embed with <BcmsForm>. Calls create_form.\",\n argsSchema: {\n request: z.string().optional().describe(\"what the form is, e.g. 'a contact form with name, email, message'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Author a BetterCMS form via the \\`create_form\\` tool.${\n request ? ` The user wants: \"${request}\".` : \"\"\n }\n\n${FORM_FLOW}\n\nAfter creating, report the form id and name, and how to embed it (\\`<BcmsForm form={getForm('Name')} />\\`).\nOn 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for component authoring.\n server.registerPrompt(\n \"new_component\",\n {\n title: \"New component (guided)\",\n description:\n \"Guided creation of a reusable BetterCMS component (a blockJson tree + overridable props) you render with <BcmsBlocks>. Calls create_component.\",\n argsSchema: {\n request: z.string().optional().describe(\"what the component is, e.g. 'a hero with heading, text and a button'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Author a reusable BetterCMS component via the \\`create_component\\` tool.${\n request ? ` The user wants: \"${request}\".` : \"\"\n }\n\n${COMPONENT_FLOW}\n\nAfter creating, report the component id, name, and slug, and how to render it (\\`<BcmsBlocks>\\`).\nOn 409 slug_taken, offer an alternative slug; on 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for end-to-end site authoring (schema → pages → AI copy → SEO).\n server.registerPrompt(\n \"build_site\",\n {\n title: \"Build a site (guided, end-to-end)\",\n description:\n \"Author a whole BetterCMS site from a repo or a brief: design the schema, create the pages, draft the copy with AI (write_content), and fill SEO (generate_seo_meta).\",\n argsSchema: {\n request: z.string().optional().describe(\"what to build, e.g. 'a SaaS marketing site from this repo'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Build a BetterCMS site end-to-end.${request ? ` The user wants: \"${request}\".` : \"\"}\n\n${SCHEMA_PROPOSAL_FLOW}\n\n${BUILD_SITE_FLOW}\n\n${STRUCTURE_RULE}\n\n${SEO_FLOW}\n\nConfirm each stage with the user before writing. On 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for programmatic-SEO / ABM landing-page generation.\n server.registerPrompt(\n \"generate_landing_pages\",\n {\n title: \"Generate landing pages (programmatic SEO / ABM)\",\n description:\n \"Spin up many personalized landing pages from one template + a dataset, drafting each page's copy with write_content and SEO with generate_seo_meta.\",\n argsSchema: {\n request: z.string().optional().describe(\"the campaign, e.g. 'a page per target company for our ABM push'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Generate programmatic landing pages.${request ? ` The user wants: \"${request}\".` : \"\"}\n\n${LANDING_PAGES_FLOW}\n\n${STRUCTURE_RULE}\n\nOn 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for an SEO metadata pass.\n server.registerPrompt(\n \"seo_optimize\",\n {\n title: \"Optimize SEO (guided)\",\n description:\n \"Generate and apply SEO metadata (title, description, keywords, JSON-LD) across pages/entries with generate_seo_meta.\",\n argsSchema: {\n request: z.string().optional().describe(\"scope, e.g. 'all blog posts' or 'the home page'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Optimize SEO metadata.${request ? ` The user wants: \"${request}\".` : \"\"}\n\n${SEO_FLOW}\n\nOn 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // FLO-1178 agent-import: the sequence that turns a LIVE imported site into an EDITABLE one.\n // A deploy alone leaves every trap in place — content only in the build (nothing binds),\n // no presentation manifest (generic previews), unpublished components (render as nothing).\n // This prompt is the ordered walk out of all three, mirroring playbook §11.\n server.registerPrompt(\n \"import-site\",\n {\n title: \"Make an imported site editable (guided)\",\n description:\n \"After deploying an existing site: bring its content into the CMS so the visual editor can bind it, declare its presentation manifest, and publish everything that renders. A deploy makes a site LIVE, not EDITABLE — this flow closes that gap.\",\n argsSchema: {\n request: z\n .string()\n .optional()\n .describe(\"scope, e.g. 'all routes' or 'just the home page'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Make my imported site editable in BetterCMS.${request ? ` Scope: \"${request}\".` : \"\"}\n\nRead bettercms://playbook/schema section 11 first, then work this order:\n\n1. AUTHORING GATE — if any deploy answered 409 AUTHORING_DECISION_REQUIRED, ask ME\n components-or-fields (do not choose), then set_authoring_preference.\n2. CONTENT INTO THE CMS, per route: create_page (slug = route) -> add_page_field (or\n create_component + publish_component + component blocks) -> set_page_content with values\n EXACTLY equal to the rendered text (binding matches by value; a paraphrase binds nothing)\n -> update_page status 'published' (the canvas binds the PUBLISHED copy).\n3. PRESENTATION MANIFEST — add bcms-presentation.json to public/ (container width, type\n scale, nav position/background, footer surface as DTCG {\"$type\",\"$value\"} entries) and\n redeploy, or structural draft previews render in a generic theme, not this site's design.\n4. VERIFY — call get_next_steps and fix what it lists (it knows about missing manifests,\n content still only in the build, and placed-but-unpublished components), or tell me why\n an item is being left.\n\nOn 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n}\n","/**\n * How to design a BetterCMS project — ONE copy, read by both MCP surfaces.\n *\n * WHY IT LIVES HERE AND NOT IN THE BACKEND. `packages/mcp` is a published npm package:\n * tsup bundles `src/index.ts` and externalises only the sdk/mcp-sdk/zod, so an import\n * reaching into backend `src/` would drag Hono, Drizzle and Postgres into the tarball.\n * The backend has no such constraint and already imports from this package (see\n * `src/__tests__/mcp/mcp-parity.test.ts`), so the dependency points backend -> package.\n * This module is deliberately dependency-free strings for exactly that reason.\n *\n * WHY A RESOURCE AND NOT A TOOL DESCRIPTION. Every tool's schema rides in the prompt on\n * every step of every turn; a resource is fetched once, on demand, by a client that wants\n * it. Long-form guidance in a description is a tax on all 82 tools forever. So the\n * remote host serves this at `bettercms://playbook/schema` and MCP_INSTRUCTIONS points at\n * it, while the stdio package folds it into its guided prompts.\n *\n * WHAT IT HAD TO FIX. The previous guidance was page-first: it mapped a site to pages,\n * groups and repeaters and never mentioned components, `sectionType` variants,\n * `kind:'block'` + `modular`, or the `document` body — so an agent asked for \"a marketing\n * site with a blog\" built a pile of flat page fields and a richtext box.\n */\n\nexport const PLAYBOOK_URI = \"bettercms://playbook/schema\";\n\nexport const SCHEMA_PLAYBOOK = `# Designing a BetterCMS project\n\nRead this BEFORE creating anything. Confirm the shape with the user before you build it.\n\n## 1. Pick the architecture first\n\n**Components-first** — a marketing site. A library of reusable *components*, each a\nsection, and thin pages that place them. Editors add, reorder and swap sections without\ntouching a schema. This is what \\`create_component\\` + \\`create_page(blockJson)\\` are for.\n\n**Schema-first** — a blog, a product catalogue, a directory: many rows sharing one shape.\nA collection (\\`create_content_model\\`) plus entries.\n\nMost real sites are both: components for the marketing pages, a collection for the blog.\nDecide before your first call; converting later means rewriting content.\n\n## 2. The decision tree\n\n Repeated visual region on a page? -> a COMPONENT with sectionType (a Section)\n ...and it comes in more than one look? -> siblings sharing that sectionType = VARIANTS\n A stack of mixed, reorderable content? -> kind:'block' models + a \\`modular\\` field\n A row in a list (post, author, tier)? -> a collection (kind:'model')\n The one body of an article? -> type:'document' (exactly one, top level)\n A fixed cluster of fields? -> group (never a 1-item repeater)\n A repeating cluster? -> repeater\n A list of plain strings? -> array (never a repeater of one text)\n Site-wide nav/footer? -> place the project's provisioned components\n\n## 3. Anatomy of a real section component\n\nA component that is only headings and text renders as an unstyled stack. Every section the\nproduct ships looks like this — a \\`section\\` block carrying \\`style\\`, with content nested in\n\\`props.children\\`:\n\n {\n type: \"section\", id: \"root\",\n style: { bg: \"surface\", paddingTop: 96, paddingBottom: 96, contentWidth: \"default\", align: \"center\" },\n props: { children: [\n { type: \"heading\", id: \"h\", props: { text: \"Headline\", level: 2 } },\n { type: \"text\", id: \"sub\", props: { html: \"<p>Supporting copy.</p>\" } },\n { type: \"button\", id: \"cta\", props: { text: \"Get started\", href: \"/signup\", variant: \"primary\" } }\n ] }\n }\n\nThen declare what an editor may change, via \\`props\\`:\n\n props: [\n { key: \"headline\", label: \"Headline\", target: { blockId: \"h\", path: \"props.text\" }, type: \"text\" },\n { key: \"body\", label: \"Body\", target: { blockId: \"sub\", path: \"props.html\" }, type: \"richtext\" },\n { key: \"ctaHref\", label: \"CTA link\", target: { blockId: \"cta\", path: \"props.href\" }, type: \"url\" }\n ]\n\n🔴 **On a components-first page, \\`props\\` is the ONLY editing surface.** Click-to-edit binds\n\\`heading\\`/\\`text\\`/\\`button\\`/\\`image\\` blocks; it does **not** bind a \\`component\\` block, because\na component's blocks belong to the shared definition, not to the instance. So a page built\nfrom \\`component\\` blocks renders correctly and emits ZERO fields on the canvas — editing goes\nthrough the declared props allowlist to per-instance overrides. **A component with no props\nis a section nobody can change.** Declare a prop for every string, link and image a marketer\nwould ever reasonably want to touch; leave out only structure and styling.\n\n## 4. Variants\n\nComponents sharing a \\`sectionType\\` are swappable layouts of one section family — \"Hero\ncentered\" and \"Hero split\" both with \\`sectionType: \"Hero\"\\`. Swapping is one write and\nkeeps content, because overrides are keyed by prop KEY.\n\nSo **use the same prop keys across a family**. A variant that calls it \\`title\\` where its\nsibling calls it \\`headline\\` silently drops that content on the swap.\n\nPair \\`sectionType\\` with a library \\`category\\` (hero, content, social-proof, conversion) or\nthe component never appears in the editor's \"Add a section\" picker.\n\n## 5. Blocks and modular fields\n\nA \\`kind:'block'\\` model holds no entries of its own; it exists to be stacked inside another\nmodel's \\`modular\\` field. Create the blocks FIRST, then name their slugs (not ids) in\n\\`config.blockSlugs\\`. This is the page-builder shape: one \\`sections\\` field holding an\nordered list of typed blocks.\n\n## 6. Blogs\n\n author collection: name, avatar, bio\n blog-post collection: title, slug, excerpt, cover (image),\n body (document), author (reference -> author)\n\n\\`document\\` is THE article body: a rich document canvas, **collections only**, at most one\nper model, top level only (never inside a group or repeater). A page's body is its block\ncontent, so \\`document\\` on a page is rejected. Use \\`richtext\\` for a short formatted field,\n\\`longtext\\` for multi-line plain text.\n\nThen the pages:\n\n create_page slug:\"blog\" pageType:\"dynamic\" fields:[...the post schema...]\n blockJson: [ nav, heading, { type:\"collection\", id:\"list\", props:{} }, footer ]\n\n create_content_entry per post, with pageId set to that page\n\nThe \\`collection\\` block is lane-aware: on \\`/blog\\` it renders a card per entry, and on\n\\`/blog/<slug>\\` it renders THAT entry. One page, both jobs. Every OTHER block in the array\nis interpolated per entry with \\`{{fieldKey}}\\` placeholders — \\`{{title}}\\`, \\`{{cover.url}}\\`,\n\\`{{body.html}}\\`. Note that richtext and document bind to \\`.html\\` only, never the bare name.\n\n## 7. Order of operations\n\n 1. blocks create_content_model kind:'block' (before anything references them)\n 2. collections create_content_model\n 3. components create_component (they land as DRAFTS)\n 4. publish publish_component <- every component you intend to place\n 5. pages create_page with blockJson placing those components\n 6. content create_content_entry / set_page_content\n 7. publish update_page status:'published'\n 8. check get_next_steps, and fix what it lists\n\n## 8. Two ways to ship a blank site\n\n**An unpublished component renders as an empty string.** Not an error, not a placeholder —\nnothing, on a page that returns 200. If a section is missing from the live site, check\n\\`publish_component\\` before anything else.\n\n**A workspace-level component (\\`projectId: null\\`) never reaches a live site.** It resolves\nin preview and is blank in production. Always pass the project's id.\n\n## 9. Check which project you are bound to, BEFORE you build\n\n\\`create_project\\` succeeds on a project-scoped connection and hands back a real new project\n— but every write that follows still lands in the project your grant is bound to.\n\\`projectId\\` is forwarded as a header for a workspace-scoped grant; a **project-scoped grant\naccepts it and ignores it**, silently. No error, no warning, wrong project.\n\nSo call \\`get_project\\` (no arguments) first — it reports the project you are actually\nwriting to. If that is not where the work belongs, stop and tell the user: only they can\napprove a grant for the other project, no tool can switch it.\n\nIf you must probe, probe with a \\`create_content_model\\` — models are deletable\n(\\`delete_content_model\\`, soft-delete) and **there is no \\`delete_component\\`**. A component\nwritten to the wrong project can only be demoted (\\`sectionType: null\\`) and left unpublished.\n\n## 10. You imported a site, or you are about to deploy one\n\n\\`deploy_project\\`, \\`deploy_from_upload\\` and \\`promote_project\\` all answer **409\nAUTHORING_DECISION_REQUIRED** until a human has chosen this project's architecture. This is\nasked ONCE per project, ever. It is not an error to retry or route around: read the message\nout, let the user pick, call \\`set_authoring_preference\\`, then deploy again.\n\nIt exists because an imported site arrives **field-driven whether anyone chose that or not**\n— a crawl-based import (Webflow, a starter, a template) emits pages with a typed field schema\nand an empty block tree, because that is all a crawl can infer. Nobody decided it. On a\nmarketing site it is the wrong answer, and §1 already says why converting later means\nrewriting content. So the platform stops once, at the last moment it is still cheap.\n\n**Answering \\`components\\` does not convert anything.** There is no field-to-block converter,\nand \\`extract_component\\` cannot stand in for one: it scans \\`blockJson\\`, which is empty on\nexactly the pages that would need converting. What it means is that you author the sections,\nin this order:\n\n 1. create_component per section (they land as DRAFTS)\n 2. publish_component each one — unpublished renders as NOTHING, on a page that 200s\n 3. set_page_content place them as \\`component\\` blocks on the page\n 4. list_extraction_candidates / extract_component\n now that blocks exist, fold any section repeated 3+ times\n\n**Answering \\`fields\\` is a real answer, not a deferral.** A blog, a catalogue or a directory\nis schema-first by design (§1) and should stay that way. Say so and move on.\n\nEither way: ask, do not choose. The 409 carries this project's actual page counts — how many\nare field-driven, block-driven, and how many place a reusable component — so quote those to\nthe user rather than describing the choice in the abstract.\n\n## 11. The canvas: what makes an imported site EDITABLE\n\nA deploy makes a site LIVE. It does not make it editable — those are different states, and the\ngap between them is the single most common disappointment after an import.\n\n**The canvas is the real site when it can be.** When a page's draft matches its published copy\nstructurally, the visual editor frames the project's OWN deployed build and paints unpublished\ntext over it. Structural drafts (new sections, unpublished pages, changed components) render on\nthe platform's own renderer instead — and that renderer previews in a GENERIC theme unless the\ndeploy artifact declares \\`bcms-presentation.json\\` at its root. Put the file in \\`public/\\`\n(the build lands it at the artifact root) declaring the site's presentation — container width,\ntype scale, nav position and background, footer surface — as DTCG \\`{\"$type\": ..., \"$value\": ...}\\`\nentries. Redeclare it on every deploy; absent means \"declared nothing\" and previews fall back\nto platform defaults that will not look like this site.\n\n**Editing binds by VALUE.** The editor matches CMS field values against the text the site\nrenders. Three consequences, each load-bearing:\n\n 1. Content that exists ONLY in the build can never be click-to-edit. Bring it in, per\n route, in this order (get_next_steps reports the state until it is done):\n\n a. create_page one per route, slug matching the route\n b. add_page_field the fields its content needs (or create_component +\n publish_component + component blocks, per your §10 answer)\n c. set_page_content values EXACTLY equal to the text the site renders —\n binding matches by value, so a paraphrase binds nothing\n d. update_page status 'published' — the canvas binds the PUBLISHED copy\n 2. A value that renders in more than one place is still ONE field: bind every element that\n renders it, and the editor keeps them in sync — an edit patches every copy at once.\n Binding only one copy leaves the others showing the old text until the next rebuild.\n 3. Make the chrome ITSELF editable by speaking the layout grammar: the nav/footer\n elements declare \\`data-bcms-layout-section=\"navigation\"\\` / \\`\"footer\"\\`, and each\n CMS-backed text inside them a \\`data-bcms-layout-field=\"layout:<sectionId>:<fieldId>\"\\`\n marker (fieldId is the field's REAL id, verbatim — production layout ids are\n section-prefixed and dotted, e.g. \\`footer.tagline\\`, so the marker reads\n \\`layout:footer:footer.tagline\\`) — the canvas then gives them hover chrome, the\n Layout side panel, and\n double-click editing, writing to the project Layout store (never the page).\n The address reaches INSIDE structured fields by walking the schema: a group's text\n sub appends its slug (\\`layout:navigation:navigation.cta.label\\`), a repeater row its\n STORED index then the slug (\\`layout:navigation:navigation.links.0.label\\`), nesting\n as deep as the schema goes (\\`layout:footer:footer.link-groups.0.links.1.label\\`).\n Three rules, each one a measured defect when broken:\n a. a field rendered by TWO elements gets a marker on BOTH — the editor keeps the copies\n in sync, and a marker on only one leaves the other stale;\n b. PROVENANCE — mark an element only when the LAYOUT supplied its value; a marker\n over a fallback/singleton-sourced string opens an editor for a row that does not\n exist;\n c. row markers use the value's STORED index (a row you filtered out of the render\n still occupies its slot), or the edit lands on the wrong row.\n Text/longtext leaves edit inline; link/select/image leaves are side-panel-only by\n design (their formats need a real control). THE DOCTRINE: every string a marketer\n can see must be addressable — no marker means read-only on the canvas, so an\n unmarked CMS-backed string is a defect, not a style choice.\n 4. Keep chrome semantic — \\`<nav>\\`, \\`<footer>\\`, page content inside \\`<main>\\`, mastheads\n as a top-level \\`<header>\\`. Chrome is edited through the project Layout, not the page,\n and semantic landmarks are how the editor keeps a nav edit from being written into page\n content. Div-built chrome outside \\`<main>\\` is still excluded; div-built chrome with no\n \\`<main>\\` anywhere loses that protection.\n\n**Structural drafts can render on the real site too — the draft bridge.** Wrap your page's\nblocks in \\`BcmsDraftBridge\\` (\\`@bettercms-ai/next/draft-bridge\\`) instead of calling\n\\`BcmsBlocks\\` directly: standalone it renders identically, and inside the visual editor it\nreceives the DRAFT block tree over a same-origin postMessage handshake and re-renders it with\nthe site's own components — so adding, removing or reordering sections previews in the site's\nreal design instead of the platform's approximate renderer. Sites without the bridge keep the\napproximate fallback; unpublished ROUTES always fall back (a static build has no file to frame).\n\n**Hosting decides whether a canvas exists at all.** A site deployed here is framed through a\nsame-origin proxy — that is what the canvas requires. A site hosted elsewhere (your own Vercel,\nyour own server) has NO canvas today: the SDK's draft mode with \\`stega: true\\` embeds invisible\nper-field provenance in fetched strings, which prepares the content for editing surfaces, but do\nnot promise a canvas for an externally-hosted site.\n\n**§12 — RECEIPTS: a claim about published state needs a read of the PUBLISHED copy.** The\ndoctrine this encodes cost a real incident (FLO-1188): a publish was verified against the\ndraft for ~50 minutes because the reader silently returned the draft, and every check was\ngreen on the wrong document. Three rules, none optional:\n 1. NEVER verify a write by re-reading the store you wrote. Draft writes verify against\n the draft; a PUBLISH claim verifies ONLY via \\`get_layout copy:'published'\\` (or the\n entry/page's published copy) — and check the response's \\`copy\\` echo says\n 'published'. A reader that ignores your copy selector hands you the draft and a\n false green; the echo is how you catch it.\n 2. Publish and deploy are SEPARATE claims. \"Published\" means the published copy changed;\n the LIVE SITE changes only after its next deploy/rebuild. Never report \"it's live\"\n from a publish receipt — fetch the live URL (cache-busted) for that claim.\n 3. A tool param the schema does not declare is SILENTLY DROPPED, not rejected. If a\n call's behavior doesn't change when you change a param, treat the param as dead and\n verify through an independent channel before trusting any result built on it.\n\n## 13. Convert an imported repo into a CMS-backed, editable site\n\n§11 says a deploy does not make a site editable. This is the recipe that does, and it ends in a\nreceipt you can read: \\`get_binding_report\\` says \\`mode: \"declared\"\\` with zero unmatched paths.\n\n**Scope, before you start.**\n\n(a) This is the FIELD-driven conversion — page fields and collections. If the human answered\n\\`components\\` at the §10 gate, go to §10's recipe instead: a component's editing surface is its\ndeclared \\`props\\`, and those bindings are NOT what \\`get_binding_report\\` walks.\n\n(b) It works for any framework that emits STATIC HTML, because the binding contract is plain\nHTML attributes — the annotator, the injector and the canvas stamper never see your source.\nThere are SDK helpers for Astro and Next. A Node-runtime site (\\`bcms-runtime.json\\`) edits on\nthe canvas but skips release annotation and publish-time injection, because there is no HTML on\ndisk to annotate. Copy rendered on the client must carry the attributes in the HYDRATED DOM,\nand only the canvas sees it — a release scan cannot.\n\n**If you know Sanity, this is the same shape under different names:**\n\n defineType schema in code -> content models / page fields (create_content_model,\n add_page_field, or bcms-content.json \"schema\")\n TypeGen -> @bettercms-ai/codegen\n GROQ query in the page -> @bettercms-ai/sdk read client, or the bcms-content.json\n build snapshot\n <PortableText> body -> @bettercms-ai/richtext portableTextToHtml, field type\n 'document'\n data-sanity / stega -> data-bcms-field + data-bcms-kind (<BcmsField>), stega on\n draft reads\n Presentation tool overlays -> the visual editor canvas, framing your own build\n\n**Imported site whose pages were DERIVED.** If this project was imported and made editable from\nits build, the schema and the values already exist — a page per route, a field per element, and\nthe original copy carried on each field as its \\`defaultValue\\`. Call \\`get_conversion_brief\\`\nfirst: it lists those pages, their routes, every bindable path with its current and original\nvalue, and the attributes to declare. SKIP steps 3 and 4 below and bind the keys it names —\nregistering the schema again builds a second one over the first.\n\n**The steps.**\n\n1. \\`pull_project_source\\` (or clone the \\`github\\` remote it returns). Read the SOURCE. Never\n reconstruct content from the deployed HTML — that is how a site ends up bound to a copy of\n its own stale build.\n2. Decide the architecture WITH the human (§10) and record it: \\`set_authoring_preference\\`.\n3. Register the schema. Per route: \\`create_page\\` + \\`add_page_field\\` (text / longtext /\n richtext / image / array groups). Per repeated content type: \\`create_content_model\\`, with a\n \\`document\\` body for articles. Site chrome goes through \\`update_layout\\`; images through\n \\`create_media_upload\\` / \\`upload_asset\\`, then reference the CMS URL. The repo-owned\n alternative to calling these one by one is a committed \\`bcms-content.json\\` carrying a\n \\`schema\\` block, which seeds models, pages and entries at connect time — the \\`defineType\\`\n analogue.\n4. Seed the entries with the copy EXACTLY as the source renders it (\\`set_page_content\\`,\n \\`create_content_entry\\`). Prose goes in as Portable Text arrays (\\`_type: \"block\"\\`); never\n markup inside a \\`text\\` field.\n **Prose MIGRATED from another CMS needs one extra check.** Every block's \\`_type\\` must be one\n this platform stores — \\`block\\`, or \\`bcmsBlock\\` carrying a \\`schemaKey\\` such as\n \\`builtin:table\\` — and a foreign node (a Sanity-shaped \\`{_type:\"table\", rows:[{cells}]}\\` is\n the one that has actually happened) is not merely unrendered: it has no component here, so it\n vanishes from the HTML every delivery surface reads while the stored value still looks whole.\n Verify each \\`_type\\` against the schema before you write, not after.\n5. Codemod the templates. Read each value from the CMS (\\`@bettercms-ai/astro\\` /\n \\`@bettercms-ai/next\\` client, or the \\`bcms-content.json\\` build snapshot), KEEP the in-code\n copy as the fallback, and declare the binding on the element that already renders it.\n Prefer schema-derived bindings — the TypeGen analogue:\n \\`npx @bettercms-ai/codegen --bindings-out src/bettercms.bindings.generated.ts\\`, then spread\n \\`{...bcms.home.hero.title}\\` / \\`{...bcms.blog.features.$(i)}\\`. The hand form is\n \\`data-bcms-field=\"<path>\"\\` (plus \\`data-bcms-kind=\"richtext\"|\"image\"\\`), \\`data-bcms-props\\`\n for an \\`href\\` / \\`alt\\` / \\`src\\`, the §11 layout markers for nav and footer, and\n \\`<div data-bcms-field=\"body\" data-bcms-kind=\"document\">\\` around a Portable Text render.\n Bind CONDITIONALLY (\\`fromCms ? path : undefined\\`) so a fallback row is never bound. A value\n rendered in N places carries the binding on ALL N — the editor keeps the copies in sync.\n **Read the LIVE SCHEMA before you bind — \\`get_page\\` / \\`get_content_model\\`, never the\n delivery snapshot.** A field nobody has authored yet is simply ABSENT from the payload, so a\n snapshot cannot tell \"this field does not exist\" from \"this field is empty\": bind against it\n and you declare a path for a \\`cover\\` field that was never created, which the report then\n reports as broken forever. The schema is the list of what exists; the snapshot is only what\n currently has a value.\n **An index or listing route binds NOTHING.** The editor loads ONE entry per route, and an\n index renders many, so a binding there addresses whichever entry the editor happened to\n load. Bind each item's fields on that item's OWN route (\\`/blog/<slug>\\`); on the index,\n render from the CMS and declare nothing.\n5b. **Where the content comes from at build time.** Two lanes, and they differ:\n - GIT-CONNECTED (recommended for a converted site): the platform's provisioned workflow\n writes \\`bcms-content.json\\` into the repo root before \\`build\\`, using the repo's\n \\`BCMS_API_KEY\\` secret. Read that file, with in-code fallbacks so a local or CI build\n without it still renders.\n - ARCHIVE (\\`deploy_project\\` / \\`deploy_from_upload\\`): the sandbox build runs with no env\n and no network content step, by design. So the archive MUST SHIP its own\n \\`bcms-content.json\\` — generate it locally with a delivery key and commit it. Without\n one the site renders its fallbacks and the report says \\`no-element\\` for every path.\n6. Push, or \\`deploy_project\\`; poll \\`get_deploy_status\\` until it is live. Then\n \\`get_binding_report\\` — still \\`text-match\\`, and \\`unmatched\\` should be EMPTY because the\n values are byte-equal to what the build renders. Now \\`set_binding_mode\n {declaredBindings: true}\\` and release again (an empty commit is enough). Do not flip before\n the report is clean: in declared mode an undeclared field simply stops being editable.\n7. **Receipts.** \\`get_binding_report\\` reads \\`mode: \"declared\"\\`, \\`unmatched: []\\`, and\n \\`bound > 0\\`. That certifies one thing only — that every non-empty field has SOME element\n carrying its path. It CANNOT see copy that was never modelled, so diff each route's visible\n text against its entry values yourself before you call the page done. Then publish, and\n fetch the live URL cache-busted (§12: publish and deploy are separate claims).\n \\`get_next_steps\\` keeps reporting the gap until every one of these holds.\n`;\n"],"mappings":"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AA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AA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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AD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","names":["s","z","z"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/token-store.ts","../src/device-auth.ts","../src/server.ts","../src/tools.ts","../../types/src/component.ts","../../types/src/layout-lucide-icons.ts","../src/prompts.ts","../src/playbook.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { loadConfig } from \"./config.js\";\nimport { FileTokenStore } from \"./token-store.js\";\nimport { DeviceAuthClient } from \"./device-auth.js\";\nimport { buildServer } from \"./server.js\";\n\nexport { buildServer } from \"./server.js\";\nexport { DeviceAuthClient } from \"./device-auth.js\";\nexport { loadConfig } from \"./config.js\";\n\n/** Entrypoint for the `bettercms-mcp` stdio server. */\nasync function main(): Promise<void> {\n const config = loadConfig();\n const store = new FileTokenStore(config.credentialsPath, config.apiUrl);\n const auth = new DeviceAuthClient(config, store);\n const server = buildServer({ auth, managementBaseUrl: config.managementBaseUrl });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n process.stderr.write(`[bettercms-mcp] ready on stdio (api: ${config.apiUrl})\\n`);\n}\n\n// Only run when executed as the entry (not when imported, e.g. in tests).\n// Compare realpaths so symlinked launch paths still detect the entrypoint:\n// `import.meta.url` is realpath-resolved by Node, but `process.argv[1]` is not,\n// so the old `file://${argv[1]}` check silently failed under npx `.bin`\n// symlinks, global installs, and macOS /var→/private/var — the server would\n// exit 0 without starting.\nfunction isMainModule(): boolean {\n const argv1 = process.argv[1];\n if (!argv1) return false;\n try {\n return realpathSync(argv1) === fileURLToPath(import.meta.url);\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n main().catch((err) => {\n process.stderr.write(`[bettercms-mcp] fatal: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n });\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/**\n * Resolved configuration for the BetterCMS MCP server.\n *\n * A single `BETTERCMS_API_URL` (origin, no path) drives both the device-auth\n * endpoints and the Management API base the SDK targets:\n * device: {apiUrl}/api/v1/auth/device/*\n * management: {apiUrl}/api/v1 (SDK appends /management/content/*)\n */\nexport interface McpConfig {\n apiUrl: string;\n deviceBaseUrl: string;\n managementBaseUrl: string;\n credentialsPath: string;\n clientName: string;\n}\n\nconst DEFAULT_API_URL = \"https://api.bettercms.ai\";\n\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): McpConfig {\n const apiUrl = (env.BETTERCMS_API_URL?.trim() || DEFAULT_API_URL).replace(/\\/+$/, \"\");\n return {\n apiUrl,\n deviceBaseUrl: `${apiUrl}/api/v1/auth/device`,\n managementBaseUrl: `${apiUrl}/api/v1`,\n credentialsPath:\n env.BETTERCMS_MCP_CREDENTIALS?.trim() ||\n join(homedir(), \".bettercms\", \"mcp-credentials.json\"),\n clientName: env.BETTERCMS_MCP_CLIENT_NAME?.trim() || \"BetterCMS MCP\",\n };\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\n/** Credentials cached between runs so the device flow runs only once per env. */\nexport interface StoredCredentials {\n accessToken: string;\n refreshToken: string;\n /** Epoch ms when the access token expires. */\n accessTokenExpiresAt: number;\n workspaceId: string | null;\n projectId: string | null;\n}\n\n/**\n * An authorization the user has been sent off to approve but hasn't yet.\n * Persisted so a later tool call can *resume* polling that same code instead of\n * minting a fresh one — this is what lets the flow survive across the\n * \"return the link → user approves → retry\" round-trip in clients (VS Code)\n * that never surface the server's stderr prompt.\n */\nexport interface PendingDevice {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n /** verification_uri with `?code=` prefilled — the link we hand the user. */\n verificationUriComplete: string;\n intervalSeconds: number;\n /** Epoch ms when the device code expires. */\n expiresAt: number;\n}\n\n/** Persistence boundary for credentials (file-backed in prod, in-memory in tests). */\nexport interface TokenStore {\n read(): Promise<StoredCredentials | null>;\n write(creds: StoredCredentials): Promise<void>;\n clear(): Promise<void>;\n /** In-progress device authorization awaiting approval, if any. */\n readPending(): Promise<PendingDevice | null>;\n writePending(pending: PendingDevice): Promise<void>;\n clearPending(): Promise<void>;\n}\n\n/**\n * File-backed token store. Credentials are namespaced by `key` (the API origin)\n * so pointing the server at a different environment doesn't reuse a stale token.\n * The file is written 0600 (owner-only) since it holds bearer credentials.\n */\nexport class FileTokenStore implements TokenStore {\n /** Pending authorizations live under a sibling key so they never shadow creds. */\n private readonly pendingKey: string;\n\n constructor(\n private readonly path: string,\n private readonly key: string,\n ) {\n this.pendingKey = `${key}::pending`;\n }\n\n private async readAll(): Promise<Record<string, unknown>> {\n try {\n const raw = await readFile(this.path, \"utf-8\");\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n return parsed && typeof parsed === \"object\" ? parsed : {};\n } catch {\n return {};\n }\n }\n\n private async writeAll(all: Record<string, unknown>): Promise<void> {\n await mkdir(dirname(this.path), { recursive: true });\n await writeFile(this.path, JSON.stringify(all, null, 2), { mode: 0o600 });\n }\n\n async read(): Promise<StoredCredentials | null> {\n const all = await this.readAll();\n return (all[this.key] as StoredCredentials | undefined) ?? null;\n }\n\n async write(creds: StoredCredentials): Promise<void> {\n const all = await this.readAll();\n all[this.key] = creds;\n await this.writeAll(all);\n }\n\n async clear(): Promise<void> {\n const all = await this.readAll();\n delete all[this.key];\n await this.writeAll(all);\n }\n\n async readPending(): Promise<PendingDevice | null> {\n const all = await this.readAll();\n return (all[this.pendingKey] as PendingDevice | undefined) ?? null;\n }\n\n async writePending(pending: PendingDevice): Promise<void> {\n const all = await this.readAll();\n all[this.pendingKey] = pending;\n await this.writeAll(all);\n }\n\n async clearPending(): Promise<void> {\n const all = await this.readAll();\n delete all[this.pendingKey];\n await this.writeAll(all);\n }\n}\n","import type { McpConfig } from \"./config.js\";\nimport type { PendingDevice, StoredCredentials, TokenStore } from \"./token-store.js\";\n\n/** Skew applied when deciding if a cached access token is still usable. */\nconst EXPIRY_SKEW_MS = 60_000;\n\n/**\n * How long a single tool call waits inline for the user to approve before it\n * gives up and hands the activation link back to the caller. Fast approvals\n * complete in the *same* call; slow ones resume on the next tool call.\n */\nconst GRACE_POLL_MS = 25_000;\n\ninterface TokenSuccess {\n access_token: string;\n token_type: string;\n expires_in: number;\n refresh_token: string;\n scope: string;\n workspace_id: string | null;\n project_id: string | null;\n}\n\ninterface DeviceCodeResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete?: string;\n expires_in: number;\n interval: number;\n}\n\n/** Injectable seams so tests can run without real timers / network / stderr. */\nexport interface DeviceAuthDeps {\n fetch?: typeof fetch;\n sleep?: (ms: number) => Promise<void>;\n log?: (message: string) => void;\n now?: () => number;\n}\n\n/** Thrown when the device flow cannot complete (denied / expired / unexpected). */\nexport class DeviceAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DeviceAuthError\";\n }\n}\n\n/**\n * Thrown when authorization is *legitimately still pending* after the inline\n * grace window. Carries the activation link so the caller (a tool handler) can\n * surface it in the visible tool result — the device flow is persisted, so the\n * next tool call resumes it and completes the user's original request.\n */\nexport class DeviceAuthPendingError extends Error {\n readonly verificationUri: string;\n readonly verificationUriComplete: string;\n readonly userCode: string;\n readonly expiresAt: number;\n\n constructor(pending: PendingDevice) {\n super(\"Authorization pending — approve in the browser, then retry.\");\n this.name = \"DeviceAuthPendingError\";\n this.verificationUri = pending.verificationUri;\n this.verificationUriComplete = pending.verificationUriComplete;\n this.userCode = pending.userCode;\n this.expiresAt = pending.expiresAt;\n }\n}\n\n/**\n * Drives the OAuth 2.0 Device Authorization Grant (RFC 8628) against the\n * BetterCMS backend and hands the SDK a valid `content:manage` access token.\n *\n * - `getAccessToken()` returns a usable token: cached if fresh, refreshed if\n * expired, or freshly minted via the full device flow if there's nothing valid.\n * - All human-facing output goes to stderr — stdout is the MCP JSON-RPC channel.\n */\nexport class DeviceAuthClient {\n private readonly fetchImpl: typeof fetch;\n private readonly sleep: (ms: number) => Promise<void>;\n private readonly log: (message: string) => void;\n private readonly now: () => number;\n private inFlight: Promise<string> | null = null;\n private refreshInFlight: Promise<string | null> | null = null;\n /** The single live poller for the current device code (see runDeviceFlow). */\n private pollTask: Promise<string | null> | null = null;\n\n constructor(\n private readonly config: McpConfig,\n private readonly store: TokenStore,\n deps: DeviceAuthDeps = {},\n ) {\n this.fetchImpl = deps.fetch ?? globalThis.fetch;\n this.sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));\n this.log = deps.log ?? ((m) => process.stderr.write(`${m}\\n`));\n this.now = deps.now ?? (() => Date.now());\n }\n\n /** Return a valid access token, doing the least work necessary. Single-flighted. */\n async getAccessToken(): Promise<string> {\n if (this.inFlight) return this.inFlight;\n this.inFlight = this.resolveToken().finally(() => {\n this.inFlight = null;\n });\n return this.inFlight;\n }\n\n private async resolveToken(): Promise<string> {\n const creds = await this.store.read();\n if (creds && creds.accessTokenExpiresAt - this.now() > EXPIRY_SKEW_MS) {\n return creds.accessToken;\n }\n if (creds?.refreshToken) {\n const refreshed = await this.refresh();\n if (refreshed) return refreshed;\n }\n return this.runDeviceFlow();\n }\n\n /**\n * Resume a still-live authorization if one is persisted, otherwise start a\n * fresh one; then grace-poll. Throws {@link DeviceAuthPendingError} (carrying\n * the activation link) if the user hasn't approved within the grace window.\n */\n private async runDeviceFlow(): Promise<string> {\n let pending = await this.store.readPending();\n if (pending && pending.expiresAt - this.now() <= EXPIRY_SKEW_MS) {\n await this.store.clearPending(); // stale — don't resume an expired code\n pending = null;\n }\n if (!pending) {\n pending = await this.startDeviceFlow();\n }\n\n const graceDeadline = Math.min(this.now() + GRACE_POLL_MS, pending.expiresAt);\n // A detached poller may already own this code (handed off by an earlier tool call).\n // Never poll it concurrently: the code is single-use, so the loser of the claim race\n // gets invalid_grant — wait on the existing poller instead of starting a second one.\n const token = this.pollTask\n ? await Promise.race([this.pollTask, this.sleep(GRACE_POLL_MS).then(() => null)])\n : await this.pollForApproval(pending, graceDeadline);\n if (token) return token;\n\n // Still pending after the grace window — hand the link to the caller so it lands in the\n // visible tool result, and keep polling in the background so a later approval is still\n // redeemed. Polling used to stop dead right here, which is how an approval that landed\n // 30s later got stranded: the grant sat at \"approved\" server-side forever, the browser\n // said \"approved ✓ — your terminal will finish connecting automatically\" with nothing\n // listening, and Settings → Connected agents stayed empty (it lists CLAIMED grants only).\n this.pollInBackground(pending);\n throw new DeviceAuthPendingError(pending);\n }\n\n /** Keep redeeming this code until it expires, detached from any tool call. One per code. */\n private pollInBackground(pending: PendingDevice): void {\n if (this.pollTask) return;\n const task = this.pollForApproval(pending, pending.expiresAt);\n this.pollTask = task;\n // Detached settle handler: swallows a terminal rejection (denied/expired) so it is never\n // an unhandled rejection, while leaving `task` itself awaitable by runDeviceFlow.\n void task.catch(() => {}).finally(() => {\n if (this.pollTask === task) this.pollTask = null;\n });\n }\n\n /** Request a fresh device code, persist it as pending, and log a breadcrumb. */\n private async startDeviceFlow(): Promise<PendingDevice> {\n const start = await this.fetchImpl(`${this.config.deviceBaseUrl}/code`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ client_name: this.config.clientName }),\n });\n if (!start.ok) {\n throw new DeviceAuthError(\n `Failed to start device authorization (HTTP ${start.status}).`,\n );\n }\n const code = (await start.json()) as DeviceCodeResponse;\n const pending: PendingDevice = {\n deviceCode: code.device_code,\n userCode: code.user_code,\n verificationUri: code.verification_uri,\n verificationUriComplete:\n code.verification_uri_complete ??\n `${code.verification_uri}?code=${encodeURIComponent(code.user_code)}`,\n intervalSeconds: code.interval,\n expiresAt: this.now() + code.expires_in * 1000,\n };\n await this.store.writePending(pending);\n // A fresh code retires any poller still chasing the previous one (which will simply\n // 400 expired_token and settle). Without this, runDeviceFlow would race the OLD task\n // and never poll the code the user is actually being shown.\n this.pollTask = null;\n\n // Breadcrumb for terminal/non-VS-Code clients that DO surface stderr.\n this.log(\"\");\n this.log(\"┌─ BetterCMS authorization required ─────────────────────────\");\n this.log(`│ Visit: ${pending.verificationUri}`);\n this.log(`│ Enter code: ${pending.userCode}`);\n this.log(`│ Or open: ${pending.verificationUriComplete}`);\n this.log(\"└────────────────────────────────────────────────────────────\");\n return pending;\n }\n\n /**\n * Poll the token endpoint until `deadline`. Returns the access token on\n * approval, or null if the deadline passes while still pending. Throws\n * {@link DeviceAuthError} on a terminal outcome (denied / expired).\n */\n private async pollForApproval(\n pending: PendingDevice,\n deadline: number,\n ): Promise<string | null> {\n let intervalMs = pending.intervalSeconds * 1000;\n\n while (this.now() < deadline) {\n await this.sleep(intervalMs);\n if (this.now() >= deadline) break; // don't poll once past the window\n\n const res = await this.fetchImpl(`${this.config.deviceBaseUrl}/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n device_code: pending.deviceCode,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n });\n\n if (res.ok) {\n const body = (await res.json()) as TokenSuccess;\n await this.store.clearPending();\n this.log(\"[bettercms-mcp] authorized ✓\");\n return this.persist(body);\n }\n\n const err = (await res.json().catch(() => ({}))) as { error?: string };\n switch (err.error) {\n case \"authorization_pending\":\n continue;\n case \"slow_down\":\n intervalMs += 5_000; // RFC 8628 §3.5\n continue;\n case \"access_denied\":\n await this.store.clearPending();\n throw new DeviceAuthError(\"Authorization was denied.\");\n case \"expired_token\":\n await this.store.clearPending();\n throw new DeviceAuthError(\"The device code expired before approval. Try again.\");\n default:\n throw new DeviceAuthError(\n `Device authorization failed: ${err.error ?? `HTTP ${res.status}`}.`,\n );\n }\n }\n return null; // still pending — caller surfaces the activation link\n }\n\n /**\n * Exchange the stored refresh token for a new access token. Single-flighted:\n * the device `/refresh` endpoint is single-use (it rotates the refresh token\n * and revokes the prior access key), so a burst of concurrent 401s must NOT\n * each fire their own refresh — the first would rotate, and the rest would\n * send the now-stale token, get `invalid_grant`, and wipe the freshly-minted\n * credentials. Collapsing them into one in-flight rotation keeps the session\n * alive without a needless re-auth.\n */\n async refresh(): Promise<string | null> {\n if (this.refreshInFlight) return this.refreshInFlight;\n this.refreshInFlight = this.doRefresh().finally(() => {\n this.refreshInFlight = null;\n });\n return this.refreshInFlight;\n }\n\n /**\n * Forget the cached credentials and start a fresh device flow. Called when the\n * bound project was deleted server-side (a key bound to a dead project can never\n * succeed again) — clearing lets the user re-authorize against a LIVE project.\n * Returns a new token if approval is fast, else throws {@link DeviceAuthPendingError}\n * carrying the activation link (the next tool call resumes into the new project).\n */\n async resetAndReauthorize(): Promise<string> {\n await this.store.clear();\n await this.store.clearPending();\n return this.getAccessToken();\n }\n\n private async doRefresh(): Promise<string | null> {\n const creds = await this.store.read();\n if (!creds?.refreshToken) return null;\n\n let res: Response;\n try {\n res = await this.fetchImpl(`${this.config.deviceBaseUrl}/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: creds.refreshToken }),\n });\n } catch {\n // Network/transport error — transient. Keep the (still-valid, 30-day)\n // refresh token so a later call can retry instead of forcing a re-auth.\n return null;\n }\n\n if (res.ok) {\n const body = (await res.json()) as TokenSuccess;\n return this.persist(body);\n }\n\n // Clear only on a definitive auth rejection: the OAuth `invalid_grant` signal\n // (the backend's \"this refresh token is dead\", sent as 400 invalid_grant) or a\n // hard 401/403. A bare 400 WITHOUT that signal (request-validation error, or a\n // WAF/infra page with an unparseable body → err={}) is treated as transient —\n // keep the refresh token so a later call can retry instead of forcing re-auth.\n const err = (await res.json().catch(() => ({}))) as { error?: string };\n if (err.error === \"invalid_grant\" || res.status === 401 || res.status === 403) {\n await this.store.clear();\n }\n return null;\n }\n\n private async persist(body: TokenSuccess): Promise<string> {\n const creds: StoredCredentials = {\n accessToken: body.access_token,\n refreshToken: body.refresh_token,\n accessTokenExpiresAt: this.now() + body.expires_in * 1000,\n workspaceId: body.workspace_id,\n projectId: body.project_id,\n };\n await this.store.write(creds);\n return creds.accessToken;\n }\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { BetterCMS } from \"@bettercms-ai/sdk\";\nimport { registerTools } from \"./tools.js\";\nimport { registerPrompts } from \"./prompts.js\";\nimport { PLAYBOOK_URI, SCHEMA_PLAYBOOK } from \"./playbook.js\";\nimport type { DeviceAuthClient } from \"./device-auth.js\";\n\nexport const SERVER_NAME = \"bettercms\";\n// Tracks the shared MCP tool-catalog version (kept in sync with the remote /mcp\n// SERVER_INFO in src/routes/mcp/index.ts) so both surfaces report the same version.\nexport const SERVER_VERSION = \"1.4.0\";\n\n/**\n * Display identity, mirroring the remote host's SERVER_INFO (src/lib/brand.ts). Not\n * imported from it: this package is published to npm and must not depend on backend\n * internals — same deliberate duplication as SERVER_VERSION above, so keep both in sync.\n *\n * The URLs are absolute and hardcoded because a published stdio server has no env to\n * derive an origin from. `title`/`websiteUrl`/`icons` are additive 2025-11-25\n * Implementation fields; older clients ignore them.\n */\nconst SERVER_DISPLAY = {\n title: \"BetterCMS\",\n websiteUrl: \"https://bettercms.ai\",\n icons: [\n { src: \"https://api.bettercms.ai/brand/mark-512.png\", mimeType: \"image/png\", sizes: [\"512x512\"] },\n { src: \"https://api.bettercms.ai/brand/mark.svg\", mimeType: \"image/svg+xml\", sizes: [\"any\"] },\n ],\n};\n\nexport interface BuildServerDeps {\n auth: DeviceAuthClient;\n managementBaseUrl: string;\n}\n\n/**\n * Build the BetterCMS MCP server with its tools registered. Auth is lazy — the\n * device flow runs on the first tool call, not at connect time, so the MCP\n * handshake/tool-listing never blocks on user approval.\n */\nexport function buildServer(deps: BuildServerDeps): McpServer {\n const server = new McpServer(\n { name: SERVER_NAME, version: SERVER_VERSION, ...SERVER_DISPLAY },\n {\n capabilities: { tools: {}, prompts: {}, resources: {} },\n instructions:\n \"BetterCMS never executes a customer's Section renderer or app code. An ordinary MCP connection is not a push runner: explicitly poll list_section_validation_requests, claim one request at an exact git commit, run implementation and responsive checks inside the user's own repository and real app shell, then submit manifest + validation with that requestId and complete it—or truthfully fail it when implementation/evidence is missing. Never invent a manifest, a passing validation, or visual evidence; these tools cannot grant the separate human Visual Approval required for publication.\",\n },\n );\n\n // The playbook is a RESOURCE, not a tool description: it is fetched once by a client\n // that wants it, rather than riding in the prompt on every turn. Mirrors the hosted\n // /mcp PLAYBOOK_RESOURCE (src/routes/mcp/index.ts) — same URI, name and mime, so the\n // `bettercms://playbook/schema` that prompts and tool descriptions point at resolves\n // on stdio too. Without this, `import-site`'s \"read section 11 first\" is a dead link.\n server.registerResource(\n \"schema-playbook\",\n PLAYBOOK_URI,\n {\n title: \"BetterCMS schema & components playbook\",\n description:\n \"How to design a components-first BetterCMS project: components vs collections, section anatomy, sectionType variants, kind:'block' + modular fields, the 'document' article body, the draft->publish order, and what makes an imported site editable.\",\n mimeType: \"text/markdown\",\n },\n () => ({\n contents: [{ uri: PLAYBOOK_URI, mimeType: \"text/markdown\", text: SCHEMA_PLAYBOOK }],\n }),\n );\n\n registerTools(server, {\n auth: deps.auth,\n createClient: (apiKey) =>\n BetterCMS.management({ apiKey, baseUrl: deps.managementBaseUrl }),\n });\n\n // Guided slash-command prompts ship with the server (auto-available as\n // /mcp__bettercms__studio and /mcp__bettercms__new_page when the MCP is added).\n registerPrompts(server);\n\n return server;\n}\n","import { z } from \"zod\";\nimport { SECTION_DOCTRINE as DOCTRINE } from \"@bettercms-ai/types\";\nimport { BetterCMSError } from \"@bettercms-ai/sdk\";\nimport { LAYOUT_SECTION_ICON_SET } from \"@bettercms-ai/types\";\nimport { DeviceAuthPendingError } from \"./device-auth.js\";\nimport type {\n ManagedContentModel,\n ManagedContentEntry,\n ManagedPage,\n ManagedForm,\n ManagedFormInput,\n ManagedComponent,\n ManagedComponentInput,\n ExtractionCandidate,\n CreateModelInput,\n UpdateModelInput,\n CreateEntryInput,\n UpdateEntryInput,\n CreateManagedPageInput,\n UploadAssetInput,\n UploadedAsset,\n WriteContentInput,\n SeoMetaInput,\n SeoMeta,\n} from \"@bettercms-ai/sdk\";\nimport type {\n LayoutDataDocument,\n LayoutStructureDocument,\n ManagementLayoutCommand,\n PageLayoutOverrideDocument,\n} from \"@bettercms-ai/types\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\n/** Subset of the management SDK client the tools use (kept narrow for testability). */\nexport interface ManagementApi {\n listPages(): Promise<ManagedPage[]>;\n getPage(id: string): Promise<ManagedPage>;\n getModel(id: string): Promise<ManagedContentModel>;\n createModel(input: CreateModelInput): Promise<ManagedContentModel>;\n updateModel(id: string, input: UpdateModelInput): Promise<ManagedContentModel>;\n createPage(input: CreateManagedPageInput): Promise<ManagedPage>;\n addPageFields(\n id: string,\n input: { addFields: OutField[] },\n ): Promise<ManagedPage>;\n setPageContent(\n id: string,\n input: { data: Record<string, unknown>; status?: \"draft\" | \"published\" },\n ): Promise<ManagedContentEntry>;\n createEntry(input: CreateEntryInput): Promise<ManagedContentEntry>;\n updateEntry(\n id: string,\n input: UpdateEntryInput,\n opts?: { ifMatch?: number },\n ): Promise<ManagedContentEntry>;\n listEntries(filter?: {\n modelId?: string;\n pageId?: string;\n status?: \"draft\" | \"published\";\n }): Promise<ManagedContentEntry[]>;\n getEntry(id: string): Promise<ManagedContentEntry>;\n uploadAsset(input: UploadAssetInput): Promise<UploadedAsset>;\n deletePage(id: string): Promise<{ id: string }>;\n deleteEntry(id: string): Promise<{ id: string }>;\n deleteModel(id: string): Promise<{ id: string }>;\n listForms(): Promise<ManagedForm[]>;\n getForm(id: string): Promise<ManagedForm>;\n createForm(input: ManagedFormInput): Promise<ManagedForm>;\n updateForm(id: string, input: ManagedFormInput): Promise<ManagedForm>;\n listComponents(): Promise<ManagedComponent[]>;\n getComponent(id: string): Promise<ManagedComponent>;\n createComponent(input: ManagedComponentInput): Promise<ManagedComponent>;\n updateComponent(id: string, input: ManagedComponentInput): Promise<ManagedComponent>;\n listExtractionCandidates(projectId?: string): Promise<ExtractionCandidate[]>;\n extractComponent(input: {\n hash: string;\n name: string;\n slug: string;\n projectId?: string;\n }): Promise<{ component: ManagedComponent; replaced: number }>;\n getManagedLayout(opts?: { scope?: \"global\" | \"page\"; pageId?: string; copy?: \"draft\" | \"published\"; projectId?: string }): Promise<ManagedLayoutDocument>;\n commandManagedLayout(input: { scope?: \"global\" | \"page\"; pageId?: string; projectId?: string; command: ManagementLayoutCommand; ifMatch: number }): Promise<ManagedLayoutDocument>;\n writeContent(input: WriteContentInput): Promise<string>;\n generateSeoMeta(input: SeoMetaInput): Promise<SeoMeta>;\n // Generic escape hatch for the lifecycle tools (media mgmt, submissions, redirects,\n // SEO, site-files, promote, versions). These management endpoints have no bespoke SDK\n // method; the MCP tools call them straight through the client's public request plumbing,\n // so parity with the remote /mcp surface needs no per-endpoint SDK code (DRY).\n url(path: string): string;\n fetchJSON<T>(url: string, init?: RequestInit): Promise<T>;\n}\n\ntype ManagedLayoutDocument =\n | { scope: \"global\"; revision: number; etag: string; status: string; structure: LayoutStructureDocument; data: LayoutDataDocument }\n | { scope: \"page\"; pageId: string; pageSlug: string; revision: number; etag: string; status: string; globalStructure: LayoutStructureDocument; globalData: LayoutDataDocument; override: PageLayoutOverrideDocument };\n\nexport interface ToolDeps {\n auth: {\n getAccessToken(): Promise<string>;\n refresh(): Promise<string | null>;\n /** Forget cached creds + re-run device flow (used when the bound project was deleted). */\n resetAndReauthorize(): Promise<string>;\n };\n /** Build a management client bound to the given access token. */\n createClient: (apiKey: string) => ManagementApi;\n /**\n * Ask the HUMAN a question mid-tool-call (MCP elicitation). Optional because plenty of\n * clients don't implement it — every caller must degrade to telling the model to ask in\n * chat instead. Wired from the McpServer in registerTools.\n */\n elicit?: (params: {\n message: string;\n requestedSchema: { type: \"object\"; properties: Record<string, unknown>; required?: string[] };\n }) => Promise<{ action: string; content?: Record<string, unknown> }>;\n}\n\n// ── The framework question ────────────────────────────────────────────────────\n// Mirrors src/lib/projects/framework-choice.ts in the backend. Deliberately duplicated\n// rather than imported: this package is published to npm and must not depend on backend\n// internals (same reasoning as SERVER_VERSION in server.ts). Keep the two in sync.\n\n/** The one sentence every page-building surface states. Shared so the surfaces cannot drift apart. */\nexport { SECTION_DOCTRINE } from \"@bettercms-ai/types\";\n\nexport const FRAMEWORK_CHOICES = [\"astro\", \"next\", \"react-ts\", \"other\"] as const;\n\nconst FRAMEWORK_LABELS: Record<(typeof FRAMEWORK_CHOICES)[number], string> = {\n astro: \"Astro — recommended default, static by default and fastest to publish\",\n next: \"Next.js\",\n \"react-ts\": \"React + TypeScript (Vite, prerendered)\",\n other: \"Other — headless project: content and API only, bring your own frontend\",\n};\n\n/** What the model must read out when it cannot ask the user through the client UI. */\nexport const FRAMEWORK_PROMPT = [\n \"Ask the user which technology this site should be built with, then call create_project again with their answer as `framework`:\",\n ...FRAMEWORK_CHOICES.map((c, i) => ` ${i + 1}. ${c} — ${FRAMEWORK_LABELS[c]}`),\n \"\",\n \"Do not choose on their behalf. Sites cannot be built as plain HTML/CSS — every project is backed by one of these starters, which is what keeps its content editable in the CMS.\",\n].join(\"\\n\");\n\n/**\n * Resolve `framework` by ASKING, never by defaulting.\n *\n * Prefers a real client-side prompt (elicitation) so the human picks from a list instead of\n * the model inventing an answer. When the client can't elicit — or the person dismisses the\n * prompt — we return the question as text for the model to put in chat. Either way the one\n * outcome that never happens is a silent default, which is the whole point: a guessed\n * framework means a forked starter and seeded content pointing at the wrong stack, and\n * nobody notices until the site is half-built.\n */\nasync function askFramework(\n deps: ToolDeps,\n): Promise<{ framework: string } | { prompt: string }> {\n if (!deps.elicit) return { prompt: FRAMEWORK_PROMPT };\n try {\n const res = await deps.elicit({\n message: \"Which technology should this site be built with?\",\n requestedSchema: {\n type: \"object\",\n properties: {\n framework: {\n type: \"string\",\n title: \"Technology\",\n description: \"The frontend stack this project's starter is based on.\",\n enum: [...FRAMEWORK_CHOICES],\n enumNames: FRAMEWORK_CHOICES.map((c) => FRAMEWORK_LABELS[c]),\n },\n },\n required: [\"framework\"],\n },\n });\n const picked = res.action === \"accept\" ? res.content?.framework : undefined;\n if (typeof picked === \"string\" && (FRAMEWORK_CHOICES as readonly string[]).includes(picked)) {\n return { framework: picked };\n }\n } catch {\n // Client advertised elicitation but couldn't serve it. Fall through to asking in chat.\n }\n return { prompt: FRAMEWORK_PROMPT };\n}\n\n// ── The authoring-architecture question ───────────────────────────────────────\n// Mirrors src/lib/projects/authoring-choice.ts in the backend, duplicated for the same\n// reason as the framework question above: this package ships to npm and must not import\n// backend internals. Keep the two in sync.\n//\n// The backend is where the ENFORCEMENT lives — deploy/promote answer 409\n// AUTHORING_DECISION_REQUIRED until this is set — and its refusal quotes the project's real\n// page counts, which this surface has no way to know at ask time. So the prompt here is the\n// generic question; the grounded one arrives in the 409.\n\nexport const AUTHORING_CHOICES = [\"components\", \"fields\"] as const;\n\nconst AUTHORING_LABELS: Record<(typeof AUTHORING_CHOICES)[number], string> = {\n components:\n \"Components — reusable section components placed as blocks; editors add, reorder and swap sections without touching a schema. Best for marketing and landing sites\",\n fields:\n \"Fields — a typed field schema per page. Best for blogs, catalogues and directories, where many rows share one shape\",\n};\n\n/** What the model must read out when it cannot ask the user through the client UI. */\nexport const AUTHORING_PROMPT = [\n \"Ask the user which authoring architecture this site should use, then call set_authoring_preference again with their answer as `preference`:\",\n ...AUTHORING_CHOICES.map((c, i) => ` ${i + 1}. ${c} — ${AUTHORING_LABELS[c]}`),\n \"\",\n \"Answering 'components' does not convert anything — there is no field-to-block converter. It means you author the sections yourself: create_component, then publish_component (an unpublished component renders as NOTHING on the live site), then set_page_content placing `component` blocks. Once a page has blocks, list_extraction_candidates and extract_component fold the repeats.\",\n \"\",\n \"Do not choose on their behalf. This is asked once per project.\",\n].join(\"\\n\");\n\n/** Resolve `preference` by ASKING, never by defaulting. Same shape as askFramework. */\nasync function askAuthoring(\n deps: ToolDeps,\n): Promise<{ preference: string } | { prompt: string }> {\n if (!deps.elicit) return { prompt: AUTHORING_PROMPT };\n try {\n const res = await deps.elicit({\n message: \"Which authoring architecture should this site use?\",\n requestedSchema: {\n type: \"object\",\n properties: {\n preference: {\n type: \"string\",\n title: \"Authoring architecture\",\n description: \"How this site's pages are composed. Asked once per project.\",\n enum: [...AUTHORING_CHOICES],\n enumNames: AUTHORING_CHOICES.map((c) => AUTHORING_LABELS[c]),\n },\n },\n required: [\"preference\"],\n },\n });\n const picked = res.action === \"accept\" ? res.content?.preference : undefined;\n if (typeof picked === \"string\" && (AUTHORING_CHOICES as readonly string[]).includes(picked)) {\n return { preference: picked };\n }\n } catch {\n // Client advertised elicitation but couldn't serve it. Fall through to asking in chat.\n }\n return { prompt: AUTHORING_PROMPT };\n}\n\n/** MCP tool result shape (text content + optional error flag). */\nexport interface ToolResult {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}\n\nexport interface ToolDef {\n name: string;\n config: { title: string; description: string; inputSchema: z.ZodRawShape };\n handler: (args: Record<string, unknown>) => Promise<ToolResult>;\n}\n\n// ── Shared schema pieces ──────────────────────────────────────────────────────\n\nconst fieldType = z.enum([\n \"text\",\n \"richtext\",\n \"image\",\n \"boolean\",\n \"number\",\n \"select\",\n \"reference\",\n \"multi-reference\",\n \"array\",\n \"date\",\n \"datetime\",\n \"group\", // Non-Repeatable Zone: one nested object of fields\n \"repeater\", // Repeatable Zone: an array of nested field-objects\n // A slot holding one component instance. This enum is a SECOND, narrower copy of the\n // field-type union, and `toField`/`OutField` below strip anything not modelled here —\n // which is why showIf/helpText/searchable/placement are all unreachable from MCP today.\n // Adding the type here without also carrying its `config` through `toField` would let an\n // agent create the field and silently lose its component allowlist.\n \"component-ref\",\n // Migration 0188. Both are LEAF types, so `toField`'s pass-through branch carries their\n // `config` verbatim — which is what the warning above demands before adding a type here.\n // `modular` needs config.blockSlugs; `location` takes no config.\n \"modular\",\n \"location\",\n // All LEAF types, so the pass-through branch above covers them. `document` is THE article\n // body — the rich document canvas, collections only, at most one per model, top level\n // only. It was the conspicuous omission: the dashboard shipped an editor for it while no\n // agent could create the field. `sections` is a page-section zone composed in the Visual\n // Editor, so it has no inline control.\n \"document\",\n \"longtext\",\n \"slug\",\n \"email\",\n \"phone\",\n \"link\",\n \"color\",\n \"json\",\n \"file\",\n \"sections\",\n]);\n\nconst slug = z\n .string()\n .regex(/^[a-z0-9-]+$/, \"lowercase letters, numbers, and hyphens only\");\n\nconst fieldKey = z\n .string()\n .regex(/^[a-zA-Z0-9_]+$/, \"letters, numbers, and underscores only\");\n\n// Recursive field schema. The MCP SDK serialises this Zod shape to the JSON\n// Schema the LLM sees — on SDK >= 1.29 (the floor pinned in package.json) the\n// `z.lazy()` below emits a proper `$ref`/`$defs` recursion so nested\n// group/repeater fields are VISIBLE. A stale older SDK collapsed it to an\n// opaque {} (the historic \"nested fields not created\" bug). The same recursive\n// shape is hand-written as JSON Schema in the remote proxy — keep the two in\n// sync: see bettercms-backend/src/routes/mcp/index.ts (FIELD_DEF).\n/** A field definition. Recursive: `group`/`repeater` nest more fields. */\nexport type FieldInput = {\n key: string;\n label: string;\n type: z.infer<typeof fieldType>;\n required?: boolean;\n /** Opt OUT of the rich-text default for a non-prose string (href, slug, id). */\n richText?: boolean;\n options?: string[];\n config?: Record<string, unknown>;\n fields?: FieldInput[];\n};\n\nconst fieldShape = {\n key: fieldKey.describe(\n \"machine field key. 🔴 UNIQUE ACROSS THE WHOLE MODEL — API IDs share ONE FLAT NAMESPACE, so a field nested inside a group must NOT reuse a key used by another field or group. Every section's heading cannot be 'title'. Prefix with the section: 'hero_title', 'pricing_title', 'faq_title'. Reusing a key is refused, and if it slips through it leaves permanent errors in the editor and breaks conditional-visibility rules, which reference fields by bare key.\",\n ),\n label: z.string().min(1).describe(\"human label shown in the editor\"),\n type: fieldType,\n required: z.boolean().optional(),\n richText: z\n .boolean()\n .optional()\n .describe(\n \"prose formatting. DEFAULTS TO TRUE for 'text': the field is created as rich text so editors can bold, link and format it on the canvas, and the API returns rich text (render with rich() from @bettercms-ai/sdk; plain() for titles and meta). Pass false for a value that is NOT prose and must stay a bare string — a URL/href, a slug, an id, an email, a phone number, a CSS class, an icon name. A link stored as rich text will not work as an href.\",\n ),\n options: z.array(z.string()).optional().describe(\"choices when type is 'select'\"),\n config: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"per-type config: reference {contentModelId}, multi-reference {contentModelId,min,max}, array {itemType: 'text'|'number'|'date'}, date {includeTime}, modular {blockSlugs: ['quote','gallery'], minItems?, maxItems?} — blockSlugs is REQUIRED, non-empty, and each slug must name an existing kind:'block' model\",\n ),\n fields: z\n .array(z.lazy(() => fieldObject))\n .optional()\n .describe(\n \"NESTED child fields — REQUIRED for type 'group' (one nested object, a Non-Repeatable Zone like blog_hero → heading, description, hero_image) and type 'repeater' (a repeatable array of such objects, a Repeatable Zone / section-list like testimonials → quote, author). A section with repeating items is a 'repeater'; a fixed grouped block is a 'group'. Recurse to any depth — do NOT flatten zones into separate top-level fields.\",\n ),\n};\nconst fieldObject: z.ZodType<FieldInput> = z.object(fieldShape);\n\n/**\n * Output field shape persisted by the API. Canonical: nesting lives on `array` via\n * `config.zones`. The LLM may still speak `group`/`repeater` (kept in the input schema\n * because it's intuitive) — toField() maps those into the canonical array.zones shape\n * here, so the backend, dashboard, codegen, and delivery all see one model.\n */\ntype OutField = {\n key: string;\n label: string;\n type: Exclude<FieldInput[\"type\"], \"group\" | \"repeater\">;\n required?: boolean;\n options?: string[];\n config?: Record<string, unknown>;\n};\n\n\n/**\n * API IDs share ONE FLAT NAMESPACE across a model — a field inside a group must not reuse a key\n * used by any other field or group. Checked here, before the write, because the failure it\n * prevents is silent: the schema saves, and the author is left with permanent red error rows in\n * the builder plus `showIf` rules that reference a bare key and therefore cannot resolve.\n *\n * This is the shape `create_page` produces by default — its own description tells the agent to\n * build a nested tree where every visual section becomes a group, and the natural key for each\n * section's heading is `title`. The marketing page came out with `title` and `subtitle` in three\n * groups. The rule was never written down anywhere the model could read it, so this is both a\n * guard and the place it gets taught.\n *\n * Depth is ONE LEVEL, matching the dashboard's own `walk` — checking deeper here would refuse\n * schemas the builder renders as clean.\n *\n * Reads BOTH dialects: `fields` (what an agent sends) and `config.zones` (what the API returns).\n */\nfunction flatFieldKeys(fields: unknown): string[] {\n const out: string[] = [];\n const childrenOf = (f: Record<string, unknown>): unknown[] => {\n const zones = (f.config as { zones?: { nonRepeatable?: unknown[]; repeatable?: { fields?: unknown[] } } } | undefined)?.zones;\n if (zones?.nonRepeatable) return zones.nonRepeatable;\n if (zones?.repeatable?.fields) return zones.repeatable.fields;\n return (f.fields as unknown[]) ?? [];\n };\n for (const raw of (Array.isArray(fields) ? fields : [])) {\n const f = raw as Record<string, unknown>;\n if (typeof f?.key === \"string\" && f.key.trim()) out.push(f.key.trim());\n for (const raw2 of childrenOf(f)) {\n const c = raw2 as Record<string, unknown>;\n if (typeof c?.key === \"string\" && c.key.trim()) out.push(c.key.trim());\n }\n }\n return out;\n}\n\n/** Keys used more than once, first-seen order. */\nfunction duplicateKeys(keys: string[]): string[] {\n const seen = new Map<string, number>();\n for (const k of keys) seen.set(k, (seen.get(k) ?? 0) + 1);\n return [...new Set(keys)].filter((k) => (seen.get(k) ?? 0) > 1);\n}\n\n/** The refusal an AGENT has to be able to act on — names the keys, the rule, the remediation. */\nfunction duplicateKeyFailure(dupes: string[]): string {\n return (\n `Duplicate API ID${dupes.length === 1 ? \"\" : \"s\"}: ${dupes.map((k) => `'${k}'`).join(\", \")}. ` +\n `API IDs share ONE flat namespace across the whole model — a field inside a group must not ` +\n `reuse a key used by another field or group. Prefix each key with its section and retry ` +\n `(e.g. 'hero_title' and 'pricing_title', never 'title' in both).`\n );\n}\n\nfunction toFields(fs: FieldInput[] | undefined): OutField[] {\n return (fs ?? []).map(toField);\n}\n\n/**\n * Prose fields are RICH TEXT unless the caller opts out.\n *\n * The default is inverted from what the type name suggests, deliberately: an agent asked for a\n * headline says `type: 'text'` because that is the word for it, and the author then finds a\n * heading they cannot bold or link on the canvas — the toolbar's marks render disabled with\n * \"enable rich text formatting to use this\", and the only route out is a schema edit.\n *\n * 🔴 The opt-out is NOT cosmetic. A richtext field's API value is an ENVELOPE, not a string, so\n * an href, slug, id, email or class name created as rich text is broken the moment a template\n * interpolates it — that is the shape that renders \"[object Object]\". `richText: false` is the\n * required answer for every non-prose string, and the input schema says so.\n */\nfunction proseType(f: FieldInput): FieldInput[\"type\"] {\n // `text` is the only prose leaf this enum carries — `longtext` is not in it, so there is\n // nothing else to widen to. Stated because \"why only text?\" is the obvious next question.\n if (f.type !== \"text\") return f.type;\n return f.richText === false ? \"text\" : \"richtext\";\n}\n\nfunction toField(f: FieldInput): OutField {\n const base = {\n key: f.key,\n label: f.label,\n ...(f.required !== undefined ? { required: f.required } : {}),\n };\n\n // group → array with a non-repeatable zone (a fixed block).\n if (f.type === \"group\") {\n return { ...base, type: \"array\", config: { zones: { nonRepeatable: toFields(f.fields) } } };\n }\n // repeater → array with a repeatable zone (a list of blocks).\n if (f.type === \"repeater\") {\n return { ...base, type: \"array\", config: { zones: { repeatable: { fields: toFields(f.fields) } } } };\n }\n // Already-canonical zoned array (the LLM emitted config.zones directly) → recurse.\n if (f.type === \"array\" && f.config && typeof f.config === \"object\" && \"zones\" in f.config) {\n const zones = (f.config as { zones?: { nonRepeatable?: FieldInput[]; repeatable?: { fields?: FieldInput[]; minItems?: number; maxItems?: number } } }).zones ?? {};\n return {\n ...base,\n type: \"array\",\n config: {\n zones: {\n ...(zones.nonRepeatable ? { nonRepeatable: toFields(zones.nonRepeatable) } : {}),\n ...(zones.repeatable\n ? {\n repeatable: {\n fields: toFields(zones.repeatable.fields),\n ...(zones.repeatable.minItems !== undefined ? { minItems: zones.repeatable.minItems } : {}),\n ...(zones.repeatable.maxItems !== undefined ? { maxItems: zones.repeatable.maxItems } : {}),\n },\n }\n : {}),\n },\n },\n };\n }\n\n // Leaf field or primitive array (config.itemType) — pass through, with the prose default\n // applied here so EVERY field-creating tool (create_page, create_content_model, add_field,\n // add_page_field) inherits it from one place rather than four that can drift.\n return {\n ...base,\n type: proseType(f) as OutField[\"type\"],\n ...(f.options ? { options: f.options } : {}),\n ...(f.config ? { config: f.config } : {}),\n };\n}\n\n// ── Result helpers ────────────────────────────────────────────────────────────\n\nfunction ok(summary: string, data: unknown): ToolResult {\n return {\n content: [\n { type: \"text\", text: summary },\n { type: \"text\", text: JSON.stringify(data, null, 2) },\n ],\n };\n}\n\nfunction fail(message: string): ToolResult {\n return { content: [{ type: \"text\", text: message }], isError: true };\n}\n\n/**\n * Authorization isn't done yet. Surface the clickable activation link *in the\n * tool result* (the one channel every MCP client renders — unlike the server's\n * stderr, which VS Code hides). The device flow is persisted, so simply\n * re-running this tool after approval resumes it and completes the request.\n */\nfunction authPrompt(err: DeviceAuthPendingError): ToolResult {\n const text = [\n \"🔐 BetterCMS authorization required — you're not signed in yet.\",\n \"\",\n `1. Open this link and approve: ${err.verificationUriComplete}`,\n ` (or visit ${err.verificationUri} and enter code ${err.userCode})`,\n \"2. Once approved, run this tool again — it resumes automatically and completes your request.\",\n ].join(\"\\n\");\n return { content: [{ type: \"text\", text }], isError: true };\n}\n\n// ── Tool definitions ──────────────────────────────────────────────────────────\n\nexport function buildToolDefs(deps: ToolDeps): ToolDef[] {\n /** Run with a token, retrying once on 401 after a refresh / re-auth. */\n async function withClient<T>(fn: (client: ManagementApi) => Promise<T>): Promise<T> {\n const token = await deps.auth.getAccessToken();\n try {\n return await fn(deps.createClient(token));\n } catch (err) {\n if (err instanceof BetterCMSError && err.status === 401) {\n const next = (await deps.auth.refresh()) ?? (await deps.auth.getAccessToken());\n return await fn(deps.createClient(next));\n }\n // The key is bound to a project that was deleted server-side (L1: 409\n // PROJECT_DELETED). It can never succeed again — clear creds and re-authorize\n // so the user picks a LIVE project, then retry the original call into it.\n // (resetAndReauthorize throws DeviceAuthPendingError if approval isn't instant,\n // which guard() turns into the clickable activation prompt.)\n if (err instanceof BetterCMSError && err.status === 409 && err.bodyCode === \"PROJECT_DELETED\") {\n const next = await deps.auth.resetAndReauthorize();\n return await fn(deps.createClient(next));\n }\n throw err;\n }\n }\n\n /** Wrap a handler with uniform error → ToolResult conversion. */\n function guard<A>(fn: (args: A) => Promise<ToolResult>) {\n return async (args: A): Promise<ToolResult> => {\n try {\n return await fn(args);\n } catch (err) {\n if (err instanceof DeviceAuthPendingError) {\n return authPrompt(err);\n }\n if (err instanceof BetterCMSError) {\n return fail(`BetterCMS error (${err.status} ${err.code}): ${err.message}`);\n }\n return fail(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);\n }\n };\n }\n\n // ── Component authoring schemas ──\n // blockJson is a recursive ContentBlock tree; props is the override allowlist. The\n // backend validates the exact block union, so blocks are typed loosely here.\n // Declared BEFORE createPageInput/createComponentInput — both reference it.\n interface BlockInput { type: string; id: string; props: Record<string, unknown>; style?: Record<string, unknown> }\n const blockObject: z.ZodType<BlockInput> = z.object({\n type: z\n .enum([\n \"heading\", \"text\", \"richtext\", \"image\", \"button\", \"spacer\", \"video\",\n \"columns\", \"section\", \"slider\", \"tabs\", \"navbar\", \"footer\", \"form\", \"component\",\n \"collection\",\n ])\n .describe(\"block type; section/slider/tabs/columns nest child blocks\"),\n id: z.string().min(1).describe(\"stable unique block id\"),\n props: z\n .record(z.string(), z.unknown())\n .describe(\n \"per-type props: heading {text, level}; text/richtext {html} (NOT {text}); image {src, alt}; button {text, href}; spacer {height}; video {url}; form {formId}; component {componentId, overrides?}; navbar {links:[{label,href}], logo?, cta?}; footer {columns, copyright?}; section {children: block[]}; columns {columns: block[][], gap} — a column may NOT hold columns/section/slider/tabs; slider {slides:[{id,children}]}; tabs {tabs:[{id,label,children}]}; collection {cardComponentId?, detailComponentId?, titleField?, excerptField?, limit?, order?, emptyText?} — lists this page's published entries as cards, and renders ONE entry on /<page>/<entrySlug>\",\n ),\n style: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"design tokens: theme, bg (none|surface|muted|accent|dark|custom), bgCustom hex, paddingTop/paddingBottom/paddingSides px, contentWidth (narrow|default|wide|full), align, corner, shadow, borderTop/borderBottom. A real marketing band is a `section` block carrying bg + padding + contentWidth.\",\n ),\n });\n\n const createPageInput = z.object({\n title: z.string().min(1).describe(\"display title of the page, e.g. 'Home'\"),\n slug: slug.describe(\"URL-safe path segment, unique per project, e.g. 'home'\"),\n pageType: z\n .enum([\"singleton\", \"dynamic\"])\n .default(\"singleton\")\n .describe(\n \"'singleton' = exactly one entry (Home, About, Contact); 'dynamic' = many entries sharing this schema (Blog posts, Products). Defaults to singleton.\",\n ),\n blockJson: z\n .array(blockObject)\n .optional()\n .describe(\n \"the page's VISUAL composition — how a components-first page is built. Place one `component` block per section: {type:'component', id:'<stable>', props:{componentId:'<id from create_component>'}}. The component must be PUBLISHED (publish_component) or it renders as nothing on the live site. Independent of `fields`, which is a typed schema for a site's own code to read.\",\n ),\n fields: z.array(fieldObject).optional().describe(\"the page's typed schema fields\"),\n metaTitle: z.string().optional().describe(\"SEO meta title\"),\n metaDescription: z.string().optional().describe(\"SEO meta description\"),\n });\n\n const writeContentInput = z.object({\n action: z\n .enum([\"write\", \"rewrite\", \"translate\"])\n .describe(\"'write' = draft from a brief, 'rewrite' = improve existing copy, 'translate' = needs targetLang\"),\n text: z.string().min(1).describe(\"the source text (a brief for 'write', the copy to change otherwise)\"),\n instructions: z.string().optional().describe(\"optional extra guidance, e.g. 'make it punchier'\"),\n targetLang: z.string().optional().describe(\"required for 'translate', e.g. 'Spanish'\"),\n context: z.string().optional().describe(\"optional surrounding context, e.g. the page title\"),\n });\n\n const generateSeoMetaInput = z.object({\n text: z.string().min(1).describe(\"the content to derive SEO metadata from\"),\n context: z.string().optional().describe(\"optional surrounding context, e.g. the page slug\"),\n });\n\n const createModelInput = z.object({\n name: z.string().min(1).describe(\"human model name, e.g. 'Blog Post'\"),\n slug: slug.describe(\"url-safe unique slug, e.g. 'blog-post'\"),\n description: z.string().optional(),\n kind: z\n .enum([\"model\", \"block\"])\n .optional()\n .describe(\n \"'model' (default) = a collection with its own entries. 'block' = a type that exists only to be stacked inside another model's 'modular' field — 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.\",\n ),\n fields: z\n .array(fieldObject)\n .optional()\n .describe(\n \"the model's typed schema fields. 'group'/'repeater' NEST their child fields (any depth) — don't flatten zones into top-level fields.\",\n ),\n });\n\n const addFieldInput = z.object({\n modelId: z.string().min(1).describe(\"id of the content model to extend\"),\n ...fieldShape,\n });\n\n const addPageFieldInput = z.object({\n pageId: z.string().min(1).describe(\"id of the page to extend (from list_pages / create_page)\"),\n ...fieldShape,\n });\n\n // Exactly one of localPath/url (enforced by the SDK + backend route, documented here).\n const uploadAssetInput = z.object({\n localPath: z\n .string()\n .min(1)\n .optional()\n .describe(\"absolute path to a local file (e.g. a repo image); provide this OR url\"),\n url: z\n .string()\n .url()\n .optional()\n .describe(\"remote image URL to ingest; provide this OR localPath\"),\n filename: z.string().optional().describe(\"override the stored filename\"),\n altText: z.string().optional().describe(\"accessibility alt text\"),\n caption: z.string().optional(),\n folderId: z.string().optional().describe(\"target Media Library folder (defaults to project root)\"),\n });\n\n const createEntryInput = z.object({\n contentModelId: z.string().min(1).describe(\"id of the model this entry belongs to\"),\n slug: slug.optional(),\n status: z.enum([\"draft\", \"published\"]).optional().describe(\"defaults to draft\"),\n data: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\"field values keyed by field key\"),\n });\n\n const getPageInput = z.object({\n pageId: z.string().min(1).describe(\"page id (from list_pages / create_page)\"),\n });\n\n const setPageContentInput = z.object({\n pageId: z.string().min(1).describe(\"id of the page to write values to\"),\n data: z\n .record(z.string(), z.unknown())\n .describe(\n \"field values keyed by field key. A nested 'array' (zone) value is an OBJECT { nonRepeatable: { childKey: value, … }, repeatable: [ { childKey: value }, … ] } — nonRepeatable holds the fixed-block values, repeatable is the list of item objects (omit a zone you didn't define). A primitive 'array' (itemType) is a plain list. An 'image' value is an asset URL or asset id (from upload_asset) — the server resolves it to { id, url, name, altText }. Read get_page first to see each field's zones.\",\n ),\n status: z.enum([\"draft\", \"published\"]).optional().describe(\"omit to leave status unchanged\"),\n });\n\n const getEntryInput = z.object({\n entryId: z.string().min(1).describe(\"content entry id\"),\n });\n\n const listEntriesInput = z.object({\n modelId: z.string().optional().describe(\"filter by content model id\"),\n pageId: z.string().optional().describe(\"filter by page id (a singleton page has one entry)\"),\n status: z.enum([\"draft\", \"published\"]).optional(),\n });\n\n const updateEntryInput = z.object({\n entryId: z.string().min(1).describe(\"content entry id\"),\n data: z.record(z.string(), z.unknown()).optional().describe(\"field values keyed by field key\"),\n status: z.enum([\"draft\", \"published\"]).optional(),\n slug: slug.optional(),\n });\n\n const deletePageInput = z.object({\n pageId: z.string().min(1).describe(\"id of the page to delete (from list_pages)\"),\n });\n const deleteEntryInput = z.object({\n entryId: z.string().min(1).describe(\"id of the content entry to delete (from list_content_entries)\"),\n });\n const deleteModelInput = z.object({\n modelId: z.string().min(1).describe(\"id of the content model to delete (from list_content_models)\"),\n });\n\n const getFormInput = z.object({\n formId: z.string().min(1).describe(\"form id (from list_forms)\"),\n });\n\n // ── Form authoring schemas ──\n // MUST stay at parity with the server's field vocabulary (packages/db FormField + the\n // route's Zod). `update_form` REPLACES the whole `fields` array, so a type this schema\n // omits cannot be echoed back: an agent that reads a form and writes it back DESTROYS\n // every human-authored field of that type. `radio`/`checkboxes` were exactly that gap.\n // Guarded by src/__tests__/mcp/mcp-parity.test.ts.\n const formFieldObject = z.object({\n key: z.string().min(1).describe(\"machine key for the submitted value, e.g. 'email'\"),\n label: z.string().min(1).describe(\"field label shown to the visitor\"),\n type: z.enum([\n \"text\", \"email\", \"textarea\", \"select\",\n \"checkbox\", // single boolean; predates `checkboxes`\n \"checkboxes\", // pick-many, value is a string[] of chosen option labels\n \"radio\", // pick-one, rendered inline rather than in a dropdown\n \"number\", \"phone\", \"date\", \"url\", \"consent\", \"hidden\",\n ]),\n placeholder: z.string().optional(),\n helpText: z.string().optional().describe(\"hint shown under the control, muted\"),\n required: z.boolean().optional(),\n options: z.array(z.string()).optional().describe(\"choices when type is 'select', 'radio' or 'checkboxes'\"),\n hidden: z.boolean().optional().describe(\"not rendered; pairs with defaultValue to capture context\"),\n defaultValue: z.string().optional(),\n showIf: z\n .object({ field: z.string(), equals: z.string() })\n .optional()\n .describe(\"show this field only when another field equals a value\"),\n validation: z\n .object({\n emailPolicy: z.enum([\"any\", \"business\"]).optional().describe(\"'email' fields only\"),\n min: z.number().optional().describe(\"'number' fields only — inclusive floor\"),\n max: z.number().optional().describe(\"'number' fields only — inclusive ceiling\"),\n phoneFormat: z.enum([\"any\", \"e164\"]).optional().describe(\"'phone' fields only\"),\n pattern: z.string().optional().describe(\"'text' / 'textarea' / 'url' fields only — a regex\"),\n })\n .optional()\n .describe(\"per-field rules the API enforces on submit; each key is only valid on the field types listed\"),\n });\n const formSettingsShape = {\n description: z.string().optional(),\n submitLabel: z.string().optional().describe(\"submit button label (default 'Submit')\"),\n successMessage: z.string().optional(),\n redirectUrl: z.string().url().optional().describe(\"URL to redirect to on success\"),\n };\n const createFormInput = z.object({\n name: z.string().min(1).describe(\"human form name (used by getForm('Name'))\"),\n fields: z.array(formFieldObject).default([]).describe(\"the form's fields\"),\n ...formSettingsShape,\n });\n const updateFormInput = z.object({\n formId: z.string().min(1).describe(\"form id (from list_forms)\"),\n name: z.string().optional(),\n fields: z.array(formFieldObject).optional().describe(\"REPLACES the field array — include all fields to keep\"),\n ...formSettingsShape,\n });\n\n const componentPropObject = z.object({\n key: z.string().min(1),\n label: z.string().min(1),\n target: z.object({ blockId: z.string().min(1), path: z.string().min(1) }),\n // MUST stay at parity with componentPropDefSchema on the server. `update_component`\n // REPLACES the whole `props` array, so a type this enum omits cannot be echoed back: an\n // agent that reads a component and writes it back DESTROYS every prop of that type.\n type: z.enum([\"text\", \"richtext\", \"image\", \"url\", \"boolean\", \"number\", \"select\", \"group\", \"table\", \"slot\"]),\n // 'slot' holds ONE nested component instance; config.componentIds restricts what may\n // fill it. Absent here until now, so a slot allowlist was unreachable from stdio even\n // once the enum allowed the type.\n config: z\n .object({\n componentIds: z.array(z.string()).optional(), // 'slot' allowlist\n options: z.array(z.string()).optional(), // 'select' — required, choices\n // 'group'/'table' sub-shape. Typed loosely here (the server validates the full\n // recursive shape) so a 3-level tree does not need a 3-level Zod mirror in the client.\n fields: z.array(z.record(z.string(), z.unknown())).optional(),\n min: z.number().optional(), // 'number'\n max: z.number().optional(),\n step: z.number().optional(),\n })\n .passthrough()\n .optional(),\n defaultValue: z.unknown().optional(),\n });\n const getLayoutInput = z.object({\n scope: z.enum([\"global\", \"page\"]).default(\"global\"),\n pageId: z.string().min(1).optional().describe(\"page id or slug; required for page scope\"),\n copy: z.enum([\"draft\", \"published\"]).optional().describe(\"which copy to read; default draft. Verifying a publish MUST read copy:'published' and check the response's copy echo — the draft is never a publish receipt (FLO-1188).\"),\n projectId: z.string().min(1).optional().describe(\"required only for a workspace-scoped grant\"),\n });\n const layoutBinding = z.object({ inputId: z.string().min(1), fieldId: z.string().min(1) });\n const layoutIcon = z.string().min(1).max(80)\n .regex(/^(?:[a-z0-9]+(?:-[a-z0-9]+)*|[A-Z][A-Za-z0-9]+)$/)\n .refine((value) => LAYOUT_SECTION_ICON_SET.has(value), \"Select a supported Lucide icon\")\n .describe(\"Lucide icon name in canonical kebab-case; legacy CamelCase Layout icon names remain accepted\");\n const sectionTarget = { sectionId: z.string().min(1) };\n const layoutCommand = z.discriminatedUnion(\"type\", [\n z.object({ type: z.literal(\"set-section-values\"), ...sectionTarget, values: z.record(z.string(), z.unknown()) }),\n z.object({ type: z.literal(\"set-field-value\"), ...sectionTarget, fieldId: z.string().min(1), value: z.unknown() }),\n z.object({ type: z.literal(\"add-component\"), ...sectionTarget, componentId: z.string().min(1), variantGroupId: z.string().min(1).optional(), bindings: z.array(layoutBinding).optional(), literalValues: z.record(z.string(), z.unknown()).optional() }),\n z.object({ type: z.literal(\"remove-item\"), ...sectionTarget, itemId: z.string().min(1) }),\n z.object({ type: z.literal(\"move-component\"), ...sectionTarget, itemId: z.string().min(1), index: z.number().int().nonnegative() }),\n z.object({ type: z.literal(\"move-item\"), ...sectionTarget, itemId: z.string().min(1), index: z.number().int().nonnegative() }),\n z.object({ type: z.literal(\"swap-component-variant\"), ...sectionTarget, itemId: z.string().min(1), componentId: z.string().min(1) }),\n z.object({ type: z.literal(\"set-page-state\"), ...sectionTarget, state: z.enum([\"inherit\", \"override-content\", \"customize-structure\", \"disable\", \"reset\"]) }),\n z.object({ type: z.literal(\"set-section-state\"), ...sectionTarget, state: z.enum([\"inherit\", \"override-content\", \"customize-structure\", \"disable\", \"reset\"]) }),\n z.object({ type: z.literal(\"add-section\"), name: z.string().min(1), icon: layoutIcon, zone: z.enum([\"before_page\", \"after_page\"]) }),\n 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() }),\n 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() }),\n z.object({ type: z.literal(\"remove-section\"), ...sectionTarget }),\n z.object({ type: z.literal(\"move-section\"), ...sectionTarget, afterId: z.string().nullable().optional(), beforeId: z.string().nullable().optional() }),\n 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() }),\n z.object({ type: z.literal(\"update-field\"), ...sectionTarget, fieldId: z.string().min(1), patch: z.object({}).passthrough() }),\n z.object({ type: z.literal(\"remove-field\"), ...sectionTarget, fieldId: z.string().min(1) }),\n z.object({ type: z.literal(\"move-field\"), ...sectionTarget, itemId: z.string().min(1), index: z.number().int().nonnegative() }),\n z.object({ type: z.literal(\"set-bindings\"), ...sectionTarget, itemId: z.string().min(1), bindings: z.array(layoutBinding), literalValues: z.record(z.string(), z.unknown()).optional() }),\n ]);\n const commandLayoutInput = z.object({\n scope: z.enum([\"global\", \"page\"]).default(\"global\"),\n pageId: z.string().min(1).optional(),\n projectId: z.string().min(1).optional().describe(\"required only for a workspace-scoped grant\"),\n command: layoutCommand.describe(\"one canonical discriminated Layout command; authority is derived from type\"),\n ifMatch: z.number().int().nonnegative().describe(\"revision returned by get_layout\"),\n });\n // Eight structural categories (what the component IS) + the four \"Add a section\" library\n // tabs (where it appears). Keep in step with componentCategorySchema in\n // src/lib/validation/schemas/components.ts — the library four were missing here, so an\n // agent could not file a component under a library tab.\n const componentCategory = z.enum([\n \"navbar\", \"footer\", \"button\", \"section\", \"slider\", \"tabs\", \"form\", \"custom\",\n \"hero\", \"content\", \"social-proof\", \"conversion\",\n ]);\n const sectionType = z\n .string()\n .min(1)\n .max(64)\n .describe(\n \"section family, e.g. 'Hero' — set this with a library category to make the component selectable in the page editor's 'Add a section' picker. Components sharing a sectionType are layout variants of one section.\",\n );\n const allowedOn = z\n .array(z.string().regex(/^(\\*|slug:[a-z0-9-]+|type:(singleton|dynamic|template))$/))\n .max(100)\n .describe(\"placement allowlist: *, slug:<page-slug>, and/or type:singleton|dynamic|template\");\n const createComponentInput = z.object({\n name: z.string().min(1),\n slug: slug.describe(\"url-safe unique slug (lowercase letters/numbers/hyphens)\"),\n category: componentCategory.optional().describe(\"defaults to 'custom'\"),\n sectionType: sectionType.optional(),\n projectId: z.string().nullable().optional().describe(\"owning project id; null creates a workspace-wide global component\"),\n allowedOn: allowedOn.optional(),\n description: z.string().optional(),\n blockJson: z.array(blockObject).default([]).describe(\"the component's block tree\"),\n props: z.array(componentPropObject).default([]).describe(\"overridable fields\"),\n });\n const updateComponentInput = z.object({\n componentId: z.string().min(1).describe(\"component id (from list_components)\"),\n name: z.string().optional(),\n category: componentCategory.optional(),\n sectionType: sectionType\n .nullable()\n .optional()\n .describe(\n \"null demotes it to an ordinary component — it disappears from the 'Add a section' picker, and instances already placed keep rendering but lose their section chrome and variant switcher\",\n ),\n allowedOn: allowedOn.optional().describe(\"REPLACES the placement allowlist\"),\n description: z.string().optional(),\n blockJson: z.array(blockObject).optional().describe(\"REPLACES the block tree\"),\n props: z.array(componentPropObject).optional(),\n });\n const getComponentInput = z.object({\n componentId: z.string().min(1).describe(\"component id (from list_components)\"),\n });\n const listExtractionCandidatesInput = z.object({\n projectId: z.string().min(1).optional().describe(\"only needed for a workspace-wide key\"),\n });\n const extractComponentInput = z.object({\n hash: z.string().min(1).describe(\"candidate hash from list_extraction_candidates\"),\n name: z.string().min(1).describe(\"name for the new component\"),\n slug: slug.describe(\"url-safe unique slug (lowercase letters/numbers/hyphens)\"),\n projectId: z.string().min(1).optional().describe(\"only needed for a workspace-wide key\"),\n });\n const sectionEvidenceProjectId = z\n .string()\n .min(1)\n .max(64)\n .describe(\"exact project id from get_project (not a slug); Section evidence is project-local and never reusable across projects\");\n const sectionId = z.string().uuid().describe(\"Section definition id from Section Studio\");\n const sectionVersion = z.number().int().positive().describe(\"exact Section schema version implemented or tested\");\n const sha256 = z.string().regex(/^[0-9a-f]{64}$/i, \"Expected a SHA-256 hex digest\");\n const sectionViewport = z.object({\n name: z.string().trim().min(1).max(64),\n width: z.number().int().min(240).max(7680),\n height: z.number().int().min(240).max(7680),\n });\n const sectionEvidenceDigest = z.string()\n .regex(/^(?:sha256:)?[0-9a-f]{64}$/i, \"Expected a SHA-256 digest\");\n const nonEmptyDescriptor = z.record(z.string(), z.unknown())\n .refine((value) => Object.keys(value).length > 0, \"Descriptor cannot be empty\");\n const sectionRequestId = z.string().uuid().describe(\"durable Section validation request id returned by list_section_validation_requests or the dashboard\");\n const sectionHttpUrl = z.string().url().max(2048).refine((value) => {\n try {\n const protocol = new URL(value).protocol;\n return protocol === \"http:\" || protocol === \"https:\";\n } catch {\n return false;\n }\n }, \"Expected an HTTP or HTTPS URL\");\n const sectionValidationViewport = sectionViewport.extend({\n status: z.enum([\"passed\", \"failed\"]),\n evidenceDigest: sectionEvidenceDigest,\n });\n const submitSectionManifestInput = z.object({\n projectId: sectionEvidenceProjectId,\n requestId: sectionRequestId.optional().describe(\"include when fulfilling a claimed dashboard request so the evidence is bound to that exact run\"),\n sectionId,\n version: sectionVersion,\n apiId: z.string().regex(/^[a-z][A-Za-z0-9]*$/, \"Use lower camelCase\").max(100),\n schemaHash: sha256.describe(\"exact SHA-256 hex hash shown for this Section version\"),\n commitSha: z.string().regex(/^[0-9a-f]{7,64}$/i).describe(\"git commit containing the implementation\"),\n loader: nonEmptyDescriptor.describe(\"non-empty serializable loader descriptor emitted by the repo build; never executable code\"),\n previewAdapter: nonEmptyDescriptor.describe(\"non-empty serializable adapter descriptor for the customer's real app shell; never executable code\"),\n nativeViewports: z\n .array(sectionViewport)\n .max(20)\n .optional()\n .describe(\"the customer's named responsive viewports; BetterCMS also enforces Desktop 1440x900, Tablet 768x1024, and Mobile 390x844\"),\n });\n const submitSectionValidationInput = z.object({\n projectId: sectionEvidenceProjectId.describe(\"exact project id from get_project (not a slug); must match the manifest's project\"),\n requestId: sectionRequestId.optional().describe(\"same claimed request id used for the manifest; binds and terminalizes that run\"),\n sectionId: sectionId.describe(\"exact Section definition id\"),\n version: sectionVersion,\n manifestId: z.string().uuid().describe(\"manifest id returned by submit_section_manifest; it pins the schema hash and commit SHA\"),\n status: z.enum([\"passed\", \"failed\"]).describe(\"the actual result of the external repo/app-shell validation\"),\n fixtureHash: sha256.describe(\"SHA-256 hex hash of the canonical preview dataset and stress fixtures used\"),\n evidenceDigest: sectionEvidenceDigest\n .describe(\"SHA-256 digest of the immutable validation evidence bundle (screenshots/report/results)\"),\n appShell: z.object({\n kind: z.literal(\"actual-app\"),\n identifier: z.string().trim().min(1).max(255),\n url: sectionHttpUrl.optional(),\n }).describe(\"the real customer application shell used for the validation run\"),\n viewportResults: z.array(sectionValidationViewport).min(1).max(23)\n .describe(\"one signed result for every required and native manifest viewport\"),\n });\n const listSectionValidationRequestsInput = z.object({\n projectId: sectionEvidenceProjectId,\n limit: z.number().int().min(1).max(100).optional(),\n });\n const claimSectionValidationRequestInput = z.object({\n projectId: sectionEvidenceProjectId,\n requestId: sectionRequestId,\n commitSha: z.string().regex(/^[0-9a-f]{7,64}$/i)\n .describe(\"exact git commit the agent will inspect and validate; evidence must use this same commit\"),\n providerRunId: z.string().trim().min(1).max(255).optional(),\n providerRunUrl: sectionHttpUrl.optional().describe(\"optional HTTP(S) link to the user's external agent run\"),\n });\n const completeSectionValidationRequestInput = z.object({\n projectId: sectionEvidenceProjectId,\n requestId: sectionRequestId,\n manifestId: z.string().uuid().optional(),\n validationRunId: z.string().uuid().optional(),\n });\n const failSectionValidationRequestInput = z.object({\n projectId: sectionEvidenceProjectId,\n requestId: sectionRequestId,\n errorCode: z.string().trim().regex(/^[A-Z][A-Z0-9_]*$/).max(100),\n errorMessage: z.string().trim().min(1).max(2_000),\n providerRunId: z.string().trim().min(1).max(255).optional(),\n providerRunUrl: sectionHttpUrl.optional().describe(\"optional HTTP(S) link to the user's external agent run\"),\n });\n\n /**\n * The content-lifecycle tools, in parity with the remote /mcp catalog. Each is a thin\n * call to an authenticated API route through the client's public request plumbing — no\n * bespoke SDK method per endpoint (DRY). Most target Management; Section evidence targets\n * the project-scoped ingest lane. `def`/`data` collapse the shared boilerplate.\n */\n function lifecycleTools(): ToolDef[] {\n const def = (\n name: string,\n title: string,\n description: string,\n shape: z.ZodRawShape,\n run: (client: ManagementApi, args: Record<string, unknown>) => Promise<ToolResult>,\n ): ToolDef => ({\n name,\n config: { title, description, inputSchema: shape },\n handler: guard(async (args: Record<string, unknown>) => withClient((client) => run(client, args))) as ToolDef[\"handler\"],\n });\n const q = (obj: Record<string, unknown>): string => {\n const p = new URLSearchParams();\n for (const [k, v] of Object.entries(obj)) if (v !== undefined && v !== null) p.set(k, String(v));\n const s = p.toString();\n return s ? `?${s}` : \"\";\n };\n /**\n * Call a management endpoint and return its `data` payload.\n *\n * 🔴 Do NOT set a content-type here. `ManagementApi.headers()` already sends\n * `Content-Type: application/json`, and `fetchJSON` merges headers as a PLAIN OBJECT —\n * so a lowercase `content-type` is a DIFFERENT key, both survive the spread, and the\n * Headers constructor then APPENDS them into `application/json, application/json`.\n * Hono's zValidator does not recognise that as JSON, reads the body as absent, and every\n * write here failed with a validation error naming a field the caller did send. It cost\n * all 16 body-carrying tools on this surface, silently, because the request looked\n * perfect from the client side and the server's complaint pointed at the body's contents.\n */\n const data = async (client: ManagementApi, method: string, path: string, body?: unknown): Promise<unknown> =>\n (await client.fetchJSON<{ data?: unknown }>(client.url(path), {\n method,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n })).data;\n const s = (v: unknown) => v as string;\n /** POST raw bytes (base64 → binary) for the binary deploy tool; returns `data`. */\n const raw = async (client: ManagementApi, path: string, base64: string, mimeType?: string): Promise<unknown> =>\n (await client.fetchJSON<{ data?: unknown }>(client.url(path), {\n method: \"POST\",\n body: Buffer.from(base64, \"base64\"),\n headers: { \"content-type\": mimeType ?? \"application/octet-stream\" },\n })).data;\n\n return [\n def(\"create_media_upload\", \"Get a presigned media-upload URL\",\n \"PREFERRED way to add an image — get a presigned URL and upload the file DIRECTLY to storage, so the bytes never pass through the conversation. Flow: (1) call this with filename, mimeType and sizeBytes (the file's exact byte length); (2) PUT the file to `uploadUrl`, e.g. `curl -X PUT -H 'Content-Type: image/jpeg' --data-binary @photo.jpg \\\"<uploadUrl>\\\"` — the url pins both headers, so they must match exactly; (3) call attach_media_upload with the `assetId` + `uploadKey`. URL expires in 10 minutes.\",\n z.object({\n filename: z.string().min(1).describe(\"file name incl. extension, e.g. 'hero.png'\"),\n mimeType: z.string().min(1).describe(\"MIME type, e.g. 'image/png'\"),\n sizeBytes: z.number().describe(\"the file's exact size in bytes (e.g. from `stat`/`wc -c`) — the presigned url pins it\"),\n }).shape,\n async (c, a) => ok(\"Upload URL.\", await data(c, \"POST\", `/management/media/upload-url`, { filename: a.filename, mimeType: a.mimeType, sizeBytes: a.sizeBytes }))),\n def(\"attach_media_upload\", \"Attach a presigned media upload\",\n \"Register a file you already uploaded via create_media_upload (step 3) into the Media Library and get back its CDN url. Pass the `assetId` + `uploadKey` from step 1, plus the filename and any alt text/caption.\",\n z.object({\n assetId: z.string().min(1).describe(\"the assetId from create_media_upload\"),\n uploadKey: z.string().min(1).describe(\"the uploadKey from create_media_upload, after the PUT succeeded\"),\n filename: z.string().min(1).describe(\"file name incl. extension\"),\n altText: z.string().optional(),\n caption: z.string().optional(),\n folderId: z.string().optional(),\n }).shape,\n async (c, a) => ok(\"Media asset.\", await data(c, \"POST\", `/management/media/from-upload`, { assetId: a.assetId, uploadKey: a.uploadKey, filename: a.filename, altText: a.altText, caption: a.caption, folderId: a.folderId }))),\n def(\"list_media\", \"List media assets\",\n \"List the images/assets already in the connected project's Media Library (id, url, filename, mimeType, size, alt/caption). Reuse an existing asset instead of re-uploading. Filter with `search` or `type` ('image'|'video'|…).\",\n z.object({ search: z.string().optional(), type: z.string().optional(), limit: z.number().optional(), page: z.number().optional() }).shape,\n async (c, a) => ok(\"Media assets.\", await data(c, \"GET\", `/management/media${q({ search: a.search, type: a.type, limit: a.limit, page: a.page })}`))),\n def(\"get_media\", \"Get a media asset\",\n \"Get one media asset by id — its CDN url, filename, MIME type, size, and alt/caption. Use the url as the value of an 'image' field.\",\n z.object({ assetId: z.string().min(1).describe(\"media asset id (from list_media / upload_asset)\") }).shape,\n async (c, a) => ok(\"Media asset.\", await data(c, \"GET\", `/management/media/${s(a.assetId)}`))),\n def(\"delete_media\", \"Delete a media asset\",\n \"Delete a media asset from the Media Library (soft delete — reversible from the dashboard trash). Provide assetId.\",\n z.object({ assetId: z.string().min(1).describe(\"media asset id (from list_media)\") }).shape,\n async (c, a) => ok(\"Deleted media asset.\", await data(c, \"DELETE\", `/management/media/${s(a.assetId)}`))),\n\n def(\"delete_form\", \"Delete a form\",\n \"Delete a form by id. Soft delete — the form stops rendering and accepting submissions, but leads already collected against it are preserved. Use it to clean up forms created by mistake.\",\n z.object({ formId: z.string().min(1).describe(\"form id (from list_forms)\") }).shape,\n async (c, a) => ok(\"Deleted form.\", await data(c, \"DELETE\", `/management/forms/${s(a.formId)}`))),\n\n def(\"list_form_submissions\", \"List a form's submissions (leads)\",\n \"List the SUBMISSIONS (leads) a form has received — each with its submitted field values. Filter with status ('inbox'|'spam') and paginate with limit/page.\",\n z.object({ formId: z.string().min(1), status: z.enum([\"inbox\", \"spam\"]).optional(), limit: z.number().optional(), page: z.number().optional() }).shape,\n async (c, a) => ok(\"Form submissions.\", await data(c, \"GET\", `/management/forms/${s(a.formId)}/submissions${q({ status: a.status, limit: a.limit, page: a.page })}`))),\n def(\"delete_form_submission\", \"Delete a form submission\",\n \"Delete one form submission (lead) — e.g. to clear spam. Provide formId and submissionId (from list_form_submissions).\",\n z.object({ formId: z.string().min(1), submissionId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Deleted submission.\", await data(c, \"DELETE\", `/management/forms/${s(a.formId)}/submissions/${s(a.submissionId)}`))),\n\n def(\"list_redirects\", \"List redirects\",\n \"List the URL redirects configured for the connected project (source path → destination, type).\",\n z.object({}).shape,\n async (c) => ok(\"Redirects.\", await data(c, \"GET\", `/management/redirects`))),\n def(\"update_redirect\", \"Update a redirect\",\n \"Update an existing redirect in place — change where it points, its HTTP status, or disable it without deleting. Prefer this over delete+create: it keeps the redirect's id and preserves the chain-collapse rewrites of other rules pointing at it. Only provided fields change. Loops 422, duplicate sources 409.\",\n z.object({ redirectId: z.string().min(1).describe(\"redirect id (from list_redirects)\"), sourcePath: z.string().min(1).optional(), destination: z.string().min(1).optional(), redirectType: z.enum([\"301\", \"302\", \"307\", \"308\"]).optional(), isActive: z.boolean().optional().describe(\"set false to disable without deleting\") }).shape,\n async (c, a) => ok(\"Updated redirect.\", await data(c, \"PATCH\", `/management/redirects/${s(a.redirectId)}`, { sourcePath: a.sourcePath, destination: a.destination, redirectType: a.redirectType, isActive: a.isActive }))),\n def(\"create_redirect\", \"Create a redirect\",\n \"Create a URL redirect — e.g. a 301 after renaming a page's slug. `sourcePath` is the path to redirect FROM ('/old-page'), `destination` the path/url TO ('/new-page'). Chains collapse; loops/dupes rejected. Defaults to 301.\",\n z.object({ sourcePath: z.string().min(1), destination: z.string().min(1), redirectType: z.enum([\"301\", \"302\", \"307\", \"308\"]).optional() }).shape,\n async (c, a) => ok(\"Created redirect.\", await data(c, \"POST\", `/management/redirects`, { sourcePath: a.sourcePath, destination: a.destination, redirectType: a.redirectType }))),\n def(\"delete_redirect\", \"Delete a redirect\",\n \"Delete a URL redirect by id (from list_redirects). Provide redirectId.\",\n z.object({ redirectId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Deleted redirect.\", await data(c, \"DELETE\", `/management/redirects/${s(a.redirectId)}`))),\n\n def(\"get_seo\", \"Get site SEO\",\n \"Get the connected project's site-wide SEO settings — default meta (title/description/ogImage), JSON-LD siteSchema, and robots/sitemap/rss config.\",\n z.object({}).shape,\n async (c) => ok(\"SEO settings.\", await data(c, \"GET\", `/management/seo`))),\n def(\"update_seo\", \"Update site SEO\",\n \"Set site-wide SEO defaults. `seoDefaults` { metaTitle, metaDescription, ogImage, twitterHandle } applies to every page unless overridden. Optionally robotsConfig / sitemapConfig / rssConfig. Each field is REPLACED whole. Rebuilds the site.\",\n z.object({ seoDefaults: z.record(z.string(), z.unknown()).optional(), siteSchema: z.record(z.string(), z.unknown()).optional(), robotsConfig: z.record(z.string(), z.unknown()).optional(), sitemapConfig: z.record(z.string(), z.unknown()).optional(), rssConfig: z.record(z.string(), z.unknown()).optional() }).shape,\n async (c, a) => ok(\"Updated SEO.\", await data(c, \"PATCH\", `/management/seo`, a))),\n\n def(\"get_site_files\", \"List site files\",\n \"List the AI-crawler files installed on the connected project (llms.txt / llms-full.txt) — metadata only.\",\n z.object({}).shape,\n async (c) => ok(\"Site files.\", await data(c, \"GET\", `/management/site-files`))),\n def(\"set_site_file\", \"Set a site file\",\n \"Create or replace an AI-crawler file served at the site root — `kind` 'llms.txt' or 'llms-full.txt' — with `content` (plain text, max 5 MB). Rebuilds the site.\",\n z.object({ kind: z.enum([\"llms.txt\", \"llms-full.txt\"]), content: z.string() }).shape,\n async (c, a) => ok(\"Saved site file.\", await data(c, \"PUT\", `/management/site-files/${s(a.kind)}`, { content: a.content }))),\n def(\"delete_site_file\", \"Delete a site file\",\n \"Remove an AI-crawler file (llms.txt / llms-full.txt) from the connected project. Provide kind.\",\n z.object({ kind: z.enum([\"llms.txt\", \"llms-full.txt\"]) }).shape,\n async (c, a) => ok(\"Deleted site file.\", await data(c, \"DELETE\", `/management/site-files/${s(a.kind)}`))),\n\n // ── Editorial board ──\n // Publishing is two decisions: may the KEY publish (content:publish, granted at\n // consent) and may the ITEM publish (it must sit in the board's gate stage). These\n // tools are the second one. Without them a publish-enabled connection still dead-ends\n // on a 409 the moment a project uses review columns.\n def(\"get_workflow_board\", \"List editorial workflow stages\",\n \"List the connected project's editorial board columns in order — each stage's `key`, name, and whether it is the `publishGate` (the one stage content may go live from). Read this BEFORE move_entry_stage / move_page_stage: stage keys are per-project and not guessable, because a project can rename or replace every column.\",\n z.object({}).shape,\n async (c) => ok(\"Workflow stages.\", await data(c, \"GET\", `/management/workflow/stages`))),\n def(\"move_entry_stage\", \"Move a content entry across the board\",\n \"Move a content entry to another editorial stage — this is how you get an entry OUT of review so it can be published. `workflowStage` is a stage key from get_workflow_board (null clears it). Optionally set `workflowAssigneeIds` / `workflowDueDate`, or pass `fromStage` to fail with 409 if someone moved it first. Moving into the publish-gate stage is an approval and needs a publish-enabled connection. Publish afterwards with update_content_entry status:'published' — approving and publishing are deliberately two separate calls.\",\n z.object({ entryId: z.string().min(1), workflowStage: z.string().max(64).describe(\"stage key from get_workflow_board\"), fromStage: z.string().max(64).optional().describe(\"the stage you believe it is in — 409s if it has moved\") }).shape,\n async (c, a) => ok(\"Moved entry.\", await data(c, \"PATCH\", `/management/content/entries/${s(a.entryId)}/workflow`, { workflowStage: a.workflowStage, fromStage: a.fromStage }))),\n def(\"move_page_stage\", \"Move a page across the board\",\n \"Move a page to another editorial stage — the page twin of move_entry_stage, and the only way to take a page out of review so update_page (status:'published') can go live. `workflowStage` is a stage key from get_workflow_board. Moving into the publish-gate stage is an approval and needs a publish-enabled connection.\",\n z.object({ pageId: z.string().min(1), workflowStage: z.string().max(64).describe(\"stage key from get_workflow_board\"), fromStage: z.string().max(64).optional().describe(\"the stage you believe it is in — 409s if it has moved\") }).shape,\n async (c, a) => ok(\"Moved page.\", await data(c, \"PATCH\", `/management/pages/${s(a.pageId)}/workflow`, { workflowStage: a.workflowStage, fromStage: a.fromStage }))),\n\n def(\"promote_project\", \"Promote staging → production\",\n \"Promote the connected project's STAGED build to PRODUCTION — the one-click publish. Flips prod to the newest staged release (no rebuild) after the QA scan passes. Managed hosting only; needs a publish-enabled connection.\",\n z.object({}).shape,\n async (c) => ok(\"Promoted to production.\", await data(c, \"POST\", `/management/projects/promote`))),\n\n def(\"list_entry_versions\", \"List a content entry's versions\",\n \"List a content entry's version history (newest first) — each version's number, data snapshot, and when it was saved. Use it to find a past state to restore.\",\n z.object({ entryId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Entry versions.\", await data(c, \"GET\", `/management/content/entries/${s(a.entryId)}/versions`))),\n def(\"restore_entry_version\", \"Restore a content entry to a past version\",\n \"Restore a content entry to a past version (undo). Copies that version's data back as the current DRAFT (non-destructive). Publish afterwards to take it live. Provide entryId and the version number (from list_entry_versions).\",\n z.object({ entryId: z.string().min(1), version: z.number().int().positive() }).shape,\n async (c, a) => ok(\"Restored entry version.\", await data(c, \"POST\", `/management/content/entries/${s(a.entryId)}/versions/${a.version}/restore`))),\n\n // ── Project / workspace (parity with remote /mcp) ──\n def(\"get_project\", \"Get the connected project\",\n \"Get the connected project's info — id, name, slug, subdomain, and its live URL (https://<handle>.bettercms.site). Use it to tell the user where their site is published / link the result.\",\n z.object({}).shape,\n async (c) => ok(\"Project.\", await data(c, \"GET\", `/management/projects/current`))),\n def(\"list_projects\", \"List projects\",\n \"List the projects this key can see — id, name, slug, and live URL each. A project-scoped key sees only its own project; a workspace-level key sees every project in the workspace. Use it to find a project you created earlier, or to confirm which sites exist before acting.\",\n z.object({}).shape,\n async (c) => ok(\"Projects.\", await data(c, \"GET\", `/management/projects`))),\n def(\"update_project\", \"Update the connected project\",\n \"Update the connected project's settings — rename it, change its slug/description, SEO defaults, or visibility. Only the provided fields change.\",\n z.object({ name: z.string().optional(), slug: z.string().optional(), description: z.string().optional(), visibility: z.string().optional(), seoDefaults: z.record(z.string(), z.unknown()).optional() }).shape,\n async (c, a) => ok(\"Updated project.\", await data(c, \"PATCH\", `/management/projects/current`, a))),\n def(\"create_project\", \"Create a new project\",\n \"Create a NEW project (site) in the connected workspace. ASK THE USER WHICH TECHNOLOGY TO BUILD WITH FIRST and pass it as `framework` — 'astro' (recommended default), 'next', 'react-ts' (React + TypeScript), or 'other' for a headless project with no generated frontend. Do not pick for them: called without it, this tool asks them directly (or hands you the question to ask). Sites cannot be created as plain HTML/CSS — every project is backed by one of these starters, which is what makes its content editable in the CMS. Optionally pass templateId to seed curated content. Returns the new project's id and slug. (Use clone_project instead to duplicate an existing project.)\",\n // `framework` is OPTIONAL in the schema on purpose, even though it is required in\n // effect: a required arg is rejected by the SDK before the handler runs, which would\n // kill the elicitation below and leave the model guessing on its own. Optional here,\n // answered by a human there. The backend rejects a create with no framework regardless.\n z.object({ name: z.string().min(1), slug: z.string().optional(), description: z.string().optional(), templateId: z.string().optional(), framework: z.enum(FRAMEWORK_CHOICES).optional().describe(\"REQUIRED in effect — the technology the USER chose. Ask them; never default it.\") }).shape,\n async (c, a) => {\n let framework = a.framework;\n if (framework === undefined) {\n const asked = await askFramework(deps);\n if (\"prompt\" in asked) return fail(asked.prompt);\n framework = asked.framework;\n }\n return ok(\"Created project.\", await data(c, \"POST\", `/management/projects`, { ...a, framework }));\n }),\n def(\"set_authoring_preference\", \"Set the site's authoring architecture\",\n \"Record which authoring architecture this site uses — 'components' (reusable section components placed as blocks; editors add, reorder and swap sections without touching a schema — best for marketing and landing sites) or 'fields' (a typed field schema per page — best for blogs, catalogues and directories). ASK THE USER; do not pick for them. Called without `preference`, this tool asks them directly (or hands you the question to ask). deploy_project, deploy_from_upload and promote_project all refuse with 409 AUTHORING_DECISION_REQUIRED until it is set, and that refusal carries this project's real page counts to show the user. Answering 'components' does NOT convert anything — there is no field-to-block converter; it means you author the sections yourself: create_component, then publish_component (an unpublished component renders as NOTHING on the live site), then set_page_content placing `component` blocks. Asked once per project; re-callable if the user changes their mind.\",\n // Optional in the schema for exactly the reason `framework` is above: a required arg is\n // rejected by the SDK before the handler runs, which would kill the elicitation below\n // and leave the model guessing. Optional here, answered by a human there. The backend\n // gate refuses the deploy regardless, so nothing ships on a guess.\n z.object({ preference: z.enum(AUTHORING_CHOICES).optional().describe(\"REQUIRED in effect — the architecture the USER chose. Ask them; never default it.\") }).shape,\n async (c, a) => {\n let preference = a.preference;\n if (preference === undefined) {\n const asked = await askAuthoring(deps);\n if (\"prompt\" in asked) return fail(asked.prompt);\n preference = asked.preference;\n }\n return ok(\"Recorded the authoring architecture.\", await data(c, \"PATCH\", `/management/projects/current/authoring-preference`, { preference }));\n }),\n def(\"set_binding_mode\", \"Set how the site's bindings are resolved\",\n \"Switch this project between the two binding resolvers, from the NEXT release on. `declaredBindings: true` makes the annotator trust the template's own data-bcms-field / data-bcms-props and never guess from rendered text — the durable state; `false` returns to text-matching, which works once (at import, when the CMS values equal the built copy) and breaks the first time anyone edits a value. Call it ONLY after every page's copy is declared in the template: undeclared fields stop being editable. The order is push → release → get_binding_report shows mode 'text-match' with 0 unmatched → set_binding_mode → release again → get_binding_report shows mode 'declared'. Flipping back is the same call. REQUIRES a project-scoped connection carrying the artifact:write scope — the same authority that deploys the site — because this decides what every future release does to every page; a workspace-wide grant is refused with 403. See section 13 of the bettercms://playbook/schema resource.\",\n z.object({ declaredBindings: z.boolean().describe(\"true = trust the template's declared bindings; false = text-match (the default)\") }).shape,\n async (c, a) => ok(\"Recorded the binding mode.\", await data(c, \"PATCH\", `/management/projects/current/binding-mode`, { declaredBindings: a.declaredBindings }))),\n def(\"clone_project\", \"Clone a project\",\n \"Clone (duplicate) a project as a reusable template into the connected workspace. Copies pages, content models + entries, components, media, forms, and SEO/custom-code settings; excludes submissions, analytics, domains, and secrets. Returns the new project's id and slug. Omit sourceProjectId to clone the connected project.\",\n z.object({ sourceProjectId: z.string().optional(), name: z.string().optional(), slug: z.string().optional() }).shape,\n async (c, a) => ok(\"Cloned project.\", await data(c, \"POST\", `/management/projects/clone`, a))),\n def(\"create_template\", \"Save a project/page as a template\",\n \"Save a project (or one page) as a REUSABLE template — a frozen snapshot of its content models, pages, entries, components, and forms (secrets/domains/analytics excluded). Later seed a new project from it with create_project { templateId }. Set visibility 'public' to list it in the cross-workspace gallery. Returns the new template's id.\",\n z.object({ sourceProjectId: z.string().min(1), name: z.string().min(1), scope: z.string().optional(), sourcePageId: z.string().optional(), description: z.string().optional(), visibility: z.string().optional() }).shape,\n async (c, a) => ok(\"Created template.\", await data(c, \"POST\", `/management/templates`, a))),\n def(\"list_templates\", \"List saved templates\",\n \"List your workspace's saved templates (id, name, scope, visibility). Use a template's id as create_project { templateId } to seed a new project from it.\",\n z.object({}).shape,\n async (c) => ok(\"Templates.\", await data(c, \"GET\", `/management/templates`))),\n\n // ── Content models (read/metadata; parity with remote /mcp) ──\n def(\"list_content_models\", \"List content models\",\n \"List the content models (reusable schemas for dynamic collections like Blog/Products) in the connected project.\",\n z.object({}).shape,\n async (c) => ok(\"Content models.\", await data(c, \"GET\", `/management/content/models`))),\n def(\"get_content_model\", \"Get a content model\",\n \"Get one content model by id INCLUDING its full field schema (keys, types, nested group/repeater children). Read this before add_field so you know the existing keys.\",\n z.object({ modelId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Content model.\", await data(c, \"GET\", `/management/content/models/${s(a.modelId)}`))),\n def(\"update_content_model\", \"Update a content model's metadata\",\n \"Rename a content model or edit its description/slug (metadata only — does NOT touch fields; use add_field to extend the schema). Provide modelId plus the fields to change.\",\n z.object({ modelId: z.string().min(1), name: z.string().optional(), slug: z.string().optional(), description: z.string().optional() }).shape,\n async (c, a) => ok(\"Updated content model.\", await data(c, \"PATCH\", `/management/content/models/${s(a.modelId)}`, { name: a.name, slug: a.slug, description: a.description }))),\n def(\"get_content_types\", \"Get generated TypeScript types\",\n \"Get the auto-generated TypeScript types for the connected project's content models/pages. Pull these to write correctly-typed code against the BetterCMS delivery SDK in the user's site.\",\n z.object({}).shape,\n async (c) => ok(\"Content types.\", await data(c, \"GET\", `/management/content/types`))),\n\n // ── Pages (metadata edit; parity with remote /mcp) ──\n def(\"update_page\", \"Edit a page\",\n \"Edit a page: title, slug, SEO metaTitle/metaDescription, publish status (draft|published), and `blockJson` (its block composition — passing it REPLACES the whole array, so read get_page first). It does NOT change the field SCHEMA — use add_page_field / set_page_content for that. Renaming the slug keeps content intact. Publishing copies the draft blocks live in the same call. \" +\n DOCTRINE,\n z.object({ pageId: z.string().min(1), title: z.string().optional(), slug: z.string().optional(), blockJson: z.array(blockObject).optional().describe(\"REPLACES the page's block composition\"), metaTitle: z.string().optional(), metaDescription: z.string().optional(), status: z.enum([\"draft\", \"published\"]).optional() }).shape,\n async (c, a) => ok(\"Updated page.\", await data(c, \"PATCH\", `/management/pages/${s(a.pageId)}/meta`, { title: a.title, slug: a.slug, blockJson: a.blockJson, metaTitle: a.metaTitle, metaDescription: a.metaDescription, status: a.status }))),\n\n // ── Code + deploy (parity with remote /mcp; needs artifact:write) ──\n def(\"pull_project_source\", \"Pull the project's live source\",\n \"Get the connected project's CURRENT live source/build so you can edit it locally. Returns a presigned tarball download url (1h) + the live commit sha — download it, extract, edit the files, then call deploy_project. If the project is connected to a GitHub repo, returns `github: {owner, repo}` so you can `git clone` that instead.\",\n z.object({}).shape,\n async (c) => ok(\"Project source.\", await data(c, \"GET\", `/management/projects/source`))),\n def(\"deploy_project\", \"Deploy new source/build\",\n \"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 — then poll get_deploy_status until it is live. IMPORTANT — 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 — 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 — that path uploads straight to storage with no size ceiling.\",\n z.object({ data: z.string().min(1).describe(\"base64 .tgz/.zip of the project\"), mimeType: z.string().optional() }).shape,\n async (c, a) => ok(\"Deploy queued.\", await raw(c, `/management/projects/deploy`, s(a.data), a.mimeType as string | undefined))),\n def(\"create_deploy_upload\", \"Get a presigned deploy-upload URL\",\n \"Get a presigned URL to upload a LARGE deploy archive directly to storage, bypassing the ~100 MB body limit deploy_project's inline `data` hits. Flow: (1) call this for `uploadUrl` + `uploadKey`; (2) PUT your .tgz/.zip to `uploadUrl` (e.g. `curl -X PUT --data-binary @archive.tgz \\\"<uploadUrl>\\\"`) — straight to storage, no size ceiling; (3) call deploy_from_upload with `uploadKey`. Still exclude node_modules/.git/build caches. URL expires in 10 minutes.\",\n z.object({}).shape,\n async (c) => ok(\"Upload URL.\", await data(c, \"POST\", `/management/projects/deploy/upload-url`))),\n def(\"deploy_from_upload\", \"Deploy from a staged upload\",\n \"Deploy from an archive already uploaded via create_deploy_upload (step 3). Pass the `uploadKey` you received. Builds SOURCE server-side or serves a prebuilt site — then poll get_deploy_status until live.\",\n z.object({ uploadKey: z.string().min(1).describe(\"the uploadKey from create_deploy_upload, after PUTting the archive to its uploadUrl\") }).shape,\n async (c, a) => ok(\"Deploy queued.\", await data(c, \"POST\", `/management/projects/deploy/from-upload`, { uploadKey: a.uploadKey }))),\n // ── Insight: what happened, what's working, what's broken ─────────────────\n def(\"list_activity\", \"List project activity\",\n \"Recent activity in the connected project — who changed what, and when. Filter by `category` (comma-separated: content, pages, media, forms, deployment, settings, members), `actorId`, or a `since`/`until` ISO window.\",\n z.object({ category: z.string().optional(), actorId: z.string().optional(), since: z.string().optional(), until: z.string().optional(), limit: z.number().optional() }).shape,\n async (c, a) => ok(\"Project activity.\", await data(c, \"GET\", `/management/insights/activity${q({ category: a.category, actorId: a.actorId, since: a.since, until: a.until, limit: a.limit })}`))),\n def(\"get_changes\", \"Get changes since a timestamp\",\n \"Read the durable project change feed since an ISO timestamp. Call this at the start of a new turn to notice dashboard or agent edits made since your previous observation.\",\n z.object({ since: z.string().datetime(), limit: z.number().int().min(1).max(100).optional() }).shape,\n async (c, a) => ok(\"Project changes.\", await data(c, \"GET\", `/management/insights/activity${q({ since: a.since, limit: a.limit ?? 100 })}`))),\n def(\"get_next_steps\", \"Get what to do next\",\n \"What is still unfinished in the connected project, as the platform sees it — pages you created without a meta description, drafts never published, collections with no entries, forms nobody is notified about, writes waiting for human approval. Each item cites the count it reacted to. Call it AFTER a batch of edits to catch what you left behind, and before telling the user you are done.\",\n z.object({}).shape,\n async (c) => ok(\"Next steps.\", await data(c, \"GET\", `/management/insights/next-steps`))),\n def(\"get_binding_report\", \"Check what on the live site is editable\",\n \"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` — 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 — 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.\",\n z.object({ slot: z.enum([\"current\", \"staging\"]).optional().describe(\"which release tree to read; defaults to the one this project deploys to\") }).shape,\n async (c, a) => ok(\"Binding report.\", await data(c, \"GET\", `/management/projects/current/binding-report${q({ slot: a.slot })}`))),\n def(\"get_conversion_brief\", \"Get the brief for making this site's bindings durable\",\n \"The per-project brief for making this site's bindings DURABLE — read it before you touch the templates. Returns what already exists in the CMS: every live page with its route, and every bindable field path with its `label`, `kind`, the value the CMS holds now (`current`) and the copy the repo renders today (`original`, the field's defaultValue) — plus the exact attributes to declare, and the ordered steps. Call it for any site whose pages were DERIVED at import, and whenever get_next_steps reports `bindings-not-declared`. It REPLACES re-registering a schema: these pages, fields and values exist already, so create_page / add_page_field / create_content_model would build a second schema over the first — edit values with set_page_content instead. `lane` says how to get the source ('git-connected' = pull_project_source returns a repo; 'archive' = a tarball). The full recipe is section 13 of the bettercms://playbook/schema resource; get_binding_report is the receipt that says you finished.\",\n z.object({}).shape,\n async (c) => ok(\"Conversion brief.\", await data(c, \"GET\", `/management/projects/current/conversion-brief`))),\n def(\"get_conversion_plan\", \"Get the approved conversion to apply\",\n \"The APPROVED conversion a human reviewed in the BetterCMS dashboard: the exact new contents of each template file, already checked against this project's real field paths. Apply it instead of writing the bindings by hand. Check out `baseHeadOid` (the exact commit it was written against — a plan applied to a different base is a different change), branch from there, write each file's `content` verbatim (whole file, no merge, no reformatting), then push or deploy however this project ships. `stale.head` / `stale.brief` say the repository or the CMS moved since it was approved: stop and ask for a fresh proposal rather than applying it anyway. Finish the loop the same way as a hand conversion — get_binding_report until `unmatched` is empty, then set_binding_mode { declaredBindings: true } and release once more. 404 with `code: \\\"no-approved-plan\\\"` means nobody has approved one: use get_conversion_brief and do the conversion yourself. Requires a project-scoped connection carrying artifact:write.\",\n z.object({}).shape,\n async (c) => ok(\"Approved conversion plan.\", await data(c, \"GET\", `/management/projects/current/conversion-plan`))),\n def(\"get_analytics_overview\", \"Get traffic overview\",\n \"Traffic totals and the daily series for the connected project — views, unique visitors, bytes, sessions and bounces. Defaults to the last 30 days; pass `from`/`to` as YYYY-MM-DD.\",\n z.object({ from: z.string().optional(), to: z.string().optional() }).shape,\n async (c, a) => ok(\"Analytics overview.\", await data(c, \"GET\", `/management/insights/analytics/overview${q({ from: a.from, to: a.to })}`))),\n def(\"get_analytics_top_pages\", \"Get top pages\",\n \"The most-viewed paths on the live site, with views and bytes. Defaults to the last 30 days; pass `from`/`to` (YYYY-MM-DD) and `limit`.\",\n z.object({ from: z.string().optional(), to: z.string().optional(), limit: z.number().optional() }).shape,\n async (c, a) => ok(\"Top pages.\", await data(c, \"GET\", `/management/insights/analytics/top-pages${q({ from: a.from, to: a.to, limit: a.limit })}`))),\n def(\"list_seo_issues\", \"List SEO issues\",\n \"Scan every published page for SEO problems (missing or over-long titles and descriptions, missing OG image, noindex, absent schema) and return them with severities. Computed live — nothing is stored.\",\n z.object({}).shape,\n async (c) => ok(\"SEO issues.\", await data(c, \"GET\", `/management/insights/seo-issues`))),\n def(\"list_ai_reports\", \"List AI report runs\",\n \"Past AI report runs for the connected project — `kind` is 'links' (internal linking) or 'aeo' (AI-answer readiness). Read-only history; starting a run stays a dashboard action.\",\n z.object({ kind: z.enum([\"links\", \"aeo\"]), limit: z.number().optional() }).shape,\n async (c, a) => ok(\"AI reports.\", await data(c, \"GET\", `/management/insights/ai-reports${q({ kind: a.kind, limit: a.limit })}`))),\n\n // ── Bulk: one dataset → many pages ────────────────────────────────────────\n def(\"generate_pages_from_dataset\", \"Generate many pages from a dataset\",\n \"Turn a dataset into many pages at once (programmatic SEO from a keyword list, or ABM pages from an account list). Give a template `pageId`, a `mapping` (contentModelId, a slugTemplate like 'for-{{company}}', and per-field values that are either a column name or {ai:{prompt}}), and `rows`. ALWAYS call with dryRun:true first and show the sample — a real run parks for approval and must be released with approve_ai_job.\",\n z.object({\n pageId: z.string().min(1),\n mapping: z.record(z.string(), z.unknown()),\n rows: z.array(z.record(z.string(), z.string())).min(1),\n dryRun: z.boolean().optional(),\n }).shape,\n async (c, a) => ok(\"Generation queued.\", await data(c, \"POST\", `/management/bulk/generate`, { pageId: a.pageId, mapping: a.mapping, rows: a.rows, dryRun: a.dryRun }))),\n def(\"list_ai_jobs\", \"List bulk jobs\",\n \"Recent bulk jobs for the connected project with status and progress. Use it to report how a generation is going.\",\n z.object({}).shape,\n async (c) => ok(\"Bulk jobs.\", await data(c, \"GET\", `/management/bulk/jobs`))),\n def(\"get_ai_job\", \"Get a bulk job\",\n \"One bulk job — status, rows processed, rows created, conflicts, and the approval plan if it is still parked.\",\n z.object({ jobId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Bulk job.\", await data(c, \"GET\", `/management/bulk/jobs/${s(a.jobId)}`))),\n def(\"approve_ai_job\", \"Approve a bulk job\",\n \"Release a job that is awaiting approval so the queue can run it. Only call this when the USER has said yes — never approve your own plan unprompted.\",\n z.object({ jobId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Job approved.\", await data(c, \"POST\", `/management/bulk/jobs/${s(a.jobId)}/approve`))),\n def(\"reject_ai_job\", \"Reject a bulk job\",\n \"Discard a job awaiting approval. Nothing was charged and nothing was written.\",\n z.object({ jobId: z.string().min(1) }).shape,\n async (c, a) => ok(\"Job rejected.\", await data(c, \"POST\", `/management/bulk/jobs/${s(a.jobId)}/reject`))),\n\n def(\"list_section_validation_requests\", \"List queued Section validation requests\",\n \"Poll for user-agent Section implementation-validation requests in this exact project. BetterCMS cannot push work into an ordinary MCP client: call this explicitly, claim one request, inspect and run the customer's real repository/app shell, then submit request-bound evidence and complete it. Returns only unclaimed user-agent requests; it never exposes another project.\",\n listSectionValidationRequestsInput.shape,\n async (c, a) => ok(\"Queued user-agent Section validation requests.\", await data(\n c,\n \"GET\",\n `/projects/${s(a.projectId)}/section-evidence/implementation-requests${q({ limit: a.limit })}`,\n ))),\n def(\"claim_section_validation_request\", \"Claim a Section validation request\",\n \"Atomically claim one queued user-agent request and pin the exact git commit you will inspect. Claim BEFORE submitting evidence. BetterCMS records coordination only; all customer code and responsive checks must run in the user's repository and real app shell.\",\n claimSectionValidationRequestInput.shape,\n async (c, a) => ok(\"Section validation request claimed.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/implementation-requests/${s(a.requestId)}/claim`,\n {\n commitSha: a.commitSha,\n providerRunId: a.providerRunId,\n providerRunUrl: a.providerRunUrl,\n },\n ))),\n def(\"complete_section_validation_request\", \"Complete a Section validation request\",\n \"Complete a claimed request only after submit_section_manifest and submit_section_validation have bound exact, passed evidence to the same requestId and pinned commit. This cannot grant the separate human Visual Approval.\",\n completeSectionValidationRequestInput.shape,\n async (c, a) => ok(\"Section validation request completed.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/implementation-requests/${s(a.requestId)}/complete`,\n { manifestId: a.manifestId, validationRunId: a.validationRunId },\n ))),\n def(\"fail_section_validation_request\", \"Fail a Section validation request\",\n \"Truthfully close a claimed request when the renderer, validation command, app shell, or required evidence is missing or fails. This path intentionally works without a manifest so 'not implemented' is representable instead of being reported as passed or left queued forever.\",\n failSectionValidationRequestInput.shape,\n async (c, a) => ok(\"Section validation request failed.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/implementation-requests/${s(a.requestId)}/fail`,\n {\n errorCode: a.errorCode,\n errorMessage: a.errorMessage,\n providerRunId: a.providerRunId,\n providerRunUrl: a.providerRunUrl,\n },\n ))),\n\n def(\"submit_section_manifest\", \"Submit a Section implementation manifest\",\n \"Record the implementation manifest produced for one exact Section schema version by CI or an agent running INSIDE the user's repository. BetterCMS does not execute customer code: inspect/build the real renderer in the user's app shell first, then submit its exact API ID, schema hash, commit SHA, loader, preview adapter, and native responsive viewports. Requires a project-scoped artifact:write credential. This records evidence only; it does not validate the implementation and cannot create human Visual Approval.\",\n submitSectionManifestInput.shape,\n async (c, a) => ok(\"Section implementation manifest recorded.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/sections/${s(a.sectionId)}/versions/${a.version}/manifests`,\n {\n requestId: a.requestId,\n apiId: a.apiId,\n schemaHash: a.schemaHash,\n commitSha: a.commitSha,\n loader: a.loader,\n previewAdapter: a.previewAdapter,\n nativeViewports: a.nativeViewports,\n },\n ))),\n def(\"submit_section_validation\", \"Submit a Section validation result\",\n \"Record a real validation result for one exact Section schema version and manifest. Run the component in the user's repository and real app shell across the canonical preview dataset, AI stress fixtures, and required/native viewports BEFORE calling this tool; BetterCMS never runs that customer code. Pass status 'passed' only when those checks actually passed, otherwise 'failed'. The manifest pins schemaHash and commitSha; fixtureHash and evidenceDigest pin the tested data and immutable evidence bundle. Requires project-scoped artifact:write and cannot create the separate human Visual Approval required for publication.\",\n submitSectionValidationInput.shape,\n async (c, a) => ok(\"Section validation result recorded.\", await data(\n c,\n \"POST\",\n `/projects/${s(a.projectId)}/section-evidence/sections/${s(a.sectionId)}/versions/${a.version}/validations`,\n {\n requestId: a.requestId,\n manifestId: a.manifestId,\n status: a.status,\n fixtureHash: a.fixtureHash,\n evidenceDigest: a.evidenceDigest,\n appShell: a.appShell,\n viewportResults: a.viewportResults,\n },\n ))),\n\n def(\"get_deploy_status\", \"Get deploy/build status\",\n \"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.\",\n z.object({}).shape,\n async (c) => ok(\"Deploy status.\", await data(c, \"GET\", `/management/projects/deploy-status`))),\n ];\n }\n\n const defs: ToolDef[] = [\n {\n name: \"list_pages\",\n config: {\n title: \"List pages in the current project\",\n description:\n \"List the pages in the project this MCP key is bound to, each with its full field SCHEMA, pageType (singleton|dynamic), and status. Use it to verify WHERE content lands and to read field keys/types before set_page_content / add_page_field.\",\n inputSchema: {},\n },\n handler: guard(async () =>\n withClient(async (client) => {\n const pages = await client.listPages();\n return ok(\n `${pages.length} page(s) in the bound project.`,\n pages.map((p) => ({\n id: p.id,\n title: p.title,\n slug: p.slug,\n pageType: p.pageType,\n status: p.status,\n fields: p.fields,\n })),\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"get_page\",\n config: {\n title: \"Get a page (with its field schema)\",\n description:\n \"Get one page by id INCLUDING its full field schema (keys, types, nested group/repeater children) and pageType. Read this before set_page_content so you write correctly-keyed values, or before add_page_field so you know the existing keys.\",\n inputSchema: getPageInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getPageInput>) =>\n withClient(async (client) => {\n const page = await client.getPage(args.pageId);\n return ok(\n `Page '${page.title}' (${page.pageType ?? \"page\"}, ${page.fields.length} field(s)).`,\n page,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_page\",\n config: {\n title: \"Create a page\",\n description:\n \"Create a page with its own typed schema. Supports pageType 'singleton' (exactly one entry — Home, About, Contact) and 'dynamic' (many entries sharing the schema — Blog posts, Products). Project-scoped from the key. Additive — does not delete or overwrite existing pages. FIRST read the page's real markup and DECOMPOSE it into a destructured tree: each visual section becomes a nested field — a fixed grouped block → type 'group', a repeating list of items (cards, testimonials, features, FAQs) → type 'repeater' — each carrying its own child `fields`. Do NOT flatten sections into many flat top-level fields. Build the full nested tree, then call this once. 🔴 Every field key must be UNIQUE ACROSS THE WHOLE TREE — the namespace is flat, so 'title' cannot appear in two sections; prefix each with its section ('hero_title', 'faq_title'). Prose fields (headings, body copy, descriptions) are created as RICH TEXT by default; pass richText:false for values that must stay bare strings — hrefs, slugs, ids, emails. That tree is the page's SCHEMA — what it holds. \" +\n DOCTRINE,\n inputSchema: createPageInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createPageInput>) =>\n withClient(async (client) => {\n // A create has no \"before\", so any collision is new. This is THE path that produced the\n // marketing page's six duplicate rows.\n const dupes = duplicateKeys(flatFieldKeys(args.fields));\n if (dupes.length > 0) return fail(duplicateKeyFailure(dupes));\n const page = await client.createPage({\n title: args.title,\n slug: args.slug,\n pageType: args.pageType ?? \"singleton\",\n ...(args.blockJson ? { blockJson: args.blockJson } : {}),\n ...(args.fields ? { fields: args.fields.map(toField) } : {}),\n ...(args.metaTitle !== undefined ? { metaTitle: args.metaTitle } : {}),\n ...(args.metaDescription !== undefined ? { metaDescription: args.metaDescription } : {}),\n });\n return ok(\n `Created ${page.pageType ?? \"page\"} page '${page.title}' (id ${page.id}, slug ${page.slug}) with ${page.fields.length} field(s).`,\n page,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_content_model\",\n config: {\n title: \"Create a content model (reusable schema)\",\n description:\n \"Create a content model — a reusable schema for a dynamic collection (Blog, Products, Testimonials). `fields` may NEST: type 'group' = one nested object of child fields; type 'repeater' = a repeatable array of child objects. Put child fields in each group/repeater's own `fields` (any depth). Pass kind:'block' to create a BLOCK type instead — see that argument.\",\n inputSchema: createModelInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createModelInput>) =>\n withClient(async (client) => {\n const modelDupes = duplicateKeys(flatFieldKeys(args.fields));\n if (modelDupes.length > 0) return fail(duplicateKeyFailure(modelDupes));\n const model = await client.createModel({\n name: args.name,\n slug: args.slug,\n ...(args.description !== undefined ? { description: args.description } : {}),\n ...(args.kind !== undefined ? { kind: args.kind } : {}),\n fields: toFields(args.fields),\n });\n return ok(\n `Created content model '${model.name}' (${model.fields.length} field(s)).`,\n model,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"add_field\",\n config: {\n title: \"Add a field to a content model\",\n description:\n \"Append a field to an existing content model. Reads the model's current fields and adds yours (read-modify-write) — never removes existing fields. For a section/zone, add ONE 'group' (fixed block) or 'repeater' (repeating list) field carrying its child `fields` — don't add the zone's inner fields as separate top-level fields.\",\n inputSchema: addFieldInput.shape,\n },\n handler: guard(async (args: z.infer<typeof addFieldInput>) =>\n withClient(async (client) => {\n const model = await client.getModel(args.modelId);\n // 🔴 Was `model.fields.some(...)` — TOP LEVEL ONLY, so a key colliding with a group's\n // child sailed through. The namespace is flat; the check has to be too.\n const dupes = duplicateKeys([...flatFieldKeys(model.fields), args.key]);\n if (dupes.length > 0) return fail(duplicateKeyFailure(dupes));\n const updated = await client.updateModel(args.modelId, {\n fields: [...model.fields, toField(args)],\n });\n return ok(\n `Added field '${args.key}' to '${updated.name}'. Model now has ${updated.fields.length} field(s).`,\n updated,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"add_page_field\",\n config: {\n title: \"Add a field to a page\",\n description:\n \"Append a field to an existing page's schema (Home, About, a blog template, etc.). Additive — the API rejects a key that already exists and never overwrites or retypes existing fields. Use this when the target is a page (singleton or dynamic); use add_field when the target is a content model. For a section/zone, add ONE 'group' (fixed block) or 'repeater' (repeating list) field carrying its child `fields` — don't add the zone's inner fields as separate top-level fields.\",\n inputSchema: addPageFieldInput.shape,\n },\n handler: guard(async (args: z.infer<typeof addPageFieldInput>) =>\n withClient(async (client) => {\n // No client-side preflight here on purpose. `addPageFields` is an additive PATCH onto\n // the page-fields route, which now refuses a NEW flat-namespace collision itself — so a\n // check here would be a second authority AND an extra round-trip, and the two could\n // drift. `add_field` keeps its check only because it already fetches the model.\n const page = await client.addPageFields(args.pageId, { addFields: [toField(args)] });\n return ok(\n `Added field '${args.key}' to page '${page.title}'. Page now has ${page.fields.length} field(s).`,\n page,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_content_entry\",\n config: {\n title: \"Create a content entry\",\n description:\n \"Create a content entry under a model. Pass its field VALUES in `data`, keyed by field key — INCLUDE ALL REQUIRED FIELDS (create validates them). New entries are drafts; pass status:'published' to take it live. Read get_content_model first for the field keys and which are required.\",\n inputSchema: createEntryInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createEntryInput>) =>\n withClient(async (client) => {\n // One-shot create WITH data — the create route validates required fields, so\n // splitting into create-empty-then-update 400s for any model with a required\n // field. Status is draft-only on create server-side, so publishing needs a\n // follow-up update.\n const created = await client.createEntry({\n contentModelId: args.contentModelId,\n ...(args.slug !== undefined ? { slug: args.slug } : {}),\n ...(args.data !== undefined ? { data: args.data } : {}),\n });\n const entry =\n args.status !== undefined && args.status !== \"draft\"\n ? await client.updateEntry(created.id, { status: args.status })\n : created;\n return ok(\n `Created entry '${entry.slug}' (id ${entry.id}, status ${entry.status}).`,\n entry,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"set_page_content\",\n config: {\n title: \"Set a page's field values (content)\",\n description:\n \"Set a page's field VALUES — the actual content. For a SINGLETON page (Home, About, Site Settings) this creates or updates its one entry, so call it again to edit. `data` is keyed by field key: a nested 'array' (zone) value is an OBJECT { nonRepeatable: { childKey: value }, repeatable: [ { childKey: value } ] }; a primitive 'array' is a plain list; an 'image' value is an asset URL. Read the schema first with get_page. This is how you populate Home/About/Settings — create_content_entry is for dynamic collections only.\",\n inputSchema: setPageContentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof setPageContentInput>) =>\n withClient(async (client) => {\n const entry = await client.setPageContent(args.pageId, {\n data: args.data,\n ...(args.status !== undefined ? { status: args.status } : {}),\n });\n return ok(\n `Set content on page ${args.pageId} (entry ${entry.id}, status ${entry.status}).`,\n entry,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"list_content_entries\",\n config: {\n title: \"List content entries (incl. drafts)\",\n description:\n \"List content entries — including drafts — filtered by model and/or page. Use it to SEE existing content before editing. For a singleton page, pass its pageId to get its single entry.\",\n inputSchema: listEntriesInput.shape,\n },\n handler: guard(async (args: z.infer<typeof listEntriesInput>) =>\n withClient(async (client) => {\n const entries = await client.listEntries({\n ...(args.modelId ? { modelId: args.modelId } : {}),\n ...(args.pageId ? { pageId: args.pageId } : {}),\n ...(args.status ? { status: args.status } : {}),\n });\n return ok(`${entries.length} entr(y/ies).`, entries);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"get_content_entry\",\n config: {\n title: \"Get a content entry (with its values)\",\n description: \"Get one content entry by id INCLUDING its `data` (field values), even when draft.\",\n inputSchema: getEntryInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getEntryInput>) =>\n withClient(async (client) => {\n const entry = await client.getEntry(args.entryId);\n return ok(`Entry '${entry.slug}' (id ${entry.id}, status ${entry.status}).`, entry);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"update_content_entry\",\n config: {\n title: \"Update a content entry's values\",\n description:\n \"Update a content entry's `data` (field values) and/or status by id. `data` is keyed by field key; a nested 'array' (zone) value is an object { nonRepeatable: {…}, repeatable: [{…}] }, a primitive 'array' is a plain list. Use this to edit an existing entry; for a singleton page prefer set_page_content.\",\n inputSchema: updateEntryInput.shape,\n },\n handler: guard(async (args: z.infer<typeof updateEntryInput>) =>\n withClient(async (client) => {\n const entry = await client.updateEntry(args.entryId, {\n ...(args.data !== undefined ? { data: args.data } : {}),\n ...(args.status !== undefined ? { status: args.status } : {}),\n ...(args.slug !== undefined ? { slug: args.slug } : {}),\n });\n return ok(`Updated entry '${entry.slug}' (id ${entry.id}, status ${entry.status}).`, entry);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"upload_asset\",\n config: {\n title: \"Upload an asset to the Media Library\",\n description:\n \"Upload an image/asset from a local file path or a remote URL into the project's Media Library. Returns the asset's stable CDN URL — put that URL into a content entry's image field. Use this BEFORE creating entries that reference images.\",\n inputSchema: uploadAssetInput.shape,\n },\n handler: guard(async (args: z.infer<typeof uploadAssetInput>) =>\n withClient(async (client) => {\n const asset = await client.uploadAsset(args);\n return ok(\n `Uploaded '${asset.filename}' (id ${asset.id}). Put this URL (or the id ${asset.id}) into an image field to attach it: ${asset.url}`,\n asset,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"delete_page\",\n config: {\n title: \"Delete a page\",\n description:\n \"DELETE a page and its content. Destructive but REVERSIBLE — it soft-deletes (can be restored from the dashboard) and is audit-logged. Use it to remove a page you created by mistake. Confirm with the user before deleting content they may want.\",\n inputSchema: deletePageInput.shape,\n },\n handler: guard(async (args: z.infer<typeof deletePageInput>) =>\n withClient(async (client) => {\n const res = await client.deletePage(args.pageId);\n return ok(`Deleted page ${res.id} (soft-delete — restorable from the dashboard).`, res);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"delete_content_entry\",\n config: {\n title: \"Delete a content entry\",\n description:\n \"DELETE a single content entry. Destructive but REVERSIBLE (soft-delete, restorable from the dashboard) and audit-logged. Use it to remove content created by mistake.\",\n inputSchema: deleteEntryInput.shape,\n },\n handler: guard(async (args: z.infer<typeof deleteEntryInput>) =>\n withClient(async (client) => {\n const res = await client.deleteEntry(args.entryId);\n return ok(`Deleted entry ${res.id} (soft-delete — restorable from the dashboard).`, res);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"delete_content_model\",\n config: {\n title: \"Delete a content model\",\n description:\n \"DELETE a content model and its entries. Destructive but REVERSIBLE (soft-delete, restorable from the dashboard) and audit-logged. Confirm with the user first — this removes all content under the model.\",\n inputSchema: deleteModelInput.shape,\n },\n handler: guard(async (args: z.infer<typeof deleteModelInput>) =>\n withClient(async (client) => {\n const res = await client.deleteModel(args.modelId);\n return ok(`Deleted content model ${res.id} and its entries (soft-delete — restorable from the dashboard).`, res);\n }),\n ) as ToolDef[\"handler\"],\n },\n // ── Forms (read-only — discover dashboard forms to embed into the site) ──\n {\n name: \"list_forms\",\n config: {\n title: \"List forms in the current project\",\n description:\n \"List the forms built in the dashboard for the bound project — each with its id, name, and field schema. Use it to find a form to add to the user's site: read it, then write `<BcmsForm form={getForm('Name')} />` (from @bettercms-ai/next) into the page/component where the user wants it.\",\n inputSchema: {},\n },\n handler: guard(async () =>\n withClient(async (client) => {\n const forms = await client.listForms();\n return ok(\n `${forms.length} form(s) in the bound project.`,\n forms.map((f) => ({ id: f.id, name: f.name, fields: f.fields })),\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"get_form\",\n config: {\n title: \"Get a form (with its field schema)\",\n description:\n \"Get one form by id INCLUDING its fields (keys, types, required, options, showIf) and settings (submitLabel, successMessage, redirectUrl, turnstileEnabled, honeypotField). Read this before wiring `<BcmsForm>` so you render the right fields.\",\n inputSchema: getFormInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getFormInput>) =>\n withClient(async (client) => {\n const form = await client.getForm(args.formId);\n return ok(`Form '${form.name}' (${form.fields.length} field(s)).`, form);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_form\",\n config: {\n title: \"Create a form\",\n description:\n \"Create a form (fields + settings) in the bound project. CONFIRM the fields with the user first. Returns the new form's id — then embed it with `<BcmsForm form={getForm('Name')} />` from @bettercms-ai/next. Field types: text,email,textarea,select(needs options),radio(needs options),checkboxes(needs options),checkbox,number,phone,date,url,consent,hidden.\",\n inputSchema: createFormInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createFormInput>) =>\n withClient(async (client) => {\n const form = await client.createForm(args as ManagedFormInput);\n return ok(`Created form '${form.name}' (id ${form.id}). Embed with <BcmsForm form={getForm('${form.name}')} />.`, form);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"update_form\",\n config: {\n title: \"Update a form\",\n description:\n \"Update a form by id — name, fields, or settings. Read get_form first. Passing `fields` REPLACES the array (include all fields to keep).\",\n inputSchema: updateFormInput.shape,\n },\n handler: guard(async (args: z.infer<typeof updateFormInput>) =>\n withClient(async (client) => {\n const { formId, ...input } = args;\n const form = await client.updateForm(formId, input as ManagedFormInput);\n return ok(`Updated form '${form.name}' (id ${form.id}).`, form);\n }),\n ) as ToolDef[\"handler\"],\n },\n // ── Project/page Layout (draft-only; publish remains dashboard-gated) ──\n {\n name: \"get_layout\",\n config: {\n title: \"Get the project or page Layout\",\n description: \"Read the Global Layout or one page's Layout override, including its optimistic revision. Always read this before update_layout. copy:'published' reads the published copy — the only honest receipt for a publish claim.\",\n inputSchema: getLayoutInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getLayoutInput>) => withClient(async (client) => {\n const layout = await client.getManagedLayout(args);\n return ok(`${layout.scope === \"global\" ? \"Global\" : `Page ${layout.pageSlug}`} Layout ${args.copy === \"published\" ? \"PUBLISHED copy\" : \"draft\"} at revision ${layout.revision}.`, layout);\n })) as ToolDef[\"handler\"],\n },\n {\n name: \"update_layout\",\n config: {\n title: \"Apply one Layout draft command\",\n description: \"Apply one permission-shaped values/composition/schema command to the Global Layout or a page override. Draft-only: this never publishes. Pass the revision from get_layout as ifMatch.\",\n inputSchema: commandLayoutInput.shape,\n },\n handler: guard(async (args: z.infer<typeof commandLayoutInput>) => withClient(async (client) => {\n const layout = await client.commandManagedLayout({ ...args, command: args.command as ManagementLayoutCommand });\n return ok(`Updated ${layout.scope === \"global\" ? \"Global\" : `Page ${layout.pageSlug}`} Layout draft to revision ${layout.revision}.`, layout);\n })) as ToolDef[\"handler\"],\n },\n // ── Components (discover + author reusable symbols) ──\n {\n name: \"list_components\",\n config: {\n title: \"List reusable components\",\n description:\n \"List the reusable components in the bound project — each with id, name, slug, category, blockJson, and props. Use it to find a component to render with `<BcmsBlocks>` from @bettercms-ai/next.\",\n inputSchema: {},\n },\n handler: guard(async () =>\n withClient(async (client) => {\n const list = await client.listComponents();\n return ok(\n `${list.length} component(s) in the bound project.`,\n list.map((cmp) => ({ id: cmp.id, name: cmp.name, slug: cmp.slug, category: cmp.category })),\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"get_component\",\n config: {\n title: \"Get a component (with its blockJson)\",\n description:\n \"Get one component by id INCLUDING its blockJson tree and props. Read this before update_component so you keep the existing blocks.\",\n inputSchema: getComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getComponentInput>) =>\n withClient(async (client) => {\n const cmp = await client.getComponent(args.componentId);\n return ok(`Component '${cmp.name}' (${cmp.blockJson.length} block(s)).`, cmp);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"create_component\",\n config: {\n title: \"Create a reusable component\",\n description:\n \"Create a reusable component from a blockJson tree. THIS IS ALSO HOW A PAGE GETS ITS SECTIONS: set `sectionType` (e.g. 'Hero') and the component becomes a placeable section, selectable in the editor's 'Add a section' picker. Components sharing a `sectionType` are its layout VARIANTS — one Hero with a 'Centered' and a 'Two-column' variant, same prop keys, so a swap keeps the content. CONFIRM the structure with the user first. blockJson is an array of blocks — the same set create_page accepts (heading, text/richtext, image, button, spacer, video, columns, section, slider, tabs, navbar, footer, form, component, collection), NOT a narrower one; `section` nests child blocks in props.children and `columns` in props.columns. `props` declares overridable fields. Returns the new id — render with `<BcmsBlocks>`. Always lands as a DRAFT: it is not on the live site until someone publishes it from the dashboard. \" +\n DOCTRINE,\n inputSchema: createComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof createComponentInput>) =>\n withClient(async (client) => {\n const cmp = await client.createComponent(args as ManagedComponentInput);\n return ok(`Created component '${cmp.name}' (id ${cmp.id}, slug ${cmp.slug}).`, cmp);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"list_extraction_candidates\",\n config: {\n title: \"Find sections that repeat across pages\",\n description:\n \"Find sections that appear IDENTICALLY (same structure and styling, different wording) on 3+ places across this project's pages, each proposed as one reusable component. Read-only — nothing changes. Returns a `hash` per candidate to pass to extract_component, plus how many places it appears, which fields differ between copies, and the exact pages involved. Use this before hand-building a component with create_component: if a section already repeats, extracting it is better than adding a 4th copy.\",\n inputSchema: listExtractionCandidatesInput.shape,\n },\n handler: guard(async (args: z.infer<typeof listExtractionCandidatesInput>) =>\n withClient(async (client) => {\n const found = await client.listExtractionCandidates(args.projectId);\n if (found.length === 0) {\n return ok(\"No section repeats on 3 or more pages in this project.\", found);\n }\n const lines = found.map(\n (c) => `- ${c.suggestedName} (hash ${c.hash}) — ${c.uses} places, ${c.props.length} varying field(s)`,\n );\n return ok(`${found.length} repeated section(s):\\n${lines.join(\"\\n\")}`, found);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"extract_component\",\n config: {\n title: \"Extract a repeated section into one component\",\n description:\n \"Fold one candidate from list_extraction_candidates into a single reusable component and repoint EVERY occurrence at it. CONFIRM WITH THE USER FIRST — this rewrites blocks on several pages at once, and name the pages from the candidate's `sites` when you ask. Only page DRAFTS change: the live site is untouched until those pages are published, and the component itself lands as a DRAFT. Fields that differ between copies become component props, so each page keeps its own wording. 409 means the sections were edited since you listed them — re-run list_extraction_candidates and ask again.\",\n inputSchema: extractComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof extractComponentInput>) =>\n withClient(async (client) => {\n const { component, replaced } = await client.extractComponent(args);\n return ok(\n `Created component '${component.name}' (id ${component.id}) and repointed ${replaced} sections to it. Page drafts changed; publish those pages to make it live.`,\n component,\n );\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"update_component\",\n config: {\n title: \"Update a reusable component\",\n description:\n \"Update a component by id — blockJson, props, name, or category. Read get_component first. Passing `blockJson`/`props` REPLACES them. This writes the DRAFT: the change does NOT appear on the live site until someone publishes the component from the dashboard.\",\n inputSchema: updateComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof updateComponentInput>) =>\n withClient(async (client) => {\n const { componentId, ...input } = args;\n const cmp = await client.updateComponent(componentId, input as ManagedComponentInput);\n return ok(`Updated component '${cmp.name}' (id ${cmp.id}).`, cmp);\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"publish_component\",\n config: {\n title: \"Publish a component\",\n description:\n \"Publish a component: copy its DRAFT definition to the live copy and re-bake every published page that embeds it. This is the ONLY way a component reaches the live site — create_component and update_component write drafts, and an unpublished component renders as NOTHING on the live site, with no error. Publish every component you place on a page. 403 PUBLISH_NOT_GRANTED means this connection may author but not publish: say so and let the user publish from the dashboard. 422 means publishing would break a Layout that uses it — the response names which.\",\n inputSchema: getComponentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof getComponentInput>) =>\n withClient(async (client) => {\n const res = await client.fetchJSON<{ data?: unknown }>(\n client.url(`/management/components/${args.componentId}/publish`),\n { method: \"POST\" },\n );\n return ok(\"Published component.\", res.data);\n }),\n ) as ToolDef[\"handler\"],\n },\n\n // ── AI content + SEO actions (Option B) ────────────────────────────────────\n {\n name: \"write_content\",\n config: {\n title: \"Write, rewrite, or translate content\",\n description:\n \"AI-write a piece of copy: action 'write' (draft from a brief), 'rewrite' (improve existing copy), or 'translate' (needs targetLang). Returns the suggested text — apply it with set_page_content or update_content_entry. Uses the workspace's own Anthropic key (BYOK, unmetered) or platform AI credits.\",\n inputSchema: writeContentInput.shape,\n },\n handler: guard(async (args: z.infer<typeof writeContentInput>) =>\n withClient(async (client) => {\n const suggestion = await client.writeContent(args);\n return ok(`Generated ${args.action} suggestion (${suggestion.length} chars).`, { suggestion });\n }),\n ) as ToolDef[\"handler\"],\n },\n {\n name: \"generate_seo_meta\",\n config: {\n title: \"Generate SEO metadata\",\n description:\n \"Generate SEO metadata (metaTitle, metaDescription, keywords, optional JSON-LD) for a piece of content. Pass the page/entry content as `text`. Returns a suggestion to apply via update_page or the entry SEO fields.\",\n inputSchema: generateSeoMetaInput.shape,\n },\n handler: guard(async (args: z.infer<typeof generateSeoMetaInput>) =>\n withClient(async (client) => {\n const meta = await client.generateSeoMeta(args);\n return ok(`Generated SEO metadata: \"${meta.metaTitle}\".`, meta);\n }),\n ) as ToolDef[\"handler\"],\n },\n\n // ── Lifecycle tools (parity with the remote /mcp surface) ──────────────────\n // Media management, form submissions (leads), redirects, SEO, AEO site-files,\n // promote, and entry version history. These call the management endpoints straight\n // through the client's request plumbing — no bespoke SDK method per endpoint.\n ...lifecycleTools(),\n ];\n\n return defs;\n}\n\n/** Register all BetterCMS tools on an MCP server. */\nexport function registerTools(server: McpServer, deps: ToolDeps): void {\n // Give the tools a way to ask the human directly. Threaded here rather than taken as a\n // dep by the caller so buildToolDefs stays server-free for the tests.\n const withElicit: ToolDeps = {\n ...deps,\n elicit: deps.elicit ?? ((params) => server.server.elicitInput(params as never)),\n };\n for (const def of buildToolDefs(withElicit)) {\n server.registerTool(def.name, def.config, def.handler as never);\n }\n}\n","/**\n * Component — a reusable, Webflow-style block tree (a \"symbol\").\n *\n * A component is authored once and placed across pages via `component` blocks\n * (see `ComponentBlock` in `./block.ts`). Its definition lives in `blockJson`;\n * `props` declares a flat allowlist of values an instance may override.\n */\nimport type { ContentBlock } from \"./block.js\";\nimport type { VariantInputMapping } from \"./layout.js\";\n\n/**\n * The category a component belongs to (drives library grouping + icons). The first eight\n * are structural (what the component IS); the last four are the \"Add a section\" library\n * tabs (where it appears). One varchar column, not a PG enum — widening is code-only.\n */\n/**\n * 🔴 THE STRUCTURE DOCTRINE — one sentence, one home, spliced into every surface that builds a page.\n *\n * It lives HERE, beside the component contract it describes, because there are THREE places that teach\n * an agent how to build a page and they drifted apart:\n * • `packages/mcp/src/tools.ts` — the MCP tool descriptions (external agents)\n * • `src/lib/ai/agent.ts` — the in-product Studio Agent's system prompt\n * • `packages/mcp/src/prompts.ts` — the authoring playbook, which a tool call does not carry\n *\n * Only the playbook explained sections. `create_page` taught the SCHEMA axis in detail (\"each visual\n * section becomes a nested field\") and said nothing about STRUCTURE; the Studio Agent's prompt named\n * \"pages & reusable components (structure/layout)\" without ever mentioning `sectionType`.\n *\n * Measured consequence, production 2026-08-18: project `acme` has three components, ALL with\n * `section_type = (none)`, and its home page is 18 loose top-level blocks with ZERO sections. Every\n * generated page came out flat, so the visual editor's section lane — outline, name, move, duplicate,\n * delete, variant swap — had nothing to attach to. The editor was faithfully showing pages that were\n * never built out of sections.\n *\n * A constant rather than three paraphrases, because updating some of them is exactly how this happened.\n */\nexport const SECTION_DOCTRINE =\n \"STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks — they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` — see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: a component's children render WITHOUT field bindings, so their text is NOT click-to-edit on the canvas — it is edited through the component's declared `props` in the section dock. A `section` block's children stay click-to-edit. So when you choose a component, DECLARE A PROP for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. Do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId — hero-centered, hero-split, feature-grid-three, cta-banner and nine more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize the blueprint with create_component so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section — never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.\";\n\nexport type ComponentCategory =\n | \"navbar\"\n | \"footer\"\n | \"button\"\n | \"section\"\n | \"slider\"\n | \"tabs\"\n | \"form\"\n | \"custom\"\n | \"hero\"\n | \"content\"\n | \"social-proof\"\n | \"conversion\";\n\n/**\n * A single overridable field on a component. `target` points at the block + JSON\n * path inside `blockJson` the override writes to (e.g. blockId \"cta\", path\n * \"props.text\"). Keeping overrides a declared allowlist (not arbitrary nested\n * rewrites) keeps instance data small and the contract explicit.\n */\nexport interface ComponentPropDef {\n key: string;\n label: string;\n target: { blockId: string; path: string };\n /**\n * `slot` holds ONE nested component instance — the component-level twin of the\n * content-model field type `component-ref` (see content-model.ts), named differently for\n * the same reason that one is: `component` already means a BLOCK type. Its value is\n * `{ componentId, overrides }` and its `target.path` is `props`, so filling a slot writes\n * that object over an empty `component` block's props.\n *\n * On a PAGE a slot fill is a LIVE reference; a published ENTRY freezes it (resolveDeep).\n */\n /**\n * The EDITOR contract, not a storage one: `applyOverrides` writes the value at\n * `target.path` whatever its shape, so `type` decides which control the inspector renders\n * and what shape that control produces (FLO-1020).\n *\n * number → a number (heading.level, columns.count)\n * select → one string from `config.options`\n * group → an object keyed by `config.fields`\n * table → an array of such objects (slider.slides)\n *\n * `reference` is absent on purpose: nothing resolves a content-entry id at component render\n * time, so such a prop would save cleanly and render as nothing.\n */\n type: \"text\" | \"richtext\" | \"image\" | \"url\" | \"boolean\" | \"number\" | \"select\" | \"group\" | \"table\" | \"slot\";\n defaultValue?: unknown;\n /** Per-type settings; the save schema enforces that each is present on the type needing it. */\n config?: {\n /** `slot` — a pick allowlist. */\n componentIds?: string[];\n /** `select` — the choices. Required, and a default must be one of them. */\n options?: string[];\n /** `group` / `table` — the sub-shape, nestable to 3 levels. */\n fields?: ComponentSubField[];\n /** `number` — bounds for the control. */\n min?: number;\n max?: number;\n step?: number;\n } & Record<string, unknown>;\n}\n\n/** One field inside a `group` prop or a `table` row. Recursive, capped at 3 levels deep. */\nexport interface ComponentSubField {\n key: string;\n label: string;\n /** No `slot`: a nested component instance belongs on the prop itself, not inside a row. */\n type: Exclude<ComponentPropDef[\"type\"], \"slot\">;\n defaultValue?: unknown;\n options?: string[];\n fields?: ComponentSubField[];\n}\n\n/** The value a `slot` prop holds — the draft half of a `component-ref`, deliberately. */\nexport interface SlotValue {\n componentId: string;\n overrides?: Record<string, unknown>;\n}\n\n/**\n * A component is a DRAFT until published; only the published copy reaches a visitor.\n * Mirrors pages and entries. See migration 0186_component_draft_live_split.sql.\n */\nexport type ComponentStatus = \"draft\" | \"published\";\n\n/**\n * Archive state (FLO-1012), deliberately SEPARATE from `ComponentStatus`.\n *\n * Archive takes a component out of the working set — hidden from the components list by\n * default, not offered in the visual editor's insert surfaces — while every existing usage\n * keeps serving. It is not unpublish (which pulls the live copy and re-bakes every page that\n * embeds it) and it is not delete.\n *\n * It is a timestamp rather than a third `status` value because a component can be published\n * AND archived; collapsing the two would lose the bit restore has to put back.\n */\n\nexport interface Component {\n id: string;\n workspaceId: string;\n projectId?: string | null;\n name: string;\n slug: string;\n category: ComponentCategory;\n /**\n * Section library: the family this component is a LAYOUT of, e.g. \"Hero\". `name` is the\n * layout label (\"Centered\"), so components sharing a sectionType are selectable variants\n * of one section. Null/absent = an ordinary component, not shown in the section library.\n */\n sectionType?: string | null;\n /** First-class variant family membership; exact workspace/project scope is enforced in DB. */\n variantGroupId?: string | null;\n variantInputMappings?: VariantInputMapping[];\n /** Placement governance: `*`, `slug:<page-slug>`, and/or `type:<page-type>`. */\n allowedOn: string[];\n description?: string | null;\n /** The DRAFT definition. Every builder/autosave/import write path targets these two. */\n blockJson: ContentBlock[];\n props: ComponentPropDef[];\n status: ComponentStatus;\n /** When it left the working set, or null/absent while active. @see ComponentStatus */\n archivedAt?: string | Date | null;\n /** Derived from `archivedAt`, so a client never has to know the column. */\n archived?: boolean;\n /**\n * The LIVE snapshot get_components_by_handle() serves. Null until the first publish.\n * Returned by GET-one (the Compare view needs it), omitted from list rows for payload.\n */\n publishedBlockJson?: ContentBlock[] | null;\n publishedProps?: ComponentPropDef[] | null;\n publishedAt?: string | null; // ISO 8601\n /**\n * Computed in SQL on list/get, never stored:\n * status='published' AND (blockJson or props has diverged from its published copy).\n * An exact jsonb compare, so it self-clears when an edit is reverted.\n */\n pendingChanges?: boolean;\n thumbnail?: string | null;\n createdAt: string; // ISO 8601\n updatedAt: string; // ISO 8601\n}\n\n/**\n * Public/delivery projection — the fields a renderer needs to resolve instances.\n *\n * DELIBERATELY UNCHANGED by the 0186 draft/live split: delivery aliases\n * publishedBlockJson -> blockJson, so every already-deployed site and every\n * bcms-content.json on disk keeps a byte-identical wire shape. Do not add `status` here —\n * delivery only ever returns published rows, so it would always be the same constant.\n */\nexport interface DeliveryComponent {\n id: string;\n name: string;\n slug: string;\n category: ComponentCategory;\n sectionType?: string | null;\n blockJson: ContentBlock[];\n props: ComponentPropDef[];\n}\n","/**\n * Generated from lucide-react@1.8.0 dynamic icon names.\n * Legacy CamelCase identifiers remain valid for existing Layout documents.\n */\nexport const LAYOUT_SECTION_ICONS: readonly string[] = Object.freeze([\n \"LayoutPanelTop\",\n \"PanelTop\",\n \"PanelBottom\",\n \"Menu\",\n \"Navigation\",\n \"Megaphone\",\n \"GalleryHorizontal\",\n \"Rows3\",\n \"Grid2X2\",\n \"FileText\",\n \"Link\",\n \"Contact\",\n \"BadgeInfo\",\n \"Sparkles\",\n \"a-arrow-down\",\n \"a-arrow-up\",\n \"a-large-small\",\n \"accessibility\",\n \"activity\",\n \"air-vent\",\n \"airplay\",\n \"alarm-clock-check\",\n \"alarm-check\",\n \"alarm-clock-minus\",\n \"alarm-minus\",\n \"alarm-clock-off\",\n \"alarm-clock-plus\",\n \"alarm-plus\",\n \"alarm-clock\",\n \"alarm-smoke\",\n \"album\",\n \"align-center-horizontal\",\n \"align-center-vertical\",\n \"align-end-horizontal\",\n \"align-end-vertical\",\n \"align-horizontal-distribute-center\",\n \"align-horizontal-distribute-end\",\n \"align-horizontal-distribute-start\",\n \"align-horizontal-justify-center\",\n \"align-horizontal-justify-end\",\n \"align-horizontal-justify-start\",\n \"align-horizontal-space-around\",\n \"align-horizontal-space-between\",\n \"align-start-horizontal\",\n \"align-start-vertical\",\n \"align-vertical-distribute-center\",\n \"align-vertical-distribute-end\",\n \"align-vertical-distribute-start\",\n \"align-vertical-justify-center\",\n \"align-vertical-justify-end\",\n \"align-vertical-justify-start\",\n \"align-vertical-space-around\",\n \"align-vertical-space-between\",\n \"ambulance\",\n \"ampersand\",\n \"ampersands\",\n \"amphora\",\n \"anchor\",\n \"angry\",\n \"annoyed\",\n \"antenna\",\n \"anvil\",\n \"aperture\",\n \"app-window-mac\",\n \"app-window\",\n \"apple\",\n \"archive-restore\",\n \"archive-x\",\n \"archive\",\n \"armchair\",\n \"arrow-big-down-dash\",\n \"arrow-big-down\",\n \"arrow-big-left-dash\",\n \"arrow-big-left\",\n \"arrow-big-right-dash\",\n \"arrow-big-right\",\n \"arrow-big-up-dash\",\n \"arrow-big-up\",\n \"arrow-down-0-1\",\n \"arrow-down-01\",\n \"arrow-down-1-0\",\n \"arrow-down-10\",\n \"arrow-down-a-z\",\n \"arrow-down-az\",\n \"arrow-down-from-line\",\n \"arrow-down-left\",\n \"arrow-down-narrow-wide\",\n \"arrow-down-right\",\n \"arrow-down-to-dot\",\n \"arrow-down-to-line\",\n \"arrow-down-up\",\n \"arrow-down-wide-narrow\",\n \"sort-desc\",\n \"arrow-down-z-a\",\n \"arrow-down-za\",\n \"arrow-down\",\n \"arrow-left-from-line\",\n \"arrow-left-right\",\n \"arrow-left-to-line\",\n \"arrow-left\",\n \"arrow-right-from-line\",\n \"arrow-right-left\",\n \"arrow-right-to-line\",\n \"arrow-right\",\n \"arrow-up-0-1\",\n \"arrow-up-01\",\n \"arrow-up-1-0\",\n \"arrow-up-10\",\n \"arrow-up-a-z\",\n \"arrow-up-az\",\n \"arrow-up-down\",\n \"arrow-up-from-dot\",\n \"arrow-up-from-line\",\n \"arrow-up-left\",\n \"arrow-up-narrow-wide\",\n \"sort-asc\",\n \"arrow-up-right\",\n \"arrow-up-to-line\",\n \"arrow-up-wide-narrow\",\n \"arrow-up-z-a\",\n \"arrow-up-za\",\n \"arrow-up\",\n \"arrows-up-from-line\",\n \"asterisk\",\n \"at-sign\",\n \"atom\",\n \"audio-lines\",\n \"audio-waveform\",\n \"award\",\n \"axe\",\n \"axis-3d\",\n \"axis-3-d\",\n \"baby\",\n \"backpack\",\n \"badge-alert\",\n \"badge-cent\",\n \"badge-check\",\n \"verified\",\n \"badge-dollar-sign\",\n \"badge-euro\",\n \"badge-indian-rupee\",\n \"badge-info\",\n \"badge-japanese-yen\",\n \"badge-minus\",\n \"badge-percent\",\n \"badge-plus\",\n \"badge-pound-sterling\",\n \"badge-question-mark\",\n \"badge-help\",\n \"badge-russian-ruble\",\n \"badge-swiss-franc\",\n \"badge-turkish-lira\",\n \"badge-x\",\n \"badge\",\n \"baggage-claim\",\n \"balloon\",\n \"ban\",\n \"banana\",\n \"bandage\",\n \"banknote-arrow-down\",\n \"banknote-arrow-up\",\n \"banknote-x\",\n \"banknote\",\n \"barcode\",\n \"barrel\",\n \"baseline\",\n \"bath\",\n \"battery-charging\",\n \"battery-full\",\n \"battery-low\",\n \"battery-medium\",\n \"battery-plus\",\n \"battery-warning\",\n \"battery\",\n \"beaker\",\n \"bean-off\",\n \"bean\",\n \"bed-double\",\n \"bed-single\",\n \"bed\",\n \"beef-off\",\n \"beef\",\n \"beer-off\",\n \"beer\",\n \"bell-dot\",\n \"bell-electric\",\n \"bell-minus\",\n \"bell-off\",\n \"bell-plus\",\n \"bell-ring\",\n \"bell\",\n \"between-horizontal-end\",\n \"between-horizonal-end\",\n \"between-horizontal-start\",\n \"between-horizonal-start\",\n \"between-vertical-end\",\n \"between-vertical-start\",\n \"biceps-flexed\",\n \"bike\",\n \"binary\",\n \"binoculars\",\n \"biohazard\",\n \"bird\",\n \"birdhouse\",\n \"bitcoin\",\n \"blend\",\n \"blinds\",\n \"blocks\",\n \"bluetooth-connected\",\n \"bluetooth-off\",\n \"bluetooth-searching\",\n \"bluetooth\",\n \"bold\",\n \"bolt\",\n \"bomb\",\n \"bone\",\n \"book-a\",\n \"book-alert\",\n \"book-audio\",\n \"book-check\",\n \"book-copy\",\n \"book-dashed\",\n \"book-template\",\n \"book-down\",\n \"book-headphones\",\n \"book-heart\",\n \"book-image\",\n \"book-key\",\n \"book-lock\",\n \"book-marked\",\n \"book-minus\",\n \"book-open-check\",\n \"book-open-text\",\n \"book-open\",\n \"book-plus\",\n \"book-search\",\n \"book-text\",\n \"book-type\",\n \"book-up-2\",\n \"book-up\",\n \"book-user\",\n \"book-x\",\n \"book\",\n \"bookmark-check\",\n \"bookmark-minus\",\n \"bookmark-off\",\n \"bookmark-plus\",\n \"bookmark-x\",\n \"bookmark\",\n \"boom-box\",\n \"bot-message-square\",\n \"bot-off\",\n \"bot\",\n \"bottle-wine\",\n \"bow-arrow\",\n \"box\",\n \"boxes\",\n \"braces\",\n \"curly-braces\",\n \"brackets\",\n \"brain-circuit\",\n \"brain-cog\",\n \"brain\",\n \"brick-wall-fire\",\n \"brick-wall-shield\",\n \"brick-wall\",\n \"briefcase-business\",\n \"briefcase-conveyor-belt\",\n \"briefcase-medical\",\n \"briefcase\",\n \"bring-to-front\",\n \"brush-cleaning\",\n \"brush\",\n \"bubbles\",\n \"bug-off\",\n \"bug-play\",\n \"bug\",\n \"building-2\",\n \"building\",\n \"bus-front\",\n \"bus\",\n \"cable-car\",\n \"cable\",\n \"cake-slice\",\n \"cake\",\n \"calculator\",\n \"calendar-1\",\n \"calendar-arrow-down\",\n \"calendar-arrow-up\",\n \"calendar-check-2\",\n \"calendar-check\",\n \"calendar-clock\",\n \"calendar-cog\",\n \"calendar-days\",\n \"calendar-fold\",\n \"calendar-heart\",\n \"calendar-minus-2\",\n \"calendar-minus\",\n \"calendar-off\",\n \"calendar-plus-2\",\n \"calendar-plus\",\n \"calendar-range\",\n \"calendar-search\",\n \"calendar-sync\",\n \"calendar-x-2\",\n \"calendar-x\",\n \"calendar\",\n \"calendars\",\n \"camera-off\",\n \"camera\",\n \"candy-cane\",\n \"candy-off\",\n \"candy\",\n \"cannabis-off\",\n \"cannabis\",\n \"captions-off\",\n \"captions\",\n \"subtitles\",\n \"car-front\",\n \"car-taxi-front\",\n \"car\",\n \"caravan\",\n \"card-sim\",\n \"carrot\",\n \"case-lower\",\n \"case-sensitive\",\n \"case-upper\",\n \"cassette-tape\",\n \"cast\",\n \"castle\",\n \"cat\",\n \"cctv-off\",\n \"cctv\",\n \"chart-area\",\n \"area-chart\",\n \"chart-bar-big\",\n \"bar-chart-horizontal-big\",\n \"chart-bar-decreasing\",\n \"chart-bar-increasing\",\n \"chart-bar-stacked\",\n \"chart-bar\",\n \"bar-chart-horizontal\",\n \"chart-candlestick\",\n \"candlestick-chart\",\n \"chart-column-big\",\n \"bar-chart-big\",\n \"chart-column-decreasing\",\n \"chart-column-increasing\",\n \"bar-chart-4\",\n \"chart-column-stacked\",\n \"chart-column\",\n \"bar-chart-3\",\n \"chart-gantt\",\n \"chart-line\",\n \"line-chart\",\n \"chart-network\",\n \"chart-no-axes-column-decreasing\",\n \"chart-no-axes-column-increasing\",\n \"bar-chart\",\n \"chart-no-axes-column\",\n \"bar-chart-2\",\n \"chart-no-axes-combined\",\n \"chart-no-axes-gantt\",\n \"gantt-chart\",\n \"chart-pie\",\n \"pie-chart\",\n \"chart-scatter\",\n \"scatter-chart\",\n \"chart-spline\",\n \"check-check\",\n \"check-line\",\n \"check\",\n \"chef-hat\",\n \"cherry\",\n \"chess-bishop\",\n \"chess-king\",\n \"chess-knight\",\n \"chess-pawn\",\n \"chess-queen\",\n \"chess-rook\",\n \"chevron-down\",\n \"chevron-first\",\n \"chevron-last\",\n \"chevron-left\",\n \"chevron-right\",\n \"chevron-up\",\n \"chevrons-down-up\",\n \"chevrons-down\",\n \"chevrons-left-right-ellipsis\",\n \"chevrons-left-right\",\n \"chevrons-left\",\n \"chevrons-right-left\",\n \"chevrons-right\",\n \"chevrons-up-down\",\n \"chevrons-up\",\n \"church\",\n \"cigarette-off\",\n \"cigarette\",\n \"circle-alert\",\n \"alert-circle\",\n \"circle-arrow-down\",\n \"arrow-down-circle\",\n \"circle-arrow-left\",\n \"arrow-left-circle\",\n \"circle-arrow-out-down-left\",\n \"arrow-down-left-from-circle\",\n \"circle-arrow-out-down-right\",\n \"arrow-down-right-from-circle\",\n \"circle-arrow-out-up-left\",\n \"arrow-up-left-from-circle\",\n \"circle-arrow-out-up-right\",\n \"arrow-up-right-from-circle\",\n \"circle-arrow-right\",\n \"arrow-right-circle\",\n \"circle-arrow-up\",\n \"arrow-up-circle\",\n \"circle-check-big\",\n \"check-circle\",\n \"circle-check\",\n \"check-circle-2\",\n \"circle-chevron-down\",\n \"chevron-down-circle\",\n \"circle-chevron-left\",\n \"chevron-left-circle\",\n \"circle-chevron-right\",\n \"chevron-right-circle\",\n \"circle-chevron-up\",\n \"chevron-up-circle\",\n \"circle-dashed\",\n \"circle-divide\",\n \"divide-circle\",\n \"circle-dollar-sign\",\n \"circle-dot-dashed\",\n \"circle-dot\",\n \"circle-ellipsis\",\n \"circle-equal\",\n \"circle-fading-arrow-up\",\n \"circle-fading-plus\",\n \"circle-gauge\",\n \"gauge-circle\",\n \"circle-minus\",\n \"minus-circle\",\n \"circle-off\",\n \"circle-parking-off\",\n \"parking-circle-off\",\n \"circle-parking\",\n \"parking-circle\",\n \"circle-pause\",\n \"pause-circle\",\n \"circle-percent\",\n \"percent-circle\",\n \"circle-pile\",\n \"circle-play\",\n \"play-circle\",\n \"circle-plus\",\n \"plus-circle\",\n \"circle-pound-sterling\",\n \"circle-power\",\n \"power-circle\",\n \"circle-question-mark\",\n \"help-circle\",\n \"circle-help\",\n \"circle-slash-2\",\n \"circle-slashed\",\n \"circle-slash\",\n \"circle-small\",\n \"circle-star\",\n \"circle-stop\",\n \"stop-circle\",\n \"circle-user-round\",\n \"user-circle-2\",\n \"circle-user\",\n \"user-circle\",\n \"circle-x\",\n \"x-circle\",\n \"circle\",\n \"circuit-board\",\n \"citrus\",\n \"clapperboard\",\n \"clipboard-check\",\n \"clipboard-clock\",\n \"clipboard-copy\",\n \"clipboard-list\",\n \"clipboard-minus\",\n \"clipboard-paste\",\n \"clipboard-pen-line\",\n \"clipboard-signature\",\n \"clipboard-pen\",\n \"clipboard-edit\",\n \"clipboard-plus\",\n \"clipboard-type\",\n \"clipboard-x\",\n \"clipboard\",\n \"clock-1\",\n \"clock-10\",\n \"clock-11\",\n \"clock-12\",\n \"clock-2\",\n \"clock-3\",\n \"clock-4\",\n \"clock-5\",\n \"clock-6\",\n \"clock-7\",\n \"clock-8\",\n \"clock-9\",\n \"clock-alert\",\n \"clock-arrow-down\",\n \"clock-arrow-up\",\n \"clock-check\",\n \"clock-fading\",\n \"clock-plus\",\n \"clock\",\n \"closed-caption\",\n \"cloud-alert\",\n \"cloud-backup\",\n \"cloud-check\",\n \"cloud-cog\",\n \"cloud-download\",\n \"download-cloud\",\n \"cloud-drizzle\",\n \"cloud-fog\",\n \"cloud-hail\",\n \"cloud-lightning\",\n \"cloud-moon-rain\",\n \"cloud-moon\",\n \"cloud-off\",\n \"cloud-rain-wind\",\n \"cloud-rain\",\n \"cloud-snow\",\n \"cloud-sun-rain\",\n \"cloud-sun\",\n \"cloud-sync\",\n \"cloud-upload\",\n \"upload-cloud\",\n \"cloud\",\n \"cloudy\",\n \"clover\",\n \"club\",\n \"code-xml\",\n \"code-2\",\n \"code\",\n \"coffee\",\n \"cog\",\n \"coins\",\n \"columns-2\",\n \"columns\",\n \"columns-3-cog\",\n \"columns-settings\",\n \"table-config\",\n \"columns-3\",\n \"panels-left-right\",\n \"columns-4\",\n \"combine\",\n \"command\",\n \"compass\",\n \"component\",\n \"computer\",\n \"concierge-bell\",\n \"cone\",\n \"construction\",\n \"contact-round\",\n \"contact-2\",\n \"contact\",\n \"container\",\n \"contrast\",\n \"cookie\",\n \"cooking-pot\",\n \"copy-check\",\n \"copy-minus\",\n \"copy-plus\",\n \"copy-slash\",\n \"copy-x\",\n \"copy\",\n \"copyleft\",\n \"copyright\",\n \"corner-down-left\",\n \"corner-down-right\",\n \"corner-left-down\",\n \"corner-left-up\",\n \"corner-right-down\",\n \"corner-right-up\",\n \"corner-up-left\",\n \"corner-up-right\",\n \"cpu\",\n \"creative-commons\",\n \"credit-card\",\n \"croissant\",\n \"crop\",\n \"cross\",\n \"crosshair\",\n \"crown\",\n \"cuboid\",\n \"cup-soda\",\n \"currency\",\n \"cylinder\",\n \"dam\",\n \"database-backup\",\n \"database-search\",\n \"database-zap\",\n \"database\",\n \"decimals-arrow-left\",\n \"decimals-arrow-right\",\n \"delete\",\n \"dessert\",\n \"diameter\",\n \"diamond-minus\",\n \"diamond-percent\",\n \"percent-diamond\",\n \"diamond-plus\",\n \"diamond\",\n \"dice-1\",\n \"dice-2\",\n \"dice-3\",\n \"dice-4\",\n \"dice-5\",\n \"dice-6\",\n \"dices\",\n \"diff\",\n \"disc-2\",\n \"disc-3\",\n \"disc-album\",\n \"disc\",\n \"divide\",\n \"dna-off\",\n \"dna\",\n \"dock\",\n \"dog\",\n \"dollar-sign\",\n \"donut\",\n \"door-closed-locked\",\n \"door-closed\",\n \"door-open\",\n \"dot\",\n \"download\",\n \"drafting-compass\",\n \"drama\",\n \"drill\",\n \"drone\",\n \"droplet-off\",\n \"droplet\",\n \"droplets\",\n \"drum\",\n \"drumstick\",\n \"dumbbell\",\n \"ear-off\",\n \"ear\",\n \"earth-lock\",\n \"earth\",\n \"globe-2\",\n \"eclipse\",\n \"egg-fried\",\n \"egg-off\",\n \"egg\",\n \"ellipse\",\n \"ellipsis-vertical\",\n \"more-vertical\",\n \"ellipsis\",\n \"more-horizontal\",\n \"equal-approximately\",\n \"equal-not\",\n \"equal\",\n \"eraser\",\n \"ethernet-port\",\n \"euro\",\n \"ev-charger\",\n \"expand\",\n \"external-link\",\n \"eye-closed\",\n \"eye-off\",\n \"eye\",\n \"factory\",\n \"fan\",\n \"fast-forward\",\n \"feather\",\n \"fence\",\n \"ferris-wheel\",\n \"file-archive\",\n \"file-axis-3d\",\n \"file-axis-3-d\",\n \"file-badge\",\n \"file-badge-2\",\n \"file-box\",\n \"file-braces-corner\",\n \"file-json-2\",\n \"file-braces\",\n \"file-json\",\n \"file-chart-column-increasing\",\n \"file-bar-chart\",\n \"file-chart-column\",\n \"file-bar-chart-2\",\n \"file-chart-line\",\n \"file-line-chart\",\n \"file-chart-pie\",\n \"file-pie-chart\",\n \"file-check-corner\",\n \"file-check-2\",\n \"file-check\",\n \"file-clock\",\n \"file-code-corner\",\n \"file-code-2\",\n \"file-code\",\n \"file-cog\",\n \"file-cog-2\",\n \"file-diff\",\n \"file-digit\",\n \"file-down\",\n \"file-exclamation-point\",\n \"file-warning\",\n \"file-headphone\",\n \"file-audio\",\n \"file-audio-2\",\n \"file-heart\",\n \"file-image\",\n \"file-input\",\n \"file-key\",\n \"file-key-2\",\n \"file-lock\",\n \"file-lock-2\",\n \"file-minus-corner\",\n \"file-minus-2\",\n \"file-minus\",\n \"file-music\",\n \"file-output\",\n \"file-pen-line\",\n \"file-signature\",\n \"file-pen\",\n \"file-edit\",\n \"file-play\",\n \"file-video\",\n \"file-plus-corner\",\n \"file-plus-2\",\n \"file-plus\",\n \"file-question-mark\",\n \"file-question\",\n \"file-scan\",\n \"file-search-corner\",\n \"file-search-2\",\n \"file-search\",\n \"file-signal\",\n \"file-volume-2\",\n \"file-sliders\",\n \"file-spreadsheet\",\n \"file-stack\",\n \"file-symlink\",\n \"file-terminal\",\n \"file-text\",\n \"file-type-corner\",\n \"file-type-2\",\n \"file-type\",\n \"file-up\",\n \"file-user\",\n \"file-video-camera\",\n \"file-video-2\",\n \"file-volume\",\n \"file-x-corner\",\n \"file-x-2\",\n \"file-x\",\n \"file\",\n \"files\",\n \"film\",\n \"fingerprint-pattern\",\n \"fingerprint\",\n \"fire-extinguisher\",\n \"fish-off\",\n \"fish-symbol\",\n \"fish\",\n \"fishing-hook\",\n \"fishing-rod\",\n \"flag-off\",\n \"flag-triangle-left\",\n \"flag-triangle-right\",\n \"flag\",\n \"flame-kindling\",\n \"flame\",\n \"flashlight-off\",\n \"flashlight\",\n \"flask-conical-off\",\n \"flask-conical\",\n \"flask-round\",\n \"flip-horizontal-2\",\n \"flip-vertical-2\",\n \"flower-2\",\n \"flower\",\n \"focus\",\n \"fold-horizontal\",\n \"fold-vertical\",\n \"folder-archive\",\n \"folder-check\",\n \"folder-clock\",\n \"folder-closed\",\n \"folder-code\",\n \"folder-cog\",\n \"folder-cog-2\",\n \"folder-dot\",\n \"folder-down\",\n \"folder-git-2\",\n \"folder-git\",\n \"folder-heart\",\n \"folder-input\",\n \"folder-kanban\",\n \"folder-key\",\n \"folder-lock\",\n \"folder-minus\",\n \"folder-open-dot\",\n \"folder-open\",\n \"folder-output\",\n \"folder-pen\",\n \"folder-edit\",\n \"folder-plus\",\n \"folder-root\",\n \"folder-search-2\",\n \"folder-search\",\n \"folder-symlink\",\n \"folder-sync\",\n \"folder-tree\",\n \"folder-up\",\n \"folder-x\",\n \"folder\",\n \"folders\",\n \"footprints\",\n \"forklift\",\n \"form\",\n \"forward\",\n \"frame\",\n \"frown\",\n \"fuel\",\n \"fullscreen\",\n \"funnel-plus\",\n \"funnel-x\",\n \"filter-x\",\n \"funnel\",\n \"filter\",\n \"gallery-horizontal-end\",\n \"gallery-horizontal\",\n \"gallery-thumbnails\",\n \"gallery-vertical-end\",\n \"gallery-vertical\",\n \"gamepad-2\",\n \"gamepad-directional\",\n \"gamepad\",\n \"gauge\",\n \"gavel\",\n \"gem\",\n \"georgian-lari\",\n \"ghost\",\n \"gift\",\n \"git-branch-minus\",\n \"git-branch-plus\",\n \"git-branch\",\n \"git-commit-horizontal\",\n \"git-commit\",\n \"git-commit-vertical\",\n \"git-compare-arrows\",\n \"git-compare\",\n \"git-fork\",\n \"git-graph\",\n \"git-merge-conflict\",\n \"git-merge\",\n \"git-pull-request-arrow\",\n \"git-pull-request-closed\",\n \"git-pull-request-create-arrow\",\n \"git-pull-request-create\",\n \"git-pull-request-draft\",\n \"git-pull-request\",\n \"glass-water\",\n \"glasses\",\n \"globe-lock\",\n \"globe-off\",\n \"globe-x\",\n \"globe\",\n \"goal\",\n \"gpu\",\n \"graduation-cap\",\n \"grape\",\n \"grid-2x2-check\",\n \"grid-2-x-2-check\",\n \"grid-2x2-plus\",\n \"grid-2-x-2-plus\",\n \"grid-2x2-x\",\n \"grid-2-x-2-x\",\n \"grid-2x2\",\n \"grid-2-x-2\",\n \"grid-3x2\",\n \"grid-3x3\",\n \"grid\",\n \"grid-3-x-3\",\n \"grip-horizontal\",\n \"grip-vertical\",\n \"grip\",\n \"group\",\n \"guitar\",\n \"ham\",\n \"hamburger\",\n \"hammer\",\n \"hand-coins\",\n \"hand-fist\",\n \"hand-grab\",\n \"grab\",\n \"hand-heart\",\n \"hand-helping\",\n \"helping-hand\",\n \"hand-metal\",\n \"hand-platter\",\n \"hand\",\n \"handbag\",\n \"handshake\",\n \"hard-drive-download\",\n \"hard-drive-upload\",\n \"hard-drive\",\n \"hard-hat\",\n \"hash\",\n \"hat-glasses\",\n \"haze\",\n \"hd\",\n \"hdmi-port\",\n \"heading-1\",\n \"heading-2\",\n \"heading-3\",\n \"heading-4\",\n \"heading-5\",\n \"heading-6\",\n \"heading\",\n \"headphone-off\",\n \"headphones\",\n \"headset\",\n \"heart-crack\",\n \"heart-handshake\",\n \"heart-minus\",\n \"heart-off\",\n \"heart-plus\",\n \"heart-pulse\",\n \"heart\",\n \"heater\",\n \"helicopter\",\n \"hexagon\",\n \"highlighter\",\n \"history\",\n \"hop-off\",\n \"hop\",\n \"hospital\",\n \"hotel\",\n \"hourglass\",\n \"house-heart\",\n \"house-plug\",\n \"house-plus\",\n \"house-wifi\",\n \"house\",\n \"home\",\n \"ice-cream-bowl\",\n \"ice-cream-2\",\n \"ice-cream-cone\",\n \"ice-cream\",\n \"id-card-lanyard\",\n \"id-card\",\n \"image-down\",\n \"image-minus\",\n \"image-off\",\n \"image-play\",\n \"image-plus\",\n \"image-up\",\n \"image-upscale\",\n \"image\",\n \"images\",\n \"import\",\n \"inbox\",\n \"indian-rupee\",\n \"infinity\",\n \"info\",\n \"inspection-panel\",\n \"italic\",\n \"iteration-ccw\",\n \"iteration-cw\",\n \"japanese-yen\",\n \"joystick\",\n \"kanban\",\n \"kayak\",\n \"key-round\",\n \"key-square\",\n \"key\",\n \"keyboard-music\",\n \"keyboard-off\",\n \"keyboard\",\n \"lamp-ceiling\",\n \"lamp-desk\",\n \"lamp-floor\",\n \"lamp-wall-down\",\n \"lamp-wall-up\",\n \"lamp\",\n \"land-plot\",\n \"landmark\",\n \"languages\",\n \"laptop-minimal-check\",\n \"laptop-minimal\",\n \"laptop-2\",\n \"laptop\",\n \"lasso-select\",\n \"lasso\",\n \"laugh\",\n \"layers-2\",\n \"layers-plus\",\n \"layers\",\n \"layers-3\",\n \"layout-dashboard\",\n \"layout-grid\",\n \"layout-list\",\n \"layout-panel-left\",\n \"layout-panel-top\",\n \"layout-template\",\n \"leaf\",\n \"leafy-green\",\n \"lectern\",\n \"lens-concave\",\n \"lens-convex\",\n \"library-big\",\n \"library\",\n \"life-buoy\",\n \"ligature\",\n \"lightbulb-off\",\n \"lightbulb\",\n \"line-dot-right-horizontal\",\n \"line-squiggle\",\n \"line-style\",\n \"link-2-off\",\n \"link-2\",\n \"link\",\n \"list-check\",\n \"list-checks\",\n \"list-chevrons-down-up\",\n \"list-chevrons-up-down\",\n \"list-collapse\",\n \"list-end\",\n \"list-filter-plus\",\n \"list-filter\",\n \"list-indent-decrease\",\n \"outdent\",\n \"indent-decrease\",\n \"list-indent-increase\",\n \"indent\",\n \"indent-increase\",\n \"list-minus\",\n \"list-music\",\n \"list-ordered\",\n \"list-plus\",\n \"list-restart\",\n \"list-start\",\n \"list-todo\",\n \"list-tree\",\n \"list-video\",\n \"list-x\",\n \"list\",\n \"loader-circle\",\n \"loader-2\",\n \"loader-pinwheel\",\n \"loader\",\n \"locate-fixed\",\n \"locate-off\",\n \"locate\",\n \"lock-keyhole-open\",\n \"unlock-keyhole\",\n \"lock-keyhole\",\n \"lock-open\",\n \"unlock\",\n \"lock\",\n \"log-in\",\n \"log-out\",\n \"logs\",\n \"lollipop\",\n \"luggage\",\n \"magnet\",\n \"mail-check\",\n \"mail-minus\",\n \"mail-open\",\n \"mail-plus\",\n \"mail-question-mark\",\n \"mail-question\",\n \"mail-search\",\n \"mail-warning\",\n \"mail-x\",\n \"mail\",\n \"mailbox\",\n \"mails\",\n \"map-minus\",\n \"map-pin-check-inside\",\n \"map-pin-check\",\n \"map-pin-house\",\n \"map-pin-minus-inside\",\n \"map-pin-minus\",\n \"map-pin-off\",\n \"map-pin-pen\",\n \"location-edit\",\n \"map-pin-plus-inside\",\n \"map-pin-plus\",\n \"map-pin-search\",\n \"map-pin-x-inside\",\n \"map-pin-x\",\n \"map-pin\",\n \"map-pinned\",\n \"map-plus\",\n \"map\",\n \"mars-stroke\",\n \"mars\",\n \"martini\",\n \"maximize-2\",\n \"maximize\",\n \"medal\",\n \"megaphone-off\",\n \"megaphone\",\n \"meh\",\n \"memory-stick\",\n \"menu\",\n \"merge\",\n \"message-circle-check\",\n \"message-circle-code\",\n \"message-circle-dashed\",\n \"message-circle-heart\",\n \"message-circle-more\",\n \"message-circle-off\",\n \"message-circle-plus\",\n \"message-circle-question-mark\",\n \"message-circle-question\",\n \"message-circle-reply\",\n \"message-circle-warning\",\n \"message-circle-x\",\n \"message-circle\",\n \"message-square-check\",\n \"message-square-code\",\n \"message-square-dashed\",\n \"message-square-diff\",\n \"message-square-dot\",\n \"message-square-heart\",\n \"message-square-lock\",\n \"message-square-more\",\n \"message-square-off\",\n \"message-square-plus\",\n \"message-square-quote\",\n \"message-square-reply\",\n \"message-square-share\",\n \"message-square-text\",\n \"message-square-warning\",\n \"message-square-x\",\n \"message-square\",\n \"messages-square\",\n \"metronome\",\n \"mic-off\",\n \"mic-vocal\",\n \"mic-2\",\n \"mic\",\n \"microchip\",\n \"microscope\",\n \"microwave\",\n \"milestone\",\n \"milk-off\",\n \"milk\",\n \"minimize-2\",\n \"minimize\",\n \"minus\",\n \"mirror-rectangular\",\n \"mirror-round\",\n \"monitor-check\",\n \"monitor-cloud\",\n \"monitor-cog\",\n \"monitor-dot\",\n \"monitor-down\",\n \"monitor-off\",\n \"monitor-pause\",\n \"monitor-play\",\n \"monitor-smartphone\",\n \"monitor-speaker\",\n \"monitor-stop\",\n \"monitor-up\",\n \"monitor-x\",\n \"monitor\",\n \"moon-star\",\n \"moon\",\n \"motorbike\",\n \"mountain-snow\",\n \"mountain\",\n \"mouse-left\",\n \"mouse-off\",\n \"mouse-pointer-2-off\",\n \"mouse-pointer-2\",\n \"mouse-pointer-ban\",\n \"mouse-pointer-click\",\n \"mouse-pointer\",\n \"mouse-right\",\n \"mouse\",\n \"move-3d\",\n \"move-3-d\",\n \"move-diagonal-2\",\n \"move-diagonal\",\n \"move-down-left\",\n \"move-down-right\",\n \"move-down\",\n \"move-horizontal\",\n \"move-left\",\n \"move-right\",\n \"move-up-left\",\n \"move-up-right\",\n \"move-up\",\n \"move-vertical\",\n \"move\",\n \"music-2\",\n \"music-3\",\n \"music-4\",\n \"music\",\n \"navigation-2-off\",\n \"navigation-2\",\n \"navigation-off\",\n \"navigation\",\n \"network\",\n \"newspaper\",\n \"nfc\",\n \"non-binary\",\n \"notebook-pen\",\n \"notebook-tabs\",\n \"notebook-text\",\n \"notebook\",\n \"notepad-text-dashed\",\n \"notepad-text\",\n \"nut-off\",\n \"nut\",\n \"octagon-alert\",\n \"alert-octagon\",\n \"octagon-minus\",\n \"octagon-pause\",\n \"pause-octagon\",\n \"octagon-x\",\n \"x-octagon\",\n \"octagon\",\n \"omega\",\n \"option\",\n \"orbit\",\n \"origami\",\n \"package-2\",\n \"package-check\",\n \"package-minus\",\n \"package-open\",\n \"package-plus\",\n \"package-search\",\n \"package-x\",\n \"package\",\n \"paint-bucket\",\n \"paint-roller\",\n \"paintbrush-vertical\",\n \"paintbrush-2\",\n \"paintbrush\",\n \"palette\",\n \"panda\",\n \"panel-bottom-close\",\n \"panel-bottom-dashed\",\n \"panel-bottom-inactive\",\n \"panel-bottom-open\",\n \"panel-bottom\",\n \"panel-left-close\",\n \"sidebar-close\",\n \"panel-left-dashed\",\n \"panel-left-inactive\",\n \"panel-left-open\",\n \"sidebar-open\",\n \"panel-left-right-dashed\",\n \"panel-left\",\n \"sidebar\",\n \"panel-right-close\",\n \"panel-right-dashed\",\n \"panel-right-inactive\",\n \"panel-right-open\",\n \"panel-right\",\n \"panel-top-bottom-dashed\",\n \"panel-top-close\",\n \"panel-top-dashed\",\n \"panel-top-inactive\",\n \"panel-top-open\",\n \"panel-top\",\n \"panels-left-bottom\",\n \"panels-right-bottom\",\n \"panels-top-left\",\n \"layout\",\n \"paperclip\",\n \"parentheses\",\n \"parking-meter\",\n \"party-popper\",\n \"pause\",\n \"paw-print\",\n \"pc-case\",\n \"pen-line\",\n \"edit-3\",\n \"pen-off\",\n \"pen-tool\",\n \"pen\",\n \"edit-2\",\n \"pencil-line\",\n \"pencil-off\",\n \"pencil-ruler\",\n \"pencil\",\n \"pentagon\",\n \"percent\",\n \"person-standing\",\n \"philippine-peso\",\n \"phone-call\",\n \"phone-forwarded\",\n \"phone-incoming\",\n \"phone-missed\",\n \"phone-off\",\n \"phone-outgoing\",\n \"phone\",\n \"pi\",\n \"piano\",\n \"pickaxe\",\n \"picture-in-picture-2\",\n \"picture-in-picture\",\n \"piggy-bank\",\n \"pilcrow-left\",\n \"pilcrow-right\",\n \"pilcrow\",\n \"pill-bottle\",\n \"pill\",\n \"pin-off\",\n \"pin\",\n \"pipette\",\n \"pizza\",\n \"plane-landing\",\n \"plane-takeoff\",\n \"plane\",\n \"play\",\n \"plug-2\",\n \"plug-zap\",\n \"plug-zap-2\",\n \"plug\",\n \"plus\",\n \"pocket-knife\",\n \"podcast\",\n \"pointer-off\",\n \"pointer\",\n \"popcorn\",\n \"popsicle\",\n \"pound-sterling\",\n \"power-off\",\n \"power\",\n \"presentation\",\n \"printer-check\",\n \"printer-x\",\n \"printer\",\n \"projector\",\n \"proportions\",\n \"puzzle\",\n \"pyramid\",\n \"qr-code\",\n \"quote\",\n \"rabbit\",\n \"radar\",\n \"radiation\",\n \"radical\",\n \"radio-off\",\n \"radio-receiver\",\n \"radio-tower\",\n \"radio\",\n \"radius\",\n \"rainbow\",\n \"rat\",\n \"ratio\",\n \"receipt-cent\",\n \"receipt-euro\",\n \"receipt-indian-rupee\",\n \"receipt-japanese-yen\",\n \"receipt-pound-sterling\",\n \"receipt-russian-ruble\",\n \"receipt-swiss-franc\",\n \"receipt-text\",\n \"receipt-turkish-lira\",\n \"receipt\",\n \"rectangle-circle\",\n \"rectangle-ellipsis\",\n \"form-input\",\n \"rectangle-goggles\",\n \"rectangle-horizontal\",\n \"rectangle-vertical\",\n \"recycle\",\n \"redo-2\",\n \"redo-dot\",\n \"redo\",\n \"refresh-ccw-dot\",\n \"refresh-ccw\",\n \"refresh-cw-off\",\n \"refresh-cw\",\n \"refrigerator\",\n \"regex\",\n \"remove-formatting\",\n \"repeat-1\",\n \"repeat-2\",\n \"repeat\",\n \"replace-all\",\n \"replace\",\n \"reply-all\",\n \"reply\",\n \"rewind\",\n \"ribbon\",\n \"road\",\n \"rocket\",\n \"rocking-chair\",\n \"roller-coaster\",\n \"rose\",\n \"rotate-3d\",\n \"rotate-3-d\",\n \"rotate-ccw-key\",\n \"rotate-ccw-square\",\n \"rotate-ccw\",\n \"rotate-cw-square\",\n \"rotate-cw\",\n \"route-off\",\n \"route\",\n \"router\",\n \"rows-2\",\n \"rows\",\n \"rows-3\",\n \"panels-top-bottom\",\n \"rows-4\",\n \"rss\",\n \"ruler-dimension-line\",\n \"ruler\",\n \"russian-ruble\",\n \"sailboat\",\n \"salad\",\n \"sandwich\",\n \"satellite-dish\",\n \"satellite\",\n \"saudi-riyal\",\n \"save-all\",\n \"save-off\",\n \"save\",\n \"scale-3d\",\n \"scale-3-d\",\n \"scale\",\n \"scaling\",\n \"scan-barcode\",\n \"scan-eye\",\n \"scan-face\",\n \"scan-heart\",\n \"scan-line\",\n \"scan-qr-code\",\n \"scan-search\",\n \"scan-text\",\n \"scan\",\n \"school\",\n \"scissors-line-dashed\",\n \"scissors\",\n \"scooter\",\n \"screen-share-off\",\n \"screen-share\",\n \"scroll-text\",\n \"scroll\",\n \"search-alert\",\n \"search-check\",\n \"search-code\",\n \"search-slash\",\n \"search-x\",\n \"search\",\n \"section\",\n \"send-horizontal\",\n \"send-horizonal\",\n \"send-to-back\",\n \"send\",\n \"separator-horizontal\",\n \"separator-vertical\",\n \"server-cog\",\n \"server-crash\",\n \"server-off\",\n \"server\",\n \"settings-2\",\n \"settings\",\n \"shapes\",\n \"share-2\",\n \"share\",\n \"sheet\",\n \"shell\",\n \"shelving-unit\",\n \"shield-alert\",\n \"shield-ban\",\n \"shield-check\",\n \"shield-cog-corner\",\n \"shield-cog\",\n \"shield-ellipsis\",\n \"shield-half\",\n \"shield-minus\",\n \"shield-off\",\n \"shield-plus\",\n \"shield-question-mark\",\n \"shield-question\",\n \"shield-user\",\n \"shield-x\",\n \"shield-close\",\n \"shield\",\n \"ship-wheel\",\n \"ship\",\n \"shirt\",\n \"shopping-bag\",\n \"shopping-basket\",\n \"shopping-cart\",\n \"shovel\",\n \"shower-head\",\n \"shredder\",\n \"shrimp\",\n \"shrink\",\n \"shrub\",\n \"shuffle\",\n \"sigma\",\n \"signal-high\",\n \"signal-low\",\n \"signal-medium\",\n \"signal-zero\",\n \"signal\",\n \"signature\",\n \"signpost-big\",\n \"signpost\",\n \"siren\",\n \"skip-back\",\n \"skip-forward\",\n \"skull\",\n \"slash\",\n \"slice\",\n \"sliders-horizontal\",\n \"sliders-vertical\",\n \"sliders\",\n \"smartphone-charging\",\n \"smartphone-nfc\",\n \"smartphone\",\n \"smile-plus\",\n \"smile\",\n \"snail\",\n \"snowflake\",\n \"soap-dispenser-droplet\",\n \"sofa\",\n \"solar-panel\",\n \"soup\",\n \"space\",\n \"spade\",\n \"sparkle\",\n \"sparkles\",\n \"stars\",\n \"speaker\",\n \"speech\",\n \"spell-check-2\",\n \"spell-check\",\n \"spline-pointer\",\n \"spline\",\n \"split\",\n \"spool\",\n \"sport-shoe\",\n \"spotlight\",\n \"spray-can\",\n \"sprout\",\n \"square-activity\",\n \"activity-square\",\n \"square-arrow-down-left\",\n \"arrow-down-left-square\",\n \"square-arrow-down-right\",\n \"arrow-down-right-square\",\n \"square-arrow-down\",\n \"arrow-down-square\",\n \"square-arrow-left\",\n \"arrow-left-square\",\n \"square-arrow-out-down-left\",\n \"arrow-down-left-from-square\",\n \"square-arrow-out-down-right\",\n \"arrow-down-right-from-square\",\n \"square-arrow-out-up-left\",\n \"arrow-up-left-from-square\",\n \"square-arrow-out-up-right\",\n \"arrow-up-right-from-square\",\n \"square-arrow-right-enter\",\n \"square-arrow-right-exit\",\n \"square-arrow-right\",\n \"arrow-right-square\",\n \"square-arrow-up-left\",\n \"arrow-up-left-square\",\n \"square-arrow-up-right\",\n \"arrow-up-right-square\",\n \"square-arrow-up\",\n \"arrow-up-square\",\n \"square-asterisk\",\n \"asterisk-square\",\n \"square-bottom-dashed-scissors\",\n \"scissors-square-dashed-bottom\",\n \"square-centerline-dashed-horizontal\",\n \"flip-horizontal\",\n \"square-centerline-dashed-vertical\",\n \"flip-vertical\",\n \"square-chart-gantt\",\n \"gantt-chart-square\",\n \"square-gantt-chart\",\n \"square-check-big\",\n \"check-square\",\n \"square-check\",\n \"check-square-2\",\n \"square-chevron-down\",\n \"chevron-down-square\",\n \"square-chevron-left\",\n \"chevron-left-square\",\n \"square-chevron-right\",\n \"chevron-right-square\",\n \"square-chevron-up\",\n \"chevron-up-square\",\n \"square-code\",\n \"code-square\",\n \"square-dashed-bottom-code\",\n \"square-dashed-bottom\",\n \"square-dashed-kanban\",\n \"kanban-square-dashed\",\n \"square-dashed-mouse-pointer\",\n \"mouse-pointer-square-dashed\",\n \"square-dashed-text\",\n \"text-selection\",\n \"text-select\",\n \"square-dashed-top-solid\",\n \"square-dashed\",\n \"box-select\",\n \"square-divide\",\n \"divide-square\",\n \"square-dot\",\n \"dot-square\",\n \"square-equal\",\n \"equal-square\",\n \"square-function\",\n \"function-square\",\n \"square-kanban\",\n \"kanban-square\",\n \"square-library\",\n \"library-square\",\n \"square-m\",\n \"m-square\",\n \"square-menu\",\n \"menu-square\",\n \"square-minus\",\n \"minus-square\",\n \"square-mouse-pointer\",\n \"inspect\",\n \"square-parking-off\",\n \"parking-square-off\",\n \"square-parking\",\n \"parking-square\",\n \"square-pause\",\n \"square-pen\",\n \"pen-box\",\n \"edit\",\n \"pen-square\",\n \"square-percent\",\n \"percent-square\",\n \"square-pi\",\n \"pi-square\",\n \"square-pilcrow\",\n \"pilcrow-square\",\n \"square-play\",\n \"play-square\",\n \"square-plus\",\n \"plus-square\",\n \"square-power\",\n \"power-square\",\n \"square-radical\",\n \"square-round-corner\",\n \"square-scissors\",\n \"scissors-square\",\n \"square-sigma\",\n \"sigma-square\",\n \"square-slash\",\n \"slash-square\",\n \"square-split-horizontal\",\n \"split-square-horizontal\",\n \"square-split-vertical\",\n \"split-square-vertical\",\n \"square-square\",\n \"square-stack\",\n \"square-star\",\n \"square-stop\",\n \"square-terminal\",\n \"terminal-square\",\n \"square-user-round\",\n \"user-square-2\",\n \"square-user\",\n \"user-square\",\n \"square-x\",\n \"x-square\",\n \"square\",\n \"squares-exclude\",\n \"squares-intersect\",\n \"squares-subtract\",\n \"squares-unite\",\n \"squircle-dashed\",\n \"squircle\",\n \"squirrel\",\n \"stamp\",\n \"star-half\",\n \"star-off\",\n \"star\",\n \"step-back\",\n \"step-forward\",\n \"stethoscope\",\n \"sticker\",\n \"sticky-note\",\n \"stone\",\n \"store\",\n \"stretch-horizontal\",\n \"stretch-vertical\",\n \"strikethrough\",\n \"subscript\",\n \"sun-dim\",\n \"sun-medium\",\n \"sun-moon\",\n \"sun-snow\",\n \"sun\",\n \"sunrise\",\n \"sunset\",\n \"superscript\",\n \"swatch-book\",\n \"swiss-franc\",\n \"switch-camera\",\n \"sword\",\n \"swords\",\n \"syringe\",\n \"table-2\",\n \"table-cells-merge\",\n \"table-cells-split\",\n \"table-columns-split\",\n \"table-of-contents\",\n \"table-properties\",\n \"table-rows-split\",\n \"table\",\n \"tablet-smartphone\",\n \"tablet\",\n \"tablets\",\n \"tag\",\n \"tags\",\n \"tally-1\",\n \"tally-2\",\n \"tally-3\",\n \"tally-4\",\n \"tally-5\",\n \"tangent\",\n \"target\",\n \"telescope\",\n \"tent-tree\",\n \"tent\",\n \"terminal\",\n \"test-tube-diagonal\",\n \"test-tube-2\",\n \"test-tube\",\n \"test-tubes\",\n \"text-align-center\",\n \"align-center\",\n \"text-align-end\",\n \"align-right\",\n \"text-align-justify\",\n \"align-justify\",\n \"text-align-start\",\n \"text\",\n \"align-left\",\n \"text-cursor-input\",\n \"text-cursor\",\n \"text-initial\",\n \"letter-text\",\n \"text-quote\",\n \"text-search\",\n \"text-wrap\",\n \"wrap-text\",\n \"theater\",\n \"thermometer-snowflake\",\n \"thermometer-sun\",\n \"thermometer\",\n \"thumbs-down\",\n \"thumbs-up\",\n \"ticket-check\",\n \"ticket-minus\",\n \"ticket-percent\",\n \"ticket-plus\",\n \"ticket-slash\",\n \"ticket-x\",\n \"ticket\",\n \"tickets-plane\",\n \"tickets\",\n \"timer-off\",\n \"timer-reset\",\n \"timer\",\n \"toggle-left\",\n \"toggle-right\",\n \"toilet\",\n \"tool-case\",\n \"toolbox\",\n \"tornado\",\n \"torus\",\n \"touchpad-off\",\n \"touchpad\",\n \"towel-rack\",\n \"tower-control\",\n \"toy-brick\",\n \"tractor\",\n \"traffic-cone\",\n \"train-front-tunnel\",\n \"train-front\",\n \"train-track\",\n \"tram-front\",\n \"train\",\n \"transgender\",\n \"trash-2\",\n \"trash\",\n \"tree-deciduous\",\n \"tree-palm\",\n \"palmtree\",\n \"tree-pine\",\n \"trees\",\n \"trending-down\",\n \"trending-up-down\",\n \"trending-up\",\n \"triangle-alert\",\n \"alert-triangle\",\n \"triangle-dashed\",\n \"triangle-right\",\n \"triangle\",\n \"trophy\",\n \"truck-electric\",\n \"truck\",\n \"turkish-lira\",\n \"turntable\",\n \"turtle\",\n \"tv-minimal-play\",\n \"tv-minimal\",\n \"tv-2\",\n \"tv\",\n \"type-outline\",\n \"type\",\n \"umbrella-off\",\n \"umbrella\",\n \"underline\",\n \"undo-2\",\n \"undo-dot\",\n \"undo\",\n \"unfold-horizontal\",\n \"unfold-vertical\",\n \"ungroup\",\n \"university\",\n \"school-2\",\n \"unlink-2\",\n \"unlink\",\n \"unplug\",\n \"upload\",\n \"usb\",\n \"user-check\",\n \"user-cog\",\n \"user-key\",\n \"user-lock\",\n \"user-minus\",\n \"user-pen\",\n \"user-plus\",\n \"user-round-check\",\n \"user-check-2\",\n \"user-round-cog\",\n \"user-cog-2\",\n \"user-round-key\",\n \"user-round-minus\",\n \"user-minus-2\",\n \"user-round-pen\",\n \"user-round-plus\",\n \"user-plus-2\",\n \"user-round-search\",\n \"user-round-x\",\n \"user-x-2\",\n \"user-round\",\n \"user-2\",\n \"user-search\",\n \"user-star\",\n \"user-x\",\n \"user\",\n \"users-round\",\n \"users-2\",\n \"users\",\n \"utensils-crossed\",\n \"fork-knife-crossed\",\n \"utensils\",\n \"fork-knife\",\n \"utility-pole\",\n \"van\",\n \"variable\",\n \"vault\",\n \"vector-square\",\n \"vegan\",\n \"venetian-mask\",\n \"venus-and-mars\",\n \"venus\",\n \"vibrate-off\",\n \"vibrate\",\n \"video-off\",\n \"video\",\n \"videotape\",\n \"view\",\n \"voicemail\",\n \"volleyball\",\n \"volume-1\",\n \"volume-2\",\n \"volume-off\",\n \"volume-x\",\n \"volume\",\n \"vote\",\n \"wallet-cards\",\n \"wallet-minimal\",\n \"wallet-2\",\n \"wallet\",\n \"wallpaper\",\n \"wand-sparkles\",\n \"wand-2\",\n \"wand\",\n \"warehouse\",\n \"washing-machine\",\n \"watch\",\n \"waves-arrow-down\",\n \"waves-arrow-up\",\n \"waves-ladder\",\n \"waves\",\n \"waypoints\",\n \"webcam\",\n \"webhook-off\",\n \"webhook\",\n \"weight-tilde\",\n \"weight\",\n \"wheat-off\",\n \"wheat\",\n \"whole-word\",\n \"wifi-cog\",\n \"wifi-high\",\n \"wifi-low\",\n \"wifi-off\",\n \"wifi-pen\",\n \"wifi-sync\",\n \"wifi-zero\",\n \"wifi\",\n \"wind-arrow-down\",\n \"wind\",\n \"wine-off\",\n \"wine\",\n \"workflow\",\n \"worm\",\n \"wrench\",\n \"x-line-top\",\n \"x\",\n \"zap-off\",\n \"zap\",\n \"zodiac-aquarius\",\n \"zodiac-aries\",\n \"zodiac-cancer\",\n \"zodiac-capricorn\",\n \"zodiac-gemini\",\n \"zodiac-leo\",\n \"zodiac-libra\",\n \"zodiac-ophiuchus\",\n \"zodiac-pisces\",\n \"zodiac-sagittarius\",\n \"zodiac-scorpio\",\n \"zodiac-taurus\",\n \"zodiac-virgo\",\n \"zoom-in\",\n \"zoom-out\",\n]);\n\nexport const LAYOUT_SECTION_ICON_SET: ReadonlySet<string> = new Set(LAYOUT_SECTION_ICONS);\nexport type LayoutSectionIcon = string;\n","import { z } from \"zod\";\nimport { SCHEMA_PLAYBOOK } from \"./playbook.js\";\nimport { SECTION_DOCTRINE } from \"@bettercms-ai/types\";\n\n/**\n * The one rule that decides whether a generated page is editable at all, injected into every\n * prompt that can end in a block tree.\n *\n * Only `studio` and `propose_schema` carried the playbook, and the playbook is where the\n * section rules lived — so `new_page`, `build_site` and `generate_landing_pages` could each\n * author a page with no idea that a page is a list of sections. A page authored as loose\n * top-level blocks gets one editor section per block: a hero of headline + lede + two CTAs\n * arrives as four sections, and the two CTAs stack instead of sitting side by side.\n */\nconst STRUCTURE_RULE = `### Page structure (non-negotiable)\n${SECTION_DOCTRINE}`;\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\n/**\n * Guided slash-command prompts that ship WITH the MCP. Claude Code (and other\n * hosts) surface server prompts automatically as `/mcp__bettercms__<name>`, so\n * adding the MCP is all it takes — no per-machine skill files.\n *\n * Design: one **generous parent** (`studio`) that reads the user's intent and\n * routes to the right sub-flow, plus thin direct entry points (`new_page`, ...)\n * for the individual flows. New BetterCMS tools get a new sub-flow section here.\n */\n\n// ── Reusable sub-flows ──────────────────────────────────────────────────────\n\nconst SCHEMA_PROPOSAL_FLOW = `### Whole-project design (confirm-first) → \\`create_component\\` / \\`create_page\\` / \\`create_content_model\\`\nDesign the WHOLE project from its brief or its code, and **confirm the shape with the user\nBEFORE creating anything**. Never silently guess.\n\n1. **Read the source** — the connected repo, or the uploaded project in your working\n directory. For each page, identify the repeated visual regions and the list-shaped data.\n2. **Classify every part** using the decision tree in the playbook below. The two mistakes\n that matter: flattening a marketing page into loose page fields when its sections should\n be COMPONENTS, and giving a blog a \\`richtext\\` field when its body should be \\`document\\`.\n3. **Present the proposal (REQUIRED gate).** Show the component library (with each section's\n family and variants), the collections and their fields, and the pages that place them.\n Ask the user (AskUserQuestion) to confirm or adjust. Do not create anything before this.\n4. **Build it in the playbook's order** — blocks, collections, components, PUBLISH the\n components, pages, content, publish. Skipping the publish step ships a blank site.\n\n${SCHEMA_PLAYBOOK}\n`;\n\nconst PAGE_FLOW = `### Page authoring → \\`create_page\\` tool\nAuthor a page (the page-first schema). Ask, in order, via AskUserQuestion:\n1. **Page type** — singleton (exactly one entry: Home, About, Contact) vs dynamic\n (many entries sharing the schema: Blog posts, Products).\n2. **Identity** — title; derive a slug (lowercase, a–z 0–9 -) and confirm; optional\n metaTitle/metaDescription.\n3. **Fields (loop until done)** — for each: key (^[a-zA-Z0-9_]+$), label, type,\n required?. Types (13): text, richtext, image, boolean, number, select (needs\n \\`options: string[]\\`), reference / multi-reference (\\`config.contentModelId\\`,\n multi adds min/max), array (primitives — \\`config.itemType\\`: text|number|date),\n date (\\`config.includeTime\\`?), datetime, **group** (Non-Repeatable Zone: ONE\n nested object — recurse to collect its \\`fields\\`, e.g. blog_hero → heading,\n description, hero_image), **repeater** (Repeatable Zone: an ARRAY of such objects\n — recurse to collect item \\`fields\\`, e.g. testimonials → quote, author). Nesting\n may go several levels deep.\n4. **Review** the assembled tree, then call \\`create_page\\` with\n { title, slug, pageType, fields, metaTitle?, metaDescription? }. Field object:\n { key, label, type, required?, options?, config?, fields? }.`;\n\nconst FIELD_FLOW = `### Add a field → \\`add_field\\` (models) / \\`add_page_field\\` (pages)\nAppend a field to an existing schema. First decide the target: a **content model**\nor a **page** (Home, About, a blog template). Ask: which target (id — use\n\\`list_pages\\` to find a page id), then the field (key, label, type — any of the 13\nabove, including nested group/repeater), required?. Confirm, then call:\n- a model → \\`add_field\\` { modelId, key, label, type, ... }\n- a page → \\`add_page_field\\` { pageId, key, label, type, ... }\nBoth are additive: they reject a key that already exists and never retype/overwrite\nan existing field (edit those in the dashboard).`;\n\nconst ENTRY_FLOW = `### Create an entry → \\`create_content_entry\\` tool\nCreate a content entry under a model. Ask: which model (id), the field values (data),\nstatus (draft/published). Then call \\`create_content_entry\\` { contentModelId, data?, status?, slug? }.`;\n\nconst FORM_FLOW = `### Form authoring → \\`create_form\\` / \\`update_form\\` tools\nAuthor a form (then the user embeds it with \\`<BcmsForm form={getForm('Name')} />\\` from\n@bettercms-ai/next). Confirm the fields with the user BEFORE creating. Never guess fields.\n1. **Discover** — \\`list_forms\\` to see existing forms; \\`get_form\\` to read one before editing.\n2. **Collect fields (loop)** — for each: key (machine key for the value), label, type. Types:\n text, email, textarea, select (needs \\`options: string[]\\`), checkbox, number, phone, date,\n url, consent, hidden. Optional per field: required?, placeholder?, defaultValue?, and\n \\`showIf: { field, equals }\\` for conditional display.\n3. **Settings** — name (used by getForm('Name')), submitLabel?, successMessage?, redirectUrl?.\n4. **Confirm**, then \\`create_form\\` { name, fields, ... } (returns the new id), or\n \\`update_form\\` { formId, ... } to edit (passing \\`fields\\` REPLACES the array — include all).\n5. Offer to wire \\`<BcmsForm>\\` into the page/component where the user wants it.`;\n\nconst COMPONENT_FLOW = `### Component authoring → \\`create_component\\` / \\`publish_component\\`\nAuthor a reusable section. blockJson is the visual definition; authoring it blind is\nerror-prone, so go slow and confirm. Never guess the layout.\n1. **Discover** — \\`list_components\\` / \\`get_component\\` (read before update; keep existing blocks).\n2. **Design the tree** — wrap the section in a \\`section\\` block carrying \\`style\\`\n (bg + paddingTop/paddingBottom + contentWidth) and nest content in props.children. See\n \"Anatomy of a real section component\" in the playbook. Give every block a stable id.\n3. **sectionType + category** — set both, or the component never appears in the editor's\n \"Add a section\" picker. Components sharing a sectionType are swappable VARIANTS, so reuse\n the same prop keys across a family or a swap drops content.\n4. **Props** — declare only what should really be editable:\n { key, label, target: { blockId, path }, type: text|richtext|image|url|boolean|slot }.\n5. **Confirm the structure** (AskUserQuestion: show the block tree), then \\`create_component\\`.\n6. **\\`publish_component\\`.** It lands as a DRAFT, and a draft component renders as NOTHING on\n the live site — no error, no placeholder. This step is not optional.\n`;\n\nconst LAYOUT_FLOW = `### Project/page Layout authoring → \\`get_layout\\` / \\`update_layout\\`\nEdit the project's draft Global Layout or one page's draft override. Layout publishing stays\nin the dashboard; these tools never change the live site.\n1. **Read first** — call \\`get_layout\\` with scope \\`global\\`, or scope \\`page\\` + pageId.\n Keep the returned \\`revision\\`; every write must pass it as \\`ifMatch\\`.\n2. **Choose one discriminated command type** — the server derives its authority family;\n callers cannot claim a weaker family for a schema or composition mutation.\n3. **Apply one canonical command** with \\`update_layout\\`, then use the returned revision for\n the next command. A 409 means somebody else edited it: re-read; never blindly retry.\n4. Direct fields are headless data. Only Component items render markup. Navigation/Footer\n are reserved Sections and cannot be deleted or moved; page overrides may inherit,\n override content, customize structure, or disable them.\n5. Read Component/Variant identities before attaching or swapping. Required values and\n bindings must be complete before a human publishes from the dashboard.`;\n\nconst BUILD_SITE_FLOW = `### Build a whole site (schema → pages → AI copy) → composes the flows below\nEnd-to-end authoring from a repo or a brief. Confirm-first at every stage.\n1. **Schema** — run the whole-project schema design above: propose the page/zone/field tree,\n get the user's approval, then \\`create_page\\` per page.\n2. **Copy** — for each page/entry, draft the real text with \\`write_content\\` (action 'write',\n pass the section as the brief + the page title as \\`context\\`). Review with the user, then\n apply via \\`set_page_content\\` / \\`create_content_entry\\` / \\`update_content_entry\\`.\n3. **SEO** — run the SEO flow to fill metaTitle/metaDescription for each page.\nNever invent brand facts — ask the user for anything the repo/brief doesn't state.`;\n\nconst LANDING_PAGES_FLOW = `### Generate landing pages (programmatic SEO / ABM) → \\`write_content\\` + \\`create_content_entry\\` + \\`generate_seo_meta\\`\nSpin up many pages sharing one template, each personalized per row (company, keyword, persona).\n1. **Template** — ensure a dynamic page or content model exists for the template\n (\\`create_page\\` pageType 'dynamic' / \\`create_content_model\\`); its fields are the per-page slots.\n2. **Dataset** — get the list of targets from the user (rows of variables, e.g. company + industry).\n3. **Per row (loop)** — draft each slot with \\`write_content\\` (the row's variables as the brief/\n \\`context\\`), pick a unique slug, then \\`create_content_entry\\` { contentModelId, data, slug, status }.\n Add SEO with \\`generate_seo_meta\\` on the drafted copy and store it on the entry.\nConfirm the first 1–2 rows with the user before generating the rest. For hundreds of rows,\nthe dashboard AI Page Builder bulk-imports a CSV — mention it.`;\n\nconst SEO_FLOW = `### Optimize SEO → \\`generate_seo_meta\\` + the page/entry update tools\nFill or refresh SEO metadata across the site.\n1. **Target** — pick the pages/entries (\\`list_pages\\` / \\`list_content_entries\\`); confirm scope with the user.\n2. **Per target** — read its content (\\`get_page\\` / \\`get_content_entry\\`), call \\`generate_seo_meta\\` with that\n content as \\`text\\`, review the suggested metaTitle/metaDescription/keywords, then apply it via\n the page/entry update tools (or the dashboard SEO fields).\nKeep titles ~60 chars and descriptions ~155; don't overwrite good existing meta without asking.`;\n\n// ── Registration ─────────────────────────────────────────────────────────────\n\nexport function registerPrompts(server: McpServer): void {\n // Parent router — the generous entry point.\n server.registerPrompt(\n \"studio\",\n {\n title: \"BetterCMS Studio (guided)\",\n description:\n \"One command to author in BetterCMS. Detects what you want — create a page, add a field, create an entry — and runs the matching guided flow, then calls the right tool.\",\n argsSchema: {\n request: z\n .string()\n .optional()\n .describe(\"what you want to do, e.g. 'a blog page with a hero zone'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are the BetterCMS authoring assistant (via the bettercms MCP).\n${request ? `The user's request: \"${request}\".\\n` : \"\"}\nFirst, **preflight**: confirm the bettercms tools are loaded (\\`create_page\\`, \\`add_field\\`,\n\\`create_content_entry\\`). If \\`create_page\\` is missing and only \\`create_model\\` shows, the host has a\nstale cached MCP — tell the user to run \\`rm -rf ~/.npm/_npx\\` and restart, then stop.\n\nThen **route** to the matching sub-flow below based on the request and conversation\ncontext. DEFAULT: when setting up a project or designing its schema from the repo (or\nwhen intent is unclear), run the **whole-repo schema design** flow — it proposes the\nstructure and confirms with the user before creating anything. Use the single-page or\nsingle-field flows only for targeted follow-ups. If still unsure, ask the user\n(AskUserQuestion: \"Design the schema from my project\" / \"Create one page\" / \"Add a field\" /\n\"Create an entry\" / \"Build a form\" / \"Build a component\"). Run flows by asking ONE step at\na time, pre-filling sensible defaults from the request but never inventing fields the user\ndidn't imply. Whatever the page/zone/form/component is scoped to follows the MCP key's project.\n\n${SCHEMA_PROPOSAL_FLOW}\n\n${PAGE_FLOW}\n\n${FIELD_FLOW}\n\n${ENTRY_FLOW}\n\n${FORM_FLOW}\n\n${COMPONENT_FLOW}\n\n${LAYOUT_FLOW}\n\n${BUILD_SITE_FLOW}\n\n${LANDING_PAGES_FLOW}\n\n${SEO_FLOW}\n\nThis assistant is extensible: when new BetterCMS tools are added, a new sub-flow appears\nhere — route to it the same way.`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"edit_layout\",\n {\n title: \"Edit project or page Layout (guided)\",\n description:\n \"Safely edit a draft Global Layout or page override with optimistic locking. Publishing remains in the dashboard.\",\n argsSchema: {\n request: z.string().optional().describe(\"what to change, e.g. 'disable the footer on the pricing page'\"),\n },\n },\n ({ request }) => ({\n messages: [{\n role: \"user\",\n content: {\n type: \"text\",\n text: `Edit the BetterCMS Layout draft.${request ? ` The user wants: \"${request}\".` : \"\"}\n\n${LAYOUT_FLOW}\n\nReport which scope changed and the new revision. Remind the user that publishing is a separate dashboard action.`,\n },\n }],\n }),\n );\n\n // Direct entry point for whole-repo schema design (the confirm-first default).\n server.registerPrompt(\n \"propose_schema\",\n {\n title: \"Design schema from repo (confirm-first)\",\n description:\n \"Read the repository, propose a destructured content schema (pages → group/repeater zones → nested fields), confirm it with you, then create it via create_page. Use this to set up a project's schema.\",\n argsSchema: {\n request: z\n .string()\n .optional()\n .describe(\"optional focus, e.g. 'just the marketing pages' or 'the whole site'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Design the BetterCMS content schema for this repository.${\n request ? ` Focus: \"${request}\".` : \"\"\n }\n\nPreflight: if \\`create_page\\` isn't available (only create_model/add_field/create_content_entry),\nthe host has a stale cached MCP — tell the user to \\`rm -rf ~/.npm/_npx\\` and restart, then stop.\n\n${SCHEMA_PROPOSAL_FLOW}\n\nAfter creating, report each page's id, slug, type, and field count, and the project it\nlanded in. On 409 slug_taken, offer an alternative slug; on 401/403, the MCP key needs\n(re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for the page flow (parent can also dispatch here).\n server.registerPrompt(\n \"new_page\",\n {\n title: \"New page (guided)\",\n description:\n \"Guided creation of a BetterCMS page (singleton or dynamic) with fields, including nested group (Non-Repeatable Zone) and repeater (Repeatable Zone) fields. Calls create_page.\",\n argsSchema: {\n request: z\n .string()\n .optional()\n .describe(\"what the page is, e.g. 'a blog page with a hero'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Create a BetterCMS page via the \\`create_page\\` tool.${\n request ? ` The user wants: \"${request}\".` : \"\"\n }\n\nPreflight: if \\`create_page\\` isn't available (only create_model/add_field/create_content_entry),\nthe host has a stale cached MCP — tell the user to \\`rm -rf ~/.npm/_npx\\` and restart, then stop.\n\n${PAGE_FLOW}\n\n${STRUCTURE_RULE}\n\nAfter creating, report the page id, slug, type, field count, and the project it landed in.\nOn 409 slug_taken, offer an alternative slug; on 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for form authoring.\n server.registerPrompt(\n \"new_form\",\n {\n title: \"New form (guided)\",\n description:\n \"Guided creation of a BetterCMS form (fields + settings) you can embed with <BcmsForm>. Calls create_form.\",\n argsSchema: {\n request: z.string().optional().describe(\"what the form is, e.g. 'a contact form with name, email, message'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Author a BetterCMS form via the \\`create_form\\` tool.${\n request ? ` The user wants: \"${request}\".` : \"\"\n }\n\n${FORM_FLOW}\n\nAfter creating, report the form id and name, and how to embed it (\\`<BcmsForm form={getForm('Name')} />\\`).\nOn 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for component authoring.\n server.registerPrompt(\n \"new_component\",\n {\n title: \"New component (guided)\",\n description:\n \"Guided creation of a reusable BetterCMS component (a blockJson tree + overridable props) you render with <BcmsBlocks>. Calls create_component.\",\n argsSchema: {\n request: z.string().optional().describe(\"what the component is, e.g. 'a hero with heading, text and a button'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Author a reusable BetterCMS component via the \\`create_component\\` tool.${\n request ? ` The user wants: \"${request}\".` : \"\"\n }\n\n${COMPONENT_FLOW}\n\nAfter creating, report the component id, name, and slug, and how to render it (\\`<BcmsBlocks>\\`).\nOn 409 slug_taken, offer an alternative slug; on 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for end-to-end site authoring (schema → pages → AI copy → SEO).\n server.registerPrompt(\n \"build_site\",\n {\n title: \"Build a site (guided, end-to-end)\",\n description:\n \"Author a whole BetterCMS site from a repo or a brief: design the schema, create the pages, draft the copy with AI (write_content), and fill SEO (generate_seo_meta).\",\n argsSchema: {\n request: z.string().optional().describe(\"what to build, e.g. 'a SaaS marketing site from this repo'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Build a BetterCMS site end-to-end.${request ? ` The user wants: \"${request}\".` : \"\"}\n\n${SCHEMA_PROPOSAL_FLOW}\n\n${BUILD_SITE_FLOW}\n\n${STRUCTURE_RULE}\n\n${SEO_FLOW}\n\nConfirm each stage with the user before writing. On 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for programmatic-SEO / ABM landing-page generation.\n server.registerPrompt(\n \"generate_landing_pages\",\n {\n title: \"Generate landing pages (programmatic SEO / ABM)\",\n description:\n \"Spin up many personalized landing pages from one template + a dataset, drafting each page's copy with write_content and SEO with generate_seo_meta.\",\n argsSchema: {\n request: z.string().optional().describe(\"the campaign, e.g. 'a page per target company for our ABM push'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Generate programmatic landing pages.${request ? ` The user wants: \"${request}\".` : \"\"}\n\n${LANDING_PAGES_FLOW}\n\n${STRUCTURE_RULE}\n\nOn 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // Direct entry point for an SEO metadata pass.\n server.registerPrompt(\n \"seo_optimize\",\n {\n title: \"Optimize SEO (guided)\",\n description:\n \"Generate and apply SEO metadata (title, description, keywords, JSON-LD) across pages/entries with generate_seo_meta.\",\n argsSchema: {\n request: z.string().optional().describe(\"scope, e.g. 'all blog posts' or 'the home page'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Optimize SEO metadata.${request ? ` The user wants: \"${request}\".` : \"\"}\n\n${SEO_FLOW}\n\nOn 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n\n // FLO-1178 agent-import: the sequence that turns a LIVE imported site into an EDITABLE one.\n // A deploy alone leaves every trap in place — content only in the build (nothing binds),\n // no presentation manifest (generic previews), unpublished components (render as nothing).\n // This prompt is the ordered walk out of all three, mirroring playbook §11.\n server.registerPrompt(\n \"import-site\",\n {\n title: \"Make an imported site editable (guided)\",\n description:\n \"After deploying an existing site: bring its content into the CMS so the visual editor can bind it, declare its presentation manifest, and publish everything that renders. A deploy makes a site LIVE, not EDITABLE — this flow closes that gap.\",\n argsSchema: {\n request: z\n .string()\n .optional()\n .describe(\"scope, e.g. 'all routes' or 'just the home page'\"),\n },\n },\n ({ request }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Make my imported site editable in BetterCMS.${request ? ` Scope: \"${request}\".` : \"\"}\n\nRead bettercms://playbook/schema section 11 first, then work this order:\n\n1. AUTHORING GATE — if any deploy answered 409 AUTHORING_DECISION_REQUIRED, ask ME\n components-or-fields (do not choose), then set_authoring_preference.\n2. CONTENT INTO THE CMS, per route: create_page (slug = route) -> add_page_field (or\n create_component + publish_component + component blocks) -> set_page_content with values\n EXACTLY equal to the rendered text (binding matches by value; a paraphrase binds nothing)\n -> update_page status 'published' (the canvas binds the PUBLISHED copy).\n3. PRESENTATION MANIFEST — add bcms-presentation.json to public/ (container width, type\n scale, nav position/background, footer surface as DTCG {\"$type\",\"$value\"} entries) and\n redeploy, or structural draft previews render in a generic theme, not this site's design.\n4. VERIFY — call get_next_steps and fix what it lists (it knows about missing manifests,\n content still only in the build, and placed-but-unpublished components), or tell me why\n an item is being left.\n\nOn 401/403, the MCP key needs (re)authorizing.`,\n },\n },\n ],\n }),\n );\n}\n","/**\n * How to design a BetterCMS project — ONE copy, read by both MCP surfaces.\n *\n * WHY IT LIVES HERE AND NOT IN THE BACKEND. `packages/mcp` is a published npm package:\n * tsup bundles `src/index.ts` and externalises only the sdk/mcp-sdk/zod, so an import\n * reaching into backend `src/` would drag Hono, Drizzle and Postgres into the tarball.\n * The backend has no such constraint and already imports from this package (see\n * `src/__tests__/mcp/mcp-parity.test.ts`), so the dependency points backend -> package.\n * This module is deliberately dependency-free strings for exactly that reason.\n *\n * WHY A RESOURCE AND NOT A TOOL DESCRIPTION. Every tool's schema rides in the prompt on\n * every step of every turn; a resource is fetched once, on demand, by a client that wants\n * it. Long-form guidance in a description is a tax on all 82 tools forever. So the\n * remote host serves this at `bettercms://playbook/schema` and MCP_INSTRUCTIONS points at\n * it, while the stdio package folds it into its guided prompts.\n *\n * WHAT IT HAD TO FIX. The previous guidance was page-first: it mapped a site to pages,\n * groups and repeaters and never mentioned components, `sectionType` variants,\n * `kind:'block'` + `modular`, or the `document` body — so an agent asked for \"a marketing\n * site with a blog\" built a pile of flat page fields and a richtext box.\n */\n\nexport const PLAYBOOK_URI = \"bettercms://playbook/schema\";\n\nexport const SCHEMA_PLAYBOOK = `# Designing a BetterCMS project\n\nRead this BEFORE creating anything. Confirm the shape with the user before you build it.\n\n## 1. Pick the architecture first\n\n**Components-first** — a marketing site. A library of reusable *components*, each a\nsection, and thin pages that place them. Editors add, reorder and swap sections without\ntouching a schema. This is what \\`create_component\\` + \\`create_page(blockJson)\\` are for.\n\n**Schema-first** — a blog, a product catalogue, a directory: many rows sharing one shape.\nA collection (\\`create_content_model\\`) plus entries.\n\nMost real sites are both: components for the marketing pages, a collection for the blog.\nDecide before your first call; converting later means rewriting content.\n\n## 2. The decision tree\n\n Repeated visual region on a page? -> a COMPONENT with sectionType (a Section)\n ...and it comes in more than one look? -> siblings sharing that sectionType = VARIANTS\n A stack of mixed, reorderable content? -> kind:'block' models + a \\`modular\\` field\n A row in a list (post, author, tier)? -> a collection (kind:'model')\n The one body of an article? -> type:'document' (exactly one, top level)\n A fixed cluster of fields? -> group (never a 1-item repeater)\n A repeating cluster? -> repeater\n A list of plain strings? -> array (never a repeater of one text)\n Site-wide nav/footer? -> place the project's provisioned components\n\n## 3. Anatomy of a real section component\n\nA component that is only headings and text renders as an unstyled stack. Every section the\nproduct ships looks like this — a \\`section\\` block carrying \\`style\\`, with content nested in\n\\`props.children\\`:\n\n {\n type: \"section\", id: \"root\",\n style: { bg: \"surface\", paddingTop: 96, paddingBottom: 96, contentWidth: \"default\", align: \"center\" },\n props: { children: [\n { type: \"heading\", id: \"h\", props: { text: \"Headline\", level: 2 } },\n { type: \"text\", id: \"sub\", props: { html: \"<p>Supporting copy.</p>\" } },\n { type: \"button\", id: \"cta\", props: { text: \"Get started\", href: \"/signup\", variant: \"primary\" } }\n ] }\n }\n\nThen declare what an editor may change, via \\`props\\`:\n\n props: [\n { key: \"headline\", label: \"Headline\", target: { blockId: \"h\", path: \"props.text\" }, type: \"text\" },\n { key: \"body\", label: \"Body\", target: { blockId: \"sub\", path: \"props.html\" }, type: \"richtext\" },\n { key: \"ctaHref\", label: \"CTA link\", target: { blockId: \"cta\", path: \"props.href\" }, type: \"url\" }\n ]\n\n🔴 **On a components-first page, \\`props\\` is the ONLY editing surface.** Click-to-edit binds\n\\`heading\\`/\\`text\\`/\\`button\\`/\\`image\\` blocks; it does **not** bind a \\`component\\` block, because\na component's blocks belong to the shared definition, not to the instance. So a page built\nfrom \\`component\\` blocks renders correctly and emits ZERO fields on the canvas — editing goes\nthrough the declared props allowlist to per-instance overrides. **A component with no props\nis a section nobody can change.** Declare a prop for every string, link and image a marketer\nwould ever reasonably want to touch; leave out only structure and styling.\n\n## 4. Variants\n\nComponents sharing a \\`sectionType\\` are swappable layouts of one section family — \"Hero\ncentered\" and \"Hero split\" both with \\`sectionType: \"Hero\"\\`. Swapping is one write and\nkeeps content, because overrides are keyed by prop KEY.\n\nSo **use the same prop keys across a family**. A variant that calls it \\`title\\` where its\nsibling calls it \\`headline\\` silently drops that content on the swap.\n\nPair \\`sectionType\\` with a library \\`category\\` (hero, content, social-proof, conversion) or\nthe component never appears in the editor's \"Add a section\" picker.\n\n## 5. Blocks and modular fields\n\nA \\`kind:'block'\\` model holds no entries of its own; it exists to be stacked inside another\nmodel's \\`modular\\` field. Create the blocks FIRST, then name their slugs (not ids) in\n\\`config.blockSlugs\\`. This is the page-builder shape: one \\`sections\\` field holding an\nordered list of typed blocks.\n\n## 6. Blogs\n\n author collection: name, avatar, bio\n blog-post collection: title, slug, excerpt, cover (image),\n body (document), author (reference -> author)\n\n\\`document\\` is THE article body: a rich document canvas, **collections only**, at most one\nper model, top level only (never inside a group or repeater). A page's body is its block\ncontent, so \\`document\\` on a page is rejected. Use \\`richtext\\` for a short formatted field,\n\\`longtext\\` for multi-line plain text.\n\nThen the pages:\n\n create_page slug:\"blog\" pageType:\"dynamic\" fields:[...the post schema...]\n blockJson: [ nav, heading, { type:\"collection\", id:\"list\", props:{} }, footer ]\n\n create_content_entry per post, with pageId set to that page\n\nThe \\`collection\\` block is lane-aware: on \\`/blog\\` it renders a card per entry, and on\n\\`/blog/<slug>\\` it renders THAT entry. One page, both jobs. Every OTHER block in the array\nis interpolated per entry with \\`{{fieldKey}}\\` placeholders — \\`{{title}}\\`, \\`{{cover.url}}\\`,\n\\`{{body.html}}\\`. Note that richtext and document bind to \\`.html\\` only, never the bare name.\n\n## 7. Order of operations\n\n 1. blocks create_content_model kind:'block' (before anything references them)\n 2. collections create_content_model\n 3. components create_component (they land as DRAFTS)\n 4. publish publish_component <- every component you intend to place\n 5. pages create_page with blockJson placing those components\n 6. content create_content_entry / set_page_content\n 7. publish update_page status:'published'\n 8. check get_next_steps, and fix what it lists\n\n## 8. Two ways to ship a blank site\n\n**An unpublished component renders as an empty string.** Not an error, not a placeholder —\nnothing, on a page that returns 200. If a section is missing from the live site, check\n\\`publish_component\\` before anything else.\n\n**A workspace-level component (\\`projectId: null\\`) never reaches a live site.** It resolves\nin preview and is blank in production. Always pass the project's id.\n\n## 9. Check which project you are bound to, BEFORE you build\n\n\\`create_project\\` succeeds on a project-scoped connection and hands back a real new project\n— but every write that follows still lands in the project your grant is bound to.\n\\`projectId\\` is forwarded as a header for a workspace-scoped grant; a **project-scoped grant\naccepts it and ignores it**, silently. No error, no warning, wrong project.\n\nSo call \\`get_project\\` (no arguments) first — it reports the project you are actually\nwriting to. If that is not where the work belongs, stop and tell the user: only they can\napprove a grant for the other project, no tool can switch it.\n\nIf you must probe, probe with a \\`create_content_model\\` — models are deletable\n(\\`delete_content_model\\`, soft-delete) and **there is no \\`delete_component\\`**. A component\nwritten to the wrong project can only be demoted (\\`sectionType: null\\`) and left unpublished.\n\n## 10. You imported a site, or you are about to deploy one\n\n\\`deploy_project\\`, \\`deploy_from_upload\\` and \\`promote_project\\` all answer **409\nAUTHORING_DECISION_REQUIRED** until a human has chosen this project's architecture. This is\nasked ONCE per project, ever. It is not an error to retry or route around: read the message\nout, let the user pick, call \\`set_authoring_preference\\`, then deploy again.\n\nIt exists because an imported site arrives **field-driven whether anyone chose that or not**\n— a crawl-based import (Webflow, a starter, a template) emits pages with a typed field schema\nand an empty block tree, because that is all a crawl can infer. Nobody decided it. On a\nmarketing site it is the wrong answer, and §1 already says why converting later means\nrewriting content. So the platform stops once, at the last moment it is still cheap.\n\n**Answering \\`components\\` does not convert anything.** There is no field-to-block converter,\nand \\`extract_component\\` cannot stand in for one: it scans \\`blockJson\\`, which is empty on\nexactly the pages that would need converting. What it means is that you author the sections,\nin this order:\n\n 1. create_component per section (they land as DRAFTS)\n 2. publish_component each one — unpublished renders as NOTHING, on a page that 200s\n 3. set_page_content place them as \\`component\\` blocks on the page\n 4. list_extraction_candidates / extract_component\n now that blocks exist, fold any section repeated 3+ times\n\n**Answering \\`fields\\` is a real answer, not a deferral.** A blog, a catalogue or a directory\nis schema-first by design (§1) and should stay that way. Say so and move on.\n\nEither way: ask, do not choose. The 409 carries this project's actual page counts — how many\nare field-driven, block-driven, and how many place a reusable component — so quote those to\nthe user rather than describing the choice in the abstract.\n\n## 11. The canvas: what makes an imported site EDITABLE\n\nA deploy makes a site LIVE. It does not make it editable — those are different states, and the\ngap between them is the single most common disappointment after an import.\n\n**The canvas is the real site when it can be.** When a page's draft matches its published copy\nstructurally, the visual editor frames the project's OWN deployed build and paints unpublished\ntext over it. Structural drafts (new sections, unpublished pages, changed components) render on\nthe platform's own renderer instead — and that renderer previews in a GENERIC theme unless the\ndeploy artifact declares \\`bcms-presentation.json\\` at its root. Put the file in \\`public/\\`\n(the build lands it at the artifact root) declaring the site's presentation — container width,\ntype scale, nav position and background, footer surface — as DTCG \\`{\"$type\": ..., \"$value\": ...}\\`\nentries. Redeclare it on every deploy; absent means \"declared nothing\" and previews fall back\nto platform defaults that will not look like this site.\n\n**Editing binds by VALUE.** The editor matches CMS field values against the text the site\nrenders. Three consequences, each load-bearing:\n\n 1. Content that exists ONLY in the build can never be click-to-edit. Bring it in, per\n route, in this order (get_next_steps reports the state until it is done):\n\n a. create_page one per route, slug matching the route\n b. add_page_field the fields its content needs (or create_component +\n publish_component + component blocks, per your §10 answer)\n c. set_page_content values EXACTLY equal to the text the site renders —\n binding matches by value, so a paraphrase binds nothing\n d. update_page status 'published' — the canvas binds the PUBLISHED copy\n 2. A value that renders in more than one place is still ONE field: bind every element that\n renders it, and the editor keeps them in sync — an edit patches every copy at once.\n Binding only one copy leaves the others showing the old text until the next rebuild.\n 3. Make the chrome ITSELF editable by speaking the layout grammar: the nav/footer\n elements declare \\`data-bcms-layout-section=\"navigation\"\\` / \\`\"footer\"\\`, and each\n CMS-backed text inside them a \\`data-bcms-layout-field=\"layout:<sectionId>:<fieldId>\"\\`\n marker (fieldId is the field's REAL id, verbatim — production layout ids are\n section-prefixed and dotted, e.g. \\`footer.tagline\\`, so the marker reads\n \\`layout:footer:footer.tagline\\`) — the canvas then gives them hover chrome, the\n Layout side panel, and\n double-click editing, writing to the project Layout store (never the page).\n The address reaches INSIDE structured fields by walking the schema: a group's text\n sub appends its slug (\\`layout:navigation:navigation.cta.label\\`), a repeater row its\n STORED index then the slug (\\`layout:navigation:navigation.links.0.label\\`), nesting\n as deep as the schema goes (\\`layout:footer:footer.link-groups.0.links.1.label\\`).\n Three rules, each one a measured defect when broken:\n a. a field rendered by TWO elements gets a marker on BOTH — the editor keeps the copies\n in sync, and a marker on only one leaves the other stale;\n b. PROVENANCE — mark an element only when the LAYOUT supplied its value; a marker\n over a fallback/singleton-sourced string opens an editor for a row that does not\n exist;\n c. row markers use the value's STORED index (a row you filtered out of the render\n still occupies its slot), or the edit lands on the wrong row.\n Text/longtext leaves edit inline; link/select/image leaves are side-panel-only by\n design (their formats need a real control). THE DOCTRINE: every string a marketer\n can see must be addressable — no marker means read-only on the canvas, so an\n unmarked CMS-backed string is a defect, not a style choice.\n 4. Keep chrome semantic — \\`<nav>\\`, \\`<footer>\\`, page content inside \\`<main>\\`, mastheads\n as a top-level \\`<header>\\`. Chrome is edited through the project Layout, not the page,\n and semantic landmarks are how the editor keeps a nav edit from being written into page\n content. Div-built chrome outside \\`<main>\\` is still excluded; div-built chrome with no\n \\`<main>\\` anywhere loses that protection.\n\n**Structural drafts can render on the real site too — the draft bridge.** Wrap your page's\nblocks in \\`BcmsDraftBridge\\` (\\`@bettercms-ai/next/draft-bridge\\`) instead of calling\n\\`BcmsBlocks\\` directly: standalone it renders identically, and inside the visual editor it\nreceives the DRAFT block tree over a same-origin postMessage handshake and re-renders it with\nthe site's own components — so adding, removing or reordering sections previews in the site's\nreal design instead of the platform's approximate renderer. Sites without the bridge keep the\napproximate fallback; unpublished ROUTES always fall back (a static build has no file to frame).\n\n**Hosting decides whether a canvas exists at all.** A site deployed here is framed through a\nsame-origin proxy — that is what the canvas requires. A site hosted elsewhere (your own Vercel,\nyour own server) has NO canvas today: the SDK's draft mode with \\`stega: true\\` embeds invisible\nper-field provenance in fetched strings, which prepares the content for editing surfaces, but do\nnot promise a canvas for an externally-hosted site.\n\n**§12 — RECEIPTS: a claim about published state needs a read of the PUBLISHED copy.** The\ndoctrine this encodes cost a real incident (FLO-1188): a publish was verified against the\ndraft for ~50 minutes because the reader silently returned the draft, and every check was\ngreen on the wrong document. Three rules, none optional:\n 1. NEVER verify a write by re-reading the store you wrote. Draft writes verify against\n the draft; a PUBLISH claim verifies ONLY via \\`get_layout copy:'published'\\` (or the\n entry/page's published copy) — and check the response's \\`copy\\` echo says\n 'published'. A reader that ignores your copy selector hands you the draft and a\n false green; the echo is how you catch it.\n 2. Publish and deploy are SEPARATE claims. \"Published\" means the published copy changed;\n the LIVE SITE changes only after its next deploy/rebuild. Never report \"it's live\"\n from a publish receipt — fetch the live URL (cache-busted) for that claim.\n 3. A tool param the schema does not declare is SILENTLY DROPPED, not rejected. If a\n call's behavior doesn't change when you change a param, treat the param as dead and\n verify through an independent channel before trusting any result built on it.\n\n## 13. Convert an imported repo into a CMS-backed, editable site\n\n§11 says a deploy does not make a site editable. This is the recipe that does, and it ends in a\nreceipt you can read: \\`get_binding_report\\` says \\`mode: \"declared\"\\` with zero unmatched paths.\n\n**Scope, before you start.**\n\n(a) This is the FIELD-driven conversion — page fields and collections. If the human answered\n\\`components\\` at the §10 gate, go to §10's recipe instead: a component's editing surface is its\ndeclared \\`props\\`, and those bindings are NOT what \\`get_binding_report\\` walks.\n\n(b) It works for any framework that emits STATIC HTML, because the binding contract is plain\nHTML attributes — the annotator, the injector and the canvas stamper never see your source.\nThere are SDK helpers for Astro and Next. A Node-runtime site (\\`bcms-runtime.json\\`) edits on\nthe canvas but skips release annotation and publish-time injection, because there is no HTML on\ndisk to annotate. Copy rendered on the client must carry the attributes in the HYDRATED DOM,\nand only the canvas sees it — a release scan cannot.\n\n**If you know Sanity, this is the same shape under different names:**\n\n defineType schema in code -> content models / page fields (create_content_model,\n add_page_field, or bcms-content.json \"schema\")\n TypeGen -> @bettercms-ai/codegen\n GROQ query in the page -> @bettercms-ai/sdk read client, or the bcms-content.json\n build snapshot\n <PortableText> body -> @bettercms-ai/richtext portableTextToHtml, field type\n 'document'\n data-sanity / stega -> data-bcms-field + data-bcms-kind (<BcmsField>), stega on\n draft reads\n Presentation tool overlays -> the visual editor canvas, framing your own build\n\n**Imported site whose pages were DERIVED.** If this project was imported and made editable from\nits build, the schema and the values already exist — a page per route, a field per element, and\nthe original copy carried on each field as its \\`defaultValue\\`. Call \\`get_conversion_brief\\`\nfirst: it lists those pages, their routes, every bindable path with its current and original\nvalue, and the attributes to declare. SKIP steps 3 and 4 below and bind the keys it names —\nregistering the schema again builds a second one over the first.\n\n**Or let BetterCMS propose the edit.** \\`get_conversion_plan\\` returns an APPROVED conversion — the\nexact new contents of each template file, reviewed by a human in the dashboard and already checked\nagainst this project's real field paths. When there is one, apply it instead of doing step 5 by\nhand: check out its \\`baseHeadOid\\`, branch from there, write each file's \\`content\\` verbatim, and\ncarry on from step 6. A 404 with \\`code: \"no-approved-plan\"\\` means nobody approved one, so the\nconversion is yours to write.\n\n**The steps.**\n\n1. \\`pull_project_source\\` (or clone the \\`github\\` remote it returns). Read the SOURCE. Never\n reconstruct content from the deployed HTML — that is how a site ends up bound to a copy of\n its own stale build.\n2. Decide the architecture WITH the human (§10) and record it: \\`set_authoring_preference\\`.\n3. Register the schema. Per route: \\`create_page\\` + \\`add_page_field\\` (text / longtext /\n richtext / image / array groups). Per repeated content type: \\`create_content_model\\`, with a\n \\`document\\` body for articles. Site chrome goes through \\`update_layout\\`; images through\n \\`create_media_upload\\` / \\`upload_asset\\`, then reference the CMS URL. The repo-owned\n alternative to calling these one by one is a committed \\`bcms-content.json\\` carrying a\n \\`schema\\` block, which seeds models, pages and entries at connect time — the \\`defineType\\`\n analogue.\n4. Seed the entries with the copy EXACTLY as the source renders it (\\`set_page_content\\`,\n \\`create_content_entry\\`). Prose goes in as Portable Text arrays (\\`_type: \"block\"\\`); never\n markup inside a \\`text\\` field.\n **Prose MIGRATED from another CMS needs one extra check.** Every block's \\`_type\\` must be one\n this platform stores — \\`block\\`, or \\`bcmsBlock\\` carrying a \\`schemaKey\\` such as\n \\`builtin:table\\` — and a foreign node (a Sanity-shaped \\`{_type:\"table\", rows:[{cells}]}\\` is\n the one that has actually happened) is not merely unrendered: it has no component here, so it\n vanishes from the HTML every delivery surface reads while the stored value still looks whole.\n Verify each \\`_type\\` against the schema before you write, not after.\n5. Codemod the templates. Read each value from the CMS (\\`@bettercms-ai/astro\\` /\n \\`@bettercms-ai/next\\` client, or the \\`bcms-content.json\\` build snapshot), KEEP the in-code\n copy as the fallback, and declare the binding on the element that already renders it.\n Prefer schema-derived bindings — the TypeGen analogue:\n \\`npx @bettercms-ai/codegen --bindings-out src/bettercms.bindings.generated.ts\\`, then spread\n \\`{...bcms.home.hero.title}\\` / \\`{...bcms.blog.features.$(i)}\\`. The hand form is\n \\`data-bcms-field=\"<path>\"\\` (plus \\`data-bcms-kind=\"richtext\"|\"image\"\\`), \\`data-bcms-props\\`\n for an \\`href\\` / \\`alt\\` / \\`src\\`, the §11 layout markers for nav and footer, and\n \\`<div data-bcms-field=\"body\" data-bcms-kind=\"document\">\\` around a Portable Text render.\n Bind CONDITIONALLY (\\`fromCms ? path : undefined\\`) so a fallback row is never bound. A value\n rendered in N places carries the binding on ALL N — the editor keeps the copies in sync.\n **Read the LIVE SCHEMA before you bind — \\`get_page\\` / \\`get_content_model\\`, never the\n delivery snapshot.** A field nobody has authored yet is simply ABSENT from the payload, so a\n snapshot cannot tell \"this field does not exist\" from \"this field is empty\": bind against it\n and you declare a path for a \\`cover\\` field that was never created, which the report then\n reports as broken forever. The schema is the list of what exists; the snapshot is only what\n currently has a value.\n **An index or listing route binds NOTHING.** The editor loads ONE entry per route, and an\n index renders many, so a binding there addresses whichever entry the editor happened to\n load. Bind each item's fields on that item's OWN route (\\`/blog/<slug>\\`); on the index,\n render from the CMS and declare nothing.\n5b. **Where the content comes from at build time.** Two lanes, and they differ:\n - GIT-CONNECTED (recommended for a converted site): the platform's provisioned workflow\n writes \\`bcms-content.json\\` into the repo root before \\`build\\`, using the repo's\n \\`BCMS_API_KEY\\` secret. Read that file, with in-code fallbacks so a local or CI build\n without it still renders.\n - ARCHIVE (\\`deploy_project\\` / \\`deploy_from_upload\\`): the sandbox build runs with no env\n and no network content step, by design. So the archive MUST SHIP its own\n \\`bcms-content.json\\` — generate it locally with a delivery key and commit it. Without\n one the site renders its fallbacks and the report says \\`no-element\\` for every path.\n6. Push, or \\`deploy_project\\`; poll \\`get_deploy_status\\` until it is live. Then\n \\`get_binding_report\\` — still \\`text-match\\`, and \\`unmatched\\` should be EMPTY because the\n values are byte-equal to what the build renders. Now \\`set_binding_mode\n {declaredBindings: true}\\` and release again (an empty commit is enough). Do not flip before\n the report is clean: in declared mode an undeclared field simply stops being editable.\n7. **Receipts.** \\`get_binding_report\\` reads \\`mode: \"declared\"\\`, \\`unmatched: []\\`, and\n \\`bound > 0\\`. That certifies one thing only — that every non-empty field has SOME element\n carrying its path. It CANNOT see copy that was never modelled, so diff each route's visible\n text against its entry values yourself before you call the page done. Then publish, and\n fetch the live URL cache-busted (§12: publish and deploy are separate claims).\n \\`get_next_steps\\` keeps reporting the gap until every one of these holds.\n`;\n"],"mappings":"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AA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AA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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["s","z","z"]}