content-distribution-mcp
An MCP server that publishes one piece of content to eight developer-community channels with idempotent state, per-subreddit anti-spam rules, and dual YAML or Notion backends. No LLM calls in the server. Your agent writes the copy, the MCP does the I/O.
Eight channels, three publish tiers
The server ships eight channel adapters. Six publish through native APIs; two write a plain-text draft for the operator to paste manually when the platform has no usable API.
| Channel | Tier | Notes |
|---|---|---|
devto |
auto | Forem API v1. Native canonical_url so your blog stays the SEO origin. |
hashnode |
auto | GraphQL. Native originalArticleURL field. Publication-scoped tokens. |
github_discussions |
auto | GraphQL per-repo. Footer link for canonical (no native field). |
bluesky |
auto | atproto SDK. Canonical link appended to post text. App-password auth. |
reddit |
manual | Plain-text draft plus pre-filled submit URL. Operator pastes into the compose form; mark_live CLI records the thread URL. No API credentials needed. |
medium_browser |
manual | Plain-text draft plus compose URL. Operator pastes into the editor and clicks Publish; mark_live CLI records the URL. |
linkedin |
manual | Returns a compose URL and needs_browser state. Paste copy into the LinkedIn post editor and click Post. |
twitter_browser |
manual | Free-tier API is unusable. Plain-text draft plus pre-filled compose URL, mark_live records the tweet. |
What it gives your agent
Eight MCP tools, namespaced by domain. The agent calls post_publish or post_schedule with one content envelope plus per-channel variants. The MCP handles state, idempotency, retries, and platform quirks.
| Tool | Purpose |
|---|---|
post_publish |
Immediate publish across the variants you supply. Idempotent on (content_id, channel): re-running with the same envelope is a no-op. |
post_schedule |
Queue variants for schedule_at timestamps. Stored in the state backend until post_drain picks them up. |
post_drain |
Fire any due scheduled posts. One-shot and cron-friendly. Skips items that are already live. |
post_status |
Per-variant state for one content piece: pending, live, failed, needs_browser, with URLs and error context. |
post_unpublish |
Best-effort delete on DEV.to and GitHub Discussions. Reddit is honor-system (no API delete). Browser channels are operator-driven. |
channel_hints |
Static per-channel metadata: character limits, tag vocabulary, canonical-URL support, recommended posting times. The agent decides what to do with them. |
profile_list |
Returns the Distribution Profiles configured in your backend (token sets, default tags, posting cadences). |
subreddit_list |
Returns the curated Subreddit Catalog: name, rules, flair vocabulary, cooldown, allowed self-promo ratio. |
What makes it different
Idempotent on (content_id, channel)
Every publish call claims a key in the state backend before hitting the API. Network blip on attempt 47? Re-run the same envelope, get the same URL back. No double-posts, no duplicate Reddit threads, no embarrassing retries.
npx — no install, no Python
Add one JSON block to your MCP host config. npx -y @ratamaha/content-distribution-mcp downloads and runs on first use. Node.js 18+ is the only requirement — no pip, no virtualenv, no version management.
Browser fallback where APIs are hostile
Medium's API is partner-only. Twitter's free tier is unusable. Reddit's API has unpredictable rate limits. For those, the MCP writes a clean draft and returns the compose URL. You paste and click Publish; mark_live records the URL.
Zero LLM calls in the server
Grep src/ for "anthropic". You'll find nothing. The host process supplies copy, credentials, and decisions. The MCP supplies idempotent I/O. Works with any model, any host, any pipeline.
Dual backend: YAML local, Notion team
Solo developer? YAML files in ~/.distribution-mcp/, zero config. Agency or team? Three Notion databases for Distribution Profiles, Subreddit Catalog, and Post Log, with URL write-back to source tasks. Same Protocol, swap with one constructor argument.
Works in any MCP host
stdio or SSE transport. No Anthropic-specific code. Tested against Claude Code, n8n's MCP Client node, Cursor, and the plain mcp Python client. The skill that ships with the repo is optional; the protocol is universal.
Install in 2 steps
-
Add the server to your MCP host config (
.claude/mcp.jsonfor Claude Code,claude_desktop_config.jsonfor Claude Desktop, equivalent for Cursor, n8n, etc.){ "mcpServers": { "content-distribution": { "command": "npx", "args": ["-y", "@ratamaha/content-distribution-mcp"] } } }Requires Node.js 18+. No global install needed —npxdownloads and runs on first use. -
Create
~/.distribution-mcp/profiles.yamlwith your channel credentialsdefault: credentials: DEV_TO_API_KEY: "..." HASHNODE_TOKEN: "..." HASHNODE_PUBLICATION_ID: "..." BLUESKY_IDENTIFIER: "you.bsky.social" BLUESKY_PASSWORD: "..." REDDIT_CLIENT_ID: "..." REDDIT_CLIENT_SECRET: "..." REDDIT_USERNAME: "..." REDDIT_PASSWORD: "..."Only set credentials for the channels you use. LinkedIn, Medium, and Twitter returnneeds_browserwith a compose URL — no credentials needed for those.
Works with Claude Code, Claude Desktop, Cursor, n8n via the MCP Client node, and any custom integration that speaks MCP over stdio or SSE. Full reference: the GitHub readme and spec.
FAQ
What does it cost?
Why not just use Buffer or Hootsuite?
post_publish once, and the MCP handles every platform's quirks (Reddit cooldowns, Bluesky's 300-char limit, Medium's missing API) in one round trip.Do I need a Notion account?
YamlBackend stores everything in four YAML files in ~/.distribution-mcp/. Zero configuration. The NotionBackend is for agency or team use; it provisions three databases and writes published URLs back to source tasks. Both implement the same Protocol; you swap with one constructor argument.How does Reddit posting work?
mark-live with the thread URL to record it in state, so post_status returns the truth.What does it not do?
subreddit_list). It doesn't game algorithms. It doesn't run analytics. It doesn't auto-follow, auto-DM, or auto-reply. It does one job: take a finished piece of content plus per-channel variants and route them with idempotent state.Want it wired into your distribution pipeline?
We use content-distribution-mcp daily to publish our own posts and tools across the developer-community channels. If you want it set up for your stack, integrated with your CMS, or a full agent pipeline built end to end, we can do that.
Get in touch