Strapi MCP Server (Strapi 5.x Only)
An MCP server for Strapi 5.x CMS that gives AI agents full access to content types, entries, media, and schema management through the Model Context Protocol.
Features
- Full CRUD on collection types and single types
- Media uploads — base64 or local file path
- Relation management — connect/disconnect related entries
- Schema management — create, update, delete content types and components (dev mode)
- Per-request auth — override server-level credentials with a JWT or API token per tool call
- Structured audit logging — JSON audit trail for all write operations
- Request correlation — optional
requestIdfor multi-agent tracing - Input validation — content type UIDs, entry IDs, file paths validated against injection (OWASP MCP02)
- Structured logging —
LOG_LEVELenv var controls verbosity (error/warn/info/debug) - Dev-mode gating — schema management tools hidden unless
STRAPI_DEV_MODE=true(20 tools in production, 25 in dev) - TTL-based cache — content types cached with configurable
STRAPI_CACHE_TTL
Quick Start
1. Install
npm install mcp-strapi
Or from source:
git clone https://github.com/andychoi/mcp-strapi.git
cd mcp-strapi
npm install
npm run build
2. Configure
Create a .env file (add to .gitignore):
STRAPI_URL=http://localhost:1337
[email protected]
STRAPI_ADMIN_PASSWORD=your_password
# STRAPI_API_TOKEN=your_api_token # Optional fallback
# STRAPI_DEV_MODE=true # Enable schema management tools
# LOG_LEVEL=debug # error | warn | info (default) | debug
# STRAPI_CACHE_TTL=300000 # Content type cache TTL in ms (default: 5 min)
3. Add to your MCP client
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%/Claude/claude_desktop_config.json on Windows):
{
"mcpServers": {
"mcp-strapi": {
"command": "npx",
"args": ["mcp-strapi"],
"env": {
"STRAPI_URL": "http://localhost:1337",
"STRAPI_ADMIN_EMAIL": "[email protected]",
"STRAPI_ADMIN_PASSWORD": "your_password"
}
}
}
}
Cursor (~/.cursor/mcp.json):
{
"strapi-mcp": {
"command": "npx",
"args": ["mcp-strapi"],
"env": {
"STRAPI_URL": "http://localhost:1337",
"STRAPI_ADMIN_EMAIL": "[email protected]",
"STRAPI_ADMIN_PASSWORD": "your_password"
}
}
}
If installed from source, replace "npx" / ["mcp-strapi"] with "node" / ["/path/to/mcp-strapi/build/index.js"].
Alternative — run directly:
node --env-file=.env build/index.js
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
STRAPI_URL |
No | http://localhost:1337 |
Strapi instance URL |
STRAPI_ADMIN_EMAIL |
Recommended | — | Admin email for full functionality |
STRAPI_ADMIN_PASSWORD |
Recommended | — | Admin password |
STRAPI_API_TOKEN |
No | — | API token fallback (limited permissions) |
STRAPI_DEV_MODE |
No | false |
Enable schema management tools |
LOG_LEVEL |
No | info |
Log verbosity: error, warn, info, debug |
STRAPI_CACHE_TTL |
No | 300000 |
Content type cache TTL in milliseconds (5 min) |
Authentication Priority
Per request: authToken parameter > admin JWT > API token
Admin credentials are recommended for full functionality (schema access, publish/unpublish, content type management).
Tools
All 20 production tools accept an optional authToken parameter for per-request auth override.
Content (Collection Types)
| Tool | Description |
|---|---|
list_content_types |
List all content types with kind (collectionType/singleType) and singularName |
get_entries |
Get entries with filtering, pagination, sorting, population |
get_entry |
Get a specific entry by ID |
create_entry |
Create a new entry |
update_entry |
Update an existing entry |
delete_entry |
Delete an entry |
publish_entry |
Publish an entry (admin required) |
unpublish_entry |
Unpublish an entry (admin required) |
Content (Single Types)
| Tool | Description |
|---|---|
get_single_type |
Get a single type entry (e.g., homepage, site-settings) |
update_single_type |
Update a single type entry |
delete_single_type |
Delete a single type entry |
publish_single_type |
Publish a single type (admin required) |
unpublish_single_type |
Unpublish a single type (admin required) |
Media
| Tool | Description |
|---|---|
upload_media |
Upload a file via base64 (max ~750KB file / 1MB base64) |
upload_media_from_path |
Upload from local file path (max 10MB) |
Schema & Relations
| Tool | Description |
|---|---|
get_content_type_schema |
Get schema (fields, types, relations) |
connect_relation |
Connect related entries to a relation field |
disconnect_relation |
Disconnect related entries from a relation field |
list_components |
List all Strapi components |
get_component_schema |
Get a component's schema |
Dev Mode Only (STRAPI_DEV_MODE=true)
| Tool | Description |
|---|---|
create_content_type |
Create a new content type (admin required) |
update_content_type |
Update a content type's attributes (admin required) |
delete_content_type |
Delete a content type (admin required) |
create_component |
Create a new component (admin required) |
update_component |
Update a component (admin required) |
Usage Examples
List content types
{
"tool": "list_content_types",
"arguments": {}
}
Get entries with filtering and pagination
{
"tool": "get_entries",
"arguments": {
"contentType": "api::article.article",
"filters": { "title": { "$contains": "hello" } },
"pagination": { "page": 1, "pageSize": 10 },
"sort": ["title:asc", "createdAt:desc"],
"populate": ["author", "categories"]
}
}
Create an entry
{
"tool": "create_entry",
"arguments": {
"contentType": "api::article.article",
"data": {
"title": "My New Article",
"content": "Article body text."
}
}
}
Per-request auth token
Override server credentials with a role-specific JWT or API token:
{
"tool": "get_entries",
"arguments": {
"contentType": "api::article.article",
"authToken": "eyJhbGciOiJIUzI1NiIs..."
}
}
Use cases:
- Operate as a specific role (admin / author / reader)
- Different content types need different permission levels
- Test access with a scoped API token
Single type operations
{
"tool": "get_single_type",
"arguments": {
"contentType": "api::homepage.homepage",
"options": "{\"populate\": [\"hero\", \"seo\"]}"
}
}
{
"tool": "update_single_type",
"arguments": {
"contentType": "api::homepage.homepage",
"data": { "title": "Welcome", "description": "Updated" }
}
}
Upload media
Base64 (small files):
{
"tool": "upload_media",
"arguments": {
"fileData": "<base64-encoded-data>",
"fileName": "image.jpg",
"fileType": "image/jpeg"
}
}
File path (recommended for larger files):
{
"tool": "upload_media_from_path",
"arguments": {
"filePath": "/path/to/image.jpg"
}
}
Connect/disconnect relations
{
"tool": "connect_relation",
"arguments": {
"contentType": "api::article.article",
"id": "1",
"relationField": "authors",
"relatedIds": [2, 3]
}
}
Create a content type (dev mode)
{
"tool": "create_content_type",
"arguments": {
"displayName": "Product",
"singularName": "product",
"pluralName": "products",
"kind": "collectionType",
"description": "Store products",
"draftAndPublish": true,
"attributes": {
"name": { "type": "string", "required": true },
"price": { "type": "decimal", "required": true },
"stock": { "type": "integer" }
}
}
}
Request correlation ID
Pass a requestId to trace requests across multi-agent systems. It appears in audit log entries:
{
"tool": "create_entry",
"arguments": {
"contentType": "api::article.article",
"data": { "title": "Traced Article" },
"requestId": "agent-abc-req-123"
}
}
Enterprise Features
Audit Logging
All write operations emit structured JSON audit events to stderr:
{"audit":true,"timestamp":"2026-02-22T03:00:00.000Z","action":"create_entry","contentType":"api::article.article","entryId":"42","authMethod":"adminJwt","status":"success","requestId":"agent-abc-req-123"}
Fields: timestamp, action, contentType, entryId, authMethod (authToken | adminJwt | apiToken | none), status (success | error), requestId, error.
Audit events are always emitted regardless of LOG_LEVEL.
Request Correlation IDs
Every tool accepts an optional requestId parameter. When provided, the ID is included in all audit log entries for that request, enabling end-to-end tracing in multi-agent deployments.
Content Type Caching
Content types are cached with a configurable TTL (default: 5 minutes). Set STRAPI_CACHE_TTL in milliseconds to adjust. The cache is automatically invalidated when schema management tools modify content types.
Security
- No token logging — tokens never appear in logs (OWASP MCP01)
- Input validation — regex validation for content type UIDs, entry IDs, component UIDs, file paths (OWASP MCP02)
- Sanitized errors — raw Strapi error details only logged at debug level
- Dev-mode gating — destructive schema tools hidden in production
Resource URIs
Content types are exposed as MCP resources:
strapi://content-type/api::article.article— all articlesstrapi://content-type/api::article.article/1— article with ID 1strapi://content-type/api::article.article?filters={"title":{"$contains":"hello"}}— filtered
Troubleshooting
Placeholder API Token Error
[Error] STRAPI_API_TOKEN appears to be a placeholder value...
Replace "strapi_token" or "your-api-token-here" with a real API token from Strapi admin > Settings > API Tokens.
Connection Refused
Cannot connect to Strapi instance: Connection refused
Ensure Strapi is running (npm run develop), the URL is correct, and the database is up.
Authentication Failed
Cannot connect to Strapi instance: Authentication failed
Verify admin email/password or API token permissions. Ensure the admin user is active.
Context Window Overflow with Uploads
Use upload_media_from_path instead of upload_media for files larger than ~500KB. The base64 tool has a 1MB limit (~750KB file).
Permission Errors (403)
Use admin credentials for full access. If using an API token, ensure it has "Full access" permissions.
Debugging
npm run inspector
Opens the MCP Inspector for debugging tool calls in your browser.
Development
npm install # Install dependencies
npm run build # Build
npm run watch # Build with auto-rebuild
For deployment details, see DEPLOYMENT.md.
License
MIT