1.1.0
November 4th, 2026
Statamic MCP 1.1.0 closes the holes a security review of 1.0.0 found, and translates the Control Panel pages into nine languages. Update soon if agents on your site can upload files or read with format: augmented.
Upgrading
#292D3E; --theme-selection-background: #00000080;">composer update danielgnh/statamic-mcp
If your site caches routes, run php artisan route:cache or php artisan optimize after updating. With the old cache, the Connections page answers 500 and the endpoint keeps its old middleware order, so the throttle still misses GET and DELETE.
Security
source_urldownloads connect only to the address the guard checked. The old pin applied only when curl read the same host asparse_url, and a host likehttp://x{a}.example.com/broke that. A caller with upload permission and a DNS name they control could reach loopback, private, and cloud metadata addresses and store the answer as an asset. URL uploads now always run on curl, and a server withcurl_execdisabled refuses them. Through an HTTP proxy, a download now sendsCONNECTto the validated IP instead of the hostname, so a proxy that filters by hostname or port can refuse it.source_urlrefuses the address ranges the docs said it did. Documentation, benchmarking, multicast, and other special-purpose ranges got through, in IPv4 and IPv6, and so did Azure's wire server at168.63.129.16.uploads.source_allowlistdoesn't override this, so a site that downloads from one of these ranges on its own network now gets a refusal.- Computed values respect
resourcesinformat: augmented. A computed value that returned entries, terms, assets, or users came back in full, with another collection's content and other users' emails. Items outside the exposure are now dropped, and the rest become stubs. A computed value that returns plain data, such as a string ortoArray(), still comes back as written, so keep those out of collections an agent can read. - A malformed
middlewareconfig no longer leaves the endpoint open.'middleware' => [['throttle:60,1']]failed after the route was registered, so an anonymous caller could initialize and list the tools, though tool calls still refused. Any entry that isn't a string now keeps the route unmounted, andmcp:doctornames it. - The kill switch and the throttle cover every request. GET and DELETE skipped both, and a POST that
laravel/mcprefused for its headers was answered before them. - Two smaller leaks are closed. A Bard image in an unexposed container rendered differently depending on whether the file existed, and the in-lock URL check could name an entry the caller can't view.
Added
- The Control Panel pages follow each user's language. Tools → MCP, the OAuth consent page, and the Access MCP permission come in German (
de,de_CH), Spanish, French, Italian, Dutch, Norwegian, Portuguese (Brazil), and Russian. Other languages stay English, and your ownlang/<locale>.jsonoverrides any wording.
Changed
- Tools → MCP opens on a page for choosing Connections or Guidelines. Super admins used to land on Guidelines. Users who can only open Connections still go straight to it.
searchtreats%and_as plain text on the Stache. A search for50%used to find500too. SQL-backed repositories keep their wildcards.- One user can hold at most 100 tokens through the Control Panel.
mcp:tokenon the console has no limit. - Only bad config keeps MCP off at boot. A
route,server, ormiddlewarevalue of the wrong shape leaves the site up with MCP unmounted. Any other exception while registering the routes now surfaces instead of quietly turning MCP off. - An outage or a bug no longer reads as the agent's mistake. A database outage inside a fieldtype, or an unexpected error during a
source_urldownload, now reaches your exception handler, and the agent gets the generic error. A third-party fieldtype that throws a plainExceptionon a bad value gets the generic error too. ThrowInvalidArgumentExceptionto keep a message that names the field. mcp:keysrefuses to generate a pair during a database outage. In OAuth mode, the endpoint's 503 andmcp:doctorblamed missing keys, andmcp:keysthen wrote a new pair that overrides the stored one, so every connected client would have to reconnect. All three now name the database. A build box that can't reach its database and has no key files now gets exit 1 frommcp:keys, so runphp artisan passport:keysthere first.
Fixed
assets_uploadanswers with an error when the disk refuses the write, instead of reporting the file as live.assets_uploadnames a stored file Statamic can't read as an image undernot_stored.assets_uploadrefuses filenames over 250 bytes, a.metafolder, and control characters infolder.- A
source_urlredirect to an unparseable URL is a tool error. - A route cache built without the MCP routes no longer breaks the Control Panel.
terms_updaterefuses a localized slug another term has in that site.- New sets of a Replicator or Grid inside a Group get fresh ids.
- The OAuth consent page shows a redirect URI with a user part as it is.
mcp:setupchanges every line of a key that appears twice in.env.mcp:doctorstops suggesting you deletetokens.yamlwhen the user store fails, and names aroute,server, ormiddlewareconfig that can't mount.mcp:tokenand the Connections page survive aroutethat isn't a path. The command issues nothing and says why, and the page opens with an alert, so tokens can still be revoked.- Malformed guideline rows in a hand-edited file no longer break
blueprints_getor the Guidelines page. Good rows keep working, and bad ones are reported. - A value that crashes a validation rule now names the field.
- Code snippets on the Connections page follow the Control Panel's theme.
- The docs now match the code on what
enabled: falseleaves running, how a bad tool argument answers, whatresourceshides, and whenuploads.max_sizestops a download.
Full changelog: https://github.com/danielgnh/statamic-mcp/compare/v1.0.0...v1.1.0
1.0.0
November 1st, 2026
Statamic MCP 1.0.0 is the first stable release. From here on, releases follow semantic versioning: a 1.x update keeps tool names, their parameters and response fields, config keys, commands, routes, and the extension API in docs/tools.md working. The README's Versioning section lists the two exceptions.
Upgrading from 0.x
#292D3E; --theme-selection-background: #00000080;">composer require danielgnh/statamic-mcp:^1.0 --with-all-dependencies
If Composer reports a conflict, UPGRADE.md covers the two usual causes: a laravel/mcp requirement in your own composer.json, and laravel/boost older than 2.9.0. It also covers the route cache, a published consent view, and what agents see differently.
Breaking
- Requires
laravel/mcp1.1.2 or newer. 1.1.2 is the first release that keeps the OAuth consent page out of other sites' frames, so a hidden frame can't trick a signed-in editor into clicking Approve. It also caps client registration at ten redirect URIs and refuses lookalikes such ashttp://localhost:80@attacker.example/. Coming fromlaravel/mcp0.x, JSON-RPC errors now come back as HTTP 400, 404, or 500 instead of 200. - Augmented reads return related items in a shorter form. With
format: augmented,entries_getandterms_getreturn an entry Statamic adds itself, such asparent, asid,title,url,permalink, andapi_url. Every user,updated_byincluded, is{id, name, api_url}, withemailonly for a caller who hasview users. Augmentedterms_getno longer hasentriesorentries_count. Raw reads, the default, are unchanged.
Security
- The OAuth consent page shows where approving sends you. Anyone can register a client under any name, so a client called "Claude" with an attacker's redirect URI used to look like Claude. The page now shows the redirect URI with its host highlighted, as the browser will reach it, so a lookalike such as
cIaude.aishows asciaude.ai. If you published the consent view, UPGRADE.md has the step to bring it up to date. - OAuth mode accepts only tokens issued for Statamic users. A token from a Passport client of another user provider, or a client credentials token, no longer signs in as the Statamic user with the same id.
- Client registration is throttled at 60 requests a minute per address, shared with
/oauth/token. - The kill switch and the auth mode hold with cached routes. Both are checked on every request; rebuild the route cache after changing either.
source_urldownloads share one 15-second budget across redirects, and NAT64, 6to4, and Teredo addresses are no longer treated as public.resourcesholds everywhere. Blueprints, asset field writes, navigation menus, unique-URL errors, and augmented relations no longer reveal collections, taxonomies, or asset containers that MCP does not expose.
Fixed
- Assets with braces in their filename can be uploaded, updated, and read.
- A path with
../gets a tool error instead of an internal error. blueprints_getwithoutblueprintdescribes the blueprintentries_createuses, with the fields addons add.entries_createandentries_localizelist undernot_storedwhat a host listener cancelled.- Two conflicting moves no longer drop both entries from the tree.
- New page builder sets get an id the tools can address.
- Rewriting a long set list costs time in proportion to its length.
Full changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.9.1...v1.0.0
0.9.1
October 15th, 2026
[0.9.1] - 2026-10-15
Added
blueprints_getreads navigation blueprints.type: navigationwith a navigation handle returns the fields a branch'sdatatakes innavigations_update, an example of one branch's data, and, on a Replicator or Bard field, its sets;setreturns a set's fields and an example row, as it does for a page builder. A mega menu whose branches hold cards no longer leaves an agent guessing the card's field names from an existing branch:navigations_getlisted the field as a replicator and nothing more, andblueprints_getrefused the type. Reading takesview {handle} nav, likenavigations_get. When the blueprint definestitleorurl,example_notessays to pass them as branch keys, not insidedata.
0.9.0
October 15th, 2026
Everyday edits cost an agent a fraction of the tokens they did: adding a block, fixing a sentence, or reading an entry with a large synced field.
Added
Find and replace in long text. entries_update, terms_update, and globals_update take {"find": "...", "replace": "..."} for a Bard, Markdown, text, or textarea field, at the top level or inside a set addressed by id:
#292D3E; --theme-selection-background: #00000080;">#89DDFF;">{#89DDFF;">"article#89DDFF;">"#89DDFF;">: #89DDFF;">{#89DDFF;">"find#89DDFF;">"#89DDFF;">: #89DDFF;">"opens at nine#89DDFF;">"#89DDFF;">, #89DDFF;">"replace#89DDFF;">"#89DDFF;">: #89DDFF;">"opens at eight#89DDFF;">"#89DDFF;">}}
Only that piece of the stored text changes:
- Cost: fixing a sentence sends about 60 tokens instead of the whole article.
- Exactly once:
findmust match the stored text exactly once, and matches that cross formatting count too. - Formatting: in Bard, the match must sit inside one formatting run, and the replacement keeps that run's marks, so a link or bold is never lost.
- Errors: a miss, several matches, or a match across formatting is an error that quotes the nearby text, so the agent can fix
findwithout reading the field again. - Concurrent edits: if someone changed the text in the meantime, it no longer matches, so nothing is overwritten.
Changed
Adding, removing, and reordering blocks no longer costs the whole page. A list sent for a Replicator or Grid field now merges by id:
- An item with a stored id merges into that set, so
{"id": "wKJQXf2s"}keeps it as it is. - An item in another type replaces its set, and any other item is a new set.
- The sets left out are removed.
Adding a block is the list of ids with the new block where it goes. entries_update returns the new set's id under added, so the next edit can address it without reading the page again. A bare id the field doesn't store is refused, so a block someone removed in the meantime never comes back empty.
entries_get returns the staged working copy by default, as the Control Panel's edit form does. That's the version entries_update builds on and entries_publish promotes. working_copy: false returns the live entry, and source says which one you got on every revision-enabled entry.
Any large value comes back as a preview. Bard, Markdown, and page builders were already previewed or indexed in entries_get and terms_get. Now any other value over 4 KB comes back as {__preview, truncated, note} too, unless the agent asks for it with fields:
- an assoc array as its key count and first keys
- a list as its item count
- a string as its first 300 characters
That includes keys the blueprint no longer defines, which fields can now name. A Grid stays inline whatever its size.
Write results no longer echo what was just written. navigations_update returns the result, the edit URL, and the ids of new branches under added, instead of the whole tree. globals_update and terms_update no longer return the saved data.
Asset summaries drop id, basename, and folder, which repeat the path and the container you passed. A page of 25 assets is about 38% smaller.
The update tools are no longer marked idempotent. Retrying a call that inserts text or adds a set applies it twice.
Fixed
Writes take back whatever a field already stores, as the Control Panel does.
- A key is unknown only when the blueprint doesn't define it and the stored value doesn't hold it. That holds at every level: page builder sets, Grid rows, Bard sets, and Groups.
- A page builder sent back with stored keys its blueprint no longer defines, sets of removed types, or asset paths whose file is gone is no longer refused.
- A set's stale key can be changed or cleared by id.
- A new key that's neither defined nor stored is still refused, so typos don't become content.
Every unknown key is reported in one error, instead of one set per attempt.
Upgrading
0.9.0 changes some behavior agents and clients may rely on:
- List items merge. A list item with a stored id merges into that set instead of replacing it, so a key left out of it stays. Send
nullto clear a key. - Working copy by default.
entries_getreturns the staged working copy when there is one. Passworking_copy: falsefor the live entry. - Large values are previews. A large
array,yaml,code,textarea, or custom fieldtype value comes back as a preview. Read it in full withfields. - Smaller write results.
navigations_update,globals_update, andterms_updateno longer return the saved tree or data.assets_list,assets_get, andassets_uploadno longer returnid,basename, orfolder; the asset tools take the container andpath.
Token counts in the chart were measured over HTTP with the cl100k tokenizer, on pages with 8 to 16 blocks.
Full changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.8.0...v0.9.0
0.8.0
October 13th, 2026
Agents can change one page builder block without resending the page.
Added
Set-scoped writes. entries_update, terms_update, and globals_update take a Replicator or Grid field as an object keyed by set id, the id Statamic stores on every set and row, and merge into just those sets. {"page_builder": {"wKJQXf2s": {"variant": "centered"}}} changes one field of one block, and the page is saved the way the Control Panel saves it, so the other blocks keep their content, including blocks someone edited in the Control Panel in between. A tweak costs 6 to 11 times fewer bytes than fetching and resending the whole field. null removes a set, a Replicator or Grid nested in a set merges by id the same way, and an unknown id is an error that lists the existing sets with their types. A list still replaces the field, which is how sets are added, reordered, or given another type. Validation errors name a set by its id, as in page_builder.wKJQXf2s.heading.
One set at a time from entries_get and terms_get. fields takes handle.<id> and returns that set of a Replicator or Grid field as an object keyed by its id. That is the shape the update tools merge, so sending it back can never drop a sibling block.
Changed
Large page builders are read as an index. entries_get and terms_get return a Replicator field over 4 KB of JSON as an index of its sets, each with id, type, enabled when it is off, and a short preview from its title or first text field, under the same __preview marker as a long Bard value. Sending the index back is refused, and the error names the by-id patch. fields: ["page_builder"] fetches the whole field as before. Grid fields stay inline whatever their size. An agent that used to fetch a long page builder and send it back whole now gets the index and one error that points at the cheaper path.
Worth knowing
What a by-id write validates. Only what you send is checked for unknown keys, and a set fetched by id can go back whole, a key its blueprint no longer defines included, as long as that key is unchanged. The page then passes the same validation as a Control Panel save, so a block that no longer satisfies its rules blocks the write and is named by id in the error. Inside a set the merge is shallow: each named field is replaced whole, a Group included, and enabled must be true or false. null clears a page builder; an empty list or object is refused, since PHP cannot tell {} from [].
What it can't address. Bard sets keep their place inside the Bard value. A blank id, the id 0, or one that several sets share is an error that points at the whole field. A global set without a blueprint refuses the object form, since nothing says which variable holds sets.
Full changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.7.2...v0.8.0
0.7.2
September 27th, 2026
Agents can read what your forms collect.
Added
Form submissions. submissions_list returns a form's submissions newest first, each with its full data, so a week of contact requests is one call. search is the Control Panel's search: a substring match over the text, textarea, and integer fields, where % and _ are wildcards. since and before bound the date; a time without an offset is read in the app's timezone, and a date alone means midnight, so before: 2026-09-27 covers everything up to the end of the 26th. submissions_get returns one submission by form and id. submissions_delete removes one and, like the other delete tools, exists only when deletes is on. Nothing creates or edits a submission, as in the Control Panel.
Permissions follow Statamic's form policies. Reading takes view {form} form submissions and deleting takes delete {form} form submissions. configure forms grants both on every form, as it does in the Control Panel.
Forms in the overview and in blueprints_get. statamic_overview lists the forms you may read, with stores_submissions (false on a form that only sends email) and their submission count. blueprints_get takes type: form and returns the fields a submission's data is keyed by.
Worth knowing
A published config needs one line. The new resources.forms key defaults to true in the package config. A config/statamic/mcp.php you published before this release has no such key, and then no form is exposed until you add 'forms' => true under resources, the same rule navigations followed in 0.5.0.
Full changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.7.1...v0.7.2
0.7.1
September 25th, 2026
Slugs follow the Control Panel's rules now, both where two entries share one and where a collection has none.
Fixed
A slug may repeat, as in the Control Panel. entries_create, entries_update, and entries_localize refused a slug that another entry of the collection already had in the site. The Control Panel only refuses a URL another entry has. So /products/overview and /services/overview can both exist, and a localization can sit under a parent with the same slug, as in /de/delivery/delivery. Agents worked around the old rule with slugs like overview-2, which then showed up in the page's URL. A taken URL is still refused, and a blueprint whose slug field sets unique_entry_value still keeps slugs unique.
entries_get no longer picks one of several entries. A lookup by collection and slug that matches several entries of the site is now an error. It lists each entry's id and URL, so the agent can pass the id of the one it means. Before, it returned whichever entry the Stache gave back first, and an agent could read, then edit, the wrong page.
Collections with slugs turned off. entries_localize failed on such a collection with "An internal server error occurred." entries_create made a slug from the title, so Statamic named the entry's file after it instead of after the entry's id, which the Control Panel never does. Both give the entry no slug now, and the three write tools refuse a slug for these entries, since the Control Panel has no field to set one. A blueprint with a slug field of its own keeps slugs.
Changed
Avatars on Connections. The User column on Tools → MCP → Connections shows each user the way the Users listing does, with their avatar or initials next to their email, and links to the user. A deleted user's rows still show the user ID.
Worth knowing
Entries that earlier versions created in a collection with slugs turned off keep the slug the tools made from their title. A save in the Control Panel clears it. entries_update refuses a slug there, so an agent can't.
Full changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.7.0...v0.7.1
0.7.0
September 25th, 2026
Agents can translate entries on multilingual sites, and MCP gets its own place in the Control Panel.
Highlights
Translate an entry into another site. entries_localize adds an entry to another site of its collection, the way the Control Panel's Localize action does. The new entry is a draft localization. It inherits every field it doesn't override, data holds its own values such as a translated title and content, and slug defaults to the origin's. On a structured collection it joins the target site's tree under the localization of the origin's parent. It needs the edit permission for the origin entry and access to the target site, and it exists on multisite installs only.
Agents see what each site has. entries_get, entries_create, and entries_localize return localizations, the id and status of the entry in each site you can access, or null where it has none. On multisite, statamic_overview lists each collection's sites, propagate, and origin_behavior, and blueprints_get marks each field localizable or not, so an agent knows what it can translate before it writes. entries_update now refuses a localization's own value for a field that isn't localizable, as the Control Panel does, and names the origin entry to change instead.
Tools → MCP in the Control Panel. MCP has its own item under Tools, with Guidelines and Connections listed under it in the sidebar like the Utilities pages. Connections is the old MCP Access utility, with your tokens and OAuth connections. Guidelines holds the site's voice and tone and the rows on how a collection's entries are put together. Only super admins can open it.
Guidelines move out of Globals. The guidelines global set sat next to the site's content, so editors took it for website content, and any agent acting as a super admin could rewrite it through globals_update. Guidelines now live in Statamic's addon settings, in resources/addons/statamic-mcp.yaml or the database. Agents read them through statamic_overview and blueprints_get as before, a row switched off on the page no longer reaches them, and no tool writes them.
mcp:guidelines moves 0.6.0 guidelines. The command no longer creates a global set. It moves the old one to the Guidelines page, prints the page's URL, and lists the page builder blocks without instructions as before.
The Boost skill sends coding agents to the Guidelines page or its YAML file.
Breaking changes
- Guidelines no longer live in the
guidelinesglobal set. Agents read the set only untilphp please mcp:guidelinesmoves it, as described below. Theguidelinesconfig key is gone, and no tool writes guidelines any more. - The Guidelines page rejects
{{, Antlers and Blade component tags, and@props,@aware, and@cascade, because Statamic runs addon settings through Antlers every time it loads them. Describe such a tag in words. - The MCP Access utility and its permission are gone. Its page is Tools → MCP → Connections, which needs Access MCP, so a role with Access MCP alone can now issue its own tokens. OAuth mode already let those users connect themselves.
- Published copies of
utilities/mcp-tokens.blade.phpno longer apply. The page ismcp/connections.blade.php.
Upgrading from 0.6.0
- Update the package:
composer update danielgnh/statamic-mcp - Move the guidelines:
php please mcp:guidelines. Run it where the content lives, locally on a flat-file site or in production when globals live in a database. It copies the guidelines global set to Tools → MCP → Guidelines, then deletes the set and its blueprint. Until you run it, agents keep reading the set and the Guidelines page shows a notice. - On a flat-file site, commit
resources/addons/statamic-mcp.yamland the deleted set files. - If the command says the set stays, follow its message. It keeps the set when the Guidelines page already has guidelines, when the set's text holds template code, or when the set's other sites hold text, which 0.6.0 never read.
- Delete the
guidelineskey from a publishedconfig/statamic/mcp.php.
Full changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.6.0...v0.7.0
0.6.0
September 24th, 2026
Guidelines for agents move where the people who run the site can edit them.
Highlights
Guidelines live in a global set. php please mcp:guidelines creates a guidelines global set once. Its Site field holds voice and tone, which statamic_overview returns to every agent. Its rows pick collections and taxonomies and say how their entries are put together, and blueprints_get returns the rows naming the requested resource with its blueprints. Admins edit the set in the Control Panel under Globals, with no deploy, and an agent whose user may edit the set can change it through globals_update.
Tab and section instructions reach agents. blueprints_get returns tabs: every tab whose own or whose sections' instructions exist, with the handles of the fields under them. A note about one blueprint, such as which existing entry to follow, goes in its first section, where editors see it too.
A readable block report. mcp:guidelines lists the blocks without instructions grouped under the blueprints that share them, one wrapped line per field, instead of a table wider than any terminal.
The Boost skill maps each kind of guidance to its one place and says never to restate a field in the global set.
Breaking changes
- The markdown files under
resources/mcp/guidelinesare no longer read, and theguidelines_pathconfig key is gone. The newguidelineskey names the set and defaults toguidelines. - Guidelines for one blueprint or for a global set have no file any more. Put them in a section's instructions.
Migrating from 0.5.0
- Update the package:
composer update danielgnh/statamic-mcp - Create the set:
php please mcp:guidelines - Paste
site.mdinto the set's Site field. - Paste each
collections/{handle}.mdinto a row that names its collection. Move anything that describes one field into that field'sinstructionsinstead. - Delete
resources/mcp/guidelines.
Full changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.5.0...v0.6.0
0.5.0
September 24th, 2026
MCP now saves content the way the Control Panel does. Each value goes through its fieldtype's processing and validation, URLs have to be unique, and permission checks follow the CP's author and site rules. Publishing is its own pair of tools.
Agents also get new tools. They can preview drafts, edit navigation menus, nest and move pages, read the blocks of your page builder fields, and follow guidelines you write in markdown.
This release has breaking changes, and two of them are security fixes. A ^0.4 constraint never resolves to 0.5, so read the upgrade notes before you bump.
Security
Two permission gaps let MCP do more than the Control Panel allows. Every version before 0.5.0 has both.
- On a blueprint with an
authorfield, a role with a collection's edit, publish, or delete permission could do that to anyone's entry through MCP. The CP limits it to entries the user authored. The entry tools now check what Statamic'sEntryPolicychecks, and a denial names the missing permission.statamic_overviewtells agents which of these permissions they have. - On multisite, MCP never checked
access {site} sitefor the default site. A role with onlyaccess fr sitecould still read and write default-site content. MCP now gates the default site like every other site.
One more fix concerns OAuth mode. mcp:setup printed the private signing key during its key step, also in unattended runs. If you ran mcp:setup --oauth in a pipeline whose logs others can read, rotate the key: delete the row in statamic_mcp_oauth_keys and any storage/oauth-*.key files. The next request provisions a fresh pair, and every connected client reconnects through the OAuth flow.
Upgrading
#292D3E; --theme-selection-background: #00000080;">composer require danielgnh/statamic-mcp:^0.5
Check these before you deploy.
- Statamic 6.31 or newer is required. Composer refuses earlier 6.x releases by default because of a security advisory, so most sites are there already. laravel/mcp 0.8 keeps working, and 0.9 and 1.x work too.
- Publishing has its own tools.
entries_createandentries_updateno longer acceptpublished. Agents publish withentries_publishand take entries offline withentries_unpublish, both behind the collection's publish permission. A client with a cached tool list gets an error that points toentries_publish. - Roles need the "other authors" permissions for entries they didn't write. Grant
edit other authors {collection} entries,publish other authors {collection} entries, ordelete other authors {collection} entriesto roles that should keep that access. Entries with no author count as someone else's. - The default site needs site access. On multisite, grant
access {site} sitefor the default site to every role that should keep reaching it. - New entries get an author. When the blueprint has an
authorfield anddatanames none,entries_createsets the acting user, as the CP does. Naming someone else, or changing the author withentries_update, needsedit other authors {collection} entries. - Published configs need the navigations key. If you published
config/statamic/mcp.php, add'navigations' => trueunderresources. Without it, the navigation tools see no menus. - Writes are validated like CP saves. Unknown set types, unknown keys inside sets, grid rows, and groups, asset paths missing from the field's container, and a URL another entry already has now fail with an error that names the problem. MCP used to save them.
- OAuth mode: run
php artisan migrate. The migration that widens Passport'suser_idcolumns ran too early on fresh installs and did nothing. It is renamed so it runs after Passport's own migrations. Sites it missed convert on the next migrate, and sites with converted columns see a no-op.
New
entries_publishandentries_unpublish. On revision-enabled collections they promote or apply the working copy and record a revision under the acting user, which only the CP could do before. Your MCP client asks for permission per tool, so allowingentries_updateno longer lets an agent publish.entries_previewreturns a Live Preview URL that renders a draft or working copy through your templates. Anyone with the URL can open it for an hour, so an agent can check its own work before anyone publishes. It changes no content, andread_onlykeeps it.navigations_getandnavigations_updateread and replace a navigation's tree.navigations_updatechecks the tree againstmax_depth, the root page rule, and the navigation's blueprint.entries_createandentries_updatetakeparentto nest or move an entry in a structured collection. Parallel tree edits take a lock per collection and site, so none of them drops another's placement.blueprints_getlists the sets of Replicator and Bard fields with their instructions. Passsetto get one set's fields and an example row. It also reports where asset, entry, term, and user fields point and how many items they take.- Guidelines for agents. Markdown files in
resources/mcp/guidelinesreach agents throughstatamic_overviewandblueprints_get.php please mcp:guidelinescreates the starter files without overwriting any and lists the blocks that have no instructions yet, blocks inside grids and groups included. Thestatamic-mcp-guidelinesBoost skill helps a coding agent write them. - Your own tools. Point the new
serverconfig key at a subclass ofDanielgnh\StatamicMcp\Server, then add, replace, or remove tools intools(). They run behind the same authentication andaccess mcpcheck as the built-in tools. - Scheduling.
statamic_overviewreports each dated collection'sdate_behaviorand the server timezone. When a date keeps a published entry hidden,entries_publishreports it as scheduled or expired.entries_gettakesworking_copy: true, andentries_listfilters bystatus: expired. - laravel/mcp 0.9 and 1.x work alongside 0.8. On 1.x, JSON-RPC errors come back as HTTP 400, 404, or 500 instead of 200, and clients on the 2026-07-28 protocol revision connect through
server/discover. If you run OAuth mode and have narrowedmcp.redirect_domains, move to laravel/mcp 0.9.6 or 1.0.1. Both fix the loopback redirect URI check in OAuth client registration, and 0.8 won't get that fix.
Fixed
- Writes store what the Control Panel stores. Each value goes through the fieldtype's
preProcess()andprocess(), so a single asset or relationship saves as a plain string, sets and grid rows get ids, dates use the field's save format, and HTML sent to a Bard field becomes ProseMirror. What the get tools return can be written back unchanged, also in collections with several blueprints:entries_getnow names the blueprint at the top level instead of insidedata. - Updating an entry, term, or global set no longer fails on a single-file asset, single-item relationship, or date that the CP saved, and a patch to a localization no longer fails on a required field it inherits from its origin.
- A new entry in a structured collection goes into the collection's tree. Its
urlused to come backnull. blueprints_getexamples match what the write tools accept.sluganddateare out of the example payload, option fields use the option's key, and relationship and date fields use the stored shape.entries_updateno longer reports "published" after a new date makes the entry scheduled or expired, and it reports the staged URL, not the live one, when it stages a working copy.entries_updaterefuses a date on a localization whose date field isn't localizable. Publishing used to drop that date without a word.mcp:keysprints only the keys on stdout, somcp:keys --json | jqandmcp:keys >> .envwork on the first run too. With only onePASSPORT_*key set, it reads each half the way Passport does.
Known caveats
entries_createalways uses the collection's default blueprint. It has noblueprintparameter, andblueprintinsidedatais refused as reserved.blueprints_getreports a set's group by name, without the group's instructions. Put instructions on the sets themselves.- Writes accept sets hidden from the CP's set picker.
blueprints_getmarks them"hidden": true.
The full list is in CHANGELOG.md.
Pull requests
- feat: add your own tools by naming a server subclass in config by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/18
- feat: publishing is its own tool pair (entries_publish / entries_unpublish) by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/19
- feat: tools() hook with a ToolRegistry to add, replace, and remove tools by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/21
- feat: make Statamic's own scheduling visible and honest to agents by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/22
- fix: writes store what the Control Panel stores by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/23
- fix: leave top-level parameters out of blueprints_get examples by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/24
- feat: page builder blocks and guidelines for agents by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/25
- feat: entries_preview returns a live-preview link for drafts by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/26
- feat: navigation tools and parent on entries_create by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/27
- fix!: match the Control Panel's author and site permissions by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/28
- feat: page builder sets as a short list, with a lookup per set by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/29
- feat: move entries in their tree with parent on entries_update by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/30
- feat: support laravel/mcp 0.9 and 1.x by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/31
- test: run the Passport-free tests in their own CI job by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/32
- fix: bugs found testing the unreleased changes end to end by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/33
0.4.2
July 20th, 2026
Full Changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.4.1...v0.4.2
0.4.1
July 16th, 2026
What's Changed
- refactor(views): show only the active auth mode on the MCP Access page by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/17
Full Changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.4.0...v0.4.1
0.4.0
July 15th, 2026
What's Changed
- feat: manage Passport's keys in the database — deploys need no key step by @danielgnh in https://github.com/danielgnh/statamic-mcp/pull/16
Full Changelog: https://github.com/danielgnh/statamic-mcp/compare/v0.3.2...v0.4.0