Skip to content

MCP Server

The Contentrain MCP (Model Context Protocol) Server enables AI coding assistants like Claude, Cursor, and other MCP-compatible tools to manage your Contentrain project's models, content, and assets directly from your development environment.

Overview

@contentrain/mcp is an open-source MCP server that provides 17 tools for managing Contentrain CMS data through AI assistants. It operates on your local Git repository with full transaction safety, worktree isolation, and structural merge conflict resolution.

Key capabilities:

  • Create, read, update, and delete content models and entries
  • Manage assets in the registry
  • Validate content against model schemas
  • Run diagnostics to detect and auto-fix data quality issues
  • Full Git sync with automatic commit, push, and conflict resolution

Prerequisites

Your Contentrain project must first be created through the Contentrain Web App. The MCP server operates on existing Contentrain projects — it does not create new projects from scratch.

Installation

bash
npm install -g @contentrain/mcp

Requirements: Node.js 18 or higher.

Configuration

Configure the MCP server in your AI tool's configuration file. The server needs to know the path to your Git repository and which environment branch to target.

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

json
{
  "mcpServers": {
    "contentrain": {
      "command": "contentrain-mcp",
      "env": {
        "CONTENTRAIN_REPO_PATH": "/path/to/your/contentrain-project",
        "CONTENTRAIN_BRANCH": "contentrain"
      }
    }
  }
}

Claude Code

Add to .mcp.json in your project root:

json
{
  "mcpServers": {
    "contentrain": {
      "command": "contentrain-mcp",
      "env": {
        "CONTENTRAIN_REPO_PATH": ".",
        "CONTENTRAIN_BRANCH": "contentrain"
      }
    }
  }
}

Cursor

Add to .cursor/mcp.json in your project:

json
{
  "mcpServers": {
    "contentrain": {
      "command": "contentrain-mcp",
      "env": {
        "CONTENTRAIN_REPO_PATH": "/path/to/your/contentrain-project",
        "CONTENTRAIN_BRANCH": "contentrain"
      }
    }
  }
}

Environment Variables

VariableDefaultDescription
CONTENTRAIN_REPO_PATHCurrent directoryPath to the Git repository
CONTENTRAIN_BRANCHcontentrainTarget environment branch
CONTENTRAIN_REMOTEoriginGit remote name
CONTENTRAIN_DIRcontentrainContentrain directory name in repo
CONTENTRAIN_DRY_RUNfalseSkip Git operations (local changes only)
CONTENTRAIN_AUTHOR_NAMEGit commit author name
CONTENTRAIN_AUTHOR_EMAILGit commit author email

Tools Reference

The MCP server provides 17 tools organized into four categories.

Model Management (5 Tools)

contentrain_list_models

List all Contentrain models with their metadata.

  • Input: None
  • Returns: Array of models with type, localization status, description, and path

contentrain_describe_model

Get the complete schema for a model including all field definitions, types, validations, and options.

  • Input: modelId (string, required)
  • Returns: Model metadata and all field definitions

TIP

Always call contentrain_describe_model before creating or updating content to understand the required fields and their types.

contentrain_create_model

Create a new Contentrain model with field definitions.

  • Input:
    • name (string, required) — Display name
    • modelId (string, required) — Unique ID in kebab-case
    • type (enum, required) — JSON, MD, or MDX
    • localization (boolean, required) — Enable multi-language support
    • description (string, optional)
    • path (string, optional) — Base path for MD/MDX files
    • fields (array, optional) — Custom field definitions

System fields (ID, createdAt, updatedAt, status) are added automatically. MD/MDX models also get slug and content fields.

contentrain_add_field

Add a new field to an existing model.

  • Input:
    • modelId (string, required) — Target model
    • name (string, required) — Display name
    • fieldId (string, required) — Unique identifier
    • componentId (string, required) — UI component type
    • fieldType (string, required) — Data type
    • options (object, optional) — Title field, default value, reference config
    • validations (object, optional) — Required, unique constraints

contentrain_delete_model

Delete a model and all its content.

  • Input: modelId (string, required)

DANGER

This operation is destructive and cannot be undone.

Content Management (6 Tools)

contentrain_list_content

List all content entries for a model.

  • Input: modelId (string, required), locale (string, optional)
  • Returns: Array of content entries with total count

contentrain_get_content

Get a single content entry by ID.

  • Input: modelId (string, required), entryId (string, required), locale (string, optional)

contentrain_create_content

Create a new content entry with automatic validation.

  • Input:
    • modelId (string, required)
    • data (object, required) — Content data matching model schema
    • locale (string, optional) — Locale code for localized models
    • status (enum, optional) — draft or publish (default: draft)
    • content (string, optional) — Markdown body for MD/MDX models

System fields are generated automatically: ID (12-char hex), createdAt, updatedAt, status.

contentrain_update_content

Update an existing content entry. Only provide the fields you want to change.

  • Input: modelId, entryId, data, locale (optional), content (optional for MD/MDX)
  • updatedAt is set automatically. createdAt is immutable.

contentrain_delete_content

Delete a content entry by ID. For localized models, removes from all locale files. For MD/MDX, also deletes the markdown file.

  • Input: modelId (string, required), entryId (string, required)

contentrain_validate

Validate content data against a model schema without writing anything. Useful for dry-run checks.

  • Input: modelId (string, required), data (object, required)
  • Returns: Validation result with valid flag and array of errors

Asset Management (3 Tools)

contentrain_list_assets

List all registered assets from assets.json.

contentrain_register_asset

Register a new asset in the registry. The file must already exist in the repository.

  • Input: path (string), mimetype (string), alt (string, optional)

contentrain_deregister_asset

Remove an asset from the registry. Does not delete the physical file.

  • Input: path (string, required)

Diagnostics (3 Tools)

contentrain_doctor

Run a full diagnostic scan on all models, content, and assets.

  • Input:
    • fix (boolean, optional, default: false) — Auto-fix repairable issues
    • modelId (string, optional) — Scope scan to a specific model

Detects:

  • Duplicate or invalid IDs
  • Type mismatches against model schema
  • Broken relation references
  • Missing asset paths
  • Locale ID inconsistencies
  • Orphan directories
  • MD/MDX sync issues between JSON index and markdown files
  • Unique constraint violations
  • Missing system fields
  • Invalid JSON files

When fix=true, changes are pushed to a staging branch for review — not directly to the target branch.

contentrain_doctor_apply

Apply a staged doctor fix by merging the staging branch into the target branch.

  • Input: branch (string, required) — Staging branch name from contentrain_doctor output

contentrain_doctor_discard

Discard a staged doctor fix by deleting the staging branch.

  • Input: branch (string, required)

Field Type Mappings

When creating fields, use the correct componentId and fieldType combination:

Component IDField TypeDescription
single-line-textstringShort text input
multi-line-textstringMulti-line text area
emailstringEmail address
urlstringURL (must start with https://)
slugstringURL-friendly identifier
colorstringColor value (HEX/RGB)
jsonstringJSON content
md-editorstringMarkdown content
rich-text-editorstringRich text content
phone-numberstringPhone number (stored as string)
integernumberWhole numbers
decimalnumberFloating-point numbers
ratingnumberRating value
percentnumberPercentage value
checkboxbooleanCheckbox toggle
switchbooleanSwitch toggle
datestringDate (ISO format)
date-timestringDate and time (ISO format)
mediastringAsset file path
one-to-onestringSingle relation (entry ID)
one-to-manyarrayMultiple relations (entry ID array)

Git Sync Architecture

The MCP server uses a transaction-based Git workflow to ensure data safety:

  1. Worktree Isolation — Every write operation creates an isolated Git worktree at a temporary path. Your main working directory is never modified directly.

  2. Automatic Commit — Changes are committed with contextual messages like [contentrain] create blog-posts entry.

  3. Push with Conflict Resolution — If the remote branch has advanced since the worktree was created, the server performs a structural 3-way merge:

    • Indexes entries by their ID field
    • New entries (added locally): appended to result
    • Deleted entries (removed locally): removed from result
    • Modified entries: field-level merge (local changes win on conflicts)
    • Remote-only entries (added by other writers): preserved
  4. Retry — Push is retried up to 3 times if conflicts are detected.

  5. Cleanup — The temporary worktree is removed after the operation completes.

This approach makes concurrent writes safe — multiple AI agents or the Contentrain Web App can operate on the same branch simultaneously.

Multiple Environments

Contentrain uses Git branches to manage environments. You can register multiple MCP server instances for different environments:

json
{
  "mcpServers": {
    "contentrain-default": {
      "command": "contentrain-mcp",
      "env": {
        "CONTENTRAIN_REPO_PATH": "/path/to/project",
        "CONTENTRAIN_BRANCH": "contentrain"
      }
    },
    "contentrain-staging": {
      "command": "contentrain-mcp",
      "env": {
        "CONTENTRAIN_REPO_PATH": "/path/to/project",
        "CONTENTRAIN_BRANCH": "contentrain-staging"
      }
    }
  }
}

Programmatic Usage

The MCP server can also be used as a Node.js library:

typescript
import { ContentrainWriter } from '@contentrain/mcp'

const writer = new ContentrainWriter({
  repoPath: '/path/to/your/project',
  branch: 'contentrain',
})

// Read operations (no Git transaction needed)
const models = await writer.model.list()
const entries = await writer.content.list('blog-posts')

// Write operations (uses Git worktree + commit + push)
await writer.transaction(async (tx) => {
  await tx.content.create('blog-posts', {
    title: 'Hello World',
    excerpt: 'My first post',
  }, { status: 'draft' })
}, { message: 'add new blog post' })

Resources

Released under the MIT License.