substack-mcp
Syncs recent posts from Substack publications, caches metadata and markdown locally, and provides tools for listing, fetching post chunks, and marking posts as summarized for daily summary generation. Supports paid subscriptions the user has access to.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@substack-mcpfetch recent Substack posts and list unsummarized ones"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-substack
Local MCP server for giving Copilot access to Substack posts that your own reader account is allowed to view, including paid posts from your subscriptions.
The main workflow is daily summary generation:
Sync recent posts from priority Substack publications.
Cache metadata and markdown locally.
Let Copilot list unsummarized posts.
Let Copilot fetch long posts in chunks.
Mark summarized posts so they do not repeat tomorrow.
Safety Boundary
This server uses only your own authenticated Substack session.
It does not:
read your normal Chrome profile
read Chrome Keychain-backed cookie storage
store your Substack password
bypass paywalls
share paid content outside your machine
Authentication is handled through a dedicated Playwright browser profile:
~/Library/Application Support/mcp-substack/browser-profile/Cached article data is stored locally:
~/Library/Application Support/mcp-substack/substack.dbLocal config is stored at:
~/Library/Application Support/mcp-substack/config.jsonRelated MCP server: Substack MCP
Requirements
macOS
Node.js 26 or newer recommended, because this project uses Node's built-in
node:sqlitenpm
Install
cd ~/path/to/substack-mcp
npm install
npx playwright install chromium
npm run buildFirst Login
Open the dedicated Substack browser profile and log in once:
npm run spike -- login 300If you are already logged in, the browser may open briefly and close.
Check login status:
npm run spike -- statusExpected result:
{
"loggedIn": true
}Priority Publications
You can optionally configure a small set of priority publications for daily summary runs. This is useful when you subscribe to many publications but only want a subset in the default summary.
Set or reset priority publications with your own publication URLs:
npm run spike -- config-priority \
https://example-newsletter.substack.com \
https://example.comShow current config:
npm run spike -- config-showLocal Sync Commands
Sync only priority publications:
npm run spike -- sync-priority 3 5This means:
last 3 days
up to 5 recent posts per priority publication
fetch full article bodies into the local cache
List cached unsummarized posts:
npm run spike -- cache-list 20Useful diagnostics:
npm run spike -- discover
npm run spike -- list-posts https://example-newsletter.substack.com 5MCP Server
Build and run the MCP server over stdio:
npm run build
npm startExample MCP client config:
{
"servers": {
"substack": {
"command": "node",
"args": [
"/absolute/path/to/substack-mcp/dist/server.js"
]
}
}
}Daily Copilot Workflow
Recommended tool sequence:
substack_sync_recent{ "days": 3, "limitPerPublication": 5, "priorityOnly": true, "fetchContent": true }substack_list_posts{ "summarized": false, "limit": 20 }For each post to summarize, call
substack_get_post_chunks.{ "postKeyOrUrl": "<postKey from substack_list_posts>", "maxChars": 8000 }After generating the daily summary, call
substack_mark_summarized.{ "postKeyOrUrls": ["<postKey>", "<postKey>"], "summaryDate": "2026-06-30" }
MCP Tools
substack_loginOpens the dedicated browser profile and waits for Substack login.
substack_sync_statusShows app paths, config, and login status.
substack_config_showShows local config.
substack_config_set_priority_publicationsSets priority publication URLs.
substack_config_set_defaultsSets default sync window and per-publication limit.
substack_discover_subscriptionsDiscovers publications from the authenticated reader account.
substack_sync_recentSyncs recent posts into SQLite.
substack_list_postsLists cached post metadata. This does not return full bodies.
substack_get_cached_postReturns one cached post with markdown.
substack_get_post_chunksReturns one cached post split into bounded markdown chunks.
substack_mark_summarizedMarks posts as included in a daily summary.
substack_list_recent_postsDiagnostic tool for listing recent posts from one publication.
substack_get_postDiagnostic tool for live-fetching one post as markdown.
Verification Status
Current verified behavior:
dedicated browser profile login works
subscription discovery works
paid full text works for authorized subscriptions
priority-only sync works
SQLite cache stores metadata and markdown
chunking works for long articles
npm run typecheckpassesnpm run buildpasses
Troubleshooting
Browser Opens and Closes Quickly
This usually means the dedicated profile is already logged in and the login check succeeded.
Run:
npm run spike -- statusPlaywright Browser Missing
Run:
npx playwright install chromiumSubstack Returns 429
Substack may rate-limit repeated sync attempts. Wait a few minutes and retry with a smaller window:
npm run spike -- sync-priority 3 2Paid Post Shows Preview Only
Check that the dedicated profile is logged into the account with the paid subscription:
npm run spike -- statusThen test the publication directly:
npm run spike -- list-posts https://example-newsletter.substack.com 5Reset Local State
The local data lives outside the repository:
~/Library/Application Support/mcp-substack/Remove only the files you intend to reset. Deleting browser-profile/ requires
logging into Substack again. Deleting substack.db removes cached articles and
summary state.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cchen7/substack-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server