MCP Server
What this is
The ComStack MCP Server is the integration surface AI assistants use to manage ComStack projects. It exposes a complete headless CMS toolkit — page CRUD, theming, two-step publishing, GitHub sync, and live voice sessions — over the Model Context Protocol.
Transport: Streamable HTTP (POST /mcp) — stateless. Stdio mode for local development.
Production endpoint: https://api.comstack.ai/mcp
How it works
Each tool call carries its own project_id, so a single authenticated session can address every project the caller has access to. Tools are filtered per caller role — a viewer doesn’t see manager-only tools such as publish.
Destructive operations are guarded by a two-step flow: publish builds a manifest and returns a confirmation token; publish-confirm uses the token to deploy. A project_name echo is required on all destructive tools as a cross-project safety check.
Two additional safeguards apply to the publish path:
project_nameecho.publish,publish-confirm,delete-page,set-page-status, and other destructive tools require aproject_nameargument that must exactly match the project’s stored name. Mismatch returns an error showing both the expected and supplied names.- Publish dry-run / confirm.
publishreturns a manifest of due READY pages with per-page diff —is_new,change_type, titles, descriptions, byte sizes, target URLs — plus aconfirmation_token(5-min TTL, single-use). Onlypublish-confirmdeploys. At confirm time the server re-builds the manifest and rejects if the ready set has changed.
When to use it
Use the MCP server when you want an AI assistant (Claude, Cursor, or any MCP-compatible client) to manage content in a ComStack project — creating pages, approving and translating, publishing to the live site.
Parameters / fields / inputs
Every project-scoped tool requires a project_id argument. Destructive tools also require project_name, which must exactly match the project’s stored name.
Authentication modes
| Mode | When to use |
|---|---|
| OAuth 2.1 Bearer | Human callers connecting via Claude, Cursor, or another OAuth-capable client |
x-api-key + x-project-id headers | Headless services and CI — use service keys (key_type: "service") |
Rate limits
| Route | Limit |
|---|---|
POST /mcp | 60 requests / min / IP |
| OAuth routes | 30 requests / min / IP |
| Auth failures | 10 failures / min / IP |
Request bodies over 1 MB are rejected with HTTP 413.
Tool filtering by role
tools/list is filtered per caller role. Role tiers (highest to lowest): platform admin → manager → editor → viewer → none. Tools beyond your role are hidden — not just rejected, but absent from the list.
Example
A typical session workflow:
1. whoami → confirm authenticated identity2. list-my-projects → pick a project_id3. get-project-state → see live pages, drafts, available templates4. get-doc-template <id> → get the metadata example and markdown template5. create-page → new page draft (validates everything at once) update-page → edit an existing page6. approve-page → translations run asynchronously; page moves to ready7. publish → review the manifest + get a confirmation_token8. publish-confirm → deploy; poll publish-status for published_urlsCommon errors
| Error | Cause | Fix |
|---|---|---|
InvalidRequest | API key scoped to wrong project | Check project_id matches the key’s scope |
403 project_name mismatch | Supplied name doesn’t match stored name | Call get-project-state to get the correct name |
| HTTP 429 | Rate limit exceeded | Back off and retry |
| HTTP 413 | Request body over 1 MB | Reduce content size |
| Token expired | OAuth refresh chain broken | Re-authenticate |
| Validation error | Missing or invalid metadata fields | The error response lists all issues at once with fixes |