danielgnh/statamic-mcp
A Model Context Protocol server for Statamic that connects AI assistants and MCP clients to your site’s content and structure through standardized tools, enabling smoother AI-powered content workflows for Laravel and Statamic developers.
composer require <vendor>/<package> and publish the config if the package ships one (php artisan vendor:publish --tag=...). Register the service provider only if auto-discovery is disabled in your app.blueprints_get, navigations_get, navigations_update). Start by authenticating a single agent/user and confirming it can hit blueprints_get for a collection you know, e.g. view {handle} pages. A successful read of a familiar blueprint is the fastest smoke test that permissions, config, and routing are wired correctly.blueprints_get with type: navigation and the navigation handle returns the field set a branch's data accepts, an example of one branch's data, and the sets for Replicator/Bard fields — the same shape you already get for a page builder. That single call removes the guesswork that previously required reading an existing branch and inferring field names.view {handle} nav, mirroring navigations_get. If blueprints_get returns a permission error rather than a blueprint, the bug is in your role definitions, not the package.Blueprint-first writes. Never let an agent call navigations_update before blueprints_get. The blueprint output is the contract: field handles, fieldtypes, and per-set examples. Feed it into the prompt or tool result verbatim and require the agent to echo the field names it used.
Set expansion for page builders and menus. For a Replicator or Bard field, request the parent field's blueprint and then the set view to get a set's fields and an example row. Card-bearing menu branches are the canonical case — the branch's data holds a set instance, so the agent needs the set's fields, not just the field handle.
Branch keys vs data. When the blueprint defines title or url, example_notes now tells you to pass them as branch keys, not inside data. Encode this in your system prompt: { title, url, data: { ... } }. Agents that lump title into data will produce branches that save but render with no label.
Round-trip verification. After navigations_update, call navigations_get and compare against the blueprint you used. This catches dropped fields from partial updates and mismatched set handles before the content goes live.
Permission-scoped agents. Because reads are gated on view {handle} nav, you can hand an agent a narrow navigation handle for menu editing while denying it page content. Use one token/role per navigation rather than a broad view * grant; it makes agent failures legible.
Cache blueprints per request, not per deploy. Blueprints change when developers change field definitions. Cache within a single agent session; invalidate on content-type or fieldset changes rather than on a fixed TTL.
blueprints_get still refuses other types. v0.9.1 added type: navigation; the refusal path for unsupported types remains. If you get a type error, check the type before assuming a permission problem — the two failures look similar in tool output.example_notes is guidance, not schema. Treat the example row as illustrative. Fields with dynamic options, locales, or computed defaults may not appear or may appear with placeholder values.navigations_update on a branch that omits sets will silently drop them depending on the package's merge behaviour. Test one destructive edit in a scratch navigation before trusting the agent with production menus.view {handle} nav uses the navigation handle, not the display title or slug of the site. A renamed navigation whose handle stayed the same will still authenticate; a new one won't until the role is updated.blueprints_get payload it received. Almost every failure is the agent having been given a stale or truncated blueprint, not the update call itself.example_notes wording and set example format) can shift between minor releases.How can I help you explore Laravel packages today?