An MCP server for Strapi CMS, providing access to content types and entries through the Model Context Protocol.
This MCP server integrates with any Strapi CMS instance to provide:
- Access to Strapi content types as resources
- Tools to create and update content types in Strapi
- Tools to manage content entries (create, read, update, delete)
- Support for Strapi in development mode
- Robust error handling with clear diagnostics and troubleshooting guidance
- Configuration validation to prevent common setup issues
It's recommended to use a .env file in the project root to store your credentials.
STRAPI_URL: The URL of your Strapi instance (default:http://localhost:1337)STRAPI_API_TOKEN: Your Strapi API token (Required for authentication).STRAPI_DEV_MODE: Set to"true"to enable development mode features (defaults tofalse).
Example .env file:
STRAPI_URL=http://localhost:1337
STRAPI_API_TOKEN=your_api_token_hereImportant:
- Add
.envto your.gitignorefile to avoid committing credentials - Avoid placeholder values like
"strapi_token"- the server validates and rejects common placeholders
npm install @wh1teee/@wh1teee/strapi-mcpFor the latest development features:
git clone https://github.com/l33tdawg/@wh1teee/strapi-mcp.git
cd @wh1teee/strapi-mcp
npm install
npm run buildRecommended Method (using Cursor MCP Configuration):
For Cursor users, configure the @wh1teee/strapi-mcp server in your ~/.cursor/mcp.json file:
"@wh1teee/strapi-mcp": {
"command": "npx",
"args": ["@wh1teee/strapi-mcp"],
"env": {
"STRAPI_URL": "http://localhost:1337",
"STRAPI_API_TOKEN": "your_api_token_here"
}
}If you installed from source, use the direct path instead:
"@wh1teee/strapi-mcp": {
"command": "node",
"args": ["/path/to/@wh1teee/strapi-mcp/build/index.js"],
"env": {
"STRAPI_URL": "http://localhost:1337",
"STRAPI_API_TOKEN": "your_api_token_here"
}
}Cursor will manage the server lifecycle automatically when @wh1teee/strapi-mcp tools are used.
Alternative Method (using .env file):
Make sure you have built the project (npm run build). Then run the server using Node.js v20.6.0+ with the --env-file flag:
node --env-file=.env build/index.jsAlternative (using environment variables directly):
export STRAPI_URL=http://localhost:1337
export STRAPI_API_TOKEN=your_api_token_here
export STRAPI_DEV_MODE=true # optional
# Run the globally installed package (if installed via npm install -g)
@wh1teee/strapi-mcp
# Or run the local build directly
node build/index.js- Performance-optimized queries with 92% smaller response sizes
- Smart field selection for minimal data transfer
- Targeted populate strategies for efficient relation loading
- Strapi v5+ compatibility with documentId support
- List and read content types
- Get, create, update, and delete entries
- Upload media files with alt text and metadata
- Connect and disconnect relations
- Get content type schemas and field information
get_lightweight_entries: Returns only essential fields, 95% smaller responsesfind_author_by_name: Fast author lookup without full content populateget_schema_fields: Schema-only endpoint without content overheadget_content_preview: Smart preview with essential fields and search
| Method | Traditional | Optimized | Improvement |
|---|---|---|---|
| Article listing | 15KB+ | <1KB | 95% smaller |
| Author search | Full populate | Direct lookup | No overhead |
| Schema queries | Mixed data | Pure metadata | Schema only |
| Content preview | Heavy load | Smart fields | 12x faster |
When creating articles (api::articles.articles):
- Description field: Maximum 80 characters allowed
- Cover field: Use
cover(notcoverImage) with media ID as integer - SEO fields: Must be in
blocksarray with__component: "shared.seo"
See Article Creation Guide for complete examples.
- NEW: Performance-Optimized API Methods: 4 new methods for high-performance operations
- NEW:
get_lightweight_entries: Returns only essential fields, 95% smaller responses than full populate - NEW:
find_author_by_name: Fast author search without heavy populate overhead - NEW:
get_schema_fields: Schema-only endpoint with enhanced field analysis - NEW:
get_content_preview: Smart preview with configurable limits and search - PERFORMANCE: 92% Response Size Reduction: From 15KB+ to <1KB for typical queries
- PERFORMANCE: 12x Faster Data Transfer: Optimized field selection and smart populate
- ENHANCED: Strapi v5+ Compatibility: Full support for documentId alongside legacy id
- ENHANCED: Smart Field Selection: Automatic optimization based on content type
- IMPROVED: Query Strategies: Targeted populate with minimal relation data
- NEW: Enhanced Article Creation Support: Improved
create_entrywith detailed article examples and validation - NEW:
get_article_structure_exampletool: Get complete examples of correct article structure - ENHANCED: Field Validation: Built-in validation for common article creation mistakes
- IMPROVED: Method Descriptions: Detailed examples and field name corrections in tool descriptions
- IMPROVED: Error Messages: Helpful validation errors with exact fixes for article creation issues
- SEE: Article Creation Guide for detailed usage instructions
- NEW: Alt Text and Media Metadata Support: Upload files with alt text, captions, and metadata for SEO and accessibility
- NEW:
update_media_metadatatool: Update existing media files with alt text and captions - ENHANCED: Media Upload Functions:
upload_media_from_pathandupload_media_from_urlnow supportfileInfoparameter - IMPROVED: Path Validation: Added strict absolute path requirement with clear error messages
- BREAKING CHANGE: Removed old
upload_mediafunction (replaced with efficient path/URL methods) - PERFORMANCE: 99.9% reduction in context token usage for media uploads
- MAJOR BUG FIX: Replaced silent failures with descriptive error messages when content types or entries cannot be fetched
- Added Configuration Validation: Detects placeholder API tokens and exits with helpful error messages
- Added Connection Validation: Tests Strapi connectivity before attempting operations with specific error diagnostics
- Enhanced Error Handling: Comprehensive error diagnostics that distinguish between legitimate empty collections vs actual errors
- Improved Troubleshooting: All error messages include specific steps to resolve common configuration issues
- Added
publish_entryandunpublish_entrytools: Complete content lifecycle management - Added Component Management:
list_components,get_component_schema,create_component,update_component - Added
delete_content_typetool: Delete existing content types via the Content-Type Builder API - Enhanced Admin Authentication: Better error handling and token management for all API operations
- Added
create_content_typetool: Allows creating new content types via the Content-Type Builder API. - Enhanced Authentication: Streamlined authentication logic for better reliability.
- Updated Documentation: Clarified authentication methods and recommended running procedures.
- Improved content type discovery with multiple fallback methods
- Added more robust error handling and logging
- Enhanced schema inference for content types
- Improved error handling with more specific error codes
- Added
ResourceNotFoundandAccessDeniederror codes - Better error messages for common API errors
- Initial public release
MIT
An MCP server for your Strapi CMS
This is a TypeScript-based MCP server that integrates with Strapi CMS. It provides access to Strapi content types and entries through the MCP protocol, allowing you to:
- Access Strapi content types as resources
- Create, read, update, and delete content entries
- Manage your Strapi content through MCP tools
- List and access content types via
strapi://content-type/URIs - Each content type exposes its entries as JSON
- Application/JSON mime type for structured content access
list_content_types- List all available content types in Strapiget_entries- Get entries for a specific content type with optional filtering, pagination, sorting, and population of relationsget_entry- Get a specific entry by IDcreate_entry- Create a new entry for a content typeupdate_entry- Update an existing entrydelete_entry- Delete an entryupload_media_from_path- Upload a media file from local path with alt text and metadata (efficient, no context token usage)upload_media_from_url- Upload a media file from URL with alt text and metadata (efficient, no context token usage)update_media_metadata- Update alt text, caption, and metadata for existing media files (SEO and accessibility)get_content_type_schema- Get the schema (fields, types, relations) for a specific content type.get_article_structure_example- Get complete examples of correct article structure with field names and validation rules.connect_relation- Connect related entries to an entry's relation field.disconnect_relation- Disconnect related entries from an entry's relation field.create_content_type- Create a new content type using the Content-Type Builder API (Requires Admin privileges).publish_entry- Publish a specific entry.unpublish_entry- Unpublish a specific entry.list_components- List all available components in Strapi.get_component_schema- Get the schema for a specific component.create_component- Create a new component.update_component- Update an existing component.
Upload media files with proper alt text, captions, and metadata for better SEO and accessibility:
// Upload from local file path with full metadata (ABSOLUTE PATH REQUIRED)
upload_media_from_path(
'/home/user/photos/image.jpg', // ABSOLUTE path required!
'custom-filename.jpg',
{
alternativeText: 'Beautiful sunset over mountain peaks during golden hour',
caption: 'Landscape photography from our hiking trip to the Alps',
name: 'sunset-alps-golden-hour.jpg'
}
)
// Upload from URL with accessibility metadata
upload_media_from_url(
'https://example.com/product-image.jpg',
null,
{
alternativeText: 'Modern laptop computer on a clean white desk',
caption: 'Product showcase - MacBook Pro 16-inch'
}
)
// Update metadata for existing media files
update_media_metadata('42', {
alternativeText: 'Updated alt text for better SEO and accessibility',
caption: 'New caption that better describes the image content'
})Why Alt Text Matters:
- SEO: Search engines use alt text to understand image content
- Accessibility: Screen readers rely on alt text for visually impaired users
- Performance: Displayed when images fail to load
- Context: Provides better content management and organization
- ABSOLUTE PATHS ONLY: Use
/home/user/image.jpgorC:\Users\user\image.jpg - NOT SUPPORTED: Relative paths (
./image.jpg,../image.jpg) or tilde paths (~/image.jpg) - VALIDATION: The server will reject non-absolute paths with a clear error message
The get_entries tool supports advanced query options:
{
"contentType": "api::article.article",
"filters": {
"title": {
"$contains": "hello"
}
},
"pagination": {
"page": 1,
"pageSize": 10
},
"sort": ["title:asc", "createdAt:desc"],
"populate": ["author", "categories"]
}Resources can be accessed with various URI formats:
strapi://content-type/api::article.article- Get all articlesstrapi://content-type/api::article.article/1- Get article with ID 1strapi://content-type/api::article.article?filters={"title":{"$contains":"hello"}}- Get filtered articles
The publish_entry and unpublish_entry tools provide control over the content lifecycle:
{
"contentType": "api::article.article",
"id": "1"
}These tools utilize the admin API paths for publishing/unpublishing actions, with a fallback to directly updating the publishedAt field if admin permissions are not available.
Strapi components can be managed with the following tools:
list_components: Get all available componentsget_component_schema: View a specific component's structurecreate_component: Create a new component with specified fieldsupdate_component: Modify an existing component
Example of creating a component:
{
"componentData": {
"displayName": "Security Settings",
"category": "security",
"icon": "shield",
"attributes": {
"enableTwoFactor": {
"type": "boolean",
"default": false
},
"passwordExpiration": {
"type": "integer",
"min": 0
}
}
}
}Install dependencies:
npm installBuild the server:
npm run buildFor development with auto-rebuild:
npm run watchFor detailed step-by-step instructions on how to deploy and test this MCP server, please see the DEPLOYMENT.md file.
Quick setup:
- Build the server:
npm run build - Configure your Strapi instance and get an API token
- Add the server config to Claude Desktop:
On MacOS: ~/Library/Application Support/Claude/claude_desktop_config.json
On Windows: %APPDATA%/Claude/claude_desktop_config.json
{
"mcpServers": {
"@wh1teee/strapi-mcp": {
"command": "npx",
"args": ["@wh1teee/@wh1teee/strapi-mcp"],
"env": {
"STRAPI_URL": "http://localhost:1337",
"STRAPI_API_TOKEN": "your_api_token_here"
}
}
}
}If you installed from source, use the direct path:
{
"mcpServers": {
"@wh1teee/strapi-mcp": {
"command": "/path/to/@wh1teee/strapi-mcp/build/index.js",
"env": {
"STRAPI_URL": "http://localhost:1337",
"STRAPI_API_TOKEN": "your_api_token_here"
}
}
}
}STRAPI_URL(optional): The URL of your Strapi instance (defaults to http://localhost:1337)STRAPI_API_TOKEN: Your Strapi API token (Required for authentication).STRAPI_DEV_MODE(optional): Set to "true" to enable development mode features (defaults to false)
The server uses API token-based authentication for secure access to your Strapi instance.
- Log in to your Strapi admin panel
- Go to Settings > API Tokens
- Click "Create new API Token"
- Set a name, description, and token type (preferably "Full access")
- Copy the generated token and use it in your MCP server configuration
Common Issues and Solutions:
[Error] STRAPI_API_TOKEN appears to be a placeholder value...
Solution: Replace "strapi_token" or "your-api-token-here" with a real API token from your Strapi admin panel.
Cannot connect to Strapi instance: Connection refused. Is Strapi running at http://localhost:1337?
Solution:
- Ensure Strapi is running:
npm run developoryarn develop - Check if the URL in
STRAPI_URLis correct - Verify your database (MySQL/PostgreSQL) is running
Cannot connect to Strapi instance: Authentication failed. Check your API token.
Solution:
- Verify your API token has proper permissions (preferably "Full access")
- Ensure the API token is not expired
This issue has been fixed in v0.1.8. If you still see these, you may be using an older version.
As of v0.1.8, the server now clearly distinguishes between:
- Empty collections (content type exists but has no entries) → Returns
{"data": [], "meta": {...}} - Actual errors (content type doesn't exist, auth failed, etc.) → Throws descriptive error with troubleshooting steps
Access forbidden. Your API token may lack necessary permissions.
Solution:
- Ensure your API token has "Full access" permissions
- If using API token, ensure it has "Full access" permissions
- Check that the content type allows public access if using limited API token
Since MCP servers communicate over stdio, debugging can be challenging. We recommend using the MCP Inspector, which is available as a package script:
npm run inspectorThe Inspector will provide a URL to access debugging tools in your browser.
Once the MCP server is configured and running, you can use it with Claude to interact with your Strapi CMS. Here are some examples:
use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "get_lightweight_entries",
arguments: {
"contentType": "api::articles.articles",
"options": JSON.stringify({
"filters": {"title": {"$containsi": "AI"}},
"pagination": {"pageSize": 10}
})
}
)use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "find_author_by_name",
arguments: {
"authorName": "Константин"
}
)use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "get_schema_fields",
arguments: {
"contentType": "api::articles.articles"
}
)use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "get_content_preview",
arguments: {
"contentType": "api::articles.articles",
"limit": 20,
"search": "neural network"
}
)use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "list_content_types",
arguments: {}
)
use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "get_entries",
arguments: {
"contentType": "api::article.article",
"filters": {
"title": {
"$contains": "hello"
}
},
"pagination": {
"page": 1,
"pageSize": 10
},
"sort": ["title:asc"]
}
)
use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "create_entry",
arguments: {
"contentType": "api::article.article",
"data": {
"title": "My New Article",
"content": "This is the content of my article.",
"publishedAt": "2023-01-01T00:00:00.000Z"
}
}
)
use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "upload_media",
arguments: {
"fileData": "base64-encoded-data-here",
"fileName": "image.jpg",
"fileType": "image/jpeg"
}
)
use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "connect_relation",
arguments: {
"contentType": "api::article.article",
"id": "1",
"relationField": "authors",
"relatedIds": [2, 3]
}
)
use_mcp_tool(
server_name: "@wh1teee/strapi-mcp",
tool_name: "disconnect_relation",
arguments: {
"contentType": "api::article.article",
"id": "1",
"relationField": "authors",
"relatedIds": [3]
}
)
use_mcp_tool(
server_name: "@wh1teee/strapi-mcp-local",
tool_name: "create_content_type",
arguments: {
"displayName": "My New Product",
"singularName": "product",
"pluralName": "products",
"kind": "collectionType",
"description": "Represents products in the store",
"draftAndPublish": true,
"attributes": {
"name": { "type": "string", "required": true },
"description": { "type": "text" },
"price": { "type": "decimal", "required": true },
"stock": { "type": "integer" }
}
}
)
use_mcp_tool(
server_name: "@wh1teee/strapi-mcp-local",
tool_name: "update_content_type",
arguments: {
"contentType": "api::speaker.speaker",
"attributes": {
"isHighlightSpeaker": {
"type": "boolean",
"default": false
},
"newTextField": {
"type": "string"
}
}
}
)