Secure MCP server for Craft CMS: audited, permission-gated access for AI clients to content and operations.
AlphaBridge demonstrates solid tool definition quality with consistent naming patterns (verb_noun), comprehensive descriptions (avg 180 chars), and well-structured JSON schemas. All 14 tools have input schemas with typed parameters and descriptions. However, output schemas are not documented in the provided source, and some parameter descriptions lack actionable constraints (e.g., enums for 'kind' in craft_list_assets, format specs for 'sql' in craft_db_query). Error handling guidance is minimal, tools describe what they do but not how to recover from failures. Security considerations are well-documented in descriptions (permission gates, read-only markers), but no explicit error classification or recovery patterns are visible.
Apply a draft to its entry: the canonical entry takes the draft's content, and the draft is gone afterwards. Refused unless the mapped user may save the canonical entry — being allowed to edit the draft is not enough.
Create a category in a group. Needs the group handle and a title; slug, status, parent and custom fields are optional. Without a parent the category is placed at the top of the group's structure. Craft validates before saving, and a failed validation is reported field by field rather than as a bare failure.
Create a draft of an existing entry. Needs entryId or entryUid; name and notes are optional. The draft starts as a copy of the entry and changes nothing about it, which is why viewing the entry is enough — Craft's own rule. This build cannot write content into the draft afterwards.
Run one narrow SELECT. Deliberately restricted: a single statement, at most one physical table, no JOIN, no subquery, and only count/min/max/avg/sum as functions — a lexical guard can only vouch for what it can fully read. Craft tables carry a prefix; write {{%entries}} and it is resolved. On PostgreSQL, Craft's columns are camelCase and must be quoted ("dateUpdated"). Rows are returned without any element permission check, so this is for administrators.
Output schemas not documented. Tool descriptions state what is returned (e.g., 'metadata', 'custom field values') but no formal schema is provided. LLMs cannot plan downstream tool calls or extract fields reliably without knowing the response structure.
Parameter 'kind' in craft_list_assets lacks enum constraint. Description lists examples ('image, pdf, video, audio, text, compressed') but no formal enum. LLMs may hallucinate invalid values like 'document' or 'spreadsheet'.
craft_db_query parameter 'sql' lacks format/pattern constraints. Description warns of restrictions (single statement, no JOIN, no subquery) but provides no regex pattern or validation guidance. LLMs cannot self-validate before calling.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | 2026-07-28+ | v2 |
The physical tables of this installation, or the columns of one table. Tables that craft_db_query may not read are listed but marked readable=false, so you can see they exist without trying. Pass the table name as Craft writes it ({{%entries}}) or as it is in the database (craft_entries).
Move a category to the trash. Craft keeps it recoverable; pass hard=true to remove it for good, which cannot be undone. Descendants are NOT deleted: Craft moves them up one level, so a nested branch stays but changes shape. Address it by id or uid — deliberately not by slug, which can name more than one category.
Discard a draft. A draft is not trashed — it is removed for good, and this cannot be undone. The canonical entry is left untouched.
One asset with its full metadata and custom field values. Address it by id or uid. Returns the file's metadata, never its contents.
One category with its custom field values and its place in the group's structure. Address it by id, uid or slug; with a slug, name the group as well when several groups may hold that slug.
List assets with their metadata: filename, kind, size, dimensions and URL. Filter by volume handle, kind (image, pdf, video, …) or filename. Only volumes the mapped user may view are searched. Read-only — this build has no upload, rename or delete for files.
List categories in structure order. Filter by group handle, status, site or structure level. Only groups the mapped user may view are searched, so an unknown or forbidden group yields an empty list rather than an error.
List entry drafts: named drafts and, on request, the control panel's provisional working copies. Narrow to one entry with entryId or entryUid, or leave both out for every draft the mapped user may see. Reports each draft's metadata — name, notes, creator, canonical entry — not its field values.
The asset volumes this user may view, with handle, name and the number of assets in each. Useful before listing assets, because the volume handle is what narrows that call.
Change an existing category. Only the fields you pass are touched; everything else keeps its value. Passing parentId moves the category inside its group's structure; a category cannot be moved to another group.
No error recovery guidance. Tools describe what they do but not how to recover from failures (e.g., 'If category not found, try craft_list_categories first'). Error responses are not shown in source, so recovery patterns cannot be verified.
Destructive operations (craft_delete_category, craft_discard_draft) lack confirmation/dry-run pattern. No evidence of a confirmation step or preview before permanent deletion. Agents may accidentally destroy data.