CommunityCoding & Developmentgithub.com

headless-cms-mcp-pipeline

Use when orchestrating Headless CMS content via MCP tools.

What is headless-cms-mcp-pipeline?

headless-cms-mcp-pipeline is a Claude Code agent skill that use when orchestrating Headless CMS content via MCP tools.

Works with✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/imadegunawinangun/skill-headless-cms-mcp-pipeline/tree/HEAD

Installed? Explore more Coding & Development skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Preview

From the skill README

headless-cms-mcp-pipeline preview

Documentation

Headless CMS MCP Content Pipeline

When to Use

  • Managing, authoring, or publishing blog posts and pages on Headless WordPress via Model Context Protocol (MCP).
  • Orchestrating autonomous AI article generation pipelines against a Next.js headless frontend.
  • Connecting external AI agents to Sayoti Suite MCP RPC (/wp-json/sayoti-mcp/v1/rpc).
  • Synchronizing editorial standards, The Borderline Matrix, clinical E-E-A-T rules, and brand visual guidelines between CMS and AI agent.
  • Configuring dynamic headless navigation menus, on-page focus keyword audits, and specialized page roles (Lead Magnets, Privacy Policy, Terms of Service).

Prerequisites & Zero-Secret Policy

⚠️ Strict Credential Protection (Zero Secret Leakage)

  • NEVER hardcode API keys, passwords, or bearer tokens inside SKILL.md or git-tracked files.
  • All credentials must strictly resolve from environment variables in $HERMES_HOME/.env or profile-specific .env files.
  • Credentials required by this pipeline:
    1. MCP_SAYOTI_CMS_KEY: The master secret key for WordPress MCP RPC authentication (headers: {'X-Sayoti-Key': '${MCP_SAYOTI_CMS_KEY}'}).
    2. HERMES_CUSTOM_9ROUTER_SAYOTI_MY_ID_API_KEY or NINEROUTER_API_KEY: The API key for 9Router multi-model gateway (image_generate and embeddings).
  • WordPress MCP Server Configuration (in config.yaml under mcp_servers):
    mcp_servers:
      sayoti-cms:
        url: "http://wordpress-sentra/wp-json/sayoti-mcp/v1/rpc"
        headers:
          X-Sayoti-Key: "${MCP_SAYOTI_CMS_KEY}"
        enabled: true
        timeout: 180
    
  • Vector Database Prerequisite:
    • In WordPress admin (sayoti_mcp_settings), embedding_status must be set to enabled with model local/nomic-embed-text to support rag_search and automatic post indexing.

Architectural Principles

  1. WordPress as a Pure Data Store (Zero Timeout):

    • WordPress must never execute long-running synchronous AI calls (LLM generation, diffusion models) during REST/MCP requests.
    • The AI agent (Hermes) acts as the execution engine: it performs research, drafts copy, generates visuals via 9Router, and embeds media before sending data to the CMS.
    • CMS operations (save_post, save_page) must execute purely as fast database transactions (< 1 second) and trigger Next.js On-Demand ISR revalidation.
  2. Strict Entity Separation via Upsert:

    • Always use dedicated upsert tools for distinct content entities: save_post for blog articles and save_page for static/landing pages.
    • Do not combine posts and pages into a single generic tool with conditional parameters; distinct schemas eliminate parameter leaks and LLM hallucinations.
    • Upsert logic: if an id or matching slug exists, perform an update; if not, create new content.
  3. Specialized Page Roles & Lead Magnet Classification:

    • Pages serve specific commercial or legal roles in the funnel: standard, lead_magnet, privacy_policy, terms_of_service, or disclaimer.
    • Never leave lead magnet pages ambiguous. Always classify page_role: 'lead_magnet' and state the exact asset type via lead_magnet_type (e.g., "Checklist Milestone Perkembangan 2–7 Tahun (PDF)").
    • The CMS exposes these via /wp-json/sayoti/v1/site-settings and registers post state badges ([🎁 LEAD MAGNET: ...], [🔒 PRIVACY POLICY], [📜 TERMS OF SERVICE]) in WordPress Admin so human editors immediately recognize page functions.
  4. Dynamic Headless Navigation Menus:

    • Menus must never be hardcoded in the frontend. WordPress is the single source of truth via /wp-json/sayoti/v1/menus?location=primary and footer.
    • Updating menus in WP Admin (Appearance -> Menus) fires an ISR revalidation webhook with tag menu and path /, instantly updating the Next.js header and footer without redeploying.
    • Always auto-seed default navigation menus on first run so the WP admin dashboard has a clean, ready-to-edit menu immediately.
  5. Single Source of Truth for Editorial & Visual Rules:

    • Editorial rules (content.md), E-E-A-T standards (sayoti-editorial.md), brand visual rules (sayoti-visual-branding.md), and On-Page SEO keyword rules reside in WordPress database options.
    • The agent fetches these rules dynamically via get_editorial_guidelines so outputs remain 100% aligned with in-dashboard generation.
  6. Decoupled 2-Plugin Architecture (Universal Content vs Headless Bridge):

    • Never couple AI, Topic Clusters, and MCP server to Headless redirect logic. A monolithic plugin breaks if a client already has an active WordPress theme (Astra, Elementor, Divi) and only wants the AI/SEO engine.
    • Separate into two clean, independent plugins:
      • sayoti-content-engine: Universal & theme-agnostic. Carries MariaDB 11.8 Vector RAG, Topic Clusters (Hub & Spoke), Link Explorer, Dead-link auto healing, In-Dashboard AI Writer, Lead Magnet CPT & CRM, and MCP Server (/wp-json/sayoti-mcp/v1/rpc). No redirects, no Next.js dependencies. Works on ANY existing WordPress installation.
      • sayoti-headless-bridge: Only installed when using a Headless Next.js frontend. Carries 301 template redirects (with configurable toggle), REST /site-settings and /menus, ISR revalidation webhooks, Page Controller (homepage & legal roles), and dynamic marketing tracking tags (GTM, Meta Pixel, TikTok, Ads) with Local SEO schema (Google Maps & business address).

Comprehensive 10-Step Article Generation Workflow

[User Topic Prompt]
        ↓ 1. Ingest Task
[WordPress MCP: get_topic_cluster & get_editorial_guidelines]
        ↓ 2. Pull Pillar Taxonomy & Editorial Guidelines
[Agent (Hermes): Focus Keyword & Angle]
        ↓ 3. Formulate Focus Keyword & Specific Angle
[WordPress MCP: rag_search]
        ↓ 4. Check Semantic Cannibalization (>80%) & Fetch Internal Link Candidates
[Web Research: Universal 4-Tier Citation Hierarchy]
        ↓ 5. Verify Facts & Ground Claims
[Agency Agents: content-creator]
        ↓ 6. Load Specialist Writing Persona
[Content Authoring: Gutenberg Native]
        ↓ 7. Draft 900-1500w Semantic HTML (Hook, H2s, Hub link, FAQ, CTA, Disclaimer)
[9Router image_generate + MCP upload_media]
        ↓ 8. Sideload Visual Assets with Adaptive Watermark (Zero-Timeout)
[WordPress MCP: save_post]
        ↓ 9. Instant Database Transaction + Auto Vector Index + Next.js ISR
[WordPress MCP: audit_post_seo]
        ↓ 10. Audit SEO Score (Target 80-100%) & Deliver Live Report
[Live on Vercel Next.js]

Step 1: Ingest Topic & Context

Receive the initial content request from the user or editorial calendar. Identify target audience pain points and commercial intent.

Step 2: Retrieve Guidelines & Taxonomies

Call sayoti-cms tools to establish structural boundaries:

  1. get_topic_cluster: Inspect available category pillars and retrieve the official Primary Hub (Post ID, Title, Slug) for the intended category.
  2. get_editorial_guidelines: Fetch active editorial length limits (900–1,500 words), mandatory opening anatomy, FAQ accordion rules, action framework, and official hex color palettes.

Step 3: Deep Focus Keyword Research & Angle Formulation

  • Search Intent & Keyword Research: Do NOT simply pick a random phrase without research. Actively research realistic search behavior and queries used by the target audience defined in the profile (informational questions, problems, or investigative comparisons via web search / keyword patterns).
  • Select Primary Focus Keyword: Based on the research findings, establish exactly 1 Primary Focus Keyword with clear long-tail search intent (e.g., "cara melatih anak speech delay 2 tahun mandiri" rather than broad, generic head terms).
  • Define Sharp & Unique Angle: Anchor the chosen keyword to a distinctive angle (e.g., specific age transition, realistic daily home routines, or tangible steps applicable in ≤24 hours).
  • Single-URL Mapping: Guarantee that this focus keyword is strictly dedicated to a single unique URL to prevent future keyword competition.

Step 4: Semantic RAG Verification & Cannibalization Check

Execute rag_search(query: "<focus_keyword> <angle>", limit: 5):

  1. Cannibalization Filter: If any published article exhibits >80% semantic similarity on the same angle, pivot the angle immediately (e.g. shift from general symptoms to home routines or specific milestone transitions).
  2. Horizontal Linking Discovery: Note relevant existing articles returned by the vector search to serve as contextual internal links.

Step 5: Multi-Tier Citation Research (Universal 4-Tier Hierarchy)

Ground all factual claims using the Universal Evidence Hierarchy:

  • Tier 1 (Primary Statutory & Scientific Authorities - Gold Standard): Official clinical associations (IDAI, Himpsi, PPHI, WHO, CDC, AAP), government health guidelines, and peer-reviewed journals. Wajib untuk angka milestone usia, definisi klinis, dan klaim medis.
  • Tier 2 (Reputable Secondary & Industry Research): Credible news agencies (Kompas, Antara, BBC) and institutional whitepapers for macro trends.
  • Tier 3 (Observational & Field Sentiment): Real audience/user struggles, practitioner field notes, and community discussions. Use to craft empathetic opening hooks. Always label as sentiment or practical field observation, never as normative statutory or clinical fact.
  • Tier 4 (Prohibited): Content farms, uncredited SEO blogs, and AI rehashes without primary links. Never cite.

Step 6: Load Specialist Persona

Invoke agency_agents_load(agent="content-creator") (or appropriate Agency specialist) and apply the communication tone dictated by the active profile's SOUL.md.

Step 7: Draft Full Semantic HTML (Gutenberg Native)

Compose 900–1,500 words of semantic HTML using native WordPress Gutenberg block comments (<!-- wp:paragraph -->, <!-- wp:heading -->, <!-- wp:separator -->, <!-- wp:list -->):

  1. Single H1: Handled by page template; start body directly with opening paragraphs.
  2. 3-Paragraph Opening Anatomy:
    • Paragraf 1 (The Hook): Real-life scenario validating audience struggles (derived from Tier 3 insights).
    • Paragraf 2 (Quick Answer): Natural, calming direct answer (no rigid "Quick Answer:" label).
    • Paragraf 3 (Transition): Warm invitation to explore solutions together.
  3. Elaboration per H2: 3 to 5 comprehensive paragraphs per heading, integrating practical home stimulation steps (≤24 hours).
  4. Internal Linking Integration:
    • Vertical (Mandatory): Natural contextual link back to the Primary Hub in the first 300–500 words: <a href="/posts/<hub-slug>" class="text-primary font-semibold underline hover:text-accent">...</a>.
    • Horizontal: Contextual link to related spoke articles discovered in Step 4.
  5. Callout Card Contrast Rule: Special notes must use <div class="my-8 rounded-2xl border-2 border-primary/25 bg-card p-6 sm:p-8 shadow-sm"> with titles in text-primary font-bold or text-foreground font-bold. Never use text-secondary on light cards.
  6. Closing Sequence:
    • <h2>Kesimpulan &amp; Langkah Pendampingan Terbaik</h2>: Wrap-up with 3 action links (/metode-belajar, /checklist-milestone, /kontak or direct WhatsApp).
    • <h2>Pertanyaan yang Sering Diajukan Orang Tua (FAQ)</h2>: Minimum 5 questions formatted as <details class="faq-accordion mb-4 rounded-xl border border-border p-4 bg-card transition-all"><summary class="cursor-pointer font-semibold text-foreground flex items-center justify-between"><span>...</span><span class="text-primary font-bold ml-2">+</span></summary><div class="mt-3 text-sm text-foreground/80 leading-relaxed border-t border-border pt-3">...</div></details>. Placed BEFORE disclaimer.
    • Mandatory Clinical Disclaimer: <div class="my-6 rounded-xl border border-border bg-muted/30 p-4 text-xs italic text-muted-foreground leading-relaxed">Catatan: Informasi dalam panduan ini bersifat edukatif untuk mendukung stimulasi mandiri di rumah dan tidak menggantikan asesmen langsung serta anjuran medis dari dokter spesialis anak atau terapis profesional.</div>
    • <h2>Referensi</h2>: <ol> list of verified sources with clickable full https:// URLs matching inline citations.
  7. 7 On-Page SEO Criteria: Focus keyword present in Title, Permalink Slug, first 100 words, at least one H2/H3, Excerpt, and density maintained at 0.5%–2.0%.

Step 8: Visual Generation & Media Sideloading (Zero Timeout)

  1. Generate image via image_generate (9Router) enforcing official brand hex colors and strict anti_text_rule (no text/numbers/watermarks on canvas).
  2. Upload image via MCP tool upload_media:
    • Pass image_url or image_base64.
    • Pass apply_watermark: true for the featured image (automatically stamps brand logo adaptively via PHP GD) and apply_watermark: false for H2 body illustrations.
    • Tool returns official id (attachment ID) and url on the CMS domain (https://cms...), 100% compliant with Next.js Vercel remotePatterns.
  3. Embed in-article images directly into <figure class="wp-block-image size-large"><img src="..." alt="..." /><figcaption>...</figcaption></figure> blocks.

Step 9: Instant Publish (save_post)

Call save_post with:

  • title, slug, content, category_id, focus_keyword, excerpt.
  • featured_media_id: Set to the attachment id returned from upload_media in Step 8.
  • generate_featured_image: false and generate_in_article_images: false (bypasses server-side synchronous image generation; executes as an instant DB write <1 second, completely eliminating timeout risks).
  • WordPress automatically:
    1. Saves the post and updates SEO meta fields.
    2. Triggers Next.js On-Demand ISR revalidation.
    3. Indexes article chunks into MariaDB vector embeddings table (wp_sayoti_vectors).

Step 10: SEO Audit & Final Reporting

  1. Call audit_post_seo(post_id: <id>) to confirm on-page score (target: 80–100%).
  2. Report live article URL, SEO audit score, and summary back to the user.

MCP Tools Reference (Sayoti Suite)

Tool NameCategoryPrimary Function
get_editorial_guidelinesKnowledge BaseRetrieves editorial rules, E-E-A-T standards, visual branding, and metaprompts.
save_postContent (Upsert)Upsert blog post. Manages HTML, focus_keyword, featured_media_id, taxonomies, and triggers ISR.
save_pageContent (Upsert)Upsert static or landing page. Supports is_homepage, page_role, and lead magnet metadata.
get_posts_and_pagesContentLists posts/pages with filters for type, status, and search keywords.
audit_post_seoSEO AuditEvaluates article against 7 on-page criteria with actionable recommendations.
delete_post_or_pageContentDeletes post or page (trash or permanent via force: true).
upload_mediaMedia UploadUploads image to WordPress Media Library. Handles adaptive GD watermark stamping (brand logo), sets SEO alt/title, and returns attachment ID and official CMS URL.
rag_searchVector RAGCosine similarity semantic search over MariaDB vector embeddings to check cannibalization and find internal links.
index_all_postsVector RAGRe-chunks and re-indexes published posts into MariaDB vector tables.
get_topic_clusterSEO ClusterInspects pillar structure (Primary HUBs and associated SPOKEs).
get_semantic_bridge_recommendationSEO ClusterRecommends H2 heading and bridge paragraph for internal backlinking.
apply_semantic_bridgeSEO ClusterInjects a semantic bridge paragraph under a chosen H2 and triggers Next.js ISR.
get_deleted_postsLink HealingRetrieves history of trashed or deleted posts.
heal_dead_linksLink HealingSweeps published articles and redirects dead links to active slugs.

Pitfalls & Lessons Learned

  • Zero Secret Leakage in Skills & Prompts: Never embed raw API keys, bearer tokens, or WordPress master secrets in SKILL.md or git commits. Always reference environment variable names (${MCP_SAYOTI_CMS_KEY}, ${NINEROUTER_API_KEY}).
  • Prevent Server-Side Image Generation Timeouts: Never set generate_in_article_images: true or generate_featured_image: true in save_post. Generating 4–5 images sequentially in WordPress PHP takes 75–125s and exceeds MCP client timeouts. Always generate images agent-side (image_generate), upload via upload_media, and pass featured_media_id directly.
  • RAG Query Conciseness: When calling rag_search, pass a concise query (Focus Keyword + Angle, ~15–30 words). Never send the entire 1,500-word draft, as embedding models truncate at 2,000 characters and dilute semantic matching.
  • Single Target Keyword per URL: Never reuse the same focus keyword across multiple articles to prevent search cannibalization. Hubs target broad terms; Spokes target long-tail terms.
  • Verbatim Substring Matching in SEO Audit: Audit tools check exact substrings in Title, Slug, and Intro. If an article uses stop words (e.g. "untuk"), omitting it in the target keyword string causes 0% title matching. Match the exact verbatim phrase when auditing or editing.
  • Strict Sequential Single-Article Generation (Anti-Batch Collapse): Never attempt to generate multiple comprehensive articles (e.g., 5 to 25 spoke articles) in a single turn, prompt, or batch Python script. Always produce articles sequentially, one by one.
  • Closing Section Ordering (Kesimpulan -> FAQ -> Disclaimer -> Referensi): Always place FAQ before the clinical disclaimer and references. Putting FAQ after references or skipping the conclusion breaks search intent and user journey flow.
  • Mandatory 3 Inbound Links in Kesimpulan: The conclusion must always provide actionable next steps linking to the 3 core destinations: /metode-belajar (framework), /checklist-milestone (lead magnet), and /kontak (booking assessment / WhatsApp).
  • Never Use text-secondary on Light Cards: Using text-secondary causes near-white text on white backgrounds (unreadable). Always use text-foreground font-bold or text-primary font-bold for card headings and text-foreground/90 font-medium for body text.
  • Dynamic Domain Resolution for MCP Links: Never hardcode the frontend domain (e.g. https://sayoti.com) in MCP tool outputs or database queries. Always read sayoti_frontend_domain dynamically via get_option('sayoti_frontend_domain', get_home_url()).

Related Skills