Both write paths state it outright: an update or a patch leaves the published snapshot serving the public API until a publish call mints a new immutable version. That makes the version list the real history, revertible and relabellable without the payload changing. Three sharp edges are named in the tools themselves, and each one costs an afternoon if you find it the hard way: a URL or permalink field has to be of type slug rather than text, a relation is written as the related entry's UUID and never as the nested object a read gave you, and a translation group can be linked through the API but only split in the dashboard.
A headless CMS client covering a project's schema, its content entries and their published versions, its assets and its webhooks. Everything is scoped to one ElmapiCMS project, addressed by its UUID.
- Project information and locales, with the default locale set and new locale codes added — removing a locale is deliberately left to the dashboard (get_project, add_project_locale, set_default_project_locale).
- Collections listed, fetched with their full field schema, created together with their fields in one request, renamed and reordered; fields added, updated and reordered (list_collections, get_collection, create_collection, update_collection, reorder_collections, create_field, update_field, reorder_fields).
- Entries queried with a where clause carrying 13 operators, OR groups and relation filtering, alongside sorting, pagination, count and first (list_entries, get_entry).
- Writes in the shape the change actually is: a full replace by PUT, a partial merge by PATCH that touches only the fields you send, and a soft delete to trash that the admin panel can restore (create_entry, update_entry, patch_entry, delete_entry).
- Publishing as its own act: publishing mints an immutable version and makes it live, unpublishing clears the live pointer while keeping every historical version, and a dirty draft can be thrown away back to the published state (publish_entry, unpublish_entry, discard_entry_draft).
- Version history as a first-class record — listed newest first with number, label, description and publisher, fetched as a raw snapshot, reverted to and republished, or relabelled while the payload itself stays immutable (list_entry_versions, get_entry_version, revert_entry_version, update_entry_version_label).
- Atomic bulk operations where one failure rolls the whole batch back rather than leaving a half-finished import (bulk_create_entries, bulk_update_entries, bulk_delete_entries).
- Two entries in different locales merged into one translation group (link_entry_translation).
- Assets listed, fetched by UUID or filename, uploaded singly or in atomic batches from absolute local paths, updated in bulk and deleted (list_assets, get_asset, upload_asset, bulk_upload_assets, bulk_update_asset_metadata, delete_asset).
- Webhooks for content and auth events, with their delivery logs (list_webhooks, get_webhook, create_webhook, update_webhook, delete_webhook, list_webhook_logs).
Three values: ELMAPI_BASE_URL pointing at your instance's API root, a project Sanctum token from Project Settings, API Tokens in ELMAPI_API_KEY, and the project UUID in ELMAPI_PROJECT_ID. Launch with `npx -y @elmapicms/mcp-server` over stdio. Abilities on the token decide what works — adding or changing a locale needs admin, and publishing, unpublishing, discarding a draft, reverting a version and linking translations all need update. Against a local instance with a self-signed certificate, fix the CA trust rather than turning TLS verification off in a config you might ship.
One command plus a key — npx -y @elmapicms/mcp-server, then supply credentials
