This release adds 3 notable features for engineering teams evaluating rollout.
✓ No known CVEs patched in this version
Topics
+8 more
Affected surfaces
ReleasePort's take
Light signalThe upcoming @contentrain/mcp 1.11.0 release fixes silent unpublishing and bulk‑status loss while introducing a mandatory migration for draft‑status drift.
Why it matters: Projects must run `contentrain_validate` and resolve draft status drift before the next Studio enforcement deadline; failure will cause unintended unpublishings.
Summary
AI summaryFixed multiple publish-status bugs causing silent unpublishing of entries and loss of bulk status updates.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Breaking | High |
Migration required: projects must run `contentrain_validate` and fix draft status drift before upcoming Studio enforcement. Migration required: projects must run `contentrain_validate` and fix draft status drift before upcoming Studio enforcement. Source: llm_adapter@2026-07-15 Confidence: high |
— |
| Feature | Low |
`update_status` accepts singletons, dictionaries, and an optional `locale` argument. `update_status` accepts singletons, dictionaries, and an optional `locale` argument. Source: llm_adapter@2026-07-15 Confidence: high |
— |
| Feature | Low |
`contentrain_validate` adds checks for draft entries alongside published ones and mismatched meta/content layouts. `contentrain_validate` adds checks for draft entries alongside published ones and mismatched meta/content layouts. Source: llm_adapter@2026-07-15 Confidence: high |
— |
| Bugfix | Medium |
`contentrain_content_save` no longer resets an entry's status during field edits. `contentrain_content_save` no longer resets an entry's status during field edits. Source: llm_adapter@2026-07-15 Confidence: high |
— |
| Bugfix | Medium |
`contentrain_bulk update_status` now persists all provided entry IDs without dropping updates. `contentrain_bulk update_status` now persists all provided entry IDs without dropping updates. Source: llm_adapter@2026-07-15 Confidence: high |
— |
| Bugfix | Low |
Non‑i18n models maintain exactly one meta record per entry ID. Non‑i18n models maintain exactly one meta record per entry ID. Source: llm_adapter@2026-07-15 Confidence: high |
— |
| Bugfix | Low |
`contentrain_doctor` SDK freshness check correctly detects stale client files. `contentrain_doctor` SDK freshness check correctly detects stale client files. Source: llm_adapter@2026-07-15 Confidence: high |
— |
Full changelog
Minor Changes
-
d617dab: fix(mcp): stop content_save unpublishing entries, and make bulk update_status persist every id
Four publish-status bugs, all found on a live project against the CDN. Each one
reported success while content quietly stopped being delivered.contentrain_content_saveno longer resets an entry's status. It rebuilt
meta from scratch on every write, so editing one field silently moved a
publishedentry todraft— and the next CDN build served the collection as
{}. Editing a field is not a publish decision, and per this repo's own split
(MCP is deterministic infra; the agent is intelligence) MCP should never have
been making it. An existing entry now keeps itsstatus,approved_byand
version; only a genuinely new entry starts atdraft.source/updated_by
still describe the current write. The same reset lived in a second copy behind
contentrain_applyand scaffolding — both now share onemergeEntryMeta.contentrain_bulk update_statusno longer drops entries. It launched one
writeMetaper entry ID throughPromise.all, and every call read the same
snapshot of the shared{locale}.jsonand rewrote the whole file — so N-1
updates were lost while the response reported all N as updated. It is now a
single read-modify-write per locale file, andupdatedcounts what actually
persisted.copy_localehad the identical race and wrote 1 meta record instead
of N. Neither had any test coverage;bulknow has a suite.update_statusworks on singletons and dictionaries. Theentry_idsguard
ran before the model-kind guard, so a singleton had no reachable path: omitting
entry_idsfailed with "requires entry_ids", supplying them failed with "only
supported for collection models". Call it withoutentry_idsfor these kinds.
It also takes an optionallocalenow, instead of always rewriting every
supported locale.Non-i18n models keep exactly one meta record. Content collapses to a single
data.jsonwhile meta was still derived from the caller's locale, so one
content file could end up withmeta/{id}/tr.jsonandmeta/{id}/en.json
and readers disagreed about which was authoritative.metaFilePathnow takes
i18nand the default locale and pins the record there. This also fixes
non-i18n collection deletes, which looked formeta/{id}/data.json— a file
that never existed — and orphaned the meta entry.contentrain_doctor's SDK freshness check works again. It compared
directory mtimes, butgeneraterewrites the client files in place (which never
moves the directory's mtime) while a selective sync recreates model files via
git checkout(which does). Once you had saved a model, it reported "Stale"
permanently. It now compares the newest file mtime under each directory.contentrain_validategained two checks for the class of failure above,
since it reported 0 errors throughout: a notice for drafts sitting alongside
published entries in one collection, and a warning for a non-i18n model whose
meta layout disagrees with its content layout. Neither is auto-fixed —
publishing is a content decision.MIGRATION — read before upgrading Studio. Projects that ran an affected version
have singletons and entries sitting atdraftthat were never meant to be. That
is currently harmless, because the CDN publishes singletons and dictionaries
regardless of status. When Studio starts enforcing status for those kinds, that
content will disappear from the CDN. Upgrade here first, run
contentrain_validateto find the drift, restore it withcontentrain_bulk update_status, and only then take the Studio change.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About Contentrain/ai
Local-first MCP server for AI content governance — 13 tools for model/content CRUD, validation, normalization, and i18n across any framework.
Related context
Related tools
Earlier breaking changes
- v@contentrain/[email protected] `validateModelDefinition` now returns `{ errors, warnings }` instead of a string array.
- v@contentrain/[email protected] `model_save` rejects models with unknown keys, `min > max`, invalid constraints, and `unique` on singletons.
- v@contentrain/[email protected] `content_save` now validates before committing and rejects invalid content.
- v@contentrain/[email protected] `validateModelDefinition` now returns `{ errors, warnings }` instead of a string array.
- v@contentrain/[email protected] `model_save` rejects models with unknown keys, `min > max`, invalid constraints, and `unique` on singletons.
Beta — feedback welcome: [email protected]