@prenta/mcp-server 0.23.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 +583 -0
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +44 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +1348 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1019 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +13 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +61 -0
- package/dist/instructions.js.map +1 -0
- package/dist/navigation.d.ts +76 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/navigation.js +228 -0
- package/dist/navigation.js.map +1 -0
- package/dist/resources.d.ts +28 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +88 -0
- package/dist/resources.js.map +1 -0
- package/dist/server.d.ts +25 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +90 -0
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +25 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +1920 -0
- package/dist/tools.js.map +1 -0
- package/package.json +43 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
# @actuate-media/mcp-server
|
|
2
|
+
|
|
3
|
+
## 0.23.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5eea995: Product rename: ActuateCMS is now **Prenta**. Every package moves from the
|
|
8
|
+
`@actuate-media/*` scope to `@prenta/*` with simplified names (`@prenta/core`,
|
|
9
|
+
`@prenta/admin`, `create-prenta`), and version numbers continue from where the
|
|
10
|
+
old scope left off.
|
|
11
|
+
|
|
12
|
+
This is a clean break — no backwards-compat aliases:
|
|
13
|
+
- **npm packages**: `@actuate-media/cms-core` → `@prenta/core`,
|
|
14
|
+
`@actuate-media/cms-admin` → `@prenta/admin`, all other packages keep their
|
|
15
|
+
suffix under `@prenta/*`. `create-actuate-cms` → `create-prenta`
|
|
16
|
+
(`npm create prenta`), `create-actuate-astro` → `create-prenta-astro`.
|
|
17
|
+
CLI bins: `actuate`/`actuate-cms` → `prenta`/`prenta-cms`; `actuate-mcp` →
|
|
18
|
+
`prenta-mcp`.
|
|
19
|
+
- **Database**: migration `0012_rename_to_prenta` renames all 36 `actuate_*`
|
|
20
|
+
tables to `prenta_*` in place (plus prefixed constraints, indexes, and
|
|
21
|
+
sequences). Run `prisma migrate deploy` when upgrading.
|
|
22
|
+
- **Runtime identifiers**: `getActuateConfig` → `getPrentaConfig`,
|
|
23
|
+
`handleActuateAPI` → `handlePrentaAPI`, `ActuateClient` → `PrentaClient`,
|
|
24
|
+
`ActuateDB` → `PrentaDB`, config file `actuate.config.ts` →
|
|
25
|
+
`prenta.config.ts`, CSS scopes `.actuate-admin`/`.actuate-canvas` →
|
|
26
|
+
`.prenta-admin`/`.prenta-canvas`, preview protocol `actuate-preview:*` →
|
|
27
|
+
`prenta-preview:*`, webhook headers `X-Actuate-*` → `X-Prenta-*`, session
|
|
28
|
+
cookie `actuate_session` → `prenta_session`, env vars `ACTUATE_*` →
|
|
29
|
+
`PRENTA_*`, purge route `/api/actuate/purge` → `/api/prenta/purge`.
|
|
30
|
+
- **Sessions and webhooks**: all sessions reset on upgrade (cookie + JWT issuer
|
|
31
|
+
changed); webhook consumers must re-verify signatures against the new
|
|
32
|
+
`X-Prenta-*` headers.
|
|
33
|
+
|
|
34
|
+
The old `@actuate-media/*` packages are deprecated on npm and will receive no
|
|
35
|
+
further releases.
|
|
36
|
+
|
|
37
|
+
## 0.22.2
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- cf97a40: Launch-critical Astro SEO + freshness: `documentPublicPath` / `rewritePublicOrigin`, first-class `AstroPageMeta.robots`, admin/MCP path builders (#739), Yoast child sitemap + XSL proxies with origin rewrite, production purge 503 without CDN credentials, globals purge webhooks, and Launch Gate docs.
|
|
42
|
+
|
|
43
|
+
## 0.22.1
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- 46ea4a7: Hash final stored media bytes (SHA-256) on upload and return the existing record with `deduplicated` / `duplicateOf` when a match exists, so seed re-runs and byte-identical twins no longer accumulate. Opt out with `forceUpload`.
|
|
48
|
+
|
|
49
|
+
## 0.22.0
|
|
50
|
+
|
|
51
|
+
### Minor Changes
|
|
52
|
+
|
|
53
|
+
- e4e55de: Add `POST /media/bulk-update` and `POST /media/bulk-delete` with per-id results (max 50), plus MCP tools `bulk_update_media` and `bulk_delete_media` for library-wide metadata backfills without one round trip per asset.
|
|
54
|
+
|
|
55
|
+
## 0.21.2
|
|
56
|
+
|
|
57
|
+
### Patch Changes
|
|
58
|
+
|
|
59
|
+
- 6eaffa5: Treat decorative media (`isDecorative` + empty alt) as alt-complete in the media SEO scorer, add a non-scoring `low-quality-alt` advisory, deep-merge media fields on document update so partial `featuredImage` patches keep `url`/`id`, and expose `isDecorative` on `update_media`.
|
|
60
|
+
|
|
61
|
+
## 0.21.1
|
|
62
|
+
|
|
63
|
+
### Patch Changes
|
|
64
|
+
|
|
65
|
+
- 0d0c5c4: Expose `description`, `caption`, and `focusKeyword` on the `update_media` MCP tool. The media API already accepted all three, but the tool omitted them, so an agent could only reach 60 of 100 on `calculateMediaSeoScore` (alt 30 + title 20 + descriptive filename 10) and every asset it touched was stuck at a "needs-work" grade. The description alone is worth the 20 points that lift an asset to a passing "good".
|
|
66
|
+
|
|
67
|
+
## 0.21.0
|
|
68
|
+
|
|
69
|
+
### Minor Changes
|
|
70
|
+
|
|
71
|
+
- 258cbc3: Warn when navigation items link to unpublished or missing internal pages (soft warnings in MCP `validate_navigation_tree`, admin nav builder, and `POST /navigations/validate-targets`).
|
|
72
|
+
|
|
73
|
+
## 0.20.2
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- cc6ad93: Split-deploy SEO redirects: ship `applyPublicRedirect` / `createAstroRedirectMiddleware`, wire Astro starters and Next scaffold to the shared engine, clarify Never hit vs Stale, and return 409 on duplicate source updates.
|
|
78
|
+
|
|
79
|
+
## 0.20.1
|
|
80
|
+
|
|
81
|
+
### Patch Changes
|
|
82
|
+
|
|
83
|
+
- 041a228: Add the MIT `license` field to every published package (previously missing) and correct `repository.url` to `github.com/actuate-media/actuatecms` (13 packages carried the wrong org).
|
|
84
|
+
|
|
85
|
+
## 0.20.0
|
|
86
|
+
|
|
87
|
+
### Minor Changes
|
|
88
|
+
|
|
89
|
+
- 55f52ed: Add Phase 1 SEO MCP parity tools: Links dashboard (snapshot, health, suggest, AI index), technical settings (crawl, robots, sitemap), redirect advanced ops (flatten, recovery, import/export), content SEO CRUD, and `/ai/seo/*` assistant endpoints.
|
|
90
|
+
|
|
91
|
+
## 0.19.0
|
|
92
|
+
|
|
93
|
+
### Minor Changes
|
|
94
|
+
|
|
95
|
+
- 4afb589: WCAG-aligned AI alt text: improved vision prompts, feature-gated `/ai/media-metadata` with `aiAltText` suggestions, post-upload auto-suggest in Media, MCP `generate_media_alt` tool, and validation warnings for static image paths outside the media library.
|
|
96
|
+
|
|
97
|
+
### Patch Changes
|
|
98
|
+
|
|
99
|
+
- 4afb589: Media upload optimization: high-quality **lossy WebP** by default (q82 / q86 for transparent PNGs) for strong compression with minimal visible quality loss. Lossless WebP available via `optimizeImage({ lossless: true })`. Original bytes kept when WebP would not reduce file size.
|
|
100
|
+
|
|
101
|
+
## 0.18.0
|
|
102
|
+
|
|
103
|
+
### Minor Changes
|
|
104
|
+
|
|
105
|
+
- 39e2419: Phase 1–2: inline SEO audit fixes (deterministic + AI approve). Phase A: markdown export of manual/content fixes for dev-team handoff. Phase B: AI content briefs for thin content, heading, and alt-text issues. Phase C: topic research subagent, research-and-brief flow, and batch brief pre-generation. MCP: seven new tools for the audit fix workflow (`export_seo_fix_brief`, suggest/apply fix, content briefs, research-and-brief, batch generate) plus server instructions.
|
|
106
|
+
|
|
107
|
+
## 0.17.1
|
|
108
|
+
|
|
109
|
+
### Patch Changes
|
|
110
|
+
|
|
111
|
+
- c656ddc: Add an `embed` (video) section type for YouTube, Vimeo, and Loom.
|
|
112
|
+
- **cms-core:** new `embed` section in the registry (`url`, `title`, `ratio`, `caption`) plus a shared, deterministic `parseEmbed()` provider allowlist (`@actuate-media/cms-core/page-sections`). Section validation rejects any URL that isn't a recognised YouTube/Vimeo/Loom link, so an arbitrary URL can never reach an iframe.
|
|
113
|
+
- **sections-react:** `EmbedSection` renderer — a lazy-loaded provider iframe inside a fixed aspect-ratio box (16:9 / 4:3 / 1:1 / 9:16) so the embed reserves its space and never causes layout shift (CLS). The URL is re-parsed through the same allowlist at render time.
|
|
114
|
+
- **cms-admin:** matching editor-canvas body for `embed` (provider + ratio placeholder) so the page/post editors preview the section instead of showing a generic "custom section" placeholder.
|
|
115
|
+
- **mcp-server:** `list_section_types` description now lists `embed`.
|
|
116
|
+
|
|
117
|
+
## 0.17.0
|
|
118
|
+
|
|
119
|
+
### Minor Changes
|
|
120
|
+
|
|
121
|
+
- e45b9cd: Teach AI agents to build fast, Core Web Vitals-friendly pages over MCP.
|
|
122
|
+
|
|
123
|
+
The server `instructions` and the `actuate://guide` resource now include an "Images & performance" section: put a page's main banner on the `hero` section's `imageUrl` (or a post's `featuredImage`) so it becomes the page's single LCP image, always set `imageAlt`, and rely on the pipeline (WebP/AVIF via `next/image`, dimension backfill for zero CLS, responsive `sizes`) instead of hand-optimising. The live `actuate://section-types` resource already exposes the new hero image fields. Docs (`mcp.md`, `media.md`) updated to match.
|
|
124
|
+
|
|
125
|
+
Also corrects the server `instructions` safety rail to list the full set of tools that require `confirm: true` (adds `export_form_entries` and `seo_scan_run` alongside the destructive `delete_*` tools).
|
|
126
|
+
|
|
127
|
+
## 0.16.2
|
|
128
|
+
|
|
129
|
+
### Patch Changes
|
|
130
|
+
|
|
131
|
+
- 854152d: Developer experience improvements from external-consumer feedback:
|
|
132
|
+
- Every published package now ships its `CHANGELOG.md` in the npm tarball, and packages that were missing a `README.md` (cli, cms-admin, cms-core, import, platform-vercel, all plugins, sections-react) now have one — so release notes and usage docs are visible on npmjs.com and in `node_modules`.
|
|
133
|
+
- New client-safe form validation entry point: `@actuate-media/cms-core/forms/client` exports `validateFormFieldClient()`, `validateFormValuesClient()`, visibility/conditional helpers, and the exact `FORM_EMAIL_RE` / `FORM_PHONE_RE` regexes the server enforces — zero Node dependencies, so public-site forms can mirror server rules without reimplementing them. The server validator now imports the same primitives, so client and server can never drift.
|
|
134
|
+
|
|
135
|
+
## 0.16.1
|
|
136
|
+
|
|
137
|
+
### Patch Changes
|
|
138
|
+
|
|
139
|
+
- aa4bd1a: Teach agents the page-ownership rule (ADR 0002): server `instructions` and the `actuate://guide` resource now explain that a page with a `_layout` is Page-Builder-owned — its `sections` are compiled from the layout and the section write tools refuse it with a 409, so agents should read the compiled sections via `get_document` rather than retrying.
|
|
140
|
+
|
|
141
|
+
## 0.16.0
|
|
142
|
+
|
|
143
|
+
### Minor Changes
|
|
144
|
+
|
|
145
|
+
- 127f91a: Make the MCP server self-teaching so agents can drive the CMS out of the box.
|
|
146
|
+
- **Server `instructions`** — the server now returns onboarding guidance during
|
|
147
|
+
MCP `initialize` (the discovery-first workflow, the canonical `sections[]`
|
|
148
|
+
page-content model, the publish lifecycle, and the destructive-tool safety
|
|
149
|
+
rails). Most MCP clients inject this into the model's system context.
|
|
150
|
+
- **MCP resources** — three pull-on-demand resources: `actuate://guide`
|
|
151
|
+
(authoring guide, markdown), `actuate://collections` (the **live** content
|
|
152
|
+
model for the connected instance), and `actuate://section-types` (the **live**
|
|
153
|
+
registered section types and schemas). Resource reads never throw — a failed
|
|
154
|
+
discovery returns an actionable payload.
|
|
155
|
+
|
|
156
|
+
New exports: `buildResources`, `AUTHORING_GUIDE`, `SERVER_INSTRUCTIONS`, and the
|
|
157
|
+
`McpResource` type. `createActuateMcpServer` now also returns `resources`.
|
|
158
|
+
|
|
159
|
+
## 0.15.0
|
|
160
|
+
|
|
161
|
+
### Minor Changes
|
|
162
|
+
|
|
163
|
+
- 01eef99: Require explicit confirmation for destructive delete tools.
|
|
164
|
+
|
|
165
|
+
`delete_document`, `delete_media`, `delete_form`, and `delete_form_entry` now
|
|
166
|
+
require `confirm: true` in their arguments. The Zod schema rejects the call
|
|
167
|
+
before any HTTP request is made, so an agent cannot delete content (or
|
|
168
|
+
irreversibly destroy form-submission PII) without first acknowledging the
|
|
169
|
+
destructive action. **Behavioral change:** existing callers must add
|
|
170
|
+
`confirm: true` to these tool invocations.
|
|
171
|
+
|
|
172
|
+
## 0.14.0
|
|
173
|
+
|
|
174
|
+
### Minor Changes
|
|
175
|
+
|
|
176
|
+
- af555c5: Add MCP form-authoring tools and correct the transport claim (WS-C C1 + C4).
|
|
177
|
+
|
|
178
|
+
Form authoring (C1): the MCP server could previously only READ form submissions. New tools let an agent build and maintain a form end-to-end over MCP: `list_forms`, `get_form`, `create_form`, `update_form`, `delete_form`, `duplicate_form`, `get_form_schema`, `save_form_schema`, plus submissions-inbox management (`set_form_entry_status`, `bulk_set_form_entry_status`, `delete_form_entry`) and `export_form_entries`. CSV export is gated behind `confirm: true` because it is a bulk PII egress, and the underlying client reads the raw `text/csv` body (the success response is not a JSON envelope).
|
|
179
|
+
|
|
180
|
+
Transport + docs truth (C4): the package description advertised "stdio or HTTP" but the server is stdio-only — corrected to "over stdio". Fixed the `repository.url` to the canonical `actuate-media/actuatecms`. Refreshed the README to drop the removed `create_service` / `create_location` / `create_team_member` tools (use `create_in_collection({ template })`) and document the form-authoring and page-section tool families.
|
|
181
|
+
|
|
182
|
+
- 2eac1b5: Add MCP navigation-menu helpers (WS-C C3) so agents can build and wire up site menus.
|
|
183
|
+
|
|
184
|
+
Menus are documents in the `navigations` collection with a recursive link tree on `data.items` (the same shape the admin Nav builder uses). Nine new tree-aware tools wrap the document API:
|
|
185
|
+
- `list_navigations` / `get_navigation` — list menus (`{ id, name, slug, location, itemCount }`) or read one with its full tree.
|
|
186
|
+
- `create_navigation` / `update_navigation` / `delete_navigation` — menu CRUD (slug derived from name; trees validated before save).
|
|
187
|
+
- `add_navigation_item` — add a link by explicit `{ label, url }` or by a `page` reference (`{ collection?, slug? | id? }`), which resolves the page's public URL and label automatically ("link page X into menu Y"); optional `parentId` nests it.
|
|
188
|
+
- `remove_navigation_item` / `reorder_navigation_items` — remove one item (and its sub-tree) or reorder one level by an exact id permutation.
|
|
189
|
+
- `validate_navigation_tree` — validate a stored menu or a candidate `items` array without saving (`{ valid, errors, warnings, stats }`).
|
|
190
|
+
|
|
191
|
+
All writes go through `update_document` semantics, preserving versioning, access control, hooks, and cache invalidation. New items get admin-compatible ids generated so menus authored over MCP stay editable in the UI.
|
|
192
|
+
|
|
193
|
+
- a413616: Add MCP relationship-resolver tools (WS-C C2) so agents stop guessing document IDs.
|
|
194
|
+
- **cms-core (additive, backward-compatible):**
|
|
195
|
+
- `listDocuments` / `GET /collections/:slug` now accept an exact `slug` filter. Because `slug` is `@@unique([collection, slug])`, this is the canonical single-query slug→id lookup.
|
|
196
|
+
- The `GET /collections` discovery endpoint now surfaces `relationTo` (for relationship fields), `hasMany`, and select `options` in each field summary, so an agent can learn where a relationship field points. (Overlaps the WS-B4 schema-surfacing work.)
|
|
197
|
+
- **mcp-server:** three new tools — `get_relationship_fields` (list relationship/media/select fields + their `relationTo`), `resolve_relationship` (exact slug → `{ id, slug, title, status }`), and `list_relationship_targets` (browse candidate documents when the slug is unknown). README updated with a "Resolving relationships" section.
|
|
198
|
+
|
|
199
|
+
## 0.13.1
|
|
200
|
+
|
|
201
|
+
### Patch Changes
|
|
202
|
+
|
|
203
|
+
- ae1af8f: Authoring correctness fixes for the AI site-building workflow (roadmap WS-B/E quick wins).
|
|
204
|
+
- **cms-core**: `createDocument` now honors a requested `status` (`DRAFT` or
|
|
205
|
+
`PUBLISHED`) instead of always forcing `DRAFT`. Publishing on create is gated
|
|
206
|
+
to EDITOR/ADMIN, stamps `publishedAt`, and emits the `document.published`
|
|
207
|
+
webhook + sitemap notify. This fixes `POST /page-builder/create?publish=true`
|
|
208
|
+
(and `status: 'PUBLISHED'`), which previously created a draft silently.
|
|
209
|
+
Statuses other than `DRAFT`/`PUBLISHED` on create are rejected with guidance
|
|
210
|
+
to schedule/archive via update.
|
|
211
|
+
- **client**: `listMedia()` now returns the canonical
|
|
212
|
+
`{ docs, total, page, pageSize, totalPages }` (`MediaList`) envelope. The
|
|
213
|
+
server returns the asset array under `items`/`data` (never `docs`), so the
|
|
214
|
+
previous typing made `listMedia().docs` always `undefined`. Adds exported
|
|
215
|
+
`MediaAsset` and `MediaList` types and an optional `init` (signal/cache) arg.
|
|
216
|
+
- **mcp-server**: the `list_media` tool now normalizes the same `items`→`docs`
|
|
217
|
+
shape so its output matches `list_documents`.
|
|
218
|
+
- **create-actuate-cms**: generated `TextBlock`/`ImageTextBlock` now sanitize
|
|
219
|
+
author-supplied HTML with `sanitizeHtml` before `dangerouslySetInnerHTML`
|
|
220
|
+
(was an XSS vector on hostile content).
|
|
221
|
+
|
|
222
|
+
## 0.13.0
|
|
223
|
+
|
|
224
|
+
### Minor Changes
|
|
225
|
+
|
|
226
|
+
- a6d6674: Forms PII/encryption, retention, audit, export, and MCP tools (PR8).
|
|
227
|
+
|
|
228
|
+
**cms-core**
|
|
229
|
+
- **Field-level encryption at rest**: submission values for fields flagged `encrypted` (or high-PII fields when `forms.encryptSensitiveFields` is enabled) are now encrypted with the `enc:v1:` AES-256-GCM envelope before persistence and transparently decrypted on every read path. Plaintext/legacy rows pass through unchanged; missing key on read fails closed.
|
|
230
|
+
- **PII retention**: `forms.retentionDays` is now wired into the cleanup cron, hard-deleting form submissions (and cascading their files) older than the window. Opt-in — disabled by default.
|
|
231
|
+
- **Audit logging**: viewing a single entry now logs `form.entry.viewed` and CSV export logs `form.entries.exported`, both with user id and IP, for PII-access traceability.
|
|
232
|
+
- **CSV export endpoint**: `GET /forms/entries/export?formId=…` streams a decrypted CSV of a form's submissions (bounded to 5000 rows) with formula-injection-safe cells. New exported helpers `exportFormEntries`, `encryptSubmissionData`, `decryptSubmissionData`, `fieldShouldEncrypt`.
|
|
233
|
+
|
|
234
|
+
**mcp-server**
|
|
235
|
+
- New `list_form_entries` and `get_form_entry` tools over the decrypted submissions inbox, both requiring an explicit `formId`/`entryId` (no enumeration) and documented as PII-sensitive. `get_form_entry` reads are audited server-side.
|
|
236
|
+
|
|
237
|
+
## 0.12.0
|
|
238
|
+
|
|
239
|
+
### Minor Changes
|
|
240
|
+
|
|
241
|
+
- 5fa84d3: SEO Operations Center — a full detect → prioritize → explain → route → fix → audit → generate workflow.
|
|
242
|
+
|
|
243
|
+
**cms-core**
|
|
244
|
+
- Additive `0009_seo` migration (mirrored to `apps/dev`): `SEOAuditRun`, `SEOIssue` (+ severity/status/category enums), `Redirect` extensions (`hits`, `lastHitAt`, `enabled`, `priority`, `preserveQuery`, `source`), `Redirect404Hit`, and `RedirectSuggestion`. All columns are nullable or defaulted, so it is safe to apply to an existing database.
|
|
245
|
+
- Pure, explainable scoring model (`seo/score.ts`): `calculatePageSeoScore` / `calculateSiteSeoScore` with documented weights and breakdowns.
|
|
246
|
+
- Persistent audit engine (`seo/audit-engine.ts`) with cross-run issue lifecycle (open / resolved / ignored / recurring) and a redirect engine (chain/loop detection, safe flatten, hit tracking, 404 logging, gated AI 404 recovery).
|
|
247
|
+
- New endpoints: `POST /seo/audit`, `GET /seo/audits[/:id]`, `GET /seo/issues[/:id]`, issue `resolve`/`ignore`/`reopen`/`fix`, `GET /seo/overview`, redirect CRUD + import/export + chains/loops/flatten/suggest, technical settings (`/seo/sitemap/*`, `/seo/crawl-settings`, `/seo/robots`), and approval-gated `/ai/seo/*` (generate-field, explain-issue, generate-schema, summarize) that degrade gracefully with 501 when `plugin-ai` is unconfigured.
|
|
248
|
+
- `/resolve` now returns Next.js-ready `metadata` plus validated JSON-LD; public `robots.txt` honors the admin-edited body.
|
|
249
|
+
|
|
250
|
+
**cms-admin**
|
|
251
|
+
- Rebuilt `SEO.tsx` into a five-tab Operations Center (Overview / Content / Technical / Redirects / Audit) with `?tab=` deep-link routing, dynamic badge counts, a typed `seo-service.ts` client, reusable token-only primitives and a focus-trapped drawer, editor/fix/copilot drawers, and full loading / empty / error / permission states.
|
|
252
|
+
|
|
253
|
+
**mcp-server**
|
|
254
|
+
- New SEO tools: `seo_overview`, `run_seo_audit`, `list_seo_audit_runs`, `list_seo_issues`, `get_seo_issue`, `set_seo_issue_status`, `list_redirect_rules`, `seo_redirect_overview`, `seo_redirect_chains`.
|
|
255
|
+
|
|
256
|
+
**create-actuate-cms**
|
|
257
|
+
- Scaffolded projects now ship a redirect-resolving `middleware.ts` backed by the database redirect table.
|
|
258
|
+
|
|
259
|
+
## 0.11.0
|
|
260
|
+
|
|
261
|
+
### Minor Changes
|
|
262
|
+
|
|
263
|
+
- 91885de: Add a section-aware bridge so AI agents (e.g. in Cursor / VS Code) can build pages section-by-section through MCP, producing real, editable, publishable Page Editor sections rather than disposable markup.
|
|
264
|
+
- **cms-core**: new `@actuate-media/cms-core/page-sections` subpath exporting the flat Page Editor section registry, pure section-array helpers, and a deterministic `validateSectionContent`. This is now the single source of truth shared by the admin editor, the REST API, and MCP. Adds REST routes: `GET /page-sections/types`, `POST /page-sections/validate`, and section CRUD over a page document's `data.sections` (`GET|POST /page-sections/:collection/:id`, `PATCH|DELETE /page-sections/:collection/:id/:sectionId`, `POST /page-sections/:collection/:id/reorder`). Mutations go through the audited `updateDocument` path (versions, hooks, cache invalidation, live-preview push) and reuse collection scope checks. Writes are rejected on collections that don't declare a `sections` JSON field.
|
|
265
|
+
- **mcp-server**: nine new tools — `list_section_types`, `get_section_schema`, `validate_section_content`, `list_page_sections`, `add_page_section`, `update_page_section`, `reorder_page_sections`, `remove_page_section`, `toggle_page_section_visibility`.
|
|
266
|
+
- **cms-admin**: the Page Editor section registry and section helpers now re-export from `@actuate-media/cms-core/page-sections`; per-section publish validation is delegated to the shared `validateSectionContent`. No behavior change — internal refactor for a single source of truth.
|
|
267
|
+
|
|
268
|
+
- 91885de: Add a design-driven Posts template system that mirrors the Pages section editor.
|
|
269
|
+
- **cms-core**: tag section types with a `scope` (`page` | `post`), add post-oriented section types (`article-body`, `quote`, `author-bio`, `related-posts`, `gallery`), `PostHeaderConfig` / `PostTemplate` types, the `getSectionTypesForScope` helper, and new field types (`richText`, `boolean`, `relationship`, `gallery`). Adds `GET/PUT /post-templates/:type` API routes and a `?scope=` filter on `GET /page-sections/types`.
|
|
270
|
+
- **cms-admin**: new `PostSectionEditor`, `PostTemplateEditor` (with header panel), `PostPreview`, post section renderers, and a `post-editor-service` data layer. The Add Section gallery now filters by scope, and post type cards expose an "Edit template" action.
|
|
271
|
+
- **mcp-server**: scope-aware `list_section_types`, plus `get_post_template` and `save_post_template` tools so an external AI agent can read and build a post type's template.
|
|
272
|
+
|
|
273
|
+
## 0.10.0
|
|
274
|
+
|
|
275
|
+
### Minor Changes
|
|
276
|
+
|
|
277
|
+
- a0f6eba: Rich `@`-mention picker for comments (last Phase 7 carry-over).
|
|
278
|
+
|
|
279
|
+
**`cms-core`**: New `GET /api/cms/users/search?q=<query>` endpoint —
|
|
280
|
+
authenticated (any role), case-insensitive `contains` matching against
|
|
281
|
+
`name` + `email`, capped at 10 results, returns only `{ id, name,
|
|
282
|
+
email }` (no role / hash / audit metadata). Empty / whitespace
|
|
283
|
+
queries return an empty array so the endpoint can't be used as a
|
|
284
|
+
directory-enumeration tool.
|
|
285
|
+
|
|
286
|
+
**`cms-admin`**: New `<MentionableTextarea>` component plus pure
|
|
287
|
+
helpers in `lib/mention-picker.ts` (`detectMentionContext`,
|
|
288
|
+
`insertMentionToken`, `searchMentionUsers`). Wired into the three
|
|
289
|
+
comment composer surfaces in `CommentSidePanel`: the new-thread
|
|
290
|
+
textarea, the reply input, and the in-place edit textarea. The
|
|
291
|
+
picker is keyboard-driven (Arrow Up / Down, Enter / Tab to commit,
|
|
292
|
+
Escape to close) with a Radix-style listbox + ARIA roles, and
|
|
293
|
+
gracefully handles slow responses (drops stale requests when typing
|
|
294
|
+
quickly).
|
|
295
|
+
|
|
296
|
+
**`mcp-server`**: New `search_users(query)` tool exposes the same
|
|
297
|
+
lookup so AI agents can resolve teammates by name fragment before
|
|
298
|
+
drafting a comment. Wire format is unchanged — the picker writes
|
|
299
|
+
`@<userId>` tokens that the existing `extractMentionedUserIds`
|
|
300
|
+
parser already understands, so no notification schema migration is
|
|
301
|
+
required.
|
|
302
|
+
|
|
303
|
+
No breaking changes.
|
|
304
|
+
|
|
305
|
+
## 0.9.0
|
|
306
|
+
|
|
307
|
+
### Minor Changes
|
|
308
|
+
|
|
309
|
+
- 21db54b: Phase 7 PR F — MCP-parity audit stylistic cleanup.
|
|
310
|
+
|
|
311
|
+
This is the final follow-up to `docs/mcp-parity-audit.md`. After this
|
|
312
|
+
PR the audit is fully retired — P0, P1, and stylistic notes are all
|
|
313
|
+
addressed.
|
|
314
|
+
|
|
315
|
+
### `@actuate-media/cms-core`
|
|
316
|
+
|
|
317
|
+
Adds `GET /api/cms/collections`: a lightweight discovery endpoint
|
|
318
|
+
sourced directly from `getActuateConfig()`. Returns
|
|
319
|
+
`{ data: CollectionMeta[] }` with one entry per configured collection
|
|
320
|
+
(`slug`, `labels`, `type`, `urlPrefix`, `hidden`, `fieldCount`,
|
|
321
|
+
`fields[{name,type,required}]`). Unauthenticated by design — the
|
|
322
|
+
response only exposes schema-shape metadata that is already public via
|
|
323
|
+
`/openapi.json` — and the contract is intentionally tight (only
|
|
324
|
+
`name` / `type` / `required` per field, no validators, hooks, or
|
|
325
|
+
access closures leak).
|
|
326
|
+
|
|
327
|
+
### `@actuate-media/mcp-server`
|
|
328
|
+
|
|
329
|
+
Three audit-mandated stylistic cleanups:
|
|
330
|
+
1. **AI-create-X collapse (6 tools → 3).** Removed `create_service`,
|
|
331
|
+
`create_location`, `create_team_member`. Their behaviour is folded
|
|
332
|
+
into `create_in_collection` via an optional `template` arg
|
|
333
|
+
(`'service' | 'location' | 'team_member' | 'generic'`) that
|
|
334
|
+
selects a built-in prompt-enrichment recipe plus a default
|
|
335
|
+
collection slug. Kept `create_blog_post` and `create_case_study`
|
|
336
|
+
as type-specific tools because their field-sets are distinctive
|
|
337
|
+
enough to be standalone agent intents.
|
|
338
|
+
|
|
339
|
+
**Breaking change** (acknowledged — pre-1.0, audit-recommended):
|
|
340
|
+
the three removed tool names will return "tool not found" on next
|
|
341
|
+
release. Migration is mechanical:
|
|
342
|
+
- `create_service({ category, ... })`
|
|
343
|
+
→ `create_in_collection({ template: 'service', category, ... })`
|
|
344
|
+
- `create_location({ cityState, ... })`
|
|
345
|
+
→ `create_in_collection({ template: 'location', cityState, ... })`
|
|
346
|
+
- `create_team_member({ name, role, ... })`
|
|
347
|
+
→ `create_in_collection({ template: 'team_member', name, role, ... })`
|
|
348
|
+
|
|
349
|
+
2. **`audit_document` split.** Replaced with `audit_document_by_id`
|
|
350
|
+
(requires `collection` + `id`) and `audit_inline_content` (requires
|
|
351
|
+
`title` + `body`). Both forward to the same `/ai/audit-document`
|
|
352
|
+
endpoint; the split exists so agents pick the right mode at the
|
|
353
|
+
tool boundary instead of constructing a half-filled blob and
|
|
354
|
+
discovering the "must provide either (collection,id) or body" rule
|
|
355
|
+
via a server-side error.
|
|
356
|
+
|
|
357
|
+
**Breaking change** (audit-recommended): `audit_document` is
|
|
358
|
+
removed. Migration: pick the explicit tool that matches the
|
|
359
|
+
intent — `audit_document_by_id` for stored docs,
|
|
360
|
+
`audit_inline_content` for ad-hoc text.
|
|
361
|
+
|
|
362
|
+
3. **`list_collections` reliability.** Now prefers the new
|
|
363
|
+
`/api/cms/collections` endpoint as the primary source so the tool
|
|
364
|
+
stays accurate when the OpenAPI generator drifts. Falls back to
|
|
365
|
+
OpenAPI only on a real HTTP 404 (older CMS server) — the decision
|
|
366
|
+
uses `ActuateClientError.status` (newly exported from the client),
|
|
367
|
+
not a regex against the error message, so an unrelated server
|
|
368
|
+
error that happens to contain "not found" in its body no longer
|
|
369
|
+
triggers the fallback. Non-404 errors propagate.
|
|
370
|
+
|
|
371
|
+
**Return-shape change** (consistent contract): `data` is now
|
|
372
|
+
ALWAYS a `CollectionSummary[]` array regardless of which path
|
|
373
|
+
responded. The OpenAPI fallback path normalises into the same
|
|
374
|
+
array shape that the new `/collections` endpoint emits, so
|
|
375
|
+
callers no longer need to branch on `source` to know whether they
|
|
376
|
+
got an array or an object map. The returned envelope is
|
|
377
|
+
`{ data: CollectionSummary[], source: 'collections' | 'openapi' }`.
|
|
378
|
+
|
|
379
|
+
**Newly exported:** `ActuateClientError` (subclass of `Error`
|
|
380
|
+
carrying `status: number`). Useful for any consumer that needs
|
|
381
|
+
to branch on the HTTP status from a `request()` failure.
|
|
382
|
+
|
|
383
|
+
### Tests
|
|
384
|
+
- mcp-server: 113 tests total (was 97 in PR E). 16 new — template
|
|
385
|
+
routing for each of service / location / team_member, audit split
|
|
386
|
+
validation, list_collections primary + fallback + 500-propagation.
|
|
387
|
+
- cms-core: 4 new tests for the discovery endpoint covering field
|
|
388
|
+
summaries, `hidden` flag, missing-config 500, and the
|
|
389
|
+
no-leak-of-validators-or-hooks contract.
|
|
390
|
+
|
|
391
|
+
## 0.8.0
|
|
392
|
+
|
|
393
|
+
### Minor Changes
|
|
394
|
+
|
|
395
|
+
- e0ac7f1: Add 4 comment + page-builder accessibility MCP tools (Phase 7 MCP-parity PR D). Combined with PRs A (10 media/folder), B (6 versions/scheduling/workflow), and C (5 SEO), this closes the remaining P0 gaps from [`docs/mcp-parity-audit.md`](https://github.com/actuate-media/actuatecms/blob/main/docs/mcp-parity-audit.md) and brings the MCP server to **100% P0 coverage**.
|
|
396
|
+
|
|
397
|
+
**Comments (2):**
|
|
398
|
+
- `list_comments` — returns the comment thread for a document. Default scope is unresolved + non-deleted; `includeResolved: true` widens to resolved threads; `includeDeleted: true` is admin-only and surfaces soft-deleted moderation history (non-admin keys get HTTP 403).
|
|
399
|
+
- `create_comment` — create a top-level comment, a thread reply (`parentId`), or a text-pinned comment (`anchor: { from, to }`). The wrapper rejects empty `body` strings at the Zod layer (server also rejects, but failing fast saves a round-trip). The server emits a `comment_created` audit event and fires a best-effort notification dispatch for any mentioned users.
|
|
400
|
+
|
|
401
|
+
**Page-builder accessibility (2):**
|
|
402
|
+
- `audit_page_a11y` — deterministic accessibility audit over a page-builder tree. Detects missing alt text, heading-level skips, missing form labels, missing ARIA attributes, and undersized touch targets. Each issue carries `autoFixable: boolean` so the caller can decide between automated cleanup vs human review.
|
|
403
|
+
- `fix_page_a11y` — auto-fix every `autoFixable: true` issue and return the mutated tree plus a report (`fixedCount` / `remainingCount` plus the unfixable remainder for human follow-up). Emits a `settings_changed` audit event.
|
|
404
|
+
|
|
405
|
+
**Schema design notes:**
|
|
406
|
+
- Both `list_comments` and `create_comment` use `id` (not `documentId`) for the document ID — matches the PR B convention and the pre-existing `audit_document` / `get_document` / `update_document` family. The collection slug is intentionally absent because comments attach to documents by ID alone.
|
|
407
|
+
- `create_comment.anchor` and `create_comment.parentId` are both `.nullable().optional()`. Publishing `["object", "null"]` and `["string", "null"]` in the JSON Schema preserves the server semantics where `null` is meaningful ("thread-level comment" / "no anchor"), not an MCP-client artefact.
|
|
408
|
+
- A11y tools take `tree: z.record(z.unknown())` — the page-builder schema is large and evolving so we accept any object and let the server enforce the top-level `tree.type === 'page'` check. Strings / numbers / arrays still fail at the Zod layer.
|
|
409
|
+
|
|
410
|
+
**Tests:** mcp-server suite 56 → 70 (+14). Covers per-method URL / method / body shape, boolean → string query encoding for `listComments`, URL encoding for awkward IDs, 403 propagation for read-only keys hitting `create_comment`, 400 propagation for malformed page trees, anchor / parentId nullable JSON Schema emission, and empty-body rejection at the wrapper layer.
|
|
411
|
+
|
|
412
|
+
This PR closes the audit's last P0 acceptance criterion. PR E (~14 P1 mop-up tools) and PR F (stylistic cleanup — collapse the `ai_create_*` family, fix the `audit_document` schema drift, OpenAPI fallback) remain as demand-driven cherry-picks.
|
|
413
|
+
|
|
414
|
+
- 942ad41: Add 14 MCP tools — P1 mop-up from the MCP-parity audit. Phase 7, PR E.
|
|
415
|
+
|
|
416
|
+
Tools shipped:
|
|
417
|
+
|
|
418
|
+
Comment thread management (4):
|
|
419
|
+
- `edit_comment` — `PATCH /comments/:id`
|
|
420
|
+
- `resolve_comment` — `POST /comments/:id/resolve`
|
|
421
|
+
- `reopen_comment` — `POST /comments/:id/reopen`
|
|
422
|
+
- `delete_comment` — `DELETE /comments/:id`
|
|
423
|
+
|
|
424
|
+
Redirects (3) — admin-only on the server, open-redirect defence preserved:
|
|
425
|
+
- `list_redirects` — `GET /redirects`
|
|
426
|
+
- `create_redirect` — `POST /redirects` (statusCode constrained to 301/302/307/308 via schema enum)
|
|
427
|
+
- `delete_redirect` — `DELETE /redirects/:id`
|
|
428
|
+
|
|
429
|
+
Page templates + saved sections (3) — admin-only discovery for the page builder:
|
|
430
|
+
- `list_page_templates` — `GET /page-templates` (optional category + collection filters)
|
|
431
|
+
- `get_page_template` — `GET /page-templates/:id`
|
|
432
|
+
- `list_saved_sections` — `GET /saved-sections`
|
|
433
|
+
|
|
434
|
+
SEO aggregate (2):
|
|
435
|
+
- `seo_summary` — cheap dashboard aggregate (`GET /seo/summary`)
|
|
436
|
+
- `seo_scan_run` — expensive site-wide scan (`POST /seo/scan`); wrapper enforces a `confirm: true` literal per the audit's gate-behind-confirmation recommendation
|
|
437
|
+
|
|
438
|
+
Forms + health (2):
|
|
439
|
+
- `list_form_submissions` — PII-sensitive; requires explicit `formId` arg, no enumeration (`GET /forms/:formId/submissions`)
|
|
440
|
+
- `health_check` — `GET /health` (unauthenticated on the server; safe first-call probe)
|
|
441
|
+
|
|
442
|
+
Notes:
|
|
443
|
+
- Comment-thread tools follow the `id` naming convention established in
|
|
444
|
+
PR B / PR D for resource-scoped tools.
|
|
445
|
+
- `list_form_submissions` uses `formId` (not `id`) because the audit
|
|
446
|
+
explicitly called out "gate behind explicit form-id arg" — the more
|
|
447
|
+
specific name makes the PII gate self-documenting in agent prompts.
|
|
448
|
+
- `seo_scan_run` rejects calls without `confirm: true` before issuing
|
|
449
|
+
the HTTP request. Defence-in-depth: Zod `.literal(true)` rejects at
|
|
450
|
+
the schema layer and the handler re-asserts so a schema regression
|
|
451
|
+
still fails closed.
|
|
452
|
+
- All 14 tools forward server errors verbatim (403 admin gate, 400
|
|
453
|
+
open-redirect defence, 403 author-only delete/edit) so agents see the
|
|
454
|
+
same affordances the admin UI does.
|
|
455
|
+
- 24 new tests (15 client + 9 tool-level wrappers, including
|
|
456
|
+
confirmation-gate, PII-naming, and enum-validation regressions).
|
|
457
|
+
Brings the mcp-server test suite to 94 tests total.
|
|
458
|
+
|
|
459
|
+
This closes out the P1 list from `docs/mcp-parity-audit.md`. After
|
|
460
|
+
PR E, every admin action the audit flagged as user-visible (P0 + P1) is
|
|
461
|
+
reachable via MCP. Only PR F (stylistic cleanup — collapsing
|
|
462
|
+
`ai-create-X`, fixing `audit_document` schema, OpenAPI fallback)
|
|
463
|
+
remains as demand-driven follow-up.
|
|
464
|
+
|
|
465
|
+
## 0.7.0
|
|
466
|
+
|
|
467
|
+
### Minor Changes
|
|
468
|
+
|
|
469
|
+
- 9517da2: Add 6 versions + scheduling + workflow MCP tools (Phase 7 MCP-parity PR B). Combined with PRs A (10 media/folder tools) and C (5 SEO tools), this retires **21 of the 24 P0 gaps** identified in [`docs/mcp-parity-audit.md`](https://github.com/actuate-media/actuatecms/blob/main/docs/mcp-parity-audit.md). The remaining 3 P0 items are comments + page-builder accessibility, queued as PR D.
|
|
470
|
+
|
|
471
|
+
**Version history (2):**
|
|
472
|
+
- `list_versions` — immutable change history of a document, newest first. Each version carries the full `data` payload at write time plus the user who made the change. Paged (default 20 / max 50).
|
|
473
|
+
- `restore_version` — roll a document back to a prior version. Goes through the normal `updateDocument` path: hooks fire, a NEW version row is created (history is never rewritten), and an audit log entry is emitted.
|
|
474
|
+
|
|
475
|
+
**Scheduling (2):**
|
|
476
|
+
- `schedule_publish` — schedule a document to publish (`scheduledAt`) and/or unpublish (`scheduledUnpublishAt`) at a future ISO 8601 timestamp. The server requires at least one of the two, both must be in the future, and `scheduledUnpublishAt` must be after `scheduledAt` when both are set. Publishing forces `status` → `SCHEDULED` so the `/cron/publish` cron picks it up; the cron does the actual status flip (decoupled so a missed tick just delays publish — it can never double-publish or skip a doc).
|
|
477
|
+
- `unschedule_publish` — cancel pending publish + unpublish. If the document was in `SCHEDULED` (not yet published) it drops back to `DRAFT`. Already-published docs stay live.
|
|
478
|
+
|
|
479
|
+
**Editorial workflow (2):**
|
|
480
|
+
- `get_workflow_state` — returns `{ stage, transitions, reviewerId, reviewNote }`. `transitions` is the list of next stages the _calling API key holder_ is allowed to move to, already role-filtered server-side. Workflow: `DRAFT → IN_REVIEW → APPROVED → PUBLISHED → ARCHIVED`.
|
|
481
|
+
- `transition_workflow` — move a document to a new stage. Server validates both that the from→to edge is legal AND that the caller's role permits it; either failure returns HTTP 400 with the reason in the error body. The `stage` arg is a Zod enum, so unknown stages are rejected at the wrapper layer before the HTTP call (clear schema error, no wasted round-trip).
|
|
482
|
+
|
|
483
|
+
**Tests:** mcp-server suite 40 → 53 (+13). Coverage includes per-method URL / method / body shape, optional-field independence on `schedule_publish`, enum validation on `transition_workflow.stage`, error propagation for both 400 paths (illegal transitions, past timestamps), and URL encoding of awkward collection slugs + document IDs.
|
|
484
|
+
|
|
485
|
+
## 0.6.0
|
|
486
|
+
|
|
487
|
+
### Minor Changes
|
|
488
|
+
|
|
489
|
+
- a142310: Add 10 media + folder MCP tools (Phase 7 MCP-parity PR A). Combined with PR C (5 SEO tools, shipped in PR #145), this retires 15 of the 24 P0 gaps identified in [`docs/mcp-parity-audit.md`](https://github.com/actuate-media/actuatecms/blob/main/docs/mcp-parity-audit.md).
|
|
490
|
+
|
|
491
|
+
**Media write tools (5):**
|
|
492
|
+
- `upload_media` — uploads a file to the media library. Bytes pass through MCP as base64 (JSON-RPC has no binary type), the tool wrapper decodes them, and the client emits a real `multipart/form-data` request. The server enforces a 50 MB hard cap, validates magic bytes against the declared `mimeType`, and sanitises SVGs.
|
|
493
|
+
- `update_media` — set alt text (accessibility), title, filename, or focal points (smart-crop hints in 0..1 normalised coords).
|
|
494
|
+
- `delete_media` — removes the DB row AND deletes the underlying blob storage object (best-effort).
|
|
495
|
+
- `optimize_media` — recompress an existing image to WebP. Returns the updated row plus an `optimization` summary. Already-WebP files short-circuit.
|
|
496
|
+
- `move_media_to_folder` — `folderId: string | null`; the server validates the target folder is in the `media` scope.
|
|
497
|
+
|
|
498
|
+
**Folder tools (5):**
|
|
499
|
+
- `list_folders` — returns a nested tree (`children[]`) for a given scope. Scopes today: `"media"`, `"documents"`, `"collections"`. The `scope` arg is required.
|
|
500
|
+
- `create_folder` — `{ name, scope, parentId? }`. Parents must already exist in the same scope.
|
|
501
|
+
- `update_folder` — rename / reparent / reorder; pass any subset of `{ name, parentId, position }`. `parentId: null` promotes a folder to root. The server prevents self-parenting and cross-scope reparenting.
|
|
502
|
+
- `delete_folder` — returns HTTP 409 if the folder still contains documents, media, or sub-folders. The caller must move or delete the contents first.
|
|
503
|
+
- `move_document_to_folder` — same shape as `move_media_to_folder`, scoped to documents/collections folders.
|
|
504
|
+
|
|
505
|
+
**Tooling improvements:**
|
|
506
|
+
- Added a `requestMultipart()` helper to `ActuateClient` for endpoints that need `multipart/form-data`. It deliberately omits the `Content-Type` header so the fetch runtime can append the multipart boundary (overriding it breaks server-side parsing).
|
|
507
|
+
- Extended the Zod → JSON Schema converter to handle `ZodNullable`. Nullable fields now publish `type: ["string", "null"]` (etc.), so MCP-aware clients accept explicit `null` from agents. The `move_*_to_folder` and `update_folder` tools rely on this.
|
|
508
|
+
|
|
509
|
+
37 new unit tests (mcp-server suite: 21 → 38). Includes regression tests for: multipart body shape, missing `Content-Type` override, base64 with data-URL prefix + whitespace, empty-bytes rejection, null `folderId` round-trip on both move tools, and URL encoding of awkward IDs.
|
|
510
|
+
|
|
511
|
+
## 0.5.0
|
|
512
|
+
|
|
513
|
+
### Minor Changes
|
|
514
|
+
|
|
515
|
+
- 8d105c3: Add five per-document SEO MCP tools (Phase 7 MCP-parity PR C):
|
|
516
|
+
- `seo_analyze_document` — runs the deterministic SEO content analysis (title, meta, headings, focus keyphrase, link counts, score) against a stored document.
|
|
517
|
+
- `seo_readability_score` — Flesch-Kincaid reading-ease + grade-level for a document body.
|
|
518
|
+
- `seo_internal_link_targets` — suggests up to 10 published documents to link TO, rooted in a specific stored document (title-keyword-based). Distinct from the existing `suggest_internal_links` tool, which is content-based and freeform.
|
|
519
|
+
- `seo_meta_preview` — resolved meta-tag preview (title, description, canonical, OG, Twitter, robots) for a document, with per-page overrides and site-level defaults applied.
|
|
520
|
+
- `seo_schema_graph` — Schema.org JSON-LD graph (`@context` + `@graph` with WebSite / WebPage / Article nodes) for a document.
|
|
521
|
+
|
|
522
|
+
All five are read-only deterministic wrappers around the existing `GET /api/cms/seo/<scope>/:documentId` endpoints — no LLM calls, no DB writes, cheap enough for an agent to invoke as part of a publish-readiness pipeline. Each requires only a `documentId` arg.
|
|
523
|
+
|
|
524
|
+
This is the first follow-up PR from the [MCP-parity audit](https://github.com/actuate-media/actuatecms/blob/main/docs/mcp-parity-audit.md) (PR #144), retiring 5 of the 24 P0 gaps identified there.
|
|
525
|
+
|
|
526
|
+
## 0.4.0
|
|
527
|
+
|
|
528
|
+
### Minor Changes
|
|
529
|
+
|
|
530
|
+
- 0ac9024: Inline AI co-author HTTP endpoint + MCP tool (Phase 2).
|
|
531
|
+
|
|
532
|
+
Adds `POST /api/cms/ai/coauthor` with four sub-actions (`rewrite`,
|
|
533
|
+
`expand`, `compress`, `proofread`) that wrap the plugin-ai writing
|
|
534
|
+
primitives behind a single endpoint. Rate-limited under the same
|
|
535
|
+
bucket as content generation (20 calls/hour/user). Missing provider
|
|
536
|
+
configuration surfaces as HTTP 501 instead of 500.
|
|
537
|
+
|
|
538
|
+
Exposed to AI agents via the MCP tool `coauthor_text` with the same
|
|
539
|
+
input shape, so the admin UI and AI agents can drive identical
|
|
540
|
+
text-transformation workflows.
|
|
541
|
+
|
|
542
|
+
Tests: 5 endpoint tests covering each action + validation errors.
|
|
543
|
+
|
|
544
|
+
- 313a23f: Add Slice F — AI quality pass.
|
|
545
|
+
|
|
546
|
+
`plugin-ai` exposes a new `auditDocument()` composer that combines SEO,
|
|
547
|
+
readability (Flesch-Kincaid / Gunning Fog / SMOG averaged + remapped to a
|
|
548
|
+
0-100 score), accessibility, and freshness scoring into a single
|
|
549
|
+
composite grade with prioritized actionable issues. The composer is
|
|
550
|
+
deterministic — it never calls an LLM — so it's cheap enough to invoke
|
|
551
|
+
on every save or debounced keystroke.
|
|
552
|
+
|
|
553
|
+
`cms-core` adds two HTTP endpoints:
|
|
554
|
+
- `POST /ai/audit-document` — runs the composite audit against a stored
|
|
555
|
+
document (`{ collection, id }`) or ad-hoc content. Honors field-level
|
|
556
|
+
access control when loading from the DB.
|
|
557
|
+
- `POST /ai/suggest-internal-links` — scans published documents for
|
|
558
|
+
phrases the supplied content could link to, returning ranked
|
|
559
|
+
anchor-text + target-URL suggestions. Optionally scopes to a single
|
|
560
|
+
collection.
|
|
561
|
+
|
|
562
|
+
`mcp-server` exposes both endpoints as MCP tools (`audit_document` and
|
|
563
|
+
`suggest_internal_links`) so AI agents can grade drafts and propose
|
|
564
|
+
internal links before publish.
|
|
565
|
+
|
|
566
|
+
Docs: `docs/ai-quality-audit.md`.
|
|
567
|
+
|
|
568
|
+
## 0.3.0
|
|
569
|
+
|
|
570
|
+
### Minor Changes
|
|
571
|
+
|
|
572
|
+
- e6a18b5: Phase 2 Slice C — AI Content Authoring for any collection.
|
|
573
|
+
- **plugin-ai**: new `generateDocumentContent()` helper that maps a prompt onto a collection's field schema and returns structured field data ready to persist. Supports tone, target audience, brand voice profile, and existing-content context. Coerces LLM output to declared field types (numbers, booleans, dates, select options, array items) and drops fields the schema doesn't declare.
|
|
574
|
+
- **cms-core**: new `POST /collections/:slug/ai-create` endpoint — the non-page counterpart to `/page-builder/create`. Generates a complete document for any collection, persists as draft, optionally publishes via a follow-up update when the caller has admin scope. Refuses page-builder collections (use `/page-builder/create` instead). Hard caps prompt at 4000 chars and shares the per-user 20/hour AI rate-limit bucket. Returns a `warning` field when create succeeds but publish is denied.
|
|
575
|
+
- **mcp-server**: six new tools — `create_in_collection` (generic) plus per-type sugar tools `create_blog_post`, `create_case_study` (with `clientName` / `industry` hints), `create_service` (`category` hint), `create_location` (`cityState` hint), and `create_team_member` (`name` / `role` hints). Each per-type tool targets the conventional collection slug shipped by the cms-core collection presets, with an explicit `collection` override for sites using custom slugs.
|
|
576
|
+
- 19 new tests (10 unit tests in plugin-ai for the content generator, 9 integration tests in cms-core for the API endpoint covering auth, validation, persistence, publish flow, and the page-builder refusal path).
|
|
577
|
+
- Docs: updated `docs/api-reference.md` with the new endpoint, `docs/mcp.md` and `packages/mcp-server/README.md` with the new tools and example agent prompts.
|
|
578
|
+
|
|
579
|
+
## 0.2.0
|
|
580
|
+
|
|
581
|
+
### Minor Changes
|
|
582
|
+
|
|
583
|
+
- e87471d: Phase 1: AI access. API key authentication (act*sk*\* bearer tokens) with scope-based authorization across collections, globals, media, and the page builder. New /api-keys admin endpoints + UI for creating, listing, and revoking keys with password reauth. CSRF is skipped for API-key requests. New /page-builder/create one-shot endpoint that generates an AI page and persists it as a document in a single call. New @actuate-media/mcp-server package exposes the CMS to AI agents (Claude, Cursor, ChatGPT, etc.) via the Model Context Protocol — full CRUD, globals, media, page generation, and one-shot create tools. Adds 44 new tests covering the API key auth path, scope enforcement, CSRF skip, and MCP client/tools.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Actuate Media
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|