Agentic CMS
Planned integration with Directus, a SQL-based headless CMS, for content management operations.
Planned integration with Payload CMS, a TypeScript-native headless CMS, for content management operations.
Planned integration with Strapi, a popular open-source headless CMS, for content management operations.
Integration with Supabase for content management, using Supabase as the backend database. Provides tools for creating, reading, updating, and tracking content via the MCP server.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Agentic CMS list pending drafts"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Agentic CMS
Open-source MCP server that turns any CMS backend into an AI-agent-ready content management system.
What is this?
Agentic CMS is a Model Context Protocol (MCP) server that gives AI agents full access to your content management workflows — create, read, update, publish, and track content through a standardized protocol.
Instead of building AI features into your CMS, Agentic CMS wraps around it. Your CMS stays as-is. The agents get a clean interface to work with.
┌─────────────────┐ MCP Protocol ┌──────────────┐
│ AI Agents │ ◄──────────────────► │ Agentic CMS │
│ │ stdio / SSE │ MCP Server │
│ · Claude │ │ │
│ · OpenClaw │ │ Adapters: │
│ · Cursor │ │ · Supabase │
│ · Any MCP client│ │ · Payload │
└─────────────────┘ │ · Strapi │
│ · (yours) │
└───────┬───────┘
│
┌───────▼───────┐
│ Your CMS DB │
└───────────────┘Related MCP server: ledric
Why?
Your CMS, your data — Self-hosted, no vendor lock-in
Adapter pattern — Supabase today, Payload/Strapi/anything tomorrow
MCP standard — Works with Claude Desktop, OpenClaw, Cursor, and any MCP-compatible client
Safety first — Publishing requires human approval by default. Agents create drafts, humans publish.
Open source — MIT licensed. Use it, fork it, extend it.
Features
Tools (MCP)
Tool | Description |
| List content with filters (status, category, tags) |
| Get a single content item by slug or ID |
| Create new content (always starts as |
| Update content fields (title, body, tags, etc.) |
| List content ideas |
| Promote an idea to a draft content item |
| Record a publication event (channel, URL, metrics) |
| Get performance metrics for content |
Safety
create_contentalways sets status todraft— agents cannot publish directlyupdate_contentblocks status changes topublished— human approval requiredAll operations are logged and auditable
Quick Start
1. Install
npm install @brxce/agentic-cms2. Configure
Create .env:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key3. Run
npx agentic-cms4. Connect to Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"agentic-cms": {
"command": "npx",
"args": ["@brxce/agentic-cms"],
"env": {
"SUPABASE_URL": "https://your-project.supabase.co",
"SUPABASE_SERVICE_ROLE_KEY": "your-key"
}
}
}
}5. Connect to OpenClaw
# ~/.openclaw/config.yaml
mcp:
servers:
agentic-cms:
command: npx
args: ["@brxce/agentic-cms"]
env:
SUPABASE_URL: https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY: your-keyAdapters
Agentic CMS uses an adapter pattern to support different CMS backends.
Available
Supabase — For Supabase/PostgreSQL-based CMS setups
Planned
Payload CMS — TypeScript-native headless CMS
Strapi — Popular open-source headless CMS
Directus — SQL-based headless CMS
Custom — Implement the
CMSAdapterinterface for any backend
Writing Your Own Adapter
import { CMSAdapter } from '@brxce/agentic-cms';
export class MyAdapter implements CMSAdapter {
async listContents(filter?: ContentFilter): Promise<Content[]> {
// Your implementation
}
async getContent(idOrSlug: string): Promise<Content> {
// Your implementation
}
// ... other methods
}Architecture
src/
├── server.ts # MCP server entry point
├── tools/ # MCP tool definitions
│ ├── contents.ts # Content CRUD tools
│ ├── ideas.ts # Idea management tools
│ └── publications.ts # Publication tracking tools
├── adapters/
│ ├── interface.ts # CMSAdapter interface
│ ├── supabase.ts # Supabase adapter
│ └── (future adapters)
└── types.ts # Shared typesSupabase Schema
If you're starting fresh, here's the minimum schema:
-- Contents
create table contents (
id uuid primary key default gen_random_uuid(),
title text not null,
slug text unique not null,
status text default 'draft' check (status in ('draft', 'review', 'published')),
category text,
body_md text,
tags text[],
hook text,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
-- Ideas
create table ideas (
id uuid primary key default gen_random_uuid(),
raw_text text not null,
source text default 'manual',
promoted_to uuid references contents(id),
created_at timestamptz default now()
);
-- Publications
create table publications (
id uuid primary key default gen_random_uuid(),
content_id uuid references contents(id),
channel text not null,
url text,
published_at timestamptz default now(),
metrics jsonb default '{}'
);Multi-tenant deployment
agentic-cms 는 env 기반 multi-tenant 구조입니다. 같은 코드베이스로 여러 고객을 각자의 Supabase · Storage · 브랜딩으로 서비스할 수 있습니다.
시스템 prerequisites (모든 tenant 공통)
# macOS
brew install ffmpeg yt-dlp node pnpm python@3.12
# Ubuntu/Debian
sudo apt install ffmpeg python3.12 python3.12-venv
pip install yt-dlp
npm install -g pnpm
# Node.js 22+: https://nodejs.org/새 고객 onboarding 체크리스트
Supabase 프로젝트 생성 (고객 전용)
Free/Pro plan, project_ref 기록
supabase/migrations/*.sql전부 적용 (Studio SQL Editor, 파일명 오름차순 순서대로)자동 적용 항목:
14+ 테이블 생성 (contents/ideas/variants/blog_posts/carousels/video_projects 등)
5 storage bucket 생성 (content-media, studio-renders, references, finished, blog-images) — migration
20260419000000이 자동 처리RLS policies 공개 읽기 + service_role 관리
.env파일 3개 작성 (각 프로젝트 루트의.env.example기준)./.env— MCP 서버용./dashboard/.env.local— Next.js dashboard./editor/.env— Python 영상 편집 서버
Multi-tenant 핵심 env (반드시 고객별로 교체)
SUPABASE_URL/SUPABASE_SERVICE_ROLE_KEY(혹은SUPABASE_SERVICE_KEY)NEXT_PUBLIC_SITE_URL— 고객 웹사이트 URLNEXT_PUBLIC_BRAND_NAME— 뉴스레터 헤더 · meta title suffix 에 노출NEXT_PUBLIC_BRAND_HANDLE/NEXT_PUBLIC_BRAND_EMOJI/NEXT_PUBLIC_BRAND_AVATAR_URL— 캐러셀 워터마크/아바타NEXT_PUBLIC_CONTACT_EMAIL/NEXT_PUBLIC_CONTACT_DOMAIN— 캐러셀 CTA 슬라이드ANALYTICS_OWN_DOMAINS— self-referrer whitelist (쉼표 구분)ANALYTICS_VERCEL_KEYWORDS— vercel preview 도메인 자사 식별NEWSLETTER_FROM— 뉴스레터 발신인"Display Name <addr@domain>"META_TITLE_SUFFIX— blog post meta_title 꼬리TABLE_PROJECTS=video_projects(editor/.env, 필수)STORAGE_MODE=cloud(editor/.env, 권장)
외부 API Key (선택 기능)
RESEND_API_KEY— 뉴스레터 발송GOOGLE_SERVICE_ACCOUNT_KEY— GA4/GSC analyticsPOSTIZ_API_URL+POSTIZ_API_KEY— 소셜 채널 발행
로컬 개발 기동
# MCP 서버용 의존성 npm install && npm run build # dashboard 의존성 cd dashboard && npm install && cd .. # editor Python 가상환경 cd editor && python3 -m venv .venv && source .venv/bin/activate pip install -r requirements.txt && cd .. # editor Remotion 의존성 cd editor/remotion && pnpm install && cd ../.. # Next.js dashboard + Python editor 동시 기동 cd dashboard && npm run dev:allClaude Code 에서 MCP 서버 연결
.mcp.json을 repo 루트에 생성 (AGENTS.md예시 참고)Claude Code 재시작 → 43+ MCP 도구 자동 노출
고객 분리 원칙
DB 분리 — 고객마다 별도 Supabase 프로젝트 (데이터 완전 격리)
코드 공유 — 동일 git branch, env 주입만 다름
브랜딩 격리 — 위 env 교체만으로 로고·이메일·도메인 전부 고객 것으로 전환
배포 분리 — 고객마다 별도 Vercel/Cloud Run 배포 권장 (env 분리 확실)
코드에 하드코딩된 브랜딩 없음 원칙
신규 기능 추가 시 "AWC", "agenticworkflows.club", "특정 이메일" 등 구체 값을 직접 박지 말고 env 로 주입. 테넌트별 차이가 생길 여지는 전부 env 통로를 둔다.
Philosophy
"Nobody cares about your tech. They care that their problem got solved."
Agentic CMS isn't about adding AI to your CMS. It's about making your content workflow AI-native — so agents handle the repetitive work and humans focus on judgment and creativity.
Built by IntelliEffect as part of the Agentic Workflow Club.
Contributing
Contributions welcome! Please read CONTRIBUTING.md before submitting PRs.
License
Available Tools
52 toolsattach_gallery_mediaC
Attach an existing media row to a gallery item with role + sort_order. role defaults to gallery.
Inputs: item_id (required), media_id (required), role, sort_order.
create_blog_post_from_markdownA
Convert a Markdown body to PlateJS JSON and insert as a draft blog post. Status is ALWAYS "draft" — agents cannot publish directly; Studio review is required. Optionally links the post to an existing category by slug. Uses @awc/content-core CLI (convert-plate) for Markdown → PlateJS conversion.
Inputs: slug (required), title (required), markdown_body (required), excerpt, +8 more.
create_carouselA
Create a new carousel with the given slides. Each slide must include templateId, category, label, and content. Slide ids are auto-generated (e.g. "slide-abc123") — do not provide them. Typical structure: 1 cover slide + several body slides + 1 cta slide.
Inputs: title (required), slides (required), caption, variant_id.
create_contentA
[Pipeline step 3 — Create (master)] Create a new master content item directly (without an Idea). Prefer promote_idea when the content came from an idea (keeps provenance). Status is always "draft". Next step: create_variant (step 4).
Inputs: slug (required), title (required), cta, hook, +8 more.
create_gallery_itemB
Create a Gallery item with one or more kinds (kinds[0] is the primary). Default status=draft, visibility=public. Use set_gallery_featured afterwards to pin to the landing carousel.
Inputs: slug (required), kinds (required), title (required), tags, +11 more.
create_ideaA
[Pipeline step 2 — Discover] Register a new content idea under a Topic. Use this when the agent discovers a new angle from research, competitor scan, user feedback, etc. Link to a Topic (list_topics first) to keep the pipeline organized. Typical next step: promote_idea(id, title, slug) — turns this idea into a draft Content (step 3).
Inputs: raw_text (required), angle, source, topic_id, +1 more.
create_mediaC
Register a media item in the CMS.
Inputs: url (required), filename (required), width, height, +6 more.
create_publicationA
[Pipeline step 6 — Publish tracking] Record a publication event (where/when the content went out). Include variant_id so the Content detail view traces which variant was published on which channel. Final pipeline step — after this use get_metrics + get_activity_logs for feedback loop.
Inputs: channel (required), content_id (required), url, metrics, +2 more.
create_topicA
[Pipeline step 1 — Strategy] Create a new topic. Topics are long-lived (3~5 total, rarely changed). Only add when a genuinely new content theme emerges.
Inputs: name (required), intent, keywords, description.
create_variantA
[Pipeline step 4 — Adapt] Create a platform/format-specific variant of a master Content. Allowed platforms: instagram/linkedin/threads/tiktok/youtube/x (social) + blog/email/self (own channels). Allowed formats: reel/carousel/single_post/article/thread/story/short + blog/video. Use variant.id as the variant_id input for the next step — create_blog_post_from_markdown / create_carousel / send_newsletter / link_video_project_to_variant.
Inputs: format (required), platform (required), content_id (required), hashtags, +3 more.
create_video_projectC
Create or save a video project.
Inputs: name (required), clips, bgmClips, clipMeta, +1 more.
delete_gallery_itemA
Hard-delete a Gallery item. gallery_item_media rows cascade. Underlying media rows + storage files are NOT deleted (other items may reference them).
Inputs: id (required).
detach_gallery_mediaB
Remove a gallery_item_media link. Underlying media row is preserved.
Inputs: link_id (required).
extract_beatsB
Extract beats from a music file for syncing video cuts.
Inputs: source (required), mode, minGap.
get_activity_logsC
List activity logs with optional filters for collection, action, actor_type, and limit.
Inputs: limit, action, actor_type, collection.
get_blog_postB
Get a single blog post (including full PlateJS content) by ID or slug.
Inputs: id_or_slug (required).
get_carouselB
Get a single carousel by id (full slide data included).
Inputs: id (required).
get_contentA
[Pipeline step 3 — Create (master)] Get a single master content item by id or slug. Use before update_content or create_variant to read the current body/hook/cta.
Inputs: id_or_slug (required).
get_human_feedbackC
Get human-authored revision feedback for a content item.
Inputs: content_id (required).
get_ideaA
[Pipeline step 2 — Discover] Get a single idea by id. Useful when promote_idea or update_idea needs full context first.
Inputs: id (required).
get_metricsA
[Feedback loop] Get publication metrics for a content item — all publish events across channels. Use to learn which variants performed best before creating the next round of variants.
Inputs: content_id (required).
get_render_statusB
Check the current rendering status.
Inputs: no named parameters.
get_revisionsC
Get revision history for a content item.
Inputs: content_id (required).
get_video_projectC
Get details of a specific video project.
Inputs: id (required).
link_video_project_to_variantA
Link (or unlink) an existing video_project to a variant (1:1). video_projects is currently created via the brxce-editor API which does not accept variant_id, so this tool fills the FK after creation. Pass variant_id=null to explicitly unlink.
Inputs: variant_id (required), video_project_id (required).
list_blog_categoriesA
List all blog post categories (name, slug, description). Use to find the correct category slug before creating a post.
Inputs: no named parameters.
list_blog_postsA
List blog posts with optional filters. Returns summary fields (not full PlateJS content).
Inputs: limit, status, category_slug.
list_carouselsA
List carousels. Returns summary (id, title, caption, slide_count, timestamps). Use get_carousel for full slide data.
Inputs: limit, offset.
list_contentsB
[Pipeline step 3 — Create (master)] List master content items. Agents typically reach this after promote_idea (step 2→3). Use filters to find drafts pending derivation.
Inputs: tags, limit, offset, status, +1 more.
list_gallery_itemsA
List AWC Gallery items. Filter by status/kinds/featured/visibility. kinds is OR-match (any overlap). Ordered by featured first, featured_rank asc, then published_at desc.
Inputs: kinds, limit, offset, status, +2 more.
list_gallery_mediaB
List gallery_item_media rows for an item, ordered by sort_order asc.
Inputs: item_id (required).
list_ideasA
[Pipeline step 2 — Discover] List content ideas with optional filters. Use this first to see what ideas already exist before creating new ones. Filter by topic_id to narrow to a single theme, or promoted=false to see ideas not yet turned into Content. Typical next step: create_idea (register new angle) or promote_idea (turn existing idea into draft Content).
Inputs: limit, promoted, topic_id.
list_mediaC
List media items, ordered by most recent first.
Inputs: limit.
list_postiz_integrationsA
[Pipeline step 6 — Publish] List connected social integrations in Postiz (returns id + platform + display name per channel). Use this first to get the integration_id before calling send_to_postiz.
Inputs: no named parameters.
list_topicsA
[Pipeline step 1 — Strategy] List all topics (long-lived content themes). Start here: the agent picks which topic an idea belongs to. Typical next step: create_idea (step 2) under the chosen topic.
Inputs: no named parameters.
list_variantsA
[Pipeline step 4 — Adapt] List variants derived from a master Content. Check here before create_variant to avoid duplicates.
Inputs: content_id (required).
list_video_projectsC
List video projects from the editor.
Inputs: limit, offset.
list_videosB
List available video source files.
Inputs: no named parameters.
probe_mediaB
Get metadata (duration, resolution, codec, etc.) for a media file.
Inputs: filename (required).
promote_ideaA
[Pipeline step 2→3 — Discover → Create] Promote an idea to a draft Content item. Creates a new Content (always status=draft; agents cannot publish directly) and links the original idea via ideas.promoted_to. Typical next step: update_content (edit hook/body/cta) → create_variant (step 4, derive per-platform).
Inputs: slug (required), title (required), idea_id (required), cta, +7 more.
render_videoC
Start rendering a video project.
Inputs: project (required).
revert_to_revisionA
Revert a content item to a specific revision. Creates a new revision and logs the revert action.
Inputs: content_id (required), revision_id (required).
send_newsletterA
Send a blog post as a newsletter to subscribers via the dashboard send pipeline. Optionally records which variant (format=blog) this send was derived from, so the Content detail page shows the send count on the Variants & Derivatives card. Prerequisites: the dashboard app must be running (DASHBOARD_API_URL env var, default http://localhost:3000).
Inputs: post_id (required), force, preview, variant_id.
send_to_postizA
[Pipeline step 6 — Publish] Send a variant to Postiz for immediate or scheduled publication to the connected social channel. Typical flow: create_variant (step 4) → update_variant to fill body_text & hashtags → list_postiz_integrations → send_to_postiz. On success: variant.status becomes "sent_to_postiz", postiz_post_id is stored in platform_settings, and a publications row is automatically created. Use raw_payload to bypass the default DTO builder when a specific Postiz feature (media, thread, poll, etc.) is needed.
Inputs: variant_id (required), integration_id (required), force, channel, +3 more.
set_gallery_coverA
Set gallery_items.cover_media_id. Use attach_gallery_media separately if you also want a gallery_item_media row with role=cover.
Inputs: item_id (required), media_id (required).
set_gallery_featuredA
Pin/unpin a Gallery item to the landing featured carousel. Set is_featured and featured_rank (lower = earlier).
Inputs: id (required), is_featured (required), featured_rank.
update_blog_postA
Update fields on an existing blog post (title, excerpt, meta, thumbnail, or body). If markdown_body is provided, it will be converted to PlateJS and replace content. Status cannot be changed to "published" via this tool — use Studio for publishing.
Inputs: id (required), title, status, excerpt, +7 more.
update_carouselA
Update an existing carousel. Any of title, caption, or slides can be replaced. If slides are provided, they REPLACE the existing slides entirely (not merged). Each new slide gets a fresh auto-generated id unless one is explicitly passed.
Inputs: id (required), title, slides, caption, +1 more.
update_contentA
[Pipeline step 3 — Create (master)] Edit master content fields (hook/body/cta/core_message/tags). Use after promote_idea to fill in the draft body. Cannot set status=published (requires human). Next step: create_variant once body is solid.
Inputs: id (required), cta, hook, slug, +10 more.
update_gallery_itemB
Patch a Gallery item. Any subset of: title, subtitle, summary, kinds, status, visibility, cover_aspect, tags, author, duration_minutes, is_featured, featured_rank, cover_media_id. kinds[0] is treated as primary. published_at/featured_at are auto-set when status flips to published or is_featured flips to true.
Inputs: id (required), tags, kinds, title, +10 more.
update_ideaA
[Pipeline step 2 — Discover] Refine an idea (angle / target_audience / raw_text). Use this when the agent learns more context before promoting the idea to Content. Pass topic_id=null to explicitly un-link from a Topic.
Inputs: id (required), angle, source, raw_text, +2 more.
update_variantC
Update an existing variant.
Inputs: id (required), status, hashtags, body_text, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 52 tools
Most tools target a distinct resource+action, and pipeline-step labels in descriptions aid selection. However, the 'media' family (list_media, list_gallery_media, list_videos) and gallery cover tools (set_gallery_cover vs attach_gallery_media role=cover) have overlapping boundaries that require careful reading.
Every tool uses snake_case with a consistent verb_noun pattern (list_*, get_*, create_*, update_*, delete_*, send_*). A few longer names like create_blog_post_from_markdown and link_video_project_to_variant remain readable and follow the same convention.
52 tools is well beyond the 25-tool threshold for a heavy server and risks overwhelming an agent's selection space. Although the server spans many subdomains (blog, gallery, video, carousel, social publishing, pipeline), the surface is bloated and could be split or consolidated.
Core pipeline and CRUD flows are well covered: ideas (list/get/create/update/promote), gallery items (full CRUD), carousels, contents, variants, and publishing. Minor gaps exist, notably missing delete/update operations for blog posts, carousels, contents, variants, media, and video projects, though agents can generally work around these.
Maintenance
Related MCP Connectors
A blog CMS that AI agents write into over MCP: Markdown drafts, versions, media, human approval.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
MCP server for building and testing AI agents with multi-model experimentation and insights.
Blog MCP server for AI agents. One signup call returns a blog, an API key and a live URL; then your agent publishes markdown posts and gets public URLs back. Your agent does the writing; you get a dashboard for stats.
Related MCP Servers
AlicenseAqualityBmaintenanceAn MCP server that enables AI assistants to manage content, media, and schemas within Cosmic CMS buckets. It allows users to perform CRUD operations on objects and types while providing tools for AI-driven text, image, and video generation.19165 npm1MIT- AlicenseNot gradedqualityDmaintenanceA self-hosted content engine with an MCP interface that enables AI agents to read, write, and manage content models through tools like describe_model, create_type, draft, and publish.Apache 2.0
- AlicenseNot gradedqualityDmaintenanceMCP server for WordPress content management that provides a secure interface for AI assistants to interact with WordPress sites, enabling content creation, editing, and media management without destructive operations.MIT
- AlicenseNot gradedqualityBmaintenanceMCP server for content-studio, enabling AI agents to manage content ideas, channels, personas, and drafts with approval-based edits.2 npmAGPL 3.0