Storyblok MCP
# Storyblok MCP
MCP server for [Storyblok](https://www.storyblok.com): fetch stories, manage tags, and use AI (Cursor, Claude Desktop) to work with your content. You only need to set 2–3 env variables.
## What you need
- **Node.js** 18+ — [nodejs.org](https://nodejs.org) (LTS)
- **Storyblok Space ID** — Space settings or from the app URL: `app.storyblok.com/#/me/spaces/<ID>/`
- **Management API token** — Storyblok → Settings → Access tokens → Create (full access or at least Stories + Tags)
## Quick start
### 1. The Universal Way (Best for non-technical users)
Deploy this server to Vercel. Once live, anyone can connect to their own Storyblok space using just the URL and token.
```json
"storyblok": {
"url": "https://your-server.vercel.app/sse",
"headers": {
"Authorization": "Bearer YOUR_TOKEN",
"x-space-id": "YOUR_SPACE_ID"
}
}
```
#### Advanced Cloud Options (SSE)
You can further customize the connection using headers or URL parameters:
- **Specific Space ID**: Use the URL `.../sse/12345` or set the `x-space-id` header.
- **Custom API Proxy**: Set the `x-api-base` header to point to your own Storyblok MAPI proxy.
- **Private Access Key**: If the server has an `MCP_API_KEY` set, provide it via the `x-mcp-key` header.
**Example with all options:**
```json
"headers": {
"Authorization": "Bearer YOUR_TOKEN",
"x-space-id": "12345",
"x-api-base": "https://your-proxy.com/v1",
"x-mcp-key": "your-secret-server-key"
}
```
### 2. Local Development
```bash
cp env.example .env
npm install
npm run build
node start-with-env.js
```
Edit `.env` and set at least:
```
STORYBLOK_SPACE_ID=12345
STORYBLOK_MANAGEMENT_TOKEN=your-management-token-here
```
### 3. Running with Docker
You can also run the server using Docker. This is great for consistent deployments.
```bash
docker build -t storyblok-mcp .
docker run -p 3000:3000 \
-e STORYBLOK_SPACE_ID=your_id \
-e STORYBLOK_MANAGEMENT_TOKEN=your_token \
storyblok-mcp
```
The Docker image defaults to **SSE mode** on port 3000.
#### Deploying to Kubernetes
1. **Push to Registry**:
```bash
docker tag storyblok-mcp your-registry/storyblok-mcp:latest
docker push your-registry/storyblok-mcp:latest
```
2. **Apply Manifests**:
Use the provided [k8s-deployment.yaml](./k8s-deployment.yaml) as a template. It sets up a Deployment, a Service, and an **Ingress** for custom domain support (HTTPS).
3. **External URL**:
Once deployed, you can point your domain (e.g., `mcp.yourdomain.com`) to your Ingress controller's IP.
### 4. Connect to Cursor or Claude Desktop
**Cursor** — edit MCP config (e.g. `~/Library/Application Support/Cursor/User/globalStorage/cursor.mcp/mcp.json` or Settings → MCP):
```json
{
"mcpServers": {
"storyblok": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/storyblok-mcp/start-with-env.js"]
}
}
}
```
**Claude Desktop** — `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
```json
{
"mcpServers": {
"storyblok": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/storyblok-mcp/start-with-env.js"]
}
}
}
```
Replace the path with your actual `storyblok-mcp` folder path. Restart Cursor or Claude.
`start-with-env.js` loads `.env` from the project folder, so you don’t need to put secrets in the MCP config.
---
## Env variables
| Variable | Required | Description |
|----------|----------|-------------|
| `STORYBLOK_SPACE_ID` | ✅ | Your Storyblok space ID |
| `STORYBLOK_MANAGEMENT_TOKEN` | ✅ | Management API token |
| `STORYBLOK_REGION` | ❌ | `eu` (default), `us`, `ca`, `ap`, `cn` — use if your Space is not in EU |
| `STORYBLOK_API_BASE` | ❌ | Override API base (if proxying) |
### Region (EU, US, etc.)
If your Storyblok Space is in the US or another region, set:
```
STORYBLOK_REGION=us
```
Options: `eu`, `us`, `ca`, `ap`, `cn`. Default: `eu`.
### Custom API URL
Only if you proxy the Storyblok Management API through your own domain:
```
STORYBLOK_API_BASE=https://your-proxy.com/path
```
#### SSE Custom Proxy
In SSE mode, you can also specify the proxy per-connection:
```json
"headers": {
"x-api-base": "https://your-proxy.com/v1"
}
```
The proxy must forward to the real Storyblok MAPI. Otherwise leave this unset.
---
## Tools
Full-featured TypeScript implementation for the Storyblok Management API.
| Category | Tools |
|----------|-------|
| **Stories** | `fetch_stories`, `get_story`, `create_story`, `update_story`, `delete_story`, `publish_story`, `unpublish_story`, `get_story_versions` |
| **Tags** | `fetch_tags`, `create_tag`, `create_tag_and_add_to_story`, `add_existing_tag_to_story`, `update_tag`, `delete_tag` |
| **Components** | `fetch_components`, `get_component`, `create_component`, `update_component`, `delete_component` |
| **Assets** | `fetch_assets`, `get_asset`, `update_asset`, `delete_asset` |
| **Releases** | `fetch_releases`, `get_release`, `create_release`, `update_release`, `delete_release` |
| **Workflows** | `fetch_workflows`, `get_workflow`, `create_workflow`, `update_workflow`, `delete_workflow`, `fetch_workflow_stages` |
| **Webhooks** | `fetch_webhooks`, `get_webhook`, `create_webhook`, `update_webhook`, `delete_webhook` |
| **Datasources** | `fetch_datasources`, `get_datasource`, `create_datasource`, `update_datasource`, `delete_datasource`, `fetch_datasource_entries`, `create_datasource_entry`, `update_datasource_entry`, `delete_datasource_entry` |
| **Space** | `get_space`, `update_space` |
| **Meta** | `list_tools` — list all tools by category |
| **Ping** | `ping` — health check (optional `check_api=1` to test API) |
---
## Example prompts
- “Fetch my Storyblok stories”
- “List all tags in my space”
- “Suggest a tag for each of my blog posts and add them”
- “Add the tag ‘product-launch’ to story ID …”
---
## Troubleshooting
- **“Missing env”** — `.env` must be next to `start-with-env.js` and contain `STORYBLOK_SPACE_ID` and `STORYBLOK_MANAGEMENT_TOKEN`.
- **401 from Storyblok** — Token invalid or expired; create a new Management token with Stories + Tags.
- **MCP not listed** — Use the **absolute** path to `start-with-env.js` and restart Cursor/Claude.
- **“Cannot find module”** — Run `npm install` and `npm run build` in your `storyblok-mcp` folder.
---
## Reference
- [Bring your Storyblok data into Claude by coding an MCP server](https://www.storyblok.com/tp/bring-your-storyblok-data-into-claude-by-coding-an-mcp-server)
TDQS
Scored across 74 tools
Most tools are clearly distinct by resource and action, but there is some overlap: 'create_tag_and_add_to_story' duplicates functionality of 'create_tag' and 'add_existing_tag_to_story', and 'list_tools' is a meta-tool that doesn't fit the domain. Overall, the majority are well-differentiated, with only minor confusion points.
Tool names follow a highly consistent verb_noun pattern throughout, with clear conventions: fetch_ for listing, get_ for retrieving single items, create_/update_/delete_ for CRUD operations, and specific action verbs like publish_ or translate_. No mixing of styles or deviations observed.
With 74 tools, the count is excessive for a content management server, making it overwhelming and likely to cause selection paralysis. A more focused set of 15-30 tools would better serve the domain without sacrificing functionality, as many operations could be consolidated or generalized.
The tool surface provides comprehensive CRUD/lifecycle coverage across all key resources (stories, assets, components, datasources, releases, tags, tasks, webhooks, workflows), including bulk operations, versioning, translations, and administrative actions. No obvious gaps are present for the Storyblok CMS domain.