PayloadCMS MCP Plugin

Welcome to the complete documentation for the PayloadCMS MCP Plugin. This plugin creates an MCP (Model Context Protocol) server compatible with Claude Desktop and other AI assistants.

A comprehensive PayloadCMS plugin that creates an MCP (Model Context Protocol) server compatible with Claude Desktop. This plugin automatically generates MCP tools for all your PayloadCMS collections and provides both embedded and standalone server options.

Features

  • šŸš€ Automatic Tool Generation: Generates MCP tools for all PayloadCMS collections
  • šŸ” API Key Authentication: Secure authentication using environment variables
  • 🌐 HTTP Transport: Reliable HTTP-based MCP communication
  • ā˜ļø Vercel Ready: Optimized for serverless deployment
  • šŸ› ļø Comprehensive Operations: List, get, create, update, and delete operations
  • šŸ“Š Rich JSON Schemas: Automatically generated schemas from collection fields
  • šŸ“ Full Claude Desktop Integration: Ready to use with Claude Desktop
  • šŸŽ›ļø Per-Collection Control: Configure operations individually for each collection
  • šŸ·ļø Custom Tool Naming: Custom prefixes and descriptions per collection

Installation

1
pnpm install payload-plugin-mcp
bash
2 lines

Quick Start

1. Environment Setup

Create a .env file in your project root:

1
openssl rand -base64 32 # => eg ACDlHFY0DoreUVnxB62dSPUU++AFg8M5W3fWy6mtyD4=
bash
2 lines
1
# Required: API key for MCP server authentication
2
MCP_API_KEY=your-secret-api-key-here
env
3 lines

2. Add to PayloadCMS Config

The plugin supports multiple configuration formats for maximum flexibility:

Option 1: Simple - Expose All Collections

1
// payload.config.ts
2
import { buildConfig } from 'payload'
3
import { PayloadPluginMcp } from 'payload-plugin-mcp'
4
5
export default buildConfig({
6
collections: [
7
// your collections here
8
],
9
plugins: [
10
// other plugins...
11
PayloadPluginMcp({
12
apiKey: process.env.MCP_API_KEY,
13
collections: 'all', // Expose all collections with default operations
14
defaultOperations: {
15
list: true,
16
get: true,
17
create: false,
18
update: false,
19
delete: false,
20
},
21
}),
22
],
23
})
ts
24 lines

Option 2: Import Collections Directly

1
// payload.config.ts
2
import { buildConfig } from 'payload'
3
import { PayloadPluginMcp } from 'payload-plugin-mcp'
4
// Import your collections
5
import { Posts } from './collections/Posts'
6
import { Users } from './collections/Users'
7
import { Media } from './collections/Media'
8
9
export default buildConfig({
10
collections: [Posts, Users, Media],
11
plugins: [
12
PayloadPluginMcp({
13
apiKey: process.env.MCP_API_KEY,
14
// Pass collections directly (like Payload's native format)
15
collections: [
16
Posts, // Uses default operations
17
Users, // Uses default operations
18
Media, // Uses default operations
19
],
20
defaultOperations: {
21
list: true,
22
get: true,
23
create: false,
24
update: false,
25
delete: false,
26
},
27
}),
28
],
29
})
typescript
30 lines

Option 3: Advanced - Per-Collection Configuration

1
// payload.config.ts
2
import { buildConfig } from 'payload'
3
import { PayloadPluginMcp } from 'payload-plugin-mcp'
4
import { Posts } from './collections/Posts'
5
import { Users } from './collections/Users'
6
import { Media } from './collections/Media'
7
8
export default buildConfig({
9
collections: [Posts, Users, Media],
10
plugins: [
11
PayloadPluginMcp({
12
apiKey: process.env.MCP_API_KEY,
13
collections: [
14
// Simple collection (uses default operations)
15
Posts,
16
17
// Collection with custom options
18
{
19
collection: Users,
20
options: {
21
operations: {
22
list: true,
23
get: true,
24
create: true, // Enable creation for users
25
update: true, // Enable updates for users
26
delete: false, // Keep delete disabled
27
},
28
toolPrefix: 'user', // Custom tool prefix
29
description: 'user management', // Custom description
30
excludeFields: ['password'], // Hide sensitive fields
31
},
32
},
33
34
// Media with different settings
35
{
36
collection: Media,
37
options: {
38
operations: {
39
list: true,
40
get: true,
41
create: true,
42
update: false,
43
delete: true, // Allow media deletion
44
},
45
toolPrefix: 'file',
46
description: 'file storage',
47
},
48
},
49
],
50
// Default operations for collections without specific config
51
defaultOperations: {
52
list: true,
53
get: true,
54
create: false,
55
update: false,
56
delete: false,
57
},
58
}),
59
],
60
})
typescript
61 lines

3. Start Your PayloadCMS Application

1
pnpm dev
bash
2 lines

The plugin will automatically:

  • Generate MCP tools for your collections
  • Start an MCP server on the configured port
  • Log available endpoints and tools

Expected output:

1
āœ… PayloadCMS MCP Plugin initialized
2
šŸ”§ Collections exposed: posts, users, media
3
šŸ› ļø Tools generated: 8
4
🌐 MCP HTTP server: http://0.0.0.0:3000/api/plugin/mcp
5
šŸ” Authentication: Enabled
6
šŸ“‹ posts: list, get
7
šŸ“‹ users: list, get, create, update
8
šŸ“‹ media: list, get, create, delete
bash
9 lines

Generated Tools

The plugin generates tools based on your collection configuration:

For the advanced configuration example above:

  1. posts_list / posts_get - Basic read operations
  2. user_list / user_get / user_create / user_update - Full CRUD except delete
  3. file_list / file_get / file_create / file_delete - File management tools

Tool Examples

List Tool (posts_list)

1
{
2
"name": "posts_list",
3
"description": "List documents from the posts collection with optional filtering, pagination, and sorting",
4
"input": {
5
"where": { "status": { "equals": "published" } },
6
"limit": 10,
7
"page": 1,
8
"sort": "-createdAt",
9
"depth": 1
10
}
11
}
json
12 lines

Custom Tool (user_create)

1
{
2
"name": "user_create",
3
"description": "Create a new document in the user management",
4
"input": {
5
"data": {
6
"name": "John Doe",
7
"email": "john@example.com"
8
// Note: 'password' field excluded due to excludeFields config
9
},
10
"depth": 1
11
}
12
}
json
13 lines

Collection Configuration Options

CollectionMcpOptions

1
interface CollectionMcpOptions {
2
/**
3
* Operations to enable for this collection
4
*/
5
operations?: {
6
list?: boolean // List documents with filtering/pagination
7
get?: boolean // Get single document by ID
8
create?: boolean // Create new documents
9
update?: boolean // Update existing documents
10
delete?: boolean // Delete documents
11
}
12
13
/**
14
* Custom tool naming prefix (defaults to collection slug)
15
* Example: 'user' generates 'user_list', 'user_get', etc.
16
*/
17
toolPrefix?: string
18
19
/**
20
* Custom description for this collection's tools
21
* Used in tool descriptions: "List documents from the {description}"
22
*/
23
description?: string
24
25
/**
26
* Fields to exclude from schemas (useful for sensitive data)
27
* Example: ['password', 'secret', 'internal']
28
*/
29
excludeFields?: string[]
30
31
/**
32
* Additional metadata for this collection
33
*/
34
metadata?: Record<string, any>
35
}
typescript
36 lines

Configuration Formats

1
// Format 1: All collections with defaults
2
collections: 'all'
3
4
// Format 2: Direct collection imports
5
collections: [Posts, Users, Media]
6
7
// Format 3: Mixed configuration
8
collections: [
9
Posts, // Uses defaults
10
{ collection: Users, options: {...} }, // Custom config
11
Media, // Uses defaults
12
]
typescript
13 lines

HTTP vs SSE: Why We Chose HTTP

This plugin uses HTTP transport instead of Server-Sent Events (SSE) for MCP communication. Here's why:

Comparison Table

AspectHTTPSSE
ConnectionRequest/response, statelessPersistent, long-lived
Data FlowClient requests dataServer can push data anytime
Use CasesStandard CRUD operationsReal-time updates, streaming
ComplexityLower (simple request/response)Higher (connection management)
PerformanceBetter for one-off operationsBetter for frequent updates
ServerlessExcellent (stateless)Challenging (timeout limits)
DebuggingEasier to debugMore complex to troubleshoot
PayloadCMS FitPerfect for CMS operationsOverkill for most CMS use cases

Why HTTP is Better for PayloadCMS

  1. CRUD Operations: Most CMS operations are request/response based
  2. Serverless Friendly: Works perfectly with Vercel/Netlify deployments
  3. Simpler Architecture: Easier to maintain and debug
  4. Stateless Design: Fits well with PayloadCMS's architecture
  5. Better Performance: For typical CMS operations, HTTP is more efficient

SSE Support

Server-Sent Events support may be considered in future releases if there is sufficient demand. SSE could be valuable for:

  • Real-time notifications when content is published
  • Live progress updates for bulk operations
  • Streaming responses for large data exports
  • Live collaboration features

Claude Desktop Integration

Claude Desktop loads the claude_desktop_config.json file when it starts up. It will send requests to the endpoints created by the plugin and will become available in your tools.

Method 1: Production (Hosted Servers)

Add to your claude_desktop_config.json:

The npx mcp-remote -y will execute a remote dependency needed to run the plugin. For example, this would work if deployed to Vercel (eg you-domain.vercel.app/api/plugin/mcp)

1
{
2
"mcpServers": {
3
"payloadcms": {
4
"command": "npx",
5
"args": [
6
"-y",
7
"mcp-remote",
8
"https://your-domain.com/api/plugin/mcp",
9
"--header",
10
"Authorization: Bearer ${MCP_API_KEY}",
11
"--header",
12
"Content-Type: application/json"
13
],
14
"env": {
15
"MCP_API_KEY": "your-api-key"
16
}
17
}
18
}
19
}
json
20 lines

Method 2: Local Development

For local development, you can connect directly:

1
{
2
"mcpServers": {
3
"payloadcms-local": {
4
"command": "npx",
5
"args": [
6
"-y",
7
"mcp-remote",
8
"http://localhost:3000/api/plugin/mcp",
9
"--header",
10
"Authorization: Bearer ${MCP_API_KEY}"
11
],
12
"env": {
13
"MCP_API_KEY": "your-api-key"
14
}
15
}
16
}
17
}
json
18 lines

Cursor Integration

Cursor is an AI-powered code editor that supports MCP (Model Context Protocol) servers. You can use this plugin with Cursor to interact with your PayloadCMS data directly from your development environment.

Setting Up Cursor MCP

  1. Install the MCP Extension (if not already installed)

    • Open Cursor
    • Go to Extensions and search for "MCP" or "Model Context Protocol"
    • Install the official MCP extension
  2. Configure MCP Server in Cursor

    Add your PayloadCMS MCP server to Cursor's MCP configuration:

    For Local Development:

    1
    {
    2
    "mcpServers": {
    3
    "payloadcms-local": {
    4
    "command": "npx",
    5
    "args": [
    6
    "-y",
    7
    "mcp-remote",
    8
    "http://localhost:3000/api/plugin/mcp",
    9
    "--header",
    10
    "Authorization: Bearer ${MCP_API_KEY}"
    11
    ],
    12
    "env": {
    13
    "MCP_API_KEY": "your-api-key"
    14
    }
    15
    }
    16
    }
    17
    }
    json
    18 lines

    For Production:

    1
    {
    2
    "mcpServers": {
    3
    "payloadcms-production": {
    4
    "command": "npx",
    5
    "args": [
    6
    "-y",
    7
    "mcp-remote",
    8
    "https://your-domain.com/api/plugin/mcp",
    9
    "--header",
    10
    "Authorization: Bearer ${MCP_API_KEY}",
    11
    "--header",
    12
    "Content-Type: application/json"
    13
    ],
    14
    "env": {
    15
    "MCP_API_KEY": "your-production-api-key"
    16
    }
    17
    }
    18
    }
    19
    }
    json
    20 lines
  3. Restart Cursor

    • Close and reopen Cursor to load the new MCP configuration
    • The PayloadCMS tools should now be available in Cursor's AI chat

Using PayloadCMS Tools in Cursor

Once configured, you can use your PayloadCMS collections directly in Cursor's AI chat:

Example Commands:

  • "List all published posts from my CMS"
  • "Create a new user with email john@example.com"
  • "Update the post with ID 123 to set status to published"
  • "Show me the latest 5 media files"
  • "Delete the user with ID 456"

Cursor will automatically:

  • Use the appropriate MCP tools based on your collection configuration
  • Handle authentication with your API key
  • Format responses in a developer-friendly way
  • Provide context about your CMS structure

Benefits of Using Cursor with PayloadCMS

  • Direct CMS Access: Query and modify your CMS data without leaving your editor
  • Code Context: Cursor understands your codebase and can suggest CMS operations based on your current work
  • Automated Workflows: Create content, manage users, and update data as part of your development workflow
  • Real-time Integration: Changes made through Cursor are immediately reflected in your CMS

Troubleshooting Cursor Integration

  1. Tools Not Appearing

    • Verify your MCP server is running (pnpm dev)
    • Check that the API key is correctly set in Cursor's environment
    • Restart Cursor after configuration changes
  2. Authentication Errors

    • Ensure MCP_API_KEY matches between your PayloadCMS config and Cursor
    • Test the API key with curl first (see Testing section below)
  3. Connection Issues

    • For local development, ensure your PayloadCMS server is running on the correct port
    • For production, verify the URL is accessible and CORS is properly configured

Testing Your MCP Server

1. Test Tool Listing

1
curl -H "Authorization: Bearer your-api-key" \
2
http://localhost:3000/api/plugin/mcp
bash
3 lines

2. Test Tool Invocation

1
curl -X POST \
2
-H "Authorization: Bearer your-api-key" \
3
-H "Content-Type: application/json" \
4
-d '{
5
"jsonrpc": "2.0",
6
"id": 1,
7
"method": "tools/call",
8
"params": {
9
"name": "posts_list",
10
"arguments": {
11
"where": { "status": { "equals": "published" } },
12
"limit": 5
13
}
14
}
15
}' \
16
http://localhost:3000/api/plugin/mcp
bash
17 lines

3. Test with MCP Inspector

Use the MCP Inspector to test your server:

1
npx @modelcontextprotocol/inspector http://localhost:3000/api/plugin/mcp
bash
2 lines

This will open the MCP Inspector at http://localhost:6274 where you can:

  • Enter your Authorization header (Bearer your-api-key)
  • Test MCP tool execution
  • Explore available tools and their schemas
  • Debug connection issues

API Endpoints

The plugin creates the following endpoints:

  • GET /api/plugin/mcp - Discovery endpoint (lists available tools)
  • POST /api/plugin/mcp - JSON-RPC 2.0 endpoint for MCP protocol
  • OPTIONS /api/plugin/mcp - CORS preflight handling

Authentication

The plugin supports API key authentication:

  1. Set the MCP_API_KEY environment variable
  2. Include the API key in requests:
    • Header: Authorization: Bearer your-api-key
    • Query parameter: ?api_key=your-api-key

Advanced Usage Examples

Content Management System

1
// CMS with different access levels
2
PayloadPluginMcp({
3
collections: [
4
// Public content - read-only
5
{
6
collection: Posts,
7
options: {
8
operations: { list: true, get: true },
9
description: 'blog posts',
10
},
11
},
12
13
// Admin content - full access
14
{
15
collection: Pages,
16
options: {
17
operations: { list: true, get: true, create: true, update: true, delete: true },
18
toolPrefix: 'page',
19
description: 'website pages',
20
},
21
},
22
23
// Media - managed uploads
24
{
25
collection: Media,
26
options: {
27
operations: { list: true, get: true, create: true, delete: true },
28
toolPrefix: 'asset',
29
description: 'media assets',
30
},
31
},
32
],
33
})
typescript
34 lines

E-commerce Setup

1
// E-commerce with product management
2
PayloadPluginMcp({
3
collections: [
4
// Products - full management
5
{
6
collection: Products,
7
options: {
8
operations: { list: true, get: true, create: true, update: true },
9
excludeFields: ['internalNotes', 'cost'],
10
},
11
},
12
13
// Orders - read and update only
14
{
15
collection: Orders,
16
options: {
17
operations: { list: true, get: true, update: true },
18
excludeFields: ['paymentDetails'],
19
},
20
},
21
22
// Categories - read-only
23
{
24
collection: Categories,
25
options: {
26
operations: { list: true, get: true },
27
},
28
},
29
],
30
})
typescript
31 lines

Vercel Deployment

1. Create an MCP token for production

1
openssl rand -base64 32
bash
2 lines

2. Environment Variables

Set in Vercel dashboard:

1
MCP_API_KEY=your-production-api-key
text
2 lines

2. Claude Desktop Configuration

1
{
2
"mcpServers": {
3
"payloadcms-production": {
4
"command": "npx",
5
"args": [
6
"-y",
7
"mcp-remote",
8
"https://your-app.vercel.app/api/mcp",
9
"--header",
10
"Authorization: Bearer ${MCP_API_KEY}",
11
"--header",
12
"application/json"
13
],
14
"env": {
15
"MCP_API_KEY": "your-production-api-key"
16
}
17
}
18
}
19
}
json
20 lines

Configuration Options

OptionTypeDefaultDescription
apiKeystringprocess.env.MCP_API_KEYAPI key for authentication
collectionsCollectionMcpConfig[] | 'all''all'Collections to expose
defaultOperationsToolOperations{list: true, get: true}Default operations for collections
portnumber3001Server port
hoststring'0.0.0.0'Server host
enableHttpTransportbooleantrueEnable HTTP server
enableStdioTransportbooleantrueEnable stdio transport
serverNamestring'PayloadCMS MCP Server'Server name
serverDescriptionstringAuto-generatedServer description
disabledbooleanfalseDisable the plugin

Troubleshooting

Common Issues

  1. "Invalid or missing API key"

    • Ensure MCP_API_KEY is set in your environment
    • Check that the API key is being passed correctly in requests
  2. "Tool not found"

    • Verify that the collection is included in the plugin configuration
    • Check that the operation is enabled in the collection's operations config
  3. "Collection not found in registered collections"

    • Ensure imported collections are also added to the main collections array
    • Check collection slug matches between import and registration

Debug Mode

Enable debug logging:

1
payloadPluginMcp({
2
// ... other options
3
debug: true, // Enable debug logging
4
})
typescript
5 lines

Health Check

Check server status:

1
curl http://localhost:3000/api/plugin/mcp
bash
2 lines

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

Support

Related

Made with ā¤ļø by

Antler Digital

Modern web applications that are fast, secure, and scalable