MultiDomainCMS provides a production Model Context Protocol (MCP) server over HTTP Server-Sent Events (SSE) alongside a direct REST publishing API on https://winwinhost.com. Web agents authenticate using dedicated Bearer API keys generated in the backoffice (/admin/api-keys), and every article creation or update is automatically attributed to the resolved author identity across MongoDB, on-disk JSON shards, and the immutable revision audit trail.
https://winwinhost.com/api/mcp/sse (MCP SSE transport) or https://winwinhost.com/api/cms/posts/upsert (REST API) with header Authorization: Bearer <YOUR_API_KEY>. Verify token identity at any time via GET https://winwinhost.com/api/cms/auth/whoami.
1. Production Endpoints & Transport Overview
Autonomous agents can interact with MultiDomainCMS through two first-class interfaces that share the same API key registry and author attribution engine:
- Model Context Protocol (HTTP + SSE Transport, Spec
2024-11-05): Exposes 14 structured JSON-RPC 2.0 tools for listing domains, inspecting posts, upserting articles with full revision history, comparing revision diffs, managing categories, reading lead submissions, and flushing Nginx + in-memory caches. - Direct REST Content API: Provides stateless HTTP JSON endpoints for single-post upserts, batch seeding, post retrieval, and token identity introspection without maintaining a persistent SSE stream.
| Endpoint URL | HTTP Method | Authentication | Purpose |
|---|---|---|---|
https://winwinhost.com/api/mcp/health |
GET |
Public (No Auth) | Returns MCP service status, version, active SSE session count, and protocol metadata. |
https://winwinhost.com/api/mcp/sse |
GET |
Authorization: Bearer <API_KEY> or x-api-key |
Opens persistent Server-Sent Events stream and emits event: endpoint with sessionId. |
https://winwinhost.com/api/mcp/messages?sessionId=<ID> |
POST |
Authorization: Bearer <API_KEY> or x-api-key |
Dispatches JSON-RPC 2.0 requests (initialize, tools/list, tools/call) to the active session. |
https://winwinhost.com/api/cms/auth/whoami |
GET / POST |
Authorization: Bearer <API_KEY> or x-api-key |
Resolves the API key and returns the bound author profile (_id, username, displayName, role, domain). |
https://winwinhost.com/api/cms/posts/upsert |
POST |
Authorization: Bearer <API_KEY> or x-api-key |
Creates or updates a single article or page with automatic author attribution and revision snapshots. |
https://winwinhost.com/api/cms/posts/seed |
POST |
Authorization: Bearer <API_KEY> or x-api-key |
Batch upserts an array of posts for a target domain with token-enforced author attribution. |
https://winwinhost.com/api/cms/posts/:domain/:slug |
GET |
Optional / Public Read | Fetches the live JSON representation of a post by domain and slug. |
2. Backoffice API Key Management & Author Attribution Architecture
Every API key in MultiDomainCMS is cryptographically bound to a specific author identity rather than acting as an anonymous shared secret. Administrators manage keys inside the backoffice at /admin/api-keys (or via the JSON administrative endpoints under /admin/api/keys).
2.1 Generating, Editing, Rotating & Revoking Keys
When an administrator generates a key in /admin/api-keys, the platform provisions a prefixed token (mdcms_live_<48-hex-chars>) and synchronizes the author record across three layers simultaneously:
- Primary MongoDB Collection (
multiDomainCMS.users): Used by both the Express backoffice and thecms-mcp-serverdaemon for real-time Bearer token authentication andlastUsedAttelemetry. - On-Disk Author Registry (
data/users.json): Used by the Originality Gate (Layer 1 Identity Verification) to confirm that every article write maps to an active, registered author account. - Identity Microservice (
users_backendon port3030): Synchronized viaPOST /users/upsert-agentand queried viaPOST /users/resolve-keyso external services share a unified author directory.
| Backoffice Action | Endpoint | Behavior |
|---|---|---|
| Generate API Key | POST /admin/api-keys/create |
Creates a new author/agent identity (username, displayName, email, role, domain) and issues a fresh mdcms_live_... API key. |
| Edit Author / Key | POST /admin/api-keys/update/:id |
Updates the author display name, username, email, role, domain scope, active status, or custom key value. |
| Rotate API Key | POST /admin/api-keys/rotate/:id |
Mints a replacement mdcms_live_... key immediately invalidating the previous secret while preserving author history. |
| Revoke or Delete | POST /admin/api-keys/delete/:id |
Supports mode=revoke (clears API key and marks isActive: false while preserving past article attribution) or mode=delete (removes the record). |
2.2 Token-Enforced Article Attribution & Anti-Spoofing
When a web agent authenticates with an API key, MultiDomainCMS resolves the token owner and enforces strict attribution invariants on every write operation:
- Automatic Metadata Stamping: The server populates
post_author(the author_id),author_username(e.g.,agent-researcher), andauthor_name(the human-readabledisplayName) directly from the resolved API key record. - Immutable Revision Audit Trail: Every update prepends a timestamped entry to
post.revisions[]withauthor: "<username> (via API key)"orauthor: "<username> (via MCP)"and archives the previous article snapshot into SQLite (data/revisions.db) and MongoDB. - Anti-Spoofing Enforcement (HTTP 403): If an agent passes an explicit
authororauthor_usernameparameter in the request body that does not match the identity bound to its API key, the server immediately rejects the write with403 Forbidden (Identity Spoofing Rejected).
2.3 Verifying Your API Key Identity (/api/cms/auth/whoami)
Before publishing content, a web agent can verify its token and inspect the exact author fields that will be stamped onto articles:
curl -s https://winwinhost.com/api/cms/auth/whoami \
-H "Authorization: Bearer mdcms_live_YOUR_API_KEY"
Example JSON response:
{
"ok": true,
"authenticated": true,
"attributed_to": {
"_id": "6a5b37000000000000000010",
"username": "agent-main",
"displayName": "Primary Orchestrator Agent",
"email": "agent-main@winwinhost.com",
"role": "agent-main",
"domain": "all"
}
}
3. Step-by-Step MCP HTTP+SSE Handshake Protocol
The MultiDomainCMS MCP server implements the official Model Context Protocol 2024-11-05 HTTP with SSE specification. Because HTTP+SSE uses a dual-channel architecture, agents must keep the GET /api/mcp/sse stream open while sending JSON-RPC 2.0 messages via POST /api/mcp/messages?sessionId=<SESSION_ID>.
Step 1: Open the Authenticated SSE Connection
Connect to https://winwinhost.com/api/mcp/sse with Accept: text/event-stream and your API key in the Authorization: Bearer <API_KEY> header (or x-api-key: <API_KEY>):
curl -i -N https://winwinhost.com/api/mcp/sse \
-H "Authorization: Bearer mdcms_live_YOUR_API_KEY" \
-H "Accept: text/event-stream"
The server validates the API key against multiDomainCMS.users, binds the resolved author identity to the session, and emits the session message endpoint:
HTTP/2 200
content-type: text/event-stream
cache-control: no-cache, no-transform
event: endpoint
data: /api/mcp/messages?sessionId=89397c52-ec33-4a9e-b174-96f2d8bf052b
Step 2: Send the initialize Request
Extract the sessionId from the data: line and send a JSON-RPC 2.0 initialize request to https://winwinhost.com/api/mcp/messages?sessionId=<SESSION_ID>:
curl -i -X POST "https://winwinhost.com/api/mcp/messages?sessionId=89397c52-ec33-4a9e-b174-96f2d8bf052b" \
-H "Authorization: Bearer mdcms_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "web-agent-client",
"version": "1.0.0"
}
}
}'
The POST request returns HTTP 202 Accepted, and the JSON-RPC response arrives on the open SSE stream:
event: message
data: {"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"multidomain-cms-mcp","version":"1.0.0"}},"jsonrpc":"2.0","id":1}
Step 3: Send the notifications/initialized Notification
Complete the MCP handshake by posting the notifications/initialized notification:
curl -i -X POST "https://winwinhost.com/api/mcp/messages?sessionId=89397c52-ec33-4a9e-b174-96f2d8bf052b" \
-H "Authorization: Bearer mdcms_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}'
Step 4: List Tools (tools/list) & Execute Tools (tools/call)
Once initialized, query the tool catalog or invoke any tool by name:
curl -i -X POST "https://winwinhost.com/api/mcp/messages?sessionId=89397c52-ec33-4a9e-b174-96f2d8bf052b" \
-H "Authorization: Bearer mdcms_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "cms_get_post",
"arguments": {
"domain": "winwinhost.com",
"slug": "mcp-documentation"
}
}
}'
4. Complete MCP Tool Catalog (14 Tools)
All 14 tools below are available over tools/call once the SSE session is initialized.
4.1 Content & Revision Tools (8 Tools)
| Tool Name | Required Arguments | Optional Arguments | Description |
|---|---|---|---|
cms_list_domains |
None | None | Lists all tenant domains with post counts across MongoDB and JSON shards. |
cms_list_posts |
domain (string) |
status, type, search, limit |
Returns summaries of posts/pages for a domain (slug, title, status, modified date, revision count). |
cms_get_post |
domain (string), slug (string) |
None | Retrieves the complete post document including post_content HTML, SEO metadata, and revision count. |
cms_upsert_post |
domain (string), slug (string), post_title (string), post_content (string) |
post_excerpt, meta_title, meta_description, keywords, focus_keyphrase, post_status, post_type, og_image, featured_image, post_category, revision_note |
Validates content through the 6-Layer Originality Gate, stamps author attribution from the session API key, archives the prior state into revisions[], and dual-writes to MongoDB + disk shards. |
cms_delete_post |
domain (string), slug (string) |
hard_delete (boolean, default false) |
Soft-trashes a post (post_status: "trash") by default, or permanently deletes when hard_delete: true. |
cms_list_revisions |
domain (string), slug (string) |
None | Lists all historical revision snapshots for a post with revision_id, timestamp, author, and note. |
cms_get_revision |
domain (string), slug (string), revision_id (string) |
None | Retrieves the full historical HTML and metadata snapshot for a specific revision_id. |
cms_diff_revisions |
domain (string), slug (string), from_revision_id (string) |
to_revision_id (defaults to "LIVE") |
Generates a unified line-by-line diff comparing two revisions or comparing a revision against the live post. |
4.2 Backoffice, Taxonomy, Leads & Cache Tools (6 Tools)
| Tool Name | Required Arguments | Optional Arguments | Description |
|---|---|---|---|
cms_list_categories |
domain (string) |
None | Lists all configured content categories for the specified domain. |
cms_create_category |
domain (string), name (string) |
slug (string), description (string) |
Creates or upserts a category for a domain. |
cms_get_domain_settings |
domain (string) |
None | Reads the domain configuration document from the settings collection. |
cms_update_domain_settings |
domain (string), settings (object) |
None | Updates allowed configuration keys (title, description, keywords, theme, customCss, analyticsId, adsenseId, socialLinks, contactEmail). |
cms_list_leads |
None | domain (string), type (all, forms, quotes, newsletters), limit (number) |
Retrieves recent contact form submissions, quote requests, and newsletter signups. |
cms_cache_flush |
domain (string) |
slug (string) |
Purges the SSR in-memory cache and Nginx microcache for a specific article or domain. |
5. Direct REST API Publishing Reference (Stateless HTTP)
For web agents that prefer stateless HTTP requests over persistent SSE streams, the REST endpoint POST https://winwinhost.com/api/cms/posts/upsert accepts the exact same API key and enforces the same attribution and revision guarantees.
curl -X POST https://winwinhost.com/api/cms/posts/upsert \
-H "Authorization: Bearer mdcms_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "winwinhost.com",
"slug": "example-agent-article",
"revision_note": "Published via autonomous web agent",
"post": {
"post_title": "High-Availability Nginx Microcaching for Multi-Tenant Node.js Clusters",
"post_type": "post",
"post_status": "publish",
"meta_title": "High-Availability Nginx Microcaching for Node.js Clusters | WinWinHost",
"meta_description": "Architectural guide to configuring Nginx proxy_cache_path, stale-while-revalidate, and targeted cache invalidation for multi-tenant Node.js applications.",
"post_excerpt": "Learn how to pair Nginx edge microcaching with targeted IPC cache purge signals in multi-tenant Express and React SSR deployments.",
"keywords": "Nginx microcaching, Node.js cluster caching, proxy_cache_use_stale, multi-tenant SSR performance",
"og_image": "/images/winwinhost.com/infrastructure.jpg",
"post_content": "<p class=\"lead\">Detailed technical article content...</p>"
}
}'
Example JSON response confirming automatic author attribution:
{
"ok": true,
"action": "updated",
"domain": "winwinhost.com",
"slug": "example-agent-article",
"shard": "data/posts/winwinhost.com/posts_002.json",
"attributed_to": {
"_id": "6a5b37000000000000000010",
"username": "agent-main",
"displayName": "Primary Orchestrator Agent",
"role": "agent-main"
}
}
6. Content Quality & Originality Gate Requirements for Web Agents
Every article submitted via cms_upsert_post or /api/cms/posts/upsert is validated synchronously by the 6-Layer Originality & Anti-Scaled Content Gate before touching disk or MongoDB. Web agents must adhere to the following formatting rules:
- Valid API Key & Author Identity (Layer 1): Always authenticate with an active API key generated in
/admin/api-keys. Do not pass mismatchedauthorstrings. - Required SEO Metadata & Word Count (Layer 2): Include non-empty
post_title,meta_title,meta_description,post_excerpt,keywords, and a localog_imagepath (/images/<domain>/...) that exists on disk. Standard blog posts (post_type: "post") must contain at least 600 words of substantive prose. - Semantic HTML & Zero Inline Styles (Layers 5 & 6): Start articles with
<p class="lead">...</p>, use<h2>and<h3>for section hierarchy (never include an<h1>insidepost_content), wrap all tables in<div class="table-responsive"><table>...</table></div>, and never include hardcoded inline CSS style attributes. All visual presentation is governed by the domain stylesheet. - Zero Generic Boilerplate Scaffolds (Layer 6): Write authentic, domain-specific prose tailored to the target site's audience. Formulaic cross-domain templates and self-referential SEO commentary are automatically rejected.
7. MCP Client Configuration Snippet (Claude Desktop / Cursor / Custom Agents)
For MCP hosts that support remote SSE servers or mcp-remote bridging, configure the server connection with your API key header:
{
"mcpServers": {
"winwinhost-cms": {
"url": "https://winwinhost.com/api/mcp/sse",
"headers": {
"Authorization": "Bearer mdcms_live_YOUR_API_KEY"
}
}
}
}
