Free · MIT licensed

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

  1. Add the server to your MCP host config (.claude/mcp.json for Claude Code, claude_desktop_config.json for 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 — npx downloads and runs on first use.
  2. Create ~/.distribution-mcp/profiles.yaml with your channel credentials
    default:
      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 return needs_browser with 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?
The MCP is MIT-licensed and free. You pay only for your agent's model usage and any platform-specific costs on the channels themselves (most are free for non-paid posting; Reddit, DEV.to, Hashnode, Bluesky, GitHub Discussions all have free posting tiers).
Why not just use Buffer or Hootsuite?
Those are scheduling UIs for marketing teams. This is an MCP server for AI agents. Different shape: the agent generates per-channel copy in chat, calls 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?
No. The 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?
The Reddit adapter writes a plain-text draft to disk and returns a pre-filled submission URL pointing at the target subreddit. No API credentials are needed. You paste the title and body into the Reddit compose form and click Submit. After posting, call mark-live with the thread URL to record it in state, so post_status returns the truth.
What does it not do?
It doesn't write copy. It doesn't pick subreddits for you (the agent does that against 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