MCP server for Concrete CMS integration providing tools to manage pages and content through the Concrete CMS API
The Concrete CMS MCP server defines 2 tools with clear verb-based names and well-structured schemas. Both tools have descriptions in the 150-250 char range (within the productive 10-1024 baseline). Input schemas are present with type information and descriptions for all parameters. However, output schemas are not formally documented, the tool code returns JSON but the expected response structure is not declared in the tool definition. Error handling is implemented but lacks recovery guidance (e.g., 'If you see BlockRemapError, try...'), and descriptions could be more specific about prerequisites and when to use each tool over alternatives. Tool annotations (readOnlyHint, destructiveHint) are present and correct. Overall, this server meets the bar for 'good' work, solid foundations with room for output schema documentation and error recovery guidance.
Review a Concrete CMS page as a document. Returns sanitized HTML, raw HTML, and plain text. Prefer this over getPageById with includes=content when summarizing or reading page copy. Does not return areas/blocks.
Update page block content safely. Creates a new editable page version (PUT page), remaps block IDs, then updates each block (PUT area). Provide blockID values from the version you inspected. Does not approve the new version.
Output schemas not formally declared. Both tools return JSON (via jsonResult() helper), but the expected response structure (fields, types, nesting) is not documented in the tool definition. LLMs cannot plan downstream calls or extract fields without seeing the output schema.
Error messages lack recovery guidance. errorResult() returns formatted errors (e.g., 'blocks must be a non-empty array'), but does not suggest what the LLM should do next. Errors should be actionable: 'Invalid pageID: must be a positive integer. Did you mean to call search_pages() first?'
update_page_content description does not explain prerequisites or when to use it. It mentions 'blockID values from the version you inspected' but does not explicitly state: 'You must call get_page_content first to discover block IDs.' This forces LLMs to infer multi-step workflows.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | A | 82 | <=2025-11-25 | v2 |
Block update array lacks defensive guidance. The 'blocks' parameter accepts an array but the description does not warn about partial failures. If 3 blocks are requested and 1 fails, the tool returns mixed results (blockResults array with per-item ok flags). The LLM needs explicit guidance: 'Some blocks may fail individually; check the ok flag in the response and retry failed blocks separately.'
Page metadata object in update_page_content is under-documented. The 'page' parameter accepts an object with properties (name, description, type, template, attributes) but the description says 'Optional page metadata' without explaining which fields are allowed, their types, or constraints. LLMs may pass invalid or extraneous fields.