Content MCP Server
Manage Moonage website content — blog, changelog, and roadmap — over the Model Context Protocol.
The Moonage Content MCP Server exposes blog, changelog, roadmap, search, and asset tools over the Model Context Protocol. Any MCP-compatible client can connect and manage website content programmatically.
This is not the Moonage MCP
Moonage runs two separate MCP servers. This page documents the narrower one.
| Endpoint | What it reaches | |
|---|---|---|
| Moonage MCP | https://mcp.moonage.ai/mcp | Your organization — agents, memory, tasks, capabilities. OAuth 2.1, governed. |
| Content MCP (this page) | https://content.moonage.ai/mcp | Website content only — blog, changelog, roadmap. |
If you want an agent to reach your workspace, you want the Moonage MCP, not this server. Its connection recipe is at moonage.ai/auth.md, its server card at /.well-known/mcp/server-card.json, and an overview in the API reference. This server has no access to your organization, its agents, or its memory.
Connection
| Property | Value |
|---|---|
| Transport | Streamable HTTP |
| Endpoint | https://content.moonage.ai/mcp |
| Server name | Moonage Content |
| Version | 1.0.0 |
Connecting with curl
# 1. Initialize a session
curl -X POST https://content.moonage.ai/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": { "name": "my-client", "version": "1.0.0" }
}
}'
# 2. Save the Mcp-Session-Id header from the response
# 3. Send initialized notification
curl -X POST https://content.moonage.ai/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: SESSION_ID" \
-d '{"jsonrpc": "2.0", "method": "notifications/initialized"}'
# 4. Call tools
curl -X POST https://content.moonage.ai/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: SESSION_ID" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "list_blog_posts",
"arguments": { "limit": 5 }
}
}'Connecting with the MCP TypeScript SDK
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const transport = new StreamableHTTPClientTransport(
new URL("https://content.moonage.ai/mcp")
);
const client = new Client({
name: "my-app",
version: "1.0.0",
});
await client.connect(transport);
// List available tools
const { tools } = await client.listTools();
// Call a tool
const result = await client.callTool("list_blog_posts", { limit: 5 });Tools
The server exposes 19 tools organized by content type.
Deletes are restricted by design: only a draft blog post or changelog entry can be deleted, and a shipped roadmap item cannot be. Deletion cannot be undone — confirm with a person before calling one.
Blog tools
list_blog_posts
List published blog posts with optional filtering.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | number | No | Max posts (1-100, default 20) |
tag | string | No | Filter by tag |
cursor | string | No | ISO date for pagination |
get_blog_post
Get a single blog post by slug, including full markdown content.
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | The blog post slug |
include_drafts | boolean | No | Include non-published posts (default false) |
create_blog_post
Create a new blog post (draft by default).
| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Post title |
content | string | No | Markdown content |
description | string | No | SEO description (50-160 chars) |
author_name | string | No | Author name |
tags | string[] | No | Tags array |
status | string | No | draft or published (default: draft) |
update_blog_post
Update an existing blog post by slug.
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Post slug |
title | string | No | New title |
content | string | No | New markdown content |
description | string | No | New SEO description |
tags | string[] | No | New tags array |
publish_blog_post
Publish a blog post (changes status to published).
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Post slug |
delete_blog_post
Permanently delete a draft blog post. A published or scheduled post is refused. This cannot be undone.
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Post slug to delete |
Changelog tools
list_changelog_entries
List published changelog entries with optional type filter.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | number | No | Max entries (1-100, default 20) |
type | string | No | release, hotfix, beta, or alpha |
get_changelog_entry
Get a single changelog entry by slug or version.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | Yes | Slug or version string |
create_changelog_entry
Create a new changelog entry.
| Parameter | Type | Required | Description |
|---|---|---|---|
version | string | Yes | Version string (e.g. v2.3.0) |
title | string | No | Entry title |
summary | string | No | Short summary |
content | string | No | Full markdown content |
type | string | No | release, hotfix, beta, alpha |
highlights | string[] | No | Key highlights |
status | string | No | draft or published |
update_changelog_entry
Update an existing changelog entry. Publishing is a two-step review flow, not a single set: the only permitted status transitions are draft → review and review → published, so a fresh draft cannot be set straight to published.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | Yes | Slug or version of the entry to update |
title | string | No | New title |
summary | string | No | New short summary |
content | string | No | New full markdown content |
type | string | No | release, hotfix, beta, alpha |
highlights | string[] | No | Key highlights |
status | string | No | draft, review, or published |
delete_changelog_entry
Permanently delete a draft changelog entry. An entry in review or published is refused. This cannot be undone.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | Yes | Slug or version of the entry to delete |
Roadmap tools
list_roadmap_items
List public roadmap items with optional filters.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | all, planned, in_progress, shipped, cancelled, considering |
category | string | No | product, platform, integrations, api, dx |
limit | number | No | Max items (1-100, default 50) |
Returns items sorted by priority and a by_status count summary.
get_roadmap_item
Get a single roadmap item by slug.
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Roadmap item slug |
create_roadmap_item
Create a new roadmap item.
| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Item title |
description | string | No | Full description (markdown) |
summary | string | No | Short summary |
category | string | No | product, platform, integrations, api, dx |
status | string | No | planned, in_progress, shipped, cancelled, considering |
priority | string | No | low, medium, high, critical |
quarter | string | No | Target quarter (e.g. Q2 2026) |
update_roadmap_item
Update an existing roadmap item.
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Item slug |
title | string | No | New title |
description | string | No | New description |
summary | string | No | New summary |
status | string | No | New status |
priority | string | No | New priority |
quarter | string | No | New target quarter |
delete_roadmap_item
Permanently delete a roadmap item and its votes. A shipped item cannot be deleted. This cannot be undone, and unlike the blog and changelog deletes it can remove something the public was being served.
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Roadmap item slug to delete |
Search tool
search_content
Search across blog posts, changelog entries, and roadmap items.
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query |
type | string | No | all, blog, changelog, roadmap (default: all) |
limit | number | No | Max results per type (1-50, default 10) |
Returns results grouped by content type.
Asset tool
get_asset_upload_url
Get information about how to upload images to the content R2 bucket. Returns the upload endpoint, accepted fields, and the public URL base.
No parameters required.
Activity tool
get_activity_log
Query the activity log for content changes.
| Parameter | Type | Required | Description |
|---|---|---|---|
resource | string | No | Filter: blog, changelog, roadmap |
limit | number | No | Max entries (1-200, default 50) |
Architecture
The MCP server runs on the same Cloudflare Worker as the REST API. Each request creates a stateless server instance with access to the D1 database and R2 bucket.
Client (Claude, Cursor, custom agent)
│
▼ Streamable HTTP
┌───────────────────────────┐
│ Cloudflare Worker │
│ /mcp → MCP Handler │
│ /blog, /changelog, ... │
│ → Hono REST API │
│ │
│ ┌─────┐ ┌────────────┐ │
│ │ D1 │ │ R2 (media) │ │
│ └─────┘ └────────────┘ │
└───────────────────────────┘The MCP tools perform the same operations as the REST endpoints but are optimized for agent consumption — they return structured JSON text content directly rather than HTTP response objects.