@prenta/mcp-server 1.0.0 → 1.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @actuate-media/mcp-server
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ef68582: Promote the only page-build sequence to MCP instructions and add a read-only `prenta://how-to-build-a-page` checklist resource. There is no tree generator.
8
+
3
9
  ## 1.0.0
4
10
 
5
11
  ### Major Changes
package/README.md CHANGED
@@ -23,7 +23,9 @@ You don't need to install this globally — your MCP client will run it via `npx
23
23
  }
24
24
  ```
25
25
 
26
- Generate an `PRENTA_API_KEY` from your CMS admin under **API Keys → New API Key**. Grant it the scopes the agent needs (e.g. content + media + pageBuilder).
26
+ Generate an `PRENTA_API_KEY` from your CMS admin under **API Keys → New API Key**. Grant it the scopes the agent needs (e.g. content + media).
27
+
28
+ The only page-build path is `create_document` → `list_section_types` → `add_page_section` → `upload_media` / `generate_media_alt` / `update_media` → `validate_section_content` → View site. Read the `prenta://how-to-build-a-page` resource for the checklist.
27
29
 
28
30
  ## Tools exposed
29
31
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { PrentaClient, type PrentaClientOptions } from './client.js';
2
2
  export { buildTools, type McpTool } from './tools.js';
3
- export { buildResources, AUTHORING_GUIDE, type McpResource } from './resources.js';
3
+ export { buildResources, AUTHORING_GUIDE, HOW_TO_BUILD_A_PAGE, type McpResource, } from './resources.js';
4
4
  export { SERVER_INSTRUCTIONS } from './instructions.js';
5
5
  export { createPrentaMcpServer, type CreateMcpServerOptions, type PrentaMcpServer, } from './server.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EACL,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EACL,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { PrentaClient } from './client.js';
2
2
  export { buildTools } from './tools.js';
3
- export { buildResources, AUTHORING_GUIDE } from './resources.js';
3
+ export { buildResources, AUTHORING_GUIDE, HOW_TO_BUILD_A_PAGE, } from './resources.js';
4
4
  export { SERVER_INSTRUCTIONS } from './instructions.js';
5
5
  export { createPrentaMcpServer, } from './server.js';
6
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA4B,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAoB,MAAM,gBAAgB,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EACL,qBAAqB,GAGtB,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA4B,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAA;AACrD,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,GAEpB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EACL,qBAAqB,GAGtB,MAAM,aAAa,CAAA"}
@@ -9,5 +9,5 @@
9
9
  * `description`; live content-model detail lives in the MCP resources
10
10
  * (`prenta://collections`, `prenta://section-types`).
11
11
  */
12
- export declare const SERVER_INSTRUCTIONS = "You are connected to an Prenta CMS instance over MCP. You can author and manage real site content (pages, posts, media, forms, navigation, SEO) by calling the tools below. Everything you write goes through the CMS's audited, access-controlled API \u2014 treat it as production data.\n\n## Start here (discovery first)\n1. Call `health_check` once \u2014 a `degraded`/`unhealthy` status reveals operator config problems early.\n2. Call `list_collections` to learn what content types exist (slugs, labels, page-vs-post type, fields). Never assume a collection exists.\n3. Read the `prenta://collections` and `prenta://section-types` resources for the live content model and the building blocks of a page.\n\n## The page-content contract (important)\nA page is an ordered array of **sections** stored on the document's `sections` field. This is the canonical model the public renderer (`@prenta/sections-react`) reads. To build a page:\n1. `list_section_types` (optionally scoped `page`/`post`) \u2192 choose section types.\n2. `add_page_section` / `update_page_section` / `reorder_page_sections` to compose the page. The server seeds each type's registry defaults; you shallow-merge `content`/`settings`.\n3. `validate_section_content` before/after to catch unknown types or bad fields.\nTree tools (`generate_page`, `create_page_from_prompt`) are gone. Always use `list_section_types` \u2192 `add_page_section` \u2192 `validate_section_content`. Leftover `_layout` trees still compile on write, `migrate:sections`, and `GET /resolve`.\n\n## Authoring lifecycle\n- Documents have a status: `DRAFT`, `PUBLISHED`, `SCHEDULED`, `ARCHIVED`. `create_document` defaults to draft \u2014 set status explicitly or use `schedule_publish` to go live.\n- **Every image must go through the media library.** Use `upload_media` first \u2014 never reference `/public/`, `/images/`, or other static paths in section `imageUrl` fields. The CMS optimizes, tracks usage, and stores alt text on media records.\n- After uploading an image, call `generate_media_alt({ mediaId })` then `update_media({ id, alt })` to set WCAG-aligned alt text (vision model when configured).\n- For library-wide metadata backfills, prefer `bulk_update_media({ items })` (max 50 per call, per-id results) over looping `update_media`. Use `bulk_delete_media({ ids, confirm: true })` for cleanup batches.\n- `upload_media` is content-hash idempotent: re-uploading the same final bytes returns the existing row with `deduplicated: true` / `duplicateOf`. Pass `forceUpload: true` only when you intentionally want a second copy.\n- Use `resolve_url` to verify a published page renders at its public path.\n\n## Images & performance (build fast pages)\nThe renderer (`@prenta/sections-react`) does the Core Web Vitals heavy lifting for you \u2014 your job is to give it the right inputs:\n- **Pick a hero image for the LCP.** For a page's main banner, set the `hero` section's `imageUrl` (+ required `imageAlt`). The renderer marks **exactly one** image per page as the priority/eager LCP element and lazy-loads the rest. Don't expect to \"prioritise\" several above-the-fold images \u2014 only one wins, so put it on the hero (or the post's `featuredImage`).\n- **Always set alt text.** It's an accessibility requirement (a hero image without alt is rejected) and feeds SEO. Workflow: `generate_media_alt` \u2192 review \u2192 `update_media({ alt })`, or set `imageAlt` inline when inserting into a section.\n- **Don't hand-optimise content images.** `upload_media` compresses to **high-quality WebP** (quality 82, 86 for transparent PNGs), downscales beyond 4096px, and **keeps the original when WebP would be larger** \u2014 upload a full-resolution source and let the pipeline balance size vs fidelity. Only pass `skipOptimize: true` for brand logos/favicons. The public site also serves AVIF/WebP via `next/image` with responsive `sizes`.\n\n## Safety rails\n- Some tools require `confirm: true` and refuse otherwise: `delete_document`, `delete_media`, `bulk_delete_media`, `delete_form`, `delete_form_entry` (destructive \u2014 confirm with the user first, prefer archiving where available), `export_form_entries` (bulk PII egress), `seo_scan_run` (expensive site-wide scan), `apply_seo_issue_fix` (writes SEO metadata + resolves an issue), and `batch_generate_seo_content_briefs` (batch AI content briefs).\n- Your API key carries scopes. A `Forbidden` error means the key lacks a permission, not that the tool is broken \u2014 surface that to the user rather than retrying blindly.\n- Tool inputs are schema-validated; read each tool's `description` for the exact shape and the response envelope (most list tools return `{ docs, total, page, pageSize }`).\n\n## SEO audit fix workflow (via MCP)\n1. `run_seo_audit` or `list_seo_issues` \u2192 triage open issues.\n2. **Metadata fixes** (meta title/desc, canonical, schema): `suggest_seo_issue_fix` \u2192 review `suggestion.changes` \u2192 `apply_seo_issue_fix` with `fingerprint` + `confirm: true`.\n3. **Content fixes** (thin content, headings, alt text): `research_and_brief_seo_issue` (thin content + optional competitor URLs) or `generate_seo_issue_content_brief`. Briefs are suggestions only \u2014 implement in page content yourself (`add_page_section`, `update_document`, etc.).\n4. `batch_generate_seo_content_briefs` with `confirm: true` to pre-warm briefs, then `export_seo_fix_brief` to pull the full markdown handoff into your workspace.\n5. `set_seo_issue_status` to resolve/ignore when done; re-run `run_seo_audit` to verify.\n\n## SEO links & technical settings (via MCP)\n- `seo_links_snapshot` / `seo_link_health` \u2014 site-wide link graph and broken-link scan (Links tab parity).\n- `run_seo_link_ai_index` with `confirm: true`, then `seo_link_suggest` \u2014 AI contextual internal link suggestions.\n- `get_seo_crawl_settings` / `update_seo_crawl_settings`, `get_seo_robots` / `update_seo_robots`, `get_seo_sitemap_status` / `regenerate_seo_sitemap` \u2014 technical SEO controls.\n- `list_seo_content` / `get_seo_content` / `update_seo_content` \u2014 bulk content SEO records without opening the admin UI.\n- Redirect advanced: `flatten_redirect_chain`, `list_redirect_suggestions`, recovery settings, `import_redirects_csv` (confirm), `export_redirects_csv`.\n- AI assistant: `ai_seo_generate_field`, `ai_seo_explain_issue`, `ai_seo_generate_schema`, `ai_seo_summarize_audit` \u2014 degrade gracefully when plugin-ai is unconfigured.";
12
+ export declare const SERVER_INSTRUCTIONS = "You are connected to an Prenta CMS instance over MCP. You can author and manage real site content (pages, posts, media, forms, navigation, SEO) by calling the tools below. Everything you write goes through the CMS's audited, access-controlled API \u2014 treat it as production data.\n\n## How to build a page (the only path)\nThis is the only page-build sequence. There is no tree generator. Read `prenta://how-to-build-a-page` for the same checklist.\n\n1. `health_check` once, then `list_collections`. Never assume a collection exists.\n2. `create_document` / `update_document` on `pages` (or the site's page collection) with title + slug. Defaults to DRAFT.\n3. `list_section_types` (optionally scoped `page`/`post`) \u2192 `get_section_schema` if you need the field schema.\n4. `add_page_section` / `update_page_section` / `reorder_page_sections`. The server seeds registry defaults; you shallow-merge `content`/`settings`.\n5. Every image: `upload_media` \u2192 `generate_media_alt({ mediaId })` \u2192 `update_media({ id, alt })`. Never put `/public/` or `/images/` paths in `imageUrl`.\n6. `validate_section_content` before you call the page done.\n7. Humans review with **View site** (public origin, `?preview=` for drafts). Share a draft via the admin Share control or `POST /preview/token`.\n\nLeftover `_layout` trees still compile on write, `migrate:sections`, and `GET /resolve`. Do not invent a BlockNode tree.\n\n## Start here (discovery)\nRead `prenta://collections` and `prenta://section-types` for the live content model. Per-tool detail lives in each tool's description.\n\n## Authoring lifecycle\n- Documents have a status: `DRAFT`, `PUBLISHED`, `SCHEDULED`, `ARCHIVED`. `create_document` defaults to draft \u2014 set status explicitly or use `schedule_publish` to go live.\n- **Every image must go through the media library.** Use `upload_media` first \u2014 never reference `/public/`, `/images/`, or other static paths in section `imageUrl` fields. The CMS optimizes, tracks usage, and stores alt text on media records.\n- After uploading an image, call `generate_media_alt({ mediaId })` then `update_media({ id, alt })` to set WCAG-aligned alt text (vision model when configured).\n- For library-wide metadata backfills, prefer `bulk_update_media({ items })` (max 50 per call, per-id results) over looping `update_media`. Use `bulk_delete_media({ ids, confirm: true })` for cleanup batches.\n- `upload_media` is content-hash idempotent: re-uploading the same final bytes returns the existing row with `deduplicated: true` / `duplicateOf`. Pass `forceUpload: true` only when you intentionally want a second copy.\n- Use `resolve_url` to verify a published page renders at its public path.\n\n## Images & performance (build fast pages)\nThe renderer (`@prenta/sections-react`) does the Core Web Vitals heavy lifting for you \u2014 your job is to give it the right inputs:\n- **Pick a hero image for the LCP.** For a page's main banner, set the `hero` section's `imageUrl` (+ required `imageAlt`). The renderer marks **exactly one** image per page as the priority/eager LCP element and lazy-loads the rest. Don't expect to \"prioritise\" several above-the-fold images \u2014 only one wins, so put it on the hero (or the post's `featuredImage`).\n- **Always set alt text.** It's an accessibility requirement (a hero image without alt is rejected) and feeds SEO. Workflow: `generate_media_alt` \u2192 review \u2192 `update_media({ alt })`, or set `imageAlt` inline when inserting into a section.\n- **Don't hand-optimise content images.** `upload_media` compresses to **high-quality WebP** (quality 82, 86 for transparent PNGs), downscales beyond 4096px, and **keeps the original when WebP would be larger** \u2014 upload a full-resolution source and let the pipeline balance size vs fidelity. Only pass `skipOptimize: true` for brand logos/favicons. The public site also serves AVIF/WebP via `next/image` with responsive `sizes`.\n\n## Safety rails\n- Some tools require `confirm: true` and refuse otherwise: `delete_document`, `delete_media`, `bulk_delete_media`, `delete_form`, `delete_form_entry` (destructive \u2014 confirm with the user first, prefer archiving where available), `export_form_entries` (bulk PII egress), `seo_scan_run` (expensive site-wide scan), `apply_seo_issue_fix` (writes SEO metadata + resolves an issue), and `batch_generate_seo_content_briefs` (batch AI content briefs).\n- Your API key carries scopes. A `Forbidden` error means the key lacks a permission, not that the tool is broken \u2014 surface that to the user rather than retrying blindly.\n- Tool inputs are schema-validated; read each tool's `description` for the exact shape and the response envelope (most list tools return `{ docs, total, page, pageSize }`).\n\n## SEO audit fix workflow (via MCP)\n1. `run_seo_audit` or `list_seo_issues` \u2192 triage open issues.\n2. **Metadata fixes** (meta title/desc, canonical, schema): `suggest_seo_issue_fix` \u2192 review `suggestion.changes` \u2192 `apply_seo_issue_fix` with `fingerprint` + `confirm: true`.\n3. **Content fixes** (thin content, headings, alt text): `research_and_brief_seo_issue` (thin content + optional competitor URLs) or `generate_seo_issue_content_brief`. Briefs are suggestions only \u2014 implement in page content yourself (`add_page_section`, `update_document`, etc.).\n4. `batch_generate_seo_content_briefs` with `confirm: true` to pre-warm briefs, then `export_seo_fix_brief` to pull the full markdown handoff into your workspace.\n5. `set_seo_issue_status` to resolve/ignore when done; re-run `run_seo_audit` to verify.\n\n## SEO links & technical settings (via MCP)\n- `seo_links_snapshot` / `seo_link_health` \u2014 site-wide link graph and broken-link scan (Links tab parity).\n- `run_seo_link_ai_index` with `confirm: true`, then `seo_link_suggest` \u2014 AI contextual internal link suggestions.\n- `get_seo_crawl_settings` / `update_seo_crawl_settings`, `get_seo_robots` / `update_seo_robots`, `get_seo_sitemap_status` / `regenerate_seo_sitemap` \u2014 technical SEO controls.\n- `list_seo_content` / `get_seo_content` / `update_seo_content` \u2014 bulk content SEO records without opening the admin UI.\n- Redirect advanced: `flatten_redirect_chain`, `list_redirect_suggestions`, recovery settings, `import_redirects_csv` (confirm), `export_redirects_csv`.\n- AI assistant: `ai_seo_generate_field`, `ai_seo_explain_issue`, `ai_seo_generate_schema`, `ai_seo_summarize_audit` \u2014 degrade gracefully when plugin-ai is unconfigured.";
13
13
  //# sourceMappingURL=instructions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,w0MA8CiJ,CAAA"}
1
+ {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,g4MAkDiJ,CAAA"}
@@ -11,17 +11,21 @@
11
11
  */
12
12
  export const SERVER_INSTRUCTIONS = `You are connected to an Prenta CMS instance over MCP. You can author and manage real site content (pages, posts, media, forms, navigation, SEO) by calling the tools below. Everything you write goes through the CMS's audited, access-controlled API — treat it as production data.
13
13
 
14
- ## Start here (discovery first)
15
- 1. Call \`health_check\` once — a \`degraded\`/\`unhealthy\` status reveals operator config problems early.
16
- 2. Call \`list_collections\` to learn what content types exist (slugs, labels, page-vs-post type, fields). Never assume a collection exists.
17
- 3. Read the \`prenta://collections\` and \`prenta://section-types\` resources for the live content model and the building blocks of a page.
18
-
19
- ## The page-content contract (important)
20
- A page is an ordered array of **sections** stored on the document's \`sections\` field. This is the canonical model the public renderer (\`@prenta/sections-react\`) reads. To build a page:
21
- 1. \`list_section_types\` (optionally scoped \`page\`/\`post\`) → choose section types.
22
- 2. \`add_page_section\` / \`update_page_section\` / \`reorder_page_sections\` to compose the page. The server seeds each type's registry defaults; you shallow-merge \`content\`/\`settings\`.
23
- 3. \`validate_section_content\` before/after to catch unknown types or bad fields.
24
- Tree tools (\`generate_page\`, \`create_page_from_prompt\`) are gone. Always use \`list_section_types\` → \`add_page_section\` → \`validate_section_content\`. Leftover \`_layout\` trees still compile on write, \`migrate:sections\`, and \`GET /resolve\`.
14
+ ## How to build a page (the only path)
15
+ This is the only page-build sequence. There is no tree generator. Read \`prenta://how-to-build-a-page\` for the same checklist.
16
+
17
+ 1. \`health_check\` once, then \`list_collections\`. Never assume a collection exists.
18
+ 2. \`create_document\` / \`update_document\` on \`pages\` (or the site's page collection) with title + slug. Defaults to DRAFT.
19
+ 3. \`list_section_types\` (optionally scoped \`page\`/\`post\`) → \`get_section_schema\` if you need the field schema.
20
+ 4. \`add_page_section\` / \`update_page_section\` / \`reorder_page_sections\`. The server seeds registry defaults; you shallow-merge \`content\`/\`settings\`.
21
+ 5. Every image: \`upload_media\` → \`generate_media_alt({ mediaId })\` → \`update_media({ id, alt })\`. Never put \`/public/\` or \`/images/\` paths in \`imageUrl\`.
22
+ 6. \`validate_section_content\` before you call the page done.
23
+ 7. Humans review with **View site** (public origin, \`?preview=\` for drafts). Share a draft via the admin Share control or \`POST /preview/token\`.
24
+
25
+ Leftover \`_layout\` trees still compile on write, \`migrate:sections\`, and \`GET /resolve\`. Do not invent a BlockNode tree.
26
+
27
+ ## Start here (discovery)
28
+ Read \`prenta://collections\` and \`prenta://section-types\` for the live content model. Per-tool detail lives in each tool's description.
25
29
 
26
30
  ## Authoring lifecycle
27
31
  - Documents have a status: \`DRAFT\`, \`PUBLISHED\`, \`SCHEDULED\`, \`ARCHIVED\`. \`create_document\` defaults to draft — set status explicitly or use \`schedule_publish\` to go live.
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iLA8C8I,CAAA"}
1
+ {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iLAkD8I,CAAA"}
@@ -23,6 +23,7 @@ export interface McpResource {
23
23
  * server `instructions` but is available as a pullable resource for clients
24
24
  * that surface resources but not instructions.
25
25
  */
26
- export declare const AUTHORING_GUIDE = "# Prenta CMS \u2014 agent authoring guide\n\n## Discovery\n- `health_check` \u2014 confirm the instance is healthy before writing.\n- `list_collections` \u2014 the content types you can author (slugs, labels, fields).\n- Resource `prenta://section-types` \u2014 the section building blocks for pages.\n\n## Build a page (canonical `sections[]` model)\n1. `list_section_types` \u2192 pick types (scope to `page`/`post`).\n2. `add_page_section` / `update_page_section` / `reorder_page_sections`.\n3. `validate_section_content` to verify.\nThe public renderer (`@prenta/sections-react`) renders this `sections` array.\n\n## Prompt-driven pages\nTree tools are gone. Build pages with `list_section_types` \u2192 `add_page_section` \u2192 `validate_section_content`. Leftover `_layout` trees still compile on write, `migrate:sections`, and `GET /resolve`.\n\n## Lifecycle\n- Status: DRAFT \u2192 PUBLISHED (or SCHEDULED / ARCHIVED). `create_document` is draft by default.\n- `upload_media` before referencing assets; `schedule_publish` to go live; `resolve_url` to verify.\n\n## Images & performance (Core Web Vitals)\nThe public renderer (`@prenta/sections-react`) optimises images for you \u2014 give it the right inputs:\n- **One LCP image per page.** Put a page's main banner on the `hero` section's `imageUrl` (+ required `imageAlt`); for posts use `featuredImage`. The renderer marks exactly one image as the eager/priority LCP element and lazy-loads the rest \u2014 only one image can \"win\" priority.\n- **Always set alt text** (`imageAlt`, or `update_media({ alt })`). A hero image without alt is rejected.\n- **No manual optimisation needed.** `upload_media` recompresses to WebP; the site serves AVIF/WebP via `next/image`, backfills intrinsic width/height (prevents layout shift / CLS), and emits responsive `sizes`. Upload a large source, reference its URL, done.\n\n## Safety\n- `delete_*` tools require `confirm: true`. Prefer archiving. Confirm destructive actions with the user.\n- API-key scopes apply; `Forbidden` means a missing permission.\n";
26
+ export declare const HOW_TO_BUILD_A_PAGE = "# How to build a page\n\nThis is the only page-build path. There is no tree generator and no second page model.\n\n1. `health_check` \u2192 `list_collections`. Confirm the page collection slug (usually `pages`).\n2. `create_document` / `update_document` with title + slug. Status defaults to DRAFT.\n3. `list_section_types` \u2192 `get_section_schema` for the field schema you need.\n4. `add_page_section` / `update_page_section` / `reorder_page_sections`.\n5. Every image: `upload_media` \u2192 `generate_media_alt({ mediaId })` \u2192 `update_media({ id, alt })`. Never use static `/public/` or `/images/` paths.\n6. `validate_section_content` until it is clean.\n7. Humans open **View site** on the public origin (`?preview=` for drafts). Share a draft with the admin Share control or `POST /preview/token`.\n\nThe public renderer (`@prenta/sections-react`) reads `data.sections` only. Leftover `_layout` trees still compile on write, `migrate:sections`, and `GET /resolve`.\n";
27
+ export declare const AUTHORING_GUIDE = "# Prenta CMS \u2014 agent authoring guide\n\n## How to build a page (the only path)\nSee also `prenta://how-to-build-a-page`.\n\n1. `create_document` / `update_document` (title + slug).\n2. `list_section_types` \u2192 `add_page_section` / `update_page_section`.\n3. `upload_media` \u2192 `generate_media_alt` \u2192 `update_media({ alt })` for every image.\n4. `validate_section_content`.\n5. Humans review with View site / a share token.\n\n## Discovery\n- `health_check` \u2014 confirm the instance is healthy before writing.\n- `list_collections` \u2014 the content types you can author (slugs, labels, fields).\n- Resource `prenta://section-types` \u2014 the section building blocks for pages.\n\n## Canonical `sections[]` model\nThe public renderer (`@prenta/sections-react`) renders this `sections` array. There is no BlockNode tree to generate.\n\n## Lifecycle\n- Status: DRAFT \u2192 PUBLISHED (or SCHEDULED / ARCHIVED). `create_document` is draft by default.\n- `upload_media` before referencing assets; `schedule_publish` to go live; `resolve_url` to verify.\n\n## Images & performance (Core Web Vitals)\nThe public renderer (`@prenta/sections-react`) optimises images for you \u2014 give it the right inputs:\n- **One LCP image per page.** Put a page's main banner on the `hero` section's `imageUrl` (+ required `imageAlt`); for posts use `featuredImage`. The renderer marks exactly one image as the eager/priority LCP element and lazy-loads the rest \u2014 only one image can \"win\" priority.\n- **Always set alt text** (`imageAlt`, or `update_media({ alt })`). A hero image without alt is rejected.\n- **No manual optimisation needed.** `upload_media` recompresses to WebP; the site serves AVIF/WebP via `next/image`, backfills intrinsic width/height (prevents layout shift / CLS), and emits responsive `sizes`. Upload a large source, reference its URL, done.\n\n## Safety\n- `delete_*` tools require `confirm: true`. Prefer archiving. Confirm destructive actions with the user.\n- API-key scopes apply; `Forbidden` means a missing permission.\n";
27
28
  export declare function buildResources(client: PrentaClient): McpResource[];
28
29
  //# sourceMappingURL=resources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,8FAA8F;IAC9F,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CAC5B;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,+gEA6B3B,CAAA;AAMD,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,CAiDlE"}
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,8FAA8F;IAC9F,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CAC5B;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,w9BAa/B,CAAA;AAED,eAAO,MAAM,eAAe,ghEAgC3B,CAAA;AAMD,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,CAyDlE"}
package/dist/resources.js CHANGED
@@ -3,21 +3,38 @@
3
3
  * server `instructions` but is available as a pullable resource for clients
4
4
  * that surface resources but not instructions.
5
5
  */
6
+ export const HOW_TO_BUILD_A_PAGE = `# How to build a page
7
+
8
+ This is the only page-build path. There is no tree generator and no second page model.
9
+
10
+ 1. \`health_check\` → \`list_collections\`. Confirm the page collection slug (usually \`pages\`).
11
+ 2. \`create_document\` / \`update_document\` with title + slug. Status defaults to DRAFT.
12
+ 3. \`list_section_types\` → \`get_section_schema\` for the field schema you need.
13
+ 4. \`add_page_section\` / \`update_page_section\` / \`reorder_page_sections\`.
14
+ 5. Every image: \`upload_media\` → \`generate_media_alt({ mediaId })\` → \`update_media({ id, alt })\`. Never use static \`/public/\` or \`/images/\` paths.
15
+ 6. \`validate_section_content\` until it is clean.
16
+ 7. Humans open **View site** on the public origin (\`?preview=\` for drafts). Share a draft with the admin Share control or \`POST /preview/token\`.
17
+
18
+ The public renderer (\`@prenta/sections-react\`) reads \`data.sections\` only. Leftover \`_layout\` trees still compile on write, \`migrate:sections\`, and \`GET /resolve\`.
19
+ `;
6
20
  export const AUTHORING_GUIDE = `# Prenta CMS — agent authoring guide
7
21
 
22
+ ## How to build a page (the only path)
23
+ See also \`prenta://how-to-build-a-page\`.
24
+
25
+ 1. \`create_document\` / \`update_document\` (title + slug).
26
+ 2. \`list_section_types\` → \`add_page_section\` / \`update_page_section\`.
27
+ 3. \`upload_media\` → \`generate_media_alt\` → \`update_media({ alt })\` for every image.
28
+ 4. \`validate_section_content\`.
29
+ 5. Humans review with View site / a share token.
30
+
8
31
  ## Discovery
9
32
  - \`health_check\` — confirm the instance is healthy before writing.
10
33
  - \`list_collections\` — the content types you can author (slugs, labels, fields).
11
34
  - Resource \`prenta://section-types\` — the section building blocks for pages.
12
35
 
13
- ## Build a page (canonical \`sections[]\` model)
14
- 1. \`list_section_types\` → pick types (scope to \`page\`/\`post\`).
15
- 2. \`add_page_section\` / \`update_page_section\` / \`reorder_page_sections\`.
16
- 3. \`validate_section_content\` to verify.
17
- The public renderer (\`@prenta/sections-react\`) renders this \`sections\` array.
18
-
19
- ## Prompt-driven pages
20
- Tree tools are gone. Build pages with \`list_section_types\` → \`add_page_section\` → \`validate_section_content\`. Leftover \`_layout\` trees still compile on write, \`migrate:sections\`, and \`GET /resolve\`.
36
+ ## Canonical \`sections[]\` model
37
+ The public renderer (\`@prenta/sections-react\`) renders this \`sections\` array. There is no BlockNode tree to generate.
21
38
 
22
39
  ## Lifecycle
23
40
  - Status: DRAFT → PUBLISHED (or SCHEDULED / ARCHIVED). \`create_document\` is draft by default.
@@ -38,6 +55,13 @@ function safeJson(value) {
38
55
  }
39
56
  export function buildResources(client) {
40
57
  return [
58
+ {
59
+ uri: 'prenta://how-to-build-a-page',
60
+ name: 'How to build a page',
61
+ description: 'The only page-build checklist: create/update document → sections → media+alt → validate → View site / share token.',
62
+ mimeType: 'text/markdown',
63
+ read: async () => HOW_TO_BUILD_A_PAGE,
64
+ },
41
65
  {
42
66
  uri: 'prenta://guide',
43
67
  name: 'Prenta authoring guide',
@@ -1 +1 @@
1
- {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B9B,CAAA;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,OAAO;QACL;YACE,GAAG,EAAE,gBAAgB;YACrB,IAAI,EAAE,wBAAwB;YAC9B,WAAW,EACT,wIAAwI;YAC1I,QAAQ,EAAE,eAAe;YACzB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe;SAClC;QACD;YACE,GAAG,EAAE,sBAAsB;YAC3B,IAAI,EAAE,kCAAkC;YACxC,WAAW,EACT,iJAAiJ;YACnJ,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE,CAAA;oBAC1C,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAC3B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,QAAQ,CAAC;wBACd,KAAK,EAAE,oDAAoD;wBAC3D,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;wBACxD,IAAI,EAAE,oGAAoG;qBAC3G,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;SACF;QACD;YACE,GAAG,EAAE,wBAAwB;YAC7B,IAAI,EAAE,2BAA2B;YACjC,WAAW,EACT,iJAAiJ;YACnJ,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAA;oBAC3C,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAC3B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,QAAQ,CAAC;wBACd,KAAK,EAAE,sDAAsD;wBAC7D,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;wBACxD,IAAI,EAAE,wFAAwF;qBAC/F,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;SACF;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;CAalC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgC9B,CAAA;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,OAAO;QACL;YACE,GAAG,EAAE,8BAA8B;YACnC,IAAI,EAAE,qBAAqB;YAC3B,WAAW,EACT,oHAAoH;YACtH,QAAQ,EAAE,eAAe;YACzB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,mBAAmB;SACtC;QACD;YACE,GAAG,EAAE,gBAAgB;YACrB,IAAI,EAAE,wBAAwB;YAC9B,WAAW,EACT,wIAAwI;YAC1I,QAAQ,EAAE,eAAe;YACzB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe;SAClC;QACD;YACE,GAAG,EAAE,sBAAsB;YAC3B,IAAI,EAAE,kCAAkC;YACxC,WAAW,EACT,iJAAiJ;YACnJ,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE,CAAA;oBAC1C,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAC3B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,QAAQ,CAAC;wBACd,KAAK,EAAE,oDAAoD;wBAC3D,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;wBACxD,IAAI,EAAE,oGAAoG;qBAC3G,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;SACF;QACD;YACE,GAAG,EAAE,wBAAwB;YAC7B,IAAI,EAAE,2BAA2B;YACjC,WAAW,EACT,iJAAiJ;YACnJ,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAA;oBAC3C,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAC3B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,QAAQ,CAAC;wBACd,KAAK,EAAE,sDAAsD;wBAC7D,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;wBACxD,IAAI,EAAE,wFAAwF;qBAC/F,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;SACF;KACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prenta/mcp-server",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "license": "MIT",
5
5
  "description": "Model Context Protocol (MCP) server for Prenta CMS — gives AI agents read/write access to your CMS over stdio",
6
6
  "repository": {