Appearance
MCP tool reference
The contract between Diggama and your MCP client. Your client caches this list, so we treat it as a published interface: see Versioning for what can change and what cannot.
Tools your token cannot use never appear. A read-only connection is offered the four read tools and nothing else. Calling a tool that is not offered is a JSON-RPC error (-32602) listing the ones that are.
Results
Every tool returns a text block for the model to read and, on success, the same data as structuredContent. get_resource, create_resource, update_resource, publish_resource and unpublish_resource also return a resource_link named Open in Diggama, pointing to the record in the dashboard, so a person reading the transcript can check what the assistant did.
Records are flattened: id, published, published_at, created_at, updated_at, then one key per field slug. A field whose slug collides with one of those five keys is returned with a _field suffix (describe_blueprint reports it as key); writes still use the slug.
Discovery
list_blueprints
Lists the content types this connection can reach, with the abilities it holds on each. No arguments. Always offered.
Each entry in structuredContent.blueprints:
| Field | |
|---|---|
slug, name | |
cardinality | many, one (single-record type) or readonly |
record_title_field | The field used as the record's title |
variants, default_variant | Language variants, or null |
field_count | |
resource_count | Records this connection can list (published only without preview) |
abilities | What the tools accept on this type: create and delete are left out on a single-record type, publish on a read-only one |
describe_blueprint
| Argument | Type | |
|---|---|---|
blueprint | string | required, restricted to your content types |
Returns the fields (slug, label, type, description, required, and writable: false for page builder fields), attributes_schema (a JSON Schema for the type's attributes, without page builder fields), the filterable and sortable names, and the filter_operators. Call it before your first write to a type.
required is read from the field's rules and advertised as a hint; writes are validated exactly as the REST API validates them.
Reading
list_resources
| Argument | Type | |
|---|---|---|
blueprint | string | required |
search | string | case-insensitive substring match across text and rich-text fields |
filter | object | {"field": value} or {"field": {"op": value}} (see Filtering). Also accepts published, published_at, created_at, updated_at |
sort | string | -published_at,title. Unknown names are ignored. Default: newest created first |
status | enum | any (default), published; plus draft and scheduled only when the connection has preview |
fields | string[] | field slugs to show in summary rows |
detail | enum | summary (default) or full |
page | integer | from 1 |
per_page | integer | default 25, max 50, or 10 with detail: "full". Larger values are clamped |
variant | string | only present when a type in scope is multilingual |
draft means never published; scheduled means dated for the future. They are separate on purpose. Without preview, only published records are listed, and asking for drafts is a FORBIDDEN error.
An unknown filter field is an error (INVALID_FILTER), not an empty result. A single-record type is not a list: use get_resource without an id (NOT_A_LIST).
The text is a compact table; structuredContent is:
json
{
"records": [{ "id": "gKqv6dx6pBk9", "published": true, "published_at": "…", "created_at": "…", "updated_at": "…", "title": "…" }],
"pagination": { "page": 1, "per_page": 25, "total": 73, "total_pages": 3, "has_more": true, "next_page": 2 }
}A summary row holds the record's title field plus up to four other short fields. Strings are shortened to about 80 characters (120 for links), and rich-text, page builder, address, multi-reference and file fields are never shown in a summary, even if named in fields. detail: "full" returns every field, as get_resource does, and ignores fields.
get_resource
| Argument | Type | |
|---|---|---|
blueprint | string | required |
id | string | omit for a single-record type |
variant | string |
Returns one record with every field. Ids are opaque: get them from list_resources rather than constructing one. A draft is NOT_FOUND without preview.
- A string value over 20,000 characters is cut there and ends with a truncation marker:
…[truncated: 20000 of 48211 chars. Full value: diggama://resources/{blueprint}/{id}#{field}]. The rest of such a value cannot currently be read over MCP; edit it in the dashboard. - A page builder field returns
block_count, the first 40blocks,truncatedandeditable: false. The compiled HTML and stylesheet are left out.
Writing
Every write fires the project's automation workflows and webhooks, except a dry_run. Writes count towards a cap of 60 a minute per project, shared by all connections.
All writes are checked before anything is stored:
- An attribute that is not a field of the type is a
VALIDATION_ERRORnaming the valid fields, rather than being silently dropped. - A page builder field is refused: it is read-only over MCP.
- A value that still contains a truncation marker is refused, since writing it back would discard the rest of the field.
- Values then go through the same validation rules as the REST API.
Image and file fields take the URL or storage path of a file that is already uploaded; MCP cannot upload files. Reference fields take record ids from list_resources.
create_resource
| Argument | Type | |
|---|---|---|
blueprint | string | required |
attributes | object | required, keyed by field slug |
published_at | string | only offered if the connection may publish; needs publish on this type |
variant | string | |
dry_run | boolean | shows the record that would exist, without writing |
Records are created as unpublished drafts unless published_at is given. Returns the new record. A dry run returns {dry_run, blueprint, would_create}, listing every field so omissions are visible.
Not offered for single-record types, whose one record always exists.
update_resource
| Argument | Type | |
|---|---|---|
blueprint | string | required |
id | string | omit for a single-record type |
attributes | object | required |
mode | enum | merge (default) or replace |
expected_updated_at | string | required with replace |
variant | string | |
dry_run | boolean | shows a field-by-field diff |
There is one update tool, not a PUT and a PATCH. merge leaves omitted fields alone. replace blanks them, and demands the updated_at you last read. The call fails with CONFLICT if someone changed the record since.
Returns the updated record, with the changed fields listed in the text. A dry run returns {dry_run, mode, diff}, where diff maps each changed field to {from, to}.
bulk_create_resources
| Argument | Type | |
|---|---|---|
blueprint | string | required |
records | object[] | required, max 25 |
variant | string | |
dry_run | boolean |
For seeding and imports. Validates every record before writing any: if one fails, nothing is written, and the error lists each failing record by index. Records are always created as drafts. Returns {created, count, blueprint}, where created is the list of new ids.
There is no bulk update, delete or publish. Loop the single tools instead: each change stays visible and reversible one at a time.
delete_resource
| Argument | Type | |
|---|---|---|
blueprint | string | required |
id | string | required |
Permanent: no soft delete, no undo. Idempotent: deleting an id that is already gone reports success, with {deleted: false, reason: "not_found"}. Not offered for single-record types.
publish_resource / unpublish_resource
| Argument | Type | |
|---|---|---|
blueprint | string | required |
id | string | omit for a single-record type |
published_at | string | publish only; omit to publish now, a future date schedules it |
unpublish_resource clears published_at, reverting the record to draft. Both return the record and apply to all its variants.
Both need the publish ability, which is stricter than the REST API, where publishing goes through a plain update. Neither is offered for read-only types.
Prompts
Slash commands in clients that support them. Each appears only when the connection could carry it out.
| Prompt | Arguments | Listed when the connection has |
|---|---|---|
audit_content | blueprint | access to at least one type |
draft_resource | blueprint, brief | create on at least one type |
translate_resource | blueprint, id, target_variant | update on at least one multilingual type |
bulk_edit_plan | blueprint, instruction | update on at least one type |
Completion
The server implements completion/complete for any argument named blueprint: it suggests the slugs of the content types this connection can see that start with what has been typed, up to 100. Other arguments get no suggestions.
Resources
Attachable by URI rather than called. resources/list returns the project, plus a schema and a sample for each content type the connection can see.
| URI | |
|---|---|
diggama://project | The project's name and slug, and its content types with their cardinality and abilities |
diggama://blueprints/{slug}/schema | Fields and the attributes JSON Schema |
diggama://blueprints/{slug}/sample | The most recent record the connection can see, as an example |
diggama://resources/{blueprint}/{id} | One record, as get_resource returns it (template), the target of the links in truncation markers |
Samples and records use the type's default variant, and drafts need preview. Reading a URI the connection cannot reach is a JSON-RPC error (-32602).
Server instructions
The initialize response carries an instructions string, which most clients add to the assistant's context before its first call. It names the project, lists up to 25 content types with their kind, variants and the connection's abilities, and adds only the rules that apply to this connection: opaque ids, merge versus replace and dry runs, automation side effects, asking before publishing or deleting, the wrong-variant pitfall, read-only types, read-only page builder fields, and missing preview.
serverInfo is diggama, titled Diggama CMS — {project name}. Supported protocol versions: 2025-06-18 and 2025-03-26. listChanged is false everywhere: the server is stateless and cannot notify the client.
Errors
Protocol faults come back as JSON-RPC errors: -32700 (body is not a JSON object), -32600 (invalid envelope, a batch, or a refused browser origin), -32601 (unknown method), -32602 (unknown or unavailable tool, prompt or resource).
Everything else is a tool result with isError: true, so the assistant can read it and correct itself. The text starts with the code; structuredContent.error holds code, message and, when there are any, details.
| Code | |
|---|---|
VALIDATION_ERROR | Field-level errors keyed by slug: invalid values, unknown fields, page builder fields, truncated values |
FORBIDDEN | The connection lacks an ability, such as preview for drafts or publish for published_at |
NOT_FOUND | No such record or content type, or a draft without preview |
NOT_A_LIST | list_resources on a single-record type |
INVALID_FILTER | Unknown filter field or operator, with the valid list |
CONFLICT | The record changed since you read it |
PRECONDITION_REQUIRED | replace without expected_updated_at |
BULK_LIMIT_EXCEEDED | More than 25 records in one call |
RATE_LIMITED | Over 60 writes a minute in this project; the HTTP response carries Retry-After. Reads are unaffected |
UNPROCESSABLE | The request was refused as unprocessable (HTTP 422) |
HTTP_ERROR | Any other refused request |
INTERNAL_ERROR | A failure on our side. It is logged; retrying the same call is unlikely to help |
Going over the shared API limit of 1,000 requests a minute answers HTTP 429 before the request reaches the server.
Versioning
Safe, and shipped without notice: a new tool, a new optional argument, a new field in a result.
Never: removing or renaming a tool or an argument, making an optional argument required, changing an argument's type, or repurposing an enum value.
A breaking change takes a new tool name, never a new URL: your config keeps working.
The catalogue is pinned by a contract test in the repository, so none of this can change by accident.
Changelog
| Date | |
|---|---|
| 2026-08-27 | First release. Ten tools, four prompts, four resource shapes. |