# An MCP server on your CMS with Payload

> How to expose your Payload CMS content over MCP so an assistant like Claude can read and create it, with API keys and per-collection permissions.

URL: https://codegea.com/en/mcp-server-on-your-cms-with-payload
CMS · 2026-10-18 · Derian Pinto

MCP (Model Context Protocol) is a standard that lets an AI assistant use external tools. If your CMS speaks it, the assistant can **read your articles, create a new one or fix a field** without you copying and pasting anything. Payload has an official plugin for this. This is how we use it on this site.

## What you get

With the MCP server on, from an assistant you can ask things like "list the articles in the CMS category" or "create a draft with this text". The assistant calls the CMS through the protocol, with permissions you define, not through the admin screen.

## Step 1: install the plugin

```bash
pnpm add @payloadcms/plugin-mcp
```

## Step 2: choose what gets exposed

The important part of the plugin is what you **don't** turn on. In `plugins/index.ts`:

```ts
mcpPlugin({
  userCollection: 'users',
  collections: {
    posts: {
      enabled: true,
      description: 'Blog articles, localized in es and en.',
    },
    projects: {
      enabled: true,
      description: 'Delivered cases and projects, localized in es and en.',
    },
    categories: { enabled: true },
    authors: { enabled: true },
    media: { enabled: { find: true, create: true, update: true } },
  },
  globals: {
    'site-settings': { enabled: true, description: 'Contact, social and clients.' },
    header: { enabled: true, description: 'Main menu and mega menu.' },
    footer: { enabled: true, description: 'Footer.' },
  },
}),
```

Notice three things:

- You only expose what the assistant needs. Our users or form submissions collections don't appear.
- Each collection's `description` helps the assistant know what it is for. Write it as you would explain it to a new person.
- On `media` only `find`, `create` and `update` are on. There is no `delete`.

## Step 3: control who gets in

API keys live in their own collection. We adjust its access control so only authenticated users manage them:

```ts
overrideApiKeyCollection: (collection) => ({
  ...collection,
  access: {
    admin: ({ req }) => Boolean(req.user),
    read: authenticated,
    create: authenticated,
    update: authenticated,
    delete: authenticated,
  },
}),
```

## Step 4: create a key and connect the assistant

In the admin panel, in the **MCP → API Keys** section, create a key and review the permissions the plugin lets you assign. Then, with Claude Code:

```bash
claude mcp add --transport http codegea http://localhost:4000/api/mcp \
  --header "Authorization: Bearer <API_KEY>"
```

The server answers at `/api/mcp` in your own application. In production, swap the URL for your domain's.

## Good practices

- **One key per person or tool**, with minimum permissions. That way you revoke one without affecting the rest.
- **Don't commit the key to the repository.** It is stored in the assistant's configuration, not in code.
- **Start with read permissions** and add write when you know what you need.
- **Review what it creates.** An assistant can publish text without review. Keep writes as drafts if your workflow allows it.
- **Mind the content it reads.** What is in your CMS reaches the assistant as context; if there is private data, don't enable that collection.

## When it isn't worth it

If you edit content a few times a month, the usual admin panel is simpler. MCP pays for itself when you do repetitive or batch tasks: migrating a hundred articles, translating, reviewing SEO fields, uploading images with their alt text.

More about the CMS we use in [Payload vs Strapi vs Directus](/en/payload-cms-vs-strapi-vs-directus-in-2026).
