Skip to main content
Glama
elmapicms

elmapicms-mcp-server

Official
by elmapicms
README.md
# ElmapiCMS MCP Server

An MCP (Model Context Protocol) server that connects AI agents like [Cursor](https://cursor.com) and [Claude Code](https://claude.com/product/claude-code) to your [ElmapiCMS](https://elmapicms.com) instance. Manage collections, fields, content entries, assets, and webhooks programmatically through natural language.

## Configuration

| Variable | Description |
|----------|-------------|
| `ELMAPI_BASE_URL` | Instance API root (e.g. `https://your-domain.com/api`). `ELMAPI_API_URL` is accepted as an alias. |
| `ELMAPI_API_KEY` | **Project** Sanctum token from **Project settings → API Tokens** |
| `ELMAPI_PROJECT_ID` | Project UUID from the project home page or **Project settings → API Access** |

## Usage with Cursor

Add this to your Cursor MCP settings (`~/.cursor/mcp.json`):

```json
{
  "mcpServers": {
    "elmapicms": {
      "command": "npx",
      "args": ["-y", "@elmapicms/mcp-server"],
      "env": {
        "ELMAPI_BASE_URL": "https://your-domain.com/api",
        "ELMAPI_API_KEY": "your-project-api-token",
        "ELMAPI_PROJECT_ID": "your-project-uuid"
      }
    }
  }
}
```

## Usage with Claude Code

```bash
claude mcp add elmapicms \
  -e ELMAPI_BASE_URL=https://your-domain.com/api \
  -e ELMAPI_API_KEY=your-project-api-token \
  -e ELMAPI_PROJECT_ID=your-project-uuid \
  -- npx -y @elmapicms/mcp-server
```

## Local Development (Laravel Herd / `.test` domains)

If your instance uses a self-signed certificate (e.g. Laravel Herd), you may need:

```json
"env": {
  "ELMAPI_BASE_URL": "https://myproject.test/api",
  "ELMAPI_API_KEY": "your-project-api-token",
  "ELMAPI_PROJECT_ID": "your-project-uuid",
  "NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
```

Prefer fixing local CA trust (e.g. `node --use-system-ca`) over disabling TLS verification in production configs.

## Available Tools (40)

### Project
- `get_project` — Get project information (`default_locale`, `locales`, etc.)
- `add_project_locale` — Add a locale code to the project (requires **admin**)
- `set_default_project_locale` — Set the default locale (requires **admin**)

Removing locales is intentionally **not** exposed here (use **Project settings → Localization** in the dashboard, or the REST/SDK APIs).

### Collections
- `list_collections` — List all collections
- `get_collection` — Get a collection with its full field schema
- `create_collection` — Create a collection (with optional batch field creation)
- `update_collection` — Update a collection's name and slug
- `reorder_collections` — Reorder collections

### Fields
- `create_field` — Add a field to a collection
- `update_field` — Update a field
- `reorder_fields` — Reorder fields within a collection

### Content Entries
- `list_entries` — List entries with advanced filtering (`where` with 13 operators, OR groups, relation filtering), sorting, pagination, count, and first
- `get_entry` — Get a single content entry
- `create_entry` — Create a content entry
- `update_entry` — Update a content entry
- `patch_entry` — Partially update an entry (HTTP PATCH; merge only the fields you send)
- `publish_entry` — Publish the draft as a new immutable version (**update**)
- `unpublish_entry` — Clear the live published pointer; versions retained (**update**)
- `discard_entry_draft` — Discard unpublished draft changes (**update**)
- `delete_entry` — Soft-delete a content entry (moves to trash)
- `bulk_create_entries` — Create multiple entries atomically
- `bulk_update_entries` — Update multiple entries atomically by UUID
- `bulk_delete_entries` — Delete multiple entries atomically by UUID
- `link_entry_translation` — Link two entries (different locales) into the same translation group (`POST …/link-translation`; requires **update**)
- `list_entry_versions` — List version history for an entry
- `get_entry_version` — Fetch one version by number (includes snapshot payload)
- `revert_entry_version` — Restore draft from a prior snapshot and publish (**update**)
- `update_entry_version_label` — Edit label/description on a version; snapshot unchanged (**update**)

**Content API shape:** Each entry has `uuid`, `locale`, `published_at`, and **`fields`** (custom field values). Field names are **kebab-case**. **Richtext** write format follows `editor.mode`: HTML string or `{ html, json }` for lexical; markdown string when `mode` is `markdown`. MCP **create_field** / **create_collection** (and richtext **update_field**) default omitted `editor.mode` to **markdown**. Pass `mode: 'lexical'` for Lexical. Never write markdown into a lexical field. Read shape follows `editor.outputFormat`. **Relation fields** return nested entry objects (or arrays for one-to-many) on read; on write send only the related entry’s **UUID** or **numeric id** (never the full nested object from a previous `get_entry`). `get_entry` supports `translation_locale`, `exclude`, `timestamps`, and `state` query parameters.

**Save ≠ publish:** `create_entry` / `update_entry` / `patch_entry` save the draft only. `state=published` list/get keep serving the last snapshot until you call `publish_entry`.

**Asset URLs:** The API returns `url`, `thumbnail_url`, and `original_url` as stable links (optional `?variant=thumbnail` or `?variant=original`).

### Assets
- `list_assets` — List assets with pagination
- `get_asset` — Get an asset by UUID or filename
- `upload_asset` — Upload a file as an asset
- `bulk_upload_assets` — Upload multiple files atomically
- `bulk_update_asset_metadata` — Update metadata for multiple assets atomically
- `delete_asset` — Delete an asset

### Webhooks
- `list_webhooks` — List all webhooks for the project
- `get_webhook` — Get a webhook by UUID
- `create_webhook` — Create a webhook for content and auth events (`name`, `url`, `events`, `sources`; optional `description`, `secret`, `payload`, `status`, `collection_ids`)
- `update_webhook` — Update a webhook by UUID (same fields as create)
- `delete_webhook` — Delete a webhook by UUID
- `list_webhook_logs` — List delivery logs for a webhook (`uuid`; optional `paginate`, `page`)

## Resources

The server exposes three reference resources that AI agents can read for context:

- **Field Types Reference** (`elmapicms://field-types`) — Complete reference of all 16 field types, their options, validations, and common patterns.
- **Collections Guide** (`elmapicms://collections-guide`) — Guide for working with collections, singletons, reserved slugs, and best practices.
- **Query Reference** (`elmapicms://query-reference`) — Full documentation for content queries: `where` filters with 13 operators, OR groups, relation filtering, sorting, pagination, and examples.

## API token abilities

Your **project** API token needs the appropriate abilities for the tools you want to use:

| Ability  | Tools                                                       |
|----------|-------------------------------------------------------------|
| `read`   | list/get collections, entries, assets, webhooks; webhook logs |
| `create` | create entries, upload assets, create webhooks               |
| `update` | update entries, publish/unpublish/discard draft, **`link_entry_translation`**, versions, update asset metadata, update webhooks |
| `delete` | delete entries, delete assets, delete webhooks               |
| `admin`  | create/update/reorder collections and fields; add/set default **project locales** (MCP does not expose locale removal) |

Create the token in the ElmapiCMS dashboard under **Project settings → API Tokens**. Copy the **Project ID** from the project home page or **Project settings → API Access** when you configure this server.

## Using Multiple Projects

Each MCP entry connects to a single ElmapiCMS project. To work with multiple projects, add separate entries in your MCP config with different env values.

## License

MIT

TDQS

B3.4/5.0

Scored across 18 tools

Disambiguation5/5

All 18 tools target distinct resources and actions (e.g., create_collection vs create_entry vs create_field), with no overlapping purposes. Each tool has a clear and separate role.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in lowercase snake_case (e.g., create_collection, list_entries, upload_asset), with no deviations or style mixing.

Tool Count4/5

With 18 tools, the count is slightly above the ideal 3-15 range but still reasonable for a full-featured CMS server. Each tool serves a specific function without bloat.

Completeness3/5

CRUD coverage is strong for entries and assets, but notable gaps exist: no delete_collection or delete_field tools, and no update_asset. Reorder operations are included but are less critical.

Maintenance

ActivitySlowing
ResponsivenessNo issues