MCP Server
Connect AI agents to Moonage content using 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 content programmatically.
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 15 tools organized by content type.
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 |
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 |
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 |
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.