AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Modulacms

mcp-hegner123-modulacms · by hegner123

Headless CMS built in Go. Single binary, tri-database, developer-first. Built on three values: Performance, Flexibility, and Transparency.

No reviews yet
0 installs
12 views
0.0% view→install

Install

$ agentstack add mcp-hegner123-modulacms

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-hegner123-modulacms)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Modulacms? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Modula

[](https://github.com/hegner123/modulacms/actions/workflows/go.yml) [](https://github.com/hegner123/modulacms/actions/workflows/windows.yml)

A headless CMS written in Go, built on three core values: performance, flexibility, and transparency.

Requirements

| Requirement | Details | |-------------|---------| | Go | 1.24+ | | CGO | Must be enabled (CGO_ENABLED=1) | | C compiler | GCC or Clang (for the SQLite driver) | | OS | Linux or macOS | | Build runner | just |

CGO is required because the SQLite driver (mattn/go-sqlite3) is a C library. Even if you use MySQL or PostgreSQL, the binary still compiles with the SQLite driver.

Quick Start

1. Build and install

git clone https://github.com/hegner123/modulacms.git
cd modulacms
just build
cp out/bin/modula /usr/local/bin/modula

Verify: modula version

2. Create a project

mkdir ~/mysite && cd ~/mysite
modula init

modula init runs an interactive setup wizard that prompts for database driver, connection details, ports, and admin credentials. It creates modula.config.json, initializes the database schema, seeds three bootstrap roles (admin, editor, viewer) with 72 permissions, and registers the project in ~/.modula/configs.json.

For non-interactive setup with defaults:

modula init --yes --admin-password your-password

Defaults: SQLite database (modula.db in working directory), HTTP on :8080, HTTPS on :4000, SSH on :2233, development environment. The admin credentials are printed to the startup log.

3. Start the server

modula serve

Three servers start concurrently:

| Server | Default Address | Purpose | |--------|-----------------|---------| | HTTP | localhost:8080 | REST API + admin panel | | HTTPS | localhost:4000 | TLS-secured API (autocert in production) | | SSH | localhost:2233 | Terminal UI |

Graceful shutdown: first SIGINT/SIGTERM triggers a 30-second shutdown; second signal forces exit.

4. Connect

Web admin panel: http://localhost:8080/admin/

Log in with system@modulacms.local and the password from init.

Terminal UI: ssh localhost -p 2233

REST API:

curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "system@modulacms.local", "password": "YOUR_PASSWORD"}' \
  -c cookies.txt

curl http://localhost:8080/api/v1/datatype -b cookies.txt

Once registered, manage a project from any directory:

modula connect              # default project, default env
modula connect mysite       # specific project
modula connect mysite prod  # specific project + env

Build & Development

just dev              # Build local binary with version info via ldflags
just run              # Build and run
just build            # Production binary to out/bin/
just build-target darwin arm64  # Cross-compile for specific OS/arch
just build-all        # Build all release targets (darwin/linux, amd64/arm64)
just check            # Compile-check without producing artifacts
just clean            # Remove build artifacts
just vendor           # Update vendor directory

Testing

just test             # Run all tests (creates/cleans testdb/ and backups/)
just coverage         # Tests with coverage report
just lint             # Run all linters (Go, Dockerfile, YAML)

# Single package or test
go test -v ./internal/db
go test -v ./internal/db -run TestSpecificName

# S3 integration tests (requires MinIO)
just test-minio       # Start MinIO container
just test-integration # Run integration tests
just test-minio-down  # Stop MinIO

# Cross-backend DB integration tests
just docker-infra         # Start Postgres, MySQL, MinIO
just test-integration-db  # Run cross-backend tests

Docker

Unified via just dc :

# Backends: full, sqlite, mysql, postgres, prod
# Actions: up, down, reset, dev, fresh, logs, destroy (full only), minio-reset (postgres only)

just dc full up       # Full stack (CMS + all databases + MinIO)
just dc full down     # Stop containers, keep volumes
just dc full reset    # Stop containers and delete volumes
just dc full dev      # Rebuild and restart CMS container only
just dc full fresh    # Reset volumes then rebuild everything
just dc full logs     # Tail CMS logs
just dc full destroy  # Remove containers, volumes, and images

just dc sqlite up     # SQLite stack
just dc mysql up      # MySQL stack
just dc postgres up   # PostgreSQL stack

Other Docker commands:

just docker-infra     # Infrastructure only (Postgres, MySQL, MinIO)
just docker-build     # Build standalone CMS image (for CI)
just docker-release   # Tag and push image with version tags

The Docker image exposes ports 8080 (HTTP), 4000 (HTTPS), and 2233 (SSH), with volumes for /app/data, /app/certs, /app/.ssh, /app/backups, and /app/plugins.

Architecture

Runtime

The serve command starts three concurrent servers sharing a single DbDriver instance:

HTTP  (default :8080)  ─┐
HTTPS (default :8443)  ─┤── stdlib ServeMux (Go 1.22+) ── Middleware Chain ── Handlers ── DbDriver
SSH   (default :2222)  ─┘   Charmbracelet Wish ── Bubbletea TUI ─────────────────────────── DbDriver

Graceful shutdown: first SIGINT/SIGTERM triggers a 30-second shutdown; second signal forces exit. Shutdown order: HTTP servers, plugin system, database connections.

Request Flow

Client Request
  -> Request ID
  -> Logging
  -> CORS
  -> Authentication (cookie session or Bearer API key)
  -> Rate Limiting (auth endpoints: 10 req/min per IP)
  -> Permission Injection (RBAC)
  -> Route Handler
  -> DbDriver Interface
  -> Database-specific wrapper (SQLite / MySQL / PostgreSQL)
  -> sqlc-generated queries

Tri-Database Pattern

One codebase supports three databases through a layered abstraction:

  1. SQL schemas in sql/schema/ define tables and queries per dialect (SQLite, MySQL, PostgreSQL)
  2. sqlc generates type-safe Go code into internal/db-sqlite/, internal/db-mysql/, internal/db-psql/
  3. DbDriver interface (~150 methods in internal/db/db.go) provides the contract
  4. Wrapper structs (Database, MysqlDatabase, PsqlDatabase) implement the interface, converting between sqlc types and application types

Switch databases by setting db_driver in modula.config.json to "sqlite", "mysql", or "postgres".

Content Model

Content uses a tree structure with sibling pointers for O(1) navigation and reordering:

  • parent_id: parent node
  • first_child_id: leftmost child
  • next_sibling_id / prev_sibling_id: doubly-linked sibling list

Content items have a status lifecycle: draft -> pending -> published -> archived.

Data Model

27 schema directories define the full entity model:

| Entity Group | Tables | |-------------|--------| | Content | contentdata, contentfields, contentrelations, admin variants | | Schema | datatypes, fields, datatypefields, admin variants | | Media | media, mediadimensions | | Routing | routes, adminroutes | | Users & Auth | users, roles, permissions, rolepermissions, tokens, useroauth, sessions, usersshkeys | | i18n | locales | | Webhooks | webhooks, webhookdeliveries | | System | backups, changeevents, tables |

All entity IDs are 26-character ULIDs wrapped in distinct Go types (ContentID, UserID, FieldID, etc.) that provide compile-time type safety.

RBAC Authorization

Role-based access control with resource:operation granular permissions:

| Role | Permissions | Description | |------|-------------|-------------| | admin | 47 (all) | Bypasses all permission checks | | editor | 28 | CRUD on content, media, routes, datatypes, fields | | viewer | 3 | Read-only: content, media, routes |

The PermissionCache maintains an in-memory role-to-permissions map with lock-free reads and 60-second periodic refresh. System-protected roles and permissions cannot be deleted or renamed.

Audited Commands

All database mutations are wrapped in transactions that atomically record change_events rows capturing:

  • Operation type (INSERT, UPDATE, DELETE)
  • Old and new JSON values
  • User ID, request ID, IP address
  • Hybrid Logical Clock timestamps for distributed ordering

Admin Panel

Server-rendered HTMX + templ web interface. No SPA: all pages are server-rendered with HTMX for interactivity.

  • Content: tree navigation, block editor with drag-and-drop, inline field editing
  • Schema: datatypes, fields, and field-datatype associations
  • Media: upload, browse, image preview with dimension presets
  • Users & Roles: user management, role assignment, permission configuration
  • Routes: URL slug management
  • Plugins: browse, enable, disable, view details
  • Webhooks: create, test, view delivery history
  • Locales: i18n configuration and locale management
  • Settings: server configuration
  • Audit Log: change event browser
  • Import: bulk import from external CMS platforms
  • Sessions & Tokens: active session and API token management

Light DOM web components (mcms-*) provide dialog, data-table, field-renderer, media-picker, tree-nav, toast, confirm, and search widgets.

just admin generate      # Regenerate templ Go code
just admin watch         # Watch .templ files for changes
just admin bundle        # Bundle block editor JS via esbuild

API

All endpoints are prefixed with /api/v1/ and follow standard REST conventions. Content delivery uses slug-based routing at /api/v1/content/{slug}.

Authentication

POST   /api/v1/auth/login          # Session login
POST   /api/v1/auth/logout         # Session logout
GET    /api/v1/auth/me             # Current user profile
POST   /api/v1/auth/register       # Registration
POST   /api/v1/auth/reset          # Password reset
GET    /api/v1/auth/oauth/login    # OAuth flow initiation
GET    /api/v1/auth/oauth/callback # OAuth callback

Content Management

GET|POST          /api/v1/contentdata            # List / Create
GET|PUT|DELETE    /api/v1/contentdata/{id}        # Get / Update / Delete
POST              /api/v1/content/create          # Create content with fields (cascade)
POST              /api/v1/content/batch           # Batch operations
POST              /api/v1/contentdata/move        # Move node in tree
POST              /api/v1/contentdata/reorder     # Reorder siblings

GET|POST          /api/v1/contentfields           # Content field values
GET|POST          /api/v1/contentrelations        # Content relationships

Publishing & Versioning

POST              /api/v1/content/publish         # Publish content (creates snapshot)
POST              /api/v1/content/unpublish       # Unpublish content
POST              /api/v1/content/schedule        # Schedule future publish
GET               /api/v1/content/versions        # List versions
POST              /api/v1/content/versions        # Create manual version
DELETE            /api/v1/content/versions/{id}   # Delete version
POST              /api/v1/content/restore         # Restore from version

Admin content mirrors exist at /api/v1/admin/content/ for draft management.

Content Delivery

GET               /api/v1/content/{slug}          # Published content by slug
GET               /api/v1/content/{slug}?preview=true  # Live draft (requires auth)
GET               /api/v1/content/{slug}?locale=en     # Locale-specific delivery
GET               /api/v1/content/{slug}?format=clean  # Format override
GET               /api/v1/globals                 # All global content trees
GET               /api/v1/query/{datatype}        # Query by datatype

The format query parameter controls response structure: contentful, sanity, strapi, wordpress, clean, or raw.

Schema

GET|POST          /api/v1/datatype               # Datatypes
GET|POST          /api/v1/fields                 # Field definitions
GET|POST          /api/v1/datatypefields         # Datatype-field associations
GET|POST          /api/v1/tables                 # Custom tables

Media

GET               /api/v1/media                  # List (paginated)
POST              /api/v1/media                  # Upload (multipart/form-data)
DELETE            /api/v1/media/{id}             # Delete
GET               /api/v1/media/health           # S3 connectivity check
DELETE            /api/v1/media/cleanup          # Remove orphaned S3 objects
GET|POST          /api/v1/mediadimensions        # Dimension presets

Routes & Locales

GET|POST          /api/v1/routes                 # Route management
GET               /api/v1/locales                # Public locale list
CRUD              /api/v1/admin/locales          # Admin locale management

Users & Access Control

GET|POST          /api/v1/users                  # User management
POST              /api/v1/users/reassign-delete  # Reassign content and delete user
GET|POST          /api/v1/roles                  # Roles
GET|POST          /api/v1/permissions            # Permissions
GET|POST          /api/v1/role-permissions       # Role-permission mappings
GET|POST|DELETE   /api/v1/ssh-keys               # SSH key management
GET|POST|DELETE   /api/v1/sessions               # Session management
GET|POST|DELETE   /api/v1/tokens                 # API token management

Webhooks

CRUD              /api/v1/admin/webhooks         # Webhook management
POST              /api/v1/admin/webhooks/{id}/test       # Test delivery
GET               /api/v1/admin/webhooks/{id}/deliveries # Delivery history
POST              /api/v1/admin/webhooks/deliveries/{id}/retry # Retry delivery

Import & Configuration

POST   /api/v1/import/contentful   # Import from Contentful
POST   /api/v1/import/sanity       # Import from Sanity
POST   /api/v1/import/strapi       # Import from Strapi
POST   /api/v1/import/wordpress    # Import from WordPress
POST   /api/v1/import/clean        # Import Modula format
POST   /api/v1/import              # Bulk import

GET               /api/v1/admin/config           # Get config (redacted)
PATCH             /api/v1/admin/config           # Update config
GET               /api/v1/admin/config/meta      # Config field metadata
GET               /api/v1/admin/plugins          # List plugins
GET               /api/v1/admin/plugins/routes   # Plugin route approval

Terminal UI

The SSH-accessible TUI is built with Charmbracelet Bubbletea following the Elm Architecture (Model-Update-View). Each screen implements a Screen interface with its own state, update, and view methods.

  • Content: browse, create, edit content with tree navigation (regular and admin views)
  • Datatypes & Fields: define and manage content schemas
  • Media: upload and manage media assets with file picker
  • Users: user management with role assignment
  • Routes: URL slug configuration
  • Plugins: browse, enable, disable, reload Lua plugins
  • Webhooks: webhook management and delivery monitoring
  • Pipelines: pipeline entry management
  • Deploy: content sync between environments
  • Configuration: edit server configuration
  • Database: database info and table browser
  • Quick Start: guided setup wizard

UI features: responsive panel layouts with three screen modes (normal/wide/full), accordion focus, panel tabs, scroll indicators, adaptive statusbar, compact/full header with breadcrumbs.

Connect System

The connect command provides a project registry for managing multiple CMS instances and environments from a single CLI. Each project can have multiple environments (local, dev, staging, prod), each pointing to a different modula.config.json. The registry lives at ~/.modula/configs.json.

###

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.