SkillAgentSearch skills...

substack-api-mcp-server

Self-hosted Substack API and MCP server in Python: all 50 Substack tools (drafts from Markdown, scheduling, Notes, comments, subscribers, stats, DMs) on your own Chrome session. Noncommercial use (PolyForm Noncommercial 1.0.0).

Install / Use

claude mcp add cotletdev -- npx -y github:cotletdev/substack-api-mcp-server

If the server publishes to npm under a different name, use that package instead β€” check the repo README.

About this skill
πŸ”Œ

MCP Server

Model Context Protocol server

Quality Score

83/100

Category

Automation

Supported Platforms

Claude Code
Claude Desktop

Our assessment of substack-api-mcp-server

substack-api-mcp-server scores 83/100 on our quality scale, 2202nd of 2,887 Automation skills we index.

Its MCP Server is 30 KB long, well organised into 38 sections with 18 code examples: a thorough specification that gives an agent plenty to work with.

It has 3 GitHub stars, so there is little community track record yet; judge it on its content.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
3/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated today, so substack-api-mcp-server is actively maintained.
  • No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
  • Its trust signals score 80/100, with 2 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit β€” read the skill file before letting an agent act on it.

substack-api-mcp-server compared with similar skills

All 4 of these similar skills score higher than substack-api-mcp-server; compare them before choosing.

SkillScoreStarsUpdatedFormat
substack-api-mcp-server (this skill)by cotletdev833todayMCP Server
Agent-Reachby Panniantong100101.5k1d agoCLAUDE.md
headroomby headroomlabs-ai10077.7ktodayCLAUDE.md
CowAgentby zhayujie10047.5ktodayCLAUDE.md
Scraplingby D4Vinci10089.4k1d agoMCP Server

Frequently asked questions

How do I install substack-api-mcp-server?
Run claude mcp add cotletdev -- npx -y github:cotletdev/substack-api-mcp-server. The install tabs above show the steps for each supported agent.
Which AI agents does substack-api-mcp-server work with?
It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
Is substack-api-mcp-server safe to use?
It declares no license and scores 80/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is substack-api-mcp-server still maintained?
The repository was last updated today, so substack-api-mcp-server is actively maintained.

Substack API and MCP server, self-hosted

<!-- mcp-name: dev.cotlet/substack -->

A Substack API and a Substack MCP server you run on your own computer, in Python, on the session of your own Google Chrome. All 50 Substack tools we run in production at Cotlet: posts and drafts from Markdown, publishing and scheduling, Notes, comments, subscribers, stats, recommendations and direct messages.

Substack has no public API to write posts, publish Notes or manage subscribers, and no official MCP server. This repo gives you both:

  • MCP server for Claude Code, Claude Desktop, Cursor, Codex and any MCP client, over stdio or HTTP. Setup
  • REST API on http://127.0.0.1:8787/api/v1/substack, with OpenAPI docs at /docs. Setup
  • Python: call("list_posts", status="draft"), plus 14 ready scripts in examples/.

It is for technical people who want to run it themselves, for noncommercial use only (license). If you want it running 24/7 on a server, kept working when Substack changes its site, for a team or a business, use the hosted version at cotlet.dev.

Substack MCP server Python 3.11+ License: PolyForm Noncommercial 1.0.0 MCP Badge

uv tool install substack-api-mcp                  # or: pip install substack-api-mcp
substack-mcp connect                               # reads your Substack session from Chrome
substack-mcp call list_posts
claude mcp add substack -- uvx substack-api-mcp mcp

Contents

How it works

AI agent (MCP) / script (REST, Python) ──▢ substack-mcp on your computer ──your Substack cookies──▢ substack.com
                                                     β–²
                         substack-mcp connect β”€β”€β”€β”€β”€β”€β”€β”˜ reads them once from your Chrome (DevTools Protocol)
  1. You sign in to Substack in your own Chrome, the way you always do.
  2. substack-mcp connect attaches to that Chrome through the Chrome DevTools Protocol, reads the substack.com cookies and saves them to ~/.config/substack-api-mcp/session.json, readable by your user only. Substack signs in by an emailed code or link, so there is no password to see or store.
  3. Every tool call is a request to Substack's own web app endpoints (substack.com/api/v1 for the reader side, yourname.substack.com/api/v1 for your publication's dashboard) with those cookies, sent with curl_cffi, which copies Chrome's TLS fingerprint. No headless browser runs.

Substack's session cookie (substack.sid) lasts about three months. When Substack signs you out, the server reads the cookies from Chrome again, if Chrome is open with remote debugging on.

Requirements

  • Python 3.11 or newer.
  • Google Chrome 144 or newer, signed in to Substack. Any Chrome or Chromium works with a debugging port.
  • macOS, Linux or Windows.
  • A Substack account. Publisher tools (posts, subscribers, stats, comments) work on the first publication your account runs as admin, owner, editor or contributor. Reader tools (feed, search, Notes, messages) work on any account.

Install

From PyPI:

uv tool install substack-api-mcp       # or: pipx install substack-api-mcp, or: pip install substack-api-mcp
substack-mcp --version

MCP clients can also run it with no install: uvx substack-api-mcp mcp.

From source:

git clone https://github.com/cotletdev/substack-api-mcp-server.git
cd substack-api-mcp-server
python3 -m venv .venv
. .venv/bin/activate              # Windows: .venv\Scripts\activate
pip install -e .
substack-mcp --version

With uv: uv venv && uv pip install -e ., then uv run substack-mcp ....

Setting it up with an AI agent (Claude Code, Codex, Cursor)? Open it in this folder and ask it to set up the repo: AGENTS.md tells it every step, and it asks you only for the steps in Chrome.

To update: uv tool upgrade substack-api-mcp (or pip install -U substack-api-mcp), from source git pull && pip install -e .. We copy every change of the hosted Substack tools into this repo.

Connect your Chrome

Option A: your everyday Chrome (recommended)

  1. Open chrome://inspect/#remote-debugging in Chrome and switch remote debugging on. Chrome then accepts DevTools connections from programs on this computer, and asks you before each one.

  2. Make sure you are signed in at substack.com.

  3. Run:

    substack-mcp connect
    
  4. Chrome asks whether to allow the connection. Click Allow.

Saved 19 Substack cookies to /Users/you/.config/substack-api-mcp/session.json
Signed in to Substack as Maya Chen (@mayachen)

You can switch remote debugging off again afterwards. Leave it on if you want the server to pick up a new session by itself after Substack signs you out.

connect looks for Chrome's DevToolsActivePort file in the default profile folder. For Chrome Beta, Canary or a custom profile folder, pass --profile-dir "<folder>".

Option B: a Chrome with a debugging port

Chrome does not open a debugging port on your default profile, so start a separate one, sign in to Substack there once, and connect to it:

# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222 --user-data-dir="$HOME/.chrome-substack"
# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.chrome-substack"
# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="%USERPROFILE%\.chrome-substack"

substack-mcp connect --cdp http://127.0.0.1:9222

--cdp also takes a ws:// DevTools URL, for example of a Chrome on another machine reached over an SSH tunnel.

Option C: paste the cookie by hand

For a server with no Chrome: in Chrome open DevTools on substack.com, Application > Cookies > https://substack.com, copy the value of substack.sid, then:

substack-mcp connect --token          # paste it, input is hidden
# or, without a session file:
export SUBSTACK_AUTH_TOKEN=...

A pasted token is not refreshed on its own. Paste a new one when Substack signs you out.

Check the session at any time:

substack-mcp status

MCP server

The MCP server lists every tool with its input schema, a description written for agents, and hints: read tools are marked read-only, and tools that publish, message or delete are marked so your client asks before running them.

Claude Code

claude mcp add substack -- uvx substack-api-mcp mcp
# read only:
claude mcp add substack -- uvx substack-api-mcp mcp --read-only

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "substack": {
      "command": "uvx",
      "args": ["substack-api-mcp", "mcp"]
    }
  }
}

Cursor

~/.cursor/mcp.json, the same block as Claude Desktop. A ready copy is in mcp.json.

Codex

~/.codex/config.toml:

[mcp_servers.substack]
command = "uvx"
args = ["substack-api-mcp", "mcp"]

Over HTTP

substack-mcp serve also serves MCP over streamable HTTP at http://127.0.0.1:8787/mcp, for clients that take a URL:

substack-mcp serve
claude mcp add --transport http substack http://127.0.0.1:8787/mcp

Then ask your agent things like:

Turn essay.md into a draft for everyone and schedule it for Tuesday 8:00 New York time. Once it is out, post a Note with a link card to it.

Find comments on my last three posts that I have not answered and draft a short reply to each.

Last week's numbers: new and paid subscribers, cancellations, revenue, and opens for each post.

Where did my readers come from in the last 30 days?

REST API

substack-mcp serve                    # http://127.0.0.1:8787, MCP at /mcp, docs at /docs

Each tool has its own route under /api/v1/substack, the same paths as the hosted API at cotlet.dev, so code written against one works with the other. Path parts and the query string are arguments, and a JSON body adds the rest.

curl 'http://127.0.0.1:8787/api/v1/substack/posts?status=scheduled'
curl 'http://127.0.0.1:8787/api/v1/substack/stats?period=30d'
curl -X POST http://127.0.0.1:8787/api/v1/substack/drafts \
  -H 'Content-Type: application/json' \
  -d '{"title": "Notes on pricing", "body_markdown": "## Why I raised prices\n\nThree reasons..."}'

Any tool by name, body as its arguments:

curl -X POST http://127.0.0.1:8787/api/v1/substack/tools/list_comments -d '{"post_id": "148213977"}'
  • GET /api/v1/substack/tools: every tool with its route, input schema and an example answer.
  • GET /docs: interactive OpenAPI docs, GET /openapi.json the schema, for n8n, Postman or a generated client.
  • Answers are JSON. Lists return next_cursor; pass it back as cursor for the next page.

The server listens on 127.0.0.1 only. To reach it from another device of yours, set a token, and every request then needs Authorization: Bearer <token>:

SUBSTACK_MCP_TOKEN=$(openssl rand -hex 24) substack-mcp serve --host 0.0.0.0

Python and the example scripts

Straight from Python, no server needed:

from substack_api_mcp import call
from substack_api_mcp.scripting import paginate, write_rows

posts = list(paginate("list_posts", {"status": "published"}, "posts"))
write_rows(posts, "posts.csv")
draft = call("create_draft", title="Notes on pricing", body_markdown="Three reasons...")
call("schedule_post", post_id=draft["post_id"], publish_at="2026-11-03T08:00:00-05:00")

Or one tool from the shell: substack-mcp call get_post_stats post_id=148213977, or with a JSON object.

Ready scripts in examples/. Each prints JSON, takes --out file.csv or --out file.json where it makes sense, and --help:

| Script | What it does | |---|---| | draft_from_markdown.py | A .md file to a draft: the first heading is the title, headings, links and lists are kept. --publish-at schedules it. | | schedule_post.py | Schedules a draft for a set time, or --cancel takes it back to drafts. | | publish_note.py | A Note now or at a set time, --link-latest adds a

Truncated for display β€” read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars3
CategoryAutomation
Updated5h ago
Forks0

Languages

Python

Trust signals

80/100

From repository metadata: license, adoption, age and documentation. Not a code audit β€” see the Safety scan above for what the skill file itself contains.

1 medium1 low
substack-api-mcp-server β€” MCP Server: Install & Safety Check | SkillAgent