Skip to content

Architecture Overview

Technical documentation for developers working with or contributing to BlokMCP.

System Architecture

BlokMCP is a SaaS MCP server that bridges AI assistants (Claude, Cursor, etc.) with the Storyblok Management API through the Model Context Protocol.

High-Level Architecture

┌─────────────────┐
│  MCP Clients    │  (Claude Desktop, Cursor IDE)
│  (User's Device)│
└────────┬────────┘
         │ MCP Protocol (HTTPS)
         │ Headers: X-Api-Key, X-Storyblok-Space-Id
         ▼
┌─────────────────────────────────────────────┐
│       BlokMCP Server                        │
│       (Cloud-hosted SaaS)                   │
│  ┌────────────────────────────────────────┐ │
│  │  Authentication Middleware             │ │
│  │  - Validate API key                    │ │
│  │  - Load organization context           │ │
│  │  - Rate limiting                       │ │
│  │  - Usage tracking                      │ │
│  └────────────┬───────────────────────────┘ │
│               ▼                             │
│  ┌────────────────────────────────────────┐ │
│  │  Tool Router (130+ tools)              │ │
│  │  - Stories, Components, Assets         │ │
│  │  - Workflows, Approvals, Tasks         │ │
│  │  - Datasources, Tags, Webhooks         │ │
│  │  - And 20+ more modules                │ │
│  └────────────┬───────────────────────────┘ │
│               ▼                             │
│  ┌────────────────────────────────────────┐ │
│  │  Storyblok API Client                  │ │
│  │  - Resolve encrypted tokens            │ │
│  │  - Make authenticated requests         │ │
│  │  - Handle pagination & errors          │ │
│  └────────────┬───────────────────────────┘ │
└───────────────┼─────────────────────────────┘
                │ HTTPS (Management API)
                ▼
       ┌─────────────────┐
       │  Storyblok API  │
       └─────────────────┘

         ┌──────────────┐
         │   Database   │  (Relational DB with multi-tenant isolation)
         │  - Organizations
         │  - Users
         │  - Subscriptions
         │  - API Keys (hashed)
         │  - Storyblok Spaces (encrypted tokens)
         │  - Usage Records
         │  - Audit Logs
         └──────────────┘

Core Components

1. MCP Server

Location: src/

The MCP server runs as a cloud-hosted service at https://mcp.blokmcp.com.

Entry points:

  • src/worker.ts - Production SaaS entry
  • src/index.ts - CLI/stdio entry (development/testing only)

Key responsibilities:

  • Implement MCP protocol (list tools, call tools)
  • Authenticate requests via API keys
  • Route tool calls to appropriate handlers
  • Interface with Storyblok Management API
  • Track usage and enforce rate limits

Technology:

  • TypeScript with strict type checking
  • MCP protocol implementation
  • Runtime schema validation
  • Modern cloud-hosted serverless architecture

2. Authentication Middleware

Location: src/middleware/auth.ts

Handles multi-tenant authentication and authorization.

Flow:

  1. Extract API key from request header
  2. Validate key format and integrity
  3. Verify against secure storage
  4. Load organization context and permissions
  5. Resolve Storyblok space selection
  6. Decrypt Storyblok tokens from encrypted storage
  7. Return authentication context for request

Security features:

  • API keys are securely hashed using industry-standard algorithms
  • Storyblok tokens are encrypted at rest using authenticated encryption
  • Rate limiting per organization
  • Usage tracking per request

3. Tool Registration System

Location: src/tools/

Each module exports a register*Tools(server) function.

Pattern:

// src/tools/stories.ts
export function registerStoriesTools(server: McpServer) {
  server.addTool({
    name: "fetch_stories",
    description: "...",
    inputSchema: storiesInputSchema,
    handler: async (params) => {
      // Implementation
    }
  });

  server.addTool({
    name: "get_story",
    // ...
  });

  // 18 tools total
}

Aggregation:

// src/tools/index.ts
import { registerStoriesTools } from './stories.js';
import { registerComponentsTools } from './components.js';
// ... 30+ imports

export function registerAllTools(server: McpServer) {
  registerStoriesTools(server);
  registerComponentsTools(server);
  // ... 30+ registrations
}

Tool naming conventions:

  • fetch_* - List/search multiple items
  • get_* - Retrieve single item by ID
  • create_* - Create new item
  • update_* - Modify existing item
  • delete_* - Remove item
  • publish_* / unpublish_* - Publication operations

4. Storyblok API Client

Location: src/utils/api.ts

Wrapper around Storyblok Management API with common patterns.

Features:

  • Authenticated requests with management token
  • Error handling and retries
  • Pagination helpers
  • Response validation
  • Rate limit respect

Example:

async function fetchStories(
  token: string,
  spaceId: string,
  params: FetchStoriesParams
) {
  const url = `https://mapi.storyblok.com/v1/spaces/${spaceId}/stories`;
  const response = await fetch(url, {
    headers: {
      'Authorization': token,
      'Content-Type': 'application/json'
    },
    params: buildQueryParams(params)
  });

  return await response.json();
}

5. Database Layer

Location: database/migrations/

Relational database with row-level security for multi-tenant isolation.

Database Architecture:

Multi-tenant relational database. Key entities:

  • Organizations and user management
  • Subscription and billing tracking
  • API key registry
  • Storyblok workspace connections (encrypted tokens)
  • Usage and audit logging

Security Features:

  • Database-level security for tenant isolation
  • Encrypted credential storage using industry-standard authenticated encryption
  • API keys securely hashed (one-way, not reversible)
  • Audit logging for compliance

6. Dashboard

Location: dashboard/

User-facing dashboard for managing BlokMCP.

Pages:

  • / - Landing page
  • /dashboard - Overview
  • /dashboard/spaces - Storyblok space connections
  • /dashboard/api-keys - API key management
  • /dashboard/billing - Subscription management
  • /dashboard/usage - Usage analytics
  • /dashboard/settings - Account settings

Tech Stack:

  • Modern web framework with TypeScript
  • Managed authentication and database services
  • Third-party billing integration
  • Component library and CSS framework

See: dashboard/CLAUDE.md for detailed dashboard documentation.


Request Flow

Typical Tool Call Flow

1. User sends message in Claude Desktop
   "Show me my recent blog posts"

2. Claude determines which tool to use
   Tool: fetch_stories

3. Claude Desktop makes MCP request
   POST https://mcp.blokmcp.com
   Headers:
     X-Api-Key: sb_mcp_abc123...
     Content-Type: application/json
   Body: {
     "jsonrpc": "2.0",
     "method": "tools/call",
     "params": {
       "name": "fetch_stories",
       "arguments": {
         "starts_with": "blog/",
         "per_page": 10,
         "sort_by": "created_at:desc"
       }
     }
   }

4. BlokMCP Worker receives request
   - Parses MCP message
   - Extracts X-Api-Key header

5. Authentication Middleware
   - Hash API key
   - Query database for key validation
   - Load organization, subscription, usage
   - Resolve space (default or from X-Storyblok-Space-Id)
   - Decrypt Storyblok management token
   - Check rate limits
   - Create tenant context

6. Tool Router
   - Find "fetch_stories" handler
   - Validate input with Zod schema
   - Call handler with tenant context

7. Tool Handler (fetch_stories)
   - Build Storyblok API request
   - Call Storyblok Management API
     GET https://mapi.storyblok.com/v1/spaces/123456/stories
     ?starts_with=blog/&per_page=10&sort_by=created_at:desc
     Authorization: {decrypted_management_token}
   - Parse response
   - Format for MCP

8. Record Usage
   - Insert usage record to database
   - Increment monthly usage counter
   - Update key last_used timestamp

9. Return MCP Response
   {
     "jsonrpc": "2.0",
     "result": {
       "content": [
         {
           "type": "text",
           "text": "Found 10 blog posts:\n1. Post Title..."
         }
       ]
     }
   }

10. Claude Desktop receives response
    - Displays results to user
    - User can continue conversation

Security Model

Multi-Tenant Isolation

  • Each organization is isolated via database-level security
  • API keys scoped to single organization
  • No cross-organization data access

Token Encryption

Storyblok tokens:

  • Encrypted at rest with industry-standard authenticated encryption
  • ENCRYPTION_KEY stored as platform secret
  • Decrypted only when needed for API calls
  • Never exposed in responses or logs

API keys:

  • Securely hashed using industry-standard algorithms (one-way)
  • Original key shown only once at creation
  • Hashed value stored in database
  • Compared via hash during authentication

Rate Limiting

Per-minute limits:

  • Tracked using efficient in-memory mechanisms
  • Scoped by organization
  • Automatic reset and cleanup
  • Returns 429 if exceeded

Monthly limits:

  • Tracked in database
  • Aggregated by billing period
  • Checked on each request
  • Enforced based on subscription tier

Multi-Tenant Isolation

Row-level security policies ensure data isolation between organizations. Users can only access data within their organization context.


Development Setup

Prerequisites

  • Node.js 18+
  • npm or pnpm
  • Database service account
  • Cloud platform account

Local Development

# MCP Server
npm install
npm run dev              # Hot reload with tsx watch
npm run worker:dev       # Run serverless locally

# Dashboard
cd dashboard
pnpm install
pnpm dev                 # Dashboard dev server on :3000

Environment Variables

MCP Server:

  • Database connection credentials
  • Encryption keys for token storage
  • Environment and configuration settings
  • Rate limiting parameters

Dashboard:

  • Database connection credentials
  • Billing provider API credentials
  • Webhook secrets
  • Application URLs and endpoints
  • Shared encryption configuration

Deployment

MCP Server:

npm run worker:deploy

Dashboard:

cd dashboard
pnpm build
# Deploy to cloud hosting platform

See Local Development Guide for complete setup.


Adding New Tools

1. Create Tool Module

// src/tools/my-new-module.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';

const myToolInputSchema = z.object({
  param1: z.string(),
  param2: z.number().optional()
});

export function registerMyNewModuleTools(server: McpServer) {
  server.addTool({
    name: "my_new_tool",
    description: "Does something useful",
    inputSchema: myToolInputSchema,
    handler: async (params, context) => {
      // Validate input
      const input = myToolInputSchema.parse(params);

      // Get tenant context
      const { organization, space, token } = context;

      // Call Storyblok API
      const result = await fetch(
        `https://mapi.storyblok.com/v1/spaces/${space.space_id}/...`,
        {
          headers: { 'Authorization': token }
        }
      );

      // Return MCP-formatted response
      return {
        content: [{
          type: "text",
          text: JSON.stringify(result, null, 2)
        }]
      };
    }
  });
}

2. Register in Index

// src/tools/index.ts
import { registerMyNewModuleTools } from './my-new-module.js';

export function registerAllTools(server: McpServer) {
  // ... existing registrations
  registerMyNewModuleTools(server);
}

3. Add Types (optional)

// src/types/my-new-module.ts
export interface MyNewToolParams {
  param1: string;
  param2?: number;
}

4. Test

npm run dev
# Test via Claude Desktop or curl

Architecture Design Principles

Serverless & Edge Computing

  • Global distribution - Low latency worldwide
  • Auto-scaling - Handles traffic spikes automatically
  • Cost efficiency - Pay-per-use pricing model
  • Zero infrastructure - Fully managed platform

Database Strategy

  • Relational model - Structured data with ACID guarantees
  • Multi-tenant security - Database-level isolation
  • Managed service - High availability and backups
  • Real-time capabilities - Live data synchronization

Type Safety

  • Compile-time checks - Prevent runtime errors
  • Enhanced tooling - Better developer experience
  • Self-documenting - Types as documentation
  • Safe refactoring - Confident code changes

Input Validation

  • Runtime safety - Validate all external inputs
  • Type inference - Automatic type derivation
  • Clear feedback - Descriptive error messages
  • Composable schemas - Reusable validation logic

Performance Considerations

Platform Constraints

The serverless architecture provides fast response times while maintaining resource efficiency. Most operations complete in single-digit milliseconds.

Caching Strategy

  • Static data - Long-term caching for rarely-changing resources
  • Metadata - Short-term caching with TTL
  • Dynamic content - No caching for frequently updated data

Database Optimization

  • Strategic indexing on frequently queried columns
  • Query optimization for filtered and aggregated queries
  • Connection management through pooling
  • Read scaling for analytics and reporting

Monitoring & Observability

Metrics Tracked

  • Request count per organization
  • Response times (p50, p95, p99)
  • Error rates by tool
  • Rate limit hits
  • Monthly usage per tier

Logging

  • Application logs from serverless platform
  • Database audit trail
  • Error tracking and monitoring

Alerts

  • Rate limit exceeded
  • High error rates
  • Database connection issues
  • Payment failures


Questions about the architecture? Open an issue or check out the contributing guide.

BlokMCP logo
BlokMCP

Give your AI assistants safe, structured access to Storyblok so content teams can move faster.

Status

Operational insights

Monitor usage, limits, and connection health in your dashboard.

© 2026 BlokMCP. All rights reserved.

Built for teams who ship content with AI.