Last Updated: 2026-03-15 Protocol: Model Context Protocol (MCP)
This document defines the MCP server interface for the Content Engine — allowing AI agents to fully control content scheduling, calendar management, and social media publishing programmatically.
1. Why MCP?
The Content Engine isn't just a dashboard for humans — it's an automation backbone that AI agents should be able to operate autonomously. By exposing the Content Engine as an MCP server, any AI agent (Claude, Gemini, custom agents) can:
- Schedule content based on strategy analysis
- Auto-generate social promotion when blog posts are published
- Manage the entire content calendar without human intervention
- React to events (e.g., trending topics, news) by scheduling timely posts
- Optimize posting times based on engagement data
IMPORTANT
MCP makes the Content Engine agent-native. Instead of AI agents needing to navigate a UI or call raw REST APIs, they interact through semantically-rich tools with structured inputs and outputs.
2. MCP Server Architecture
┌─────────────────────────────────────────────────────┐
│ AI Agent │
│ (Claude, Gemini, Custom Agent, Automation Engine) │
└──────────┬──────────────────────────────┬────────────┘
│ MCP Protocol (stdio/SSE) │
▼ ▼
┌──────────────────────┐ ┌──────────────────────────┐
│ Content Engine MCP │ │ Other MCP Servers │
│ Server │ │ (Blog, Media, etc.) │
└──────────┬───────────┘ └──────────────────────────┘
│
│ Internal REST API
▼
┌──────────────────────┐
│ Content Engine │
│ Worker (Hono) │
└──────────────────────┘Deployment Options
- Standalone MCP Server — A Node.js process (
packages/content-engine-mcp/) that wraps the Content Engine REST API - SSE Transport — For remote agents connecting over HTTP (agent → MCP server over Server-Sent Events)
- Stdio Transport — For local agent frameworks (e.g., Claude Desktop, VS Code extensions)
3. MCP Tools
3.1 Calendar & Scheduling Tools
schedule_content
Create and schedule a content slot for publishing.
{
"name": "schedule_content",
"description": "Schedule a piece of content for publishing to one or more social media accounts at a specified time.",
"parameters": {
"caption": { "type": "string", "description": "The post text/copy to publish", "required": true },
"contentType": { "type": "string", "enum": ["text", "image", "video", "carousel", "story", "link"], "description": "Type of content being published", "required": true },
"connectionIds": { "type": "array", "items": "string", "description": "Target social connection IDs to publish to. Use `list_connections` to find available connection IDs.", "required": true },
"scheduledAt": { "type": "string", "description": "ISO 8601 datetime for publishing (UTC). Omit for 'next best time'.", "required": false },
"mediaIds": { "type": "array", "items": "string", "description": "Media asset IDs from the Media Service", "required": false },
"linkUrl": { "type": "string", "description": "URL to include in the post (for link-type content)", "required": false },
"campaignId": { "type": "string", "description": "Campaign ID to associate with", "required": false },
"labels": { "type": "array", "items": "string", "description": "Label names to attach", "required": false },
"autoApprove": { "type": "boolean", "description": "Skip approval workflow and schedule directly", "required": false }
}
}Note: A tenant can have multiple connections per platform (e.g., 3 Twitter accounts for different client brands). Use
list_connectionsfirst to discover availableconnectionIdvalues.
Returns: Created content slot with ID, status, and target details.
reschedule_content
Move an existing content slot to a different time.
{
"name": "reschedule_content",
"parameters": {
"slotId": { "type": "string", "required": true },
"newScheduledAt": { "type": "string", "description": "New ISO 8601 datetime (UTC)", "required": true }
}
}cancel_content
Cancel/delete a scheduled or draft content slot.
{
"name": "cancel_content",
"parameters": {
"slotId": { "type": "string", "required": true },
"reason": { "type": "string", "description": "Why the content is being cancelled", "required": false }
}
}get_calendar
Retrieve the content calendar for a date range.
{
"name": "get_calendar",
"description": "Get all scheduled content slots for a given date range. Use this to understand what's already planned before scheduling new content.",
"parameters": {
"from": { "type": "string", "description": "Start date (ISO 8601)", "required": true },
"to": { "type": "string", "description": "End date (ISO 8601)", "required": true },
"platform": { "type": "string", "description": "Filter by platform", "required": false },
"status": { "type": "string", "description": "Filter by status", "required": false }
}
}get_slot_details
Get full details and publish history of a specific content slot.
{
"name": "get_slot_details",
"parameters": {
"slotId": { "type": "string", "required": true }
}
}edit_content
Update an existing content slot's caption, media, or targets.
{
"name": "edit_content",
"description": "Edit a draft or pending_review content slot. Use this to update captions, change platforms, or swap media before publishing.",
"parameters": {
"slotId": { "type": "string", "required": true },
"caption": { "type": "string", "required": false },
"contentType": { "type": "string", "required": false },
"mediaIds": { "type": "array", "items": "string", "required": false },
"platforms": { "type": "array", "items": "string", "description": "Replace target platforms", "required": false },
"linkUrl": { "type": "string", "required": false }
}
}3.2 Social Account Tools
list_connections
List all connected social media accounts.
{
"name": "list_connections",
"description": "List all connected social media accounts for the current workspace. Use this to know which platforms are available for publishing."
}check_connection_health
Check if a social connection's OAuth token is valid and publishing-ready.
{
"name": "check_connection_health",
"parameters": {
"connectionId": { "type": "string", "required": true }
}
}3.3 Campaign & Organization Tools
create_campaign
Create a new content campaign for organized planning.
{
"name": "create_campaign",
"parameters": {
"name": { "type": "string", "required": true },
"description": { "type": "string", "required": false },
"startDate": { "type": "string", "required": true },
"endDate": { "type": "string", "required": true },
"color": { "type": "string", "description": "Hex color for calendar display", "required": false }
}
}list_campaigns
List all active campaigns.
{
"name": "list_campaigns",
"parameters": {
"status": { "type": "string", "description": "'active', 'completed', 'archived'", "required": false }
}
}3.4 Publishing & Status Tools
get_publish_status
Check the publishing status and results of a content slot.
{
"name": "get_publish_status",
"parameters": {
"slotId": { "type": "string", "required": true }
}
}Returns: Per-platform status, external post URLs, error messages.
retry_failed_publish
Retry publishing for a failed content slot.
{
"name": "retry_failed_publish",
"parameters": {
"slotId": { "type": "string", "required": true }
}
}3.5 Recurring Schedule Tools
create_recurring_schedule
Set up a recurring content pattern.
{
"name": "create_recurring_schedule",
"parameters": {
"name": { "type": "string", "required": true },
"cronExpression": { "type": "string", "description": "Cron pattern, e.g., '0 10 * * 1' for Monday 10 AM", "required": true },
"timezone": { "type": "string", "description": "IANA timezone", "required": true },
"templateCaption": { "type": "string", "required": true },
"targetConnectionIds": { "type": "array", "items": "string", "description": "Connection IDs to publish to", "required": true },
"autoSchedule": { "type": "boolean", "required": false }
}
}list_recurring_schedules
List all recurring content schedules.
{
"name": "list_recurring_schedules"
}3.6 Bulk Operations (Agent-Optimized)
bulk_schedule
Schedule multiple content slots at once. Designed for AI agents that plan an entire week of content in one shot.
{
"name": "bulk_schedule",
"description": "Schedule multiple content slots at once. Use this when planning a full week or campaign of content.",
"parameters": {
"slots": {
"type": "array",
"items": {
"caption": "string",
"connectionIds": ["string"],
"scheduledAt": "string",
"mediaIds": ["string"],
"campaignId": "string",
"labels": ["string"]
},
"required": true
},
"campaignId": { "type": "string", "description": "Apply campaign to all slots", "required": false }
}
}bulk_action
Perform an action on multiple content slots (approve all, reschedule batch, delete batch).
{
"name": "bulk_action",
"parameters": {
"slotIds": { "type": "array", "items": "string", "required": true },
"action": { "type": "string", "enum": ["approve", "reject", "cancel", "reschedule"], "required": true },
"rescheduleMap": { "type": "object", "description": "When action is 'reschedule': map of slotId → new ISO 8601 datetime. Example: { 'slot-1': '2026-03-15T10:00:00Z', 'slot-2': '2026-03-15T14:00:00Z' }", "required": false },
"reason": { "type": "string", "required": false }
}
}Note:
rescheduleMapreplaces the previousnewScheduledAtfield to support per-slot rescheduling when bulk-rescheduling multiple content slots.
4. MCP Resources
Resources provide read-only context to agents about the current state of the Content Engine.
| Resource URI | Description |
|---|---|
content://calendar/today |
Today's scheduled content |
content://calendar/week |
This week's content calendar |
content://connections |
List of all connected social accounts and health status |
content://campaigns/active |
Currently active campaigns |
content://stats/overview |
Quick stats: total scheduled, published this week, failed |
content://queue/pending |
Content currently in the publish queue |
5. Agent Personas & Use Cases
5.1 "Content Strategist" Agent
An AI agent that operates the Content Engine autonomously:
- Analyzes the blog content and generates social media copies
- Checks the calendar for open slots
- Schedules content at optimal times
- Monitors publish results and retries failures
Example Agent Flow:
1. Agent calls `list_connections` → knows Twitter + LinkedIn are connected
2. Agent calls `get_calendar(this_week)` → sees Monday & Wednesday have posts
3. Agent decides Tuesday & Thursday need content
4. Agent calls `schedule_content` for Tuesday (Twitter + LinkedIn)
5. Agent calls `schedule_content` for Thursday (Twitter + LinkedIn)
6. Agent calls `get_calendar(this_week)` → confirms 4 slots planned ✅5.2 "Blog Promoter" Agent (Optional — requires Blog Engine)
Triggered when a blog post is published (via blog.published event):
- Reads the blog post title and summary
- Generates platform-specific social copies
- Calls
bulk_scheduleto publish across all platforms - Uses
get_publish_statusto confirm success
Note: This persona only applies when the Blog Engine is also active. The Content Engine works fully without it.
5.3 "Calendar Manager" Agent
Helps maintain the content cadence:
- Checks for gaps in the weekly schedule
- Suggests content to fill empty slots
- Reschedules failed posts
- Balances content across platforms
6. Authentication & Authorization
Agent Authentication
- Agents authenticate via API Key (
x-api-keyheader withls_prefix secret key) - API Key must have
content:*permissions scoped - Each agent action is logged with
agentIdin the audit trail
Permission Mapping
Every MCP tool maps directly to a PBAC permission:
| MCP Tool | Required Permission |
|---|---|
schedule_content |
content:slots.write |
edit_content |
content:slots.write |
get_calendar |
content:slots.read |
get_slot_details |
content:slots.read |
list_connections |
content:connections.read |
create_campaign |
content:campaigns.write |
bulk_schedule |
content:slots.write |
bulk_action |
content:slots.write + content:slots.approve (for approve action) |
7. Rate Limits & Safety
| Guard | Value | Rationale |
|---|---|---|
Max slots per bulk_schedule call |
50 | Prevent calendar flooding |
| Max slots per hour per agent | 200 | Prevent abuse |
Agent actions require agentId header |
Mandatory | Audit trail |
autoApprove defaults to false |
— | Human review by default, agents must opt-in |
| Dry-run mode available | Optional dryRun: true param |
Preview actions without executing |