Substack MCP Server & CLI
A free, open source Substack MCP server and CLI that lets Claude Code, Codex, Cursor and other AI agents draft posts, publish Notes and read your subscribers and stats.
This free Substack MCP server and CLI gives your AI real access to your Substack publication. It drafts posts, publishes Notes, reads your subscribers and stats, and studies other writers.
It's one install with 2 ways in. Claude, Codex, Cursor or any other MCP app calls its 65 tools for you, and the same tools work as a CLI that agents like Claude Code, Codex and OpenCode run, or that you type yourself.
Here's what the Substack MCP server is, how to set it up in each app, and every tool it has.
What is the Substack MCP server & CLI?
The Substack MCP server & CLI is a free, open source program that lets AI agents work in your Substack for you, in 2 ways. The MCP server is what an AI app like Claude, Codex or Cursor connects to, through MCP (Model Context Protocol), the open standard AI apps use to call outside tools.
You ask in plain language. Your AI picks the right tool, and the server makes the call to Substack.
The CLI is the same program as commands. substack-cli list-drafts runs the same code your AI runs when you ask what you have in progress, whether an agent like Claude Code runs it or you do.
What can you ask it?
Once it's set up, you ask the way you'd ask an assistant. These are real prompts it handles:
Try askingDraft this week's post from my notes, in the voice of my last 5.
Which of my posts got the most paid conversions, and what do they have in common?
How many subscribers haven't opened anything in 90 days?
Add a paywall after the third section of that draft.
Schedule this Note for 9am Tuesday.
Turn my last 3 posts into a guide, and put the YouTube version at the top.
The last one shows why this is useful. It writes the new draft in your format and embeds the video as a real player, not a blue link.
How to install the Substack MCP server
Pick your app in the box at the top of this page. You log in once in a terminal, then add the server to your app with a single command or a pasted block.
Watch out: Use the substack.com address even if your publication has its own domain. Substack doesn't answer its API on custom domains, so the request ends in a 404.
Set up your Substack account
Substack has no public API and no app to register. The server works through your browser's session cookie, the same way the Substack tab you have open does.
Treat that cookie like a password, because it gives full access to your account. Never paste it into an issue, a chat or a shared doc.
npx -y @thenavidm/substack-mcp-cli loginTurn off ad blockers before you look for the cookie. Some of them hide it from that panel.
Other ways to log in
login --playwriter reads the cookie from the Chrome you already have open, using the Playwriter extension. login --playwright opens a browser for you to sign in, which is slower but works on a computer without Chrome.
You can also skip the login and set SUBSTACK_PUBLICATION_URL and SUBSTACK_SESSION_TOKEN in your app's config instead.
When the session runs out
Substack sessions expire, commonly reported at around 90 days. When calls start failing with a sign-in error, run the login again, and the doctor warns you once a stored session passes 75 days.
Check that it works
Run the doctor. It checks your credentials, your settings, the connection and your byline, and names what's wrong.
npx -y @thenavidm/substack-mcp-cli doctorWhen it passes, restart your app and ask for a summary of your dashboard.
Use the Substack CLI
The CLI is the same 65 tools as commands. AI agents that run commands, like Claude Code, Codex and OpenCode, use it on their own, and you can type the same commands in a terminal or a script. Every tool name becomes a command with dashes, so create_draft runs as substack-cli create-draft.
npm install -g @thenavidm/substack-mcp-cli
substack-cli
substack-cli list-drafts
substack-cli get-dashboard-summary
substack-cli rank-posts --limit 10The bare substack-cli lists every command, and substack-cli <command> --help shows what a command takes. Publishing, deleting and posting Notes need --confirm, the terminal's version of the check your AI has to pass.
These flags work on every command:
| Flag | What it does |
|---|---|
--json | Prints JSON |
--compact | Prints the JSON on one line |
--agent | Machine mode: JSON, compact, no prompts and no color |
--select a,b.c | Keeps only those fields, and a dotted path goes deeper |
--confirm | Lets a write that asks first go ahead |
A script can branch on the exit code:
| Exit code | What it means |
|---|---|
| 0 | It worked |
| 2 | The command was typed wrong, or a write needed --confirm |
| 3 | It wasn't found |
| 4 | Substack rejected the session |
| 5 | Substack's API failed |
| 7 | You hit a rate limit, so wait and try again |
| 10 | Nothing is set up yet |
MCP server or CLI: which one?
Both are the same program with the same 65 tools. The difference is when your AI pays for them, in the tokens it reads.
- MCP server
- 25,200 tokens
- CLI
- Nothing
- MCP server
- 1,200 tokens
- CLI
- Nothing
- MCP server
- Nothing more, or in Claude Code the tools it picks
- CLI
- 2,300 tokens, once
- MCP server
- 504,000 tokens
- CLI
- 2,300 tokens
- MCP server
- Yes
- CLI
- No, there's no terminal there
- MCP server
- No
- CLI
- Yes
An app that loads every tool up front sends the full list with every message, whether you mention Substack or not. Claude Code doesn't by default: its tool search sends only the tool names and the server's instructions, and loads a tool's full definition when your AI reaches for it.
The CLI costs nothing until Substack comes up. Then your agent reads its skill file once and runs the commands it needs. With the skill added, Claude Code also lists its one-line description with every message, about 140 tokens.
When the whole conversation is about Substack, the gap closes. Then the MCP server is the better experience, because you ask in plain language and your AI never has to look up a command.
Where the MCP server's tokens go
| Part of the tool list | Share |
|---|---|
| JSON Schema structure, like types, required lists and nesting | 47% |
| Argument descriptions | 36% |
| Tool descriptions | 17% |
47% of it is MCP writing every tool out as JSON Schema, which any server with this many tools pays. The rest is the wording that lets your AI use each tool without guessing.
How to spend less
In Claude Code, leave tool search on, which it is unless you've set ENABLE_TOOL_SEARCH=false.
Turn the server off when you aren't using Substack. In Claude Code that's the /mcp panel, and every AI app has its own switch. SUBSTACK_READ_ONLY=1 cuts it to the 41 reading tools.
Or install the CLI and connect the server later, on the days it earns its place. Every tool stays in reach, and the standing cost drops to nothing.
Every number here was measured on September 27, 2026 in Claude Code 2.1.257 with Claude Opus 5. It's the same one-line prompt with and without the server connected, once with tool search off so every tool loads, and once with Claude Code's default. The skill was measured the same way, and other apps and models count tokens a little differently.
How it writes posts
Substack stores a post as its own document format, not HTML. The server turns your AI's markdown into that format, so a draft looks like one you made by hand.
A line with only a YouTube, X, Spotify or Vimeo link becomes a real embedded player. Write <paywall> on its own line to mark where the paid part starts.
The free part everyone reads.
https://youtu.be/VIDEO_ID
<paywall>
The part only paying subscribers get.Substack's format has no tables, so a table in your draft is kept as a code block you can reformat in the editor. preview_draft_body shows what a body will turn into, embeds and paywall included, without changing anything.
Every Substack tool
All 65 tools, grouped the way the repo groups them. 41 only read, and 24 change something in your publication.
Drafts and publishing
create_draft- What it does
- Create a new draft post.
- Kind
- Writes
update_draft- What it does
- Change any part of an existing draft.
- Kind
- Writes
get_draft- What it does
- Read one draft in full.
- Kind
- Reads
list_drafts- What it does
- List unpublished drafts, most recently edited first.
- Kind
- Reads
delete_draft- What it does
- Permanently delete an unpublished draft.
- Kind
- Asks first
publish_draft- What it does
- Publish a draft immediately.
- Kind
- Asks first
schedule_draft- What it does
- Schedule a draft to publish at a future time.
- Kind
- Writes
unschedule_draft- What it does
- Cancel a scheduled publication and return the post to being a plain draft.
- Kind
- Writes
list_scheduled_posts- What it does
- List posts queued to publish later, soonest first.
- Kind
- Reads
set_draft_body- What it does
- Replace a draft's body with a Substack document you build node by node.
- Kind
- Writes
preview_draft_body- What it does
- Convert a body to Substack's document format and show what it produced, without creating or touching anything.
- Kind
- Reads
get_sections- What it does
- List the publication's sections, which are the categories a post can be filed under.
- Kind
- Reads
Published posts
list_posts- What it does
- List published posts, newest first.
- Kind
- Reads
get_post- What it does
- Read a published post in full by its slug.
- Kind
- Reads
get_post_by_id- What it does
- Read a published post by its numeric id rather than its slug.
- Kind
- Reads
search_posts- What it does
- Search your own published posts by keyword, across title and body.
- Kind
- Reads
get_post_stats- What it does
- Full performance detail for one published post: opens, clicks, views, signups driven, reactions, restacks and comments.
- Kind
- Reads
rank_posts- What it does
- Rank published posts by a performance metric, to find what actually worked.
- Kind
- Reads
Notes
publish_note- What it does
- Publish a Substack Note.
- Kind
- Asks first
publish_note_with_link- What it does
- Publish a Note with a link attached, which renders as a preview card rather than a bare URL.
- Kind
- Asks first
schedule_note- What it does
- Queue a Note to publish later.
- Kind
- Writes
list_scheduled_notes- What it does
- List Notes queued by schedule_note, soonest first.
- Kind
- Reads
cancel_scheduled_note- What it does
- Cancel a queued Note before it publishes.
- Kind
- Writes
list_notes- What it does
- List Notes you have published, newest first.
- Kind
- Reads
delete_note- What it does
- Delete one of your published Notes.
- Kind
- Asks first
Subscribers
list_subscribers- What it does
- List subscribers, with the same filtering the Subscribers dashboard offers: 48 columns, free-text search, sorting and paging.
- Kind
- Reads
export_subscribers- What it does
- Export subscribers as full records, which is the only way to actually read the engagement metrics list_subscribers can only filter on: opens over 7d/30d/6mo, unique emails seen, post views, comments, shares, links clicked, days active and activity rating.
- Kind
- Reads
get_subscriber_count- What it does
- Total subscribers, split by free and paid.
- Kind
- Reads
add_subscriber- What it does
- Add an email address to your subscriber list.
- Kind
- Writes
Analytics
get_analytics- What it does
- Read one of the publication-level reports behind the dashboard's Stats tabs.
- Kind
- Reads
get_dashboard_summary- What it does
- The headline numbers from the publishing dashboard: subscribers at the start and end of the window, paid subscribers, ARR and recent activity.
- Kind
- Reads
get_email_stats- What it does
- Overall email performance: delivery, open rate and click rate across the publication.
- Kind
- Reads
get_growth_sources- What it does
- Where new subscribers came from in a window, ranked by how many each source brought.
- Kind
- Reads
get_revenue_summary- What it does
- Revenue and subscription plans: what each tier costs, how many are on it, and what it brings in.
- Kind
- Reads
Comments
get_post_comments- What it does
- Read the comments on one of your posts, newest first.
- Kind
- Reads
comment_on_post- What it does
- Post a comment on one of your posts.
- Kind
- Asks first
delete_comment- What it does
- Delete a comment by id.
- Kind
- Asks first
Tags
list_publication_tags- What it does
- List every tag defined on the publication, with the ids that add_tag_to_post takes.
- Kind
- Reads
create_tag- What it does
- Create a new tag on the publication.
- Kind
- Writes
get_post_tags- What it does
- List the tags currently on one post.
- Kind
- Reads
add_tag_to_post- What it does
- Put an existing tag on a post.
- Kind
- Writes
remove_tag_from_post- What it does
- Take a tag off a post.
- Kind
- Asks first
Templates
list_templates- What it does
- List your saved post templates, with the ids create_draft_from_template takes.
- Kind
- Reads
create_template- What it does
- Save a reusable post template.
- Kind
- Writes
delete_template- What it does
- Delete a saved template.
- Kind
- Asks first
create_draft_from_template- What it does
- Create a new draft pre-filled with a saved template's body.
- Kind
- Writes
Your reader feed
list_subscriptions- What it does
- List the publications this account subscribes to, free and paid.
- Kind
- Reads
list_reader_posts- What it does
- The posts in your Substack inbox, from the publications you subscribe to, newest first.
- Kind
- Reads
get_reader_post- What it does
- Read the full text of any post you have access to, including paid posts from publications you pay for.
- Kind
- Reads
get_reader_feed- What it does
- The Notes feed, which is Substack's timeline.
- Kind
- Reads
get_profile_feed- What it does
- Everything one account has published to Notes, newest first.
- Kind
- Reads
get_comment_thread- What it does
- Read one Note together with the replies under it.
- Kind
- Reads
restack_note- What it does
- Restack a Note, which republishes it to your own followers under your name.
- Kind
- Asks first
Research other writers
research_creator_posts- What it does
- Pull another publication's recent posts with their engagement numbers: likes, comments and restacks.
- Kind
- Reads
research_creator_notes- What it does
- Pull another writer's recent Notes with likes, replies and restacks.
- Kind
- Reads
compare_publications- What it does
- Pull recent posts from several publications at once and rank them together by engagement, so you can see which topics and formats are working across a whole niche rather than one writer at a time.
- Kind
- Reads
scrape_post- What it does
- Fetch a public Substack post by URL and pull out the title, subtitle, author and body text.
- Kind
- Reads
Publication settings
get_publication_settings- What it does
- Read the publication's full settings: name, hero text, logo, cover, sender name, theme colours, sections, welcome email, podcast feed and everything else on the settings page.
- Kind
- Reads
update_publication_settings- What it does
- Change publication settings.
- Kind
- Writes
get_user_profile- What it does
- Read the account behind the session: name, handle, user id, bio and which publications it owns.
- Kind
- Reads
list_contributors- What it does
- List the people attached to the publication, with their role and their numeric user id.
- Kind
- Reads
get_import_status- What it does
- Read the result of the most recent subscriber import: when it ran, how many addresses were in it, how many were added, and how many were skipped.
- Kind
- Reads
search_publications- What it does
- Search Substack for publications by name or topic.
- Kind
- Reads
get_publication_info- What it does
- Read the public details of any Substack publication from its homepage: name, description, author and cover image.
- Kind
- Reads
Images
upload_image- What it does
- Upload an image to Substack's CDN and get back a URL you can use in a post body or as a cover image.
- Kind
- Writes
Is the Substack MCP server safe?
Publishing a draft with the email on sends it to every subscriber, and there's no unsend. Deleting a draft has no undo, and a Note or a comment is public the moment it runs. So 10 tools refuse to run until your AI passes confirm: true. They're the ones marked Asks first in the tool tables above.
A careless call stops at that check, and one you meant clears it in a single retry. Drafting and editing don't ask, because nothing there is public or permanent.
Make it read-only
Set SUBSTACK_READ_ONLY=1 and every write disappears from the tool list, leaving 41 reading tools. Your AI can't call a tool it can't see.
SUBSTACK_ALLOW_DESTRUCTIVE=0 is the middle setting. Drafting and tagging still work, and publishing and deleting don't.
Keep a log of every write
Set SUBSTACK_AUDIT_LOG to a file path. The server writes one line per attempted write, allowed or blocked.
Watch out: Comments, your reader feed and other writers' posts are text other people wrote, and a comment can try to give your AI orders. The server tells your AI to treat it as data, but SUBSTACK_READ_ONLY=1 is the real defense for an agent working on its own.
Your data
Nothing goes anywhere but Substack. There's no tracking, no analytics and no other service in between.
If you use the login, your session is stored in ~/.substack-mcp, encrypted with a key tied to your computer and your user account. Your posts, drafts and subscribers are never copied to your computer, and every read goes to Substack live.
Substack MCP server settings
Every setting is an environment variable, in your app's config or your shell.
SUBSTACK_PUBLICATION_URL- Default
- none
- What it does
- Sets your publication, like
example.substack.com
SUBSTACK_SESSION_TOKEN- Default
- none
- What it does
- Holds the
connect.sidcookie value when you skip the login
SUBSTACK_USER_ID- Default
- looked up
- What it does
- Sets your numeric user ID for the byline
SUBSTACK_PUBLICATIONS- Default
- none
- What it does
- Lists several publications, as JSON
SUBSTACK_READ_ONLY- Default
0- What it does
1hides every write
SUBSTACK_ALLOW_DESTRUCTIVE- Default
1- What it does
0blocks publishing and deleting
SUBSTACK_AUDIT_LOG- Default
- none
- What it does
- Logs every attempted write to a file
SUBSTACK_REQUEST_TIMEOUT_MS- Default
30000- What it does
- Sets how long a request can take
SUBSTACK_MIN_REQUEST_INTERVAL_MS- Default
350- What it does
- Spaces out requests, so your account isn't rate limited
SUBSTACK_MCP_HOME- Default
~/.substack-mcp- What it does
- Sets where the session and the Notes queue live
Troubleshooting
Run the doctor first. It names what's wrong and the fix.
| What you see | What to do |
|---|---|
| "Substack rejected the session" | The cookie expired. Run the login again with a fresh one |
| Calls fail on a custom domain | Set your publication to its yourname.substack.com address |
| A post shows HTML tags as text | Something else wrote that draft. Check it with preview_draft_body |
| Making a draft fails on the byline | Set SUBSTACK_USER_ID, and the doctor tells you when you need to |
| A scheduled Note didn't go out | The server wasn't running at that time. It posts on the next start |
| Tools are missing from the list | SUBSTACK_READ_ONLY is on, so the writes are hidden |
Scheduled Notes go out from the computer the server runs on. A Note queued for 9am only goes out if that computer is awake.
More free tools for your newsletter
Turn a post into images for social, or tag the links you share so you can check what sent readers.
Substack MCP Server FAQs
Here are the questions people ask most about the Substack MCP server and CLI.
The Substack MCP server & CLI is a free, open source program that lets an AI app like Claude, Codex or Cursor work in your Substack publication.
It has 65 tools for drafts, publishing, Notes, subscribers, analytics, tags, comments and research on other writers, and the same tools run as a CLI that agents like Claude Code and Codex use, or that you type yourself.
An MCP server is a standard way to give an AI app real access to a tool, so it can act instead of guessing.
MCP stands for Model Context Protocol, and Claude, Codex, Cursor and many other AI apps speak it.
The Substack CLI is the same program as the Substack MCP server, run as commands.
AI agents like Claude Code, Codex and OpenCode run them for you, and you can type them in a terminal or a script.
Every tool is a command with dashes, so create_draft runs as substack-cli create-draft, and one npm package installs both.
Use the Substack MCP server in an AI app with no terminal, like Claude Desktop's chat, and the CLI in a terminal, a script or a cron job.
In an AI app that can run commands, like Claude Code, Codex or Cursor, the CLI is the lighter choice, because it costs nothing until it runs.
Yes, the Substack MCP server is free and open source under the MIT license.
The only thing you pay for is your own AI app.
No, Substack has no public API and no app to register.
The Substack MCP server works through your browser's session cookie, the same way your signed-in Substack tab does.
Your Substack session cookie stays on your computer, encrypted with a key tied to your machine, and it only ever goes to Substack.
Treat it like a password, because it gives full access to your account.
The Substack MCP server publishes when you ask it to.
Publishing, deleting and posting Notes only run once your AI passes a confirm check, and read-only mode removes every write so your AI can't see them at all.
The Substack MCP server needs your publication's yourname.substack.com address, even if readers use a custom domain.
Substack doesn't answer its API on custom domains.
The Substack MCP server works with any app that speaks MCP.
That includes Claude Code, Claude Desktop, Codex, Cursor, VS Code, GitHub Copilot CLI, Gemini CLI, OpenCode, OpenClaw, Antigravity and Hermes.
Yes, the Substack MCP server takes several publications through the SUBSTACK_PUBLICATIONS setting.
Every publication tool then takes an optional publication, and the first one acts when you don't name any.
Navid.me is reader-supported. When you buy through links on this site, I may earn an affiliate commission. Learn more.
More MCP servers & CLIs
The most actionable AI newsletter for founders
Every week, get proven AI strategies, curated tools, and step-by-step systems to grow your audience, create better content, and build a profitable creator business.
No fluff, no filler, no BS. Just five minutes each week that might level up your online business and life.
P.S. Sign up now to get free access to my ultimate AI tools guide for creators.


