Substack MCP Server
Allows for the programmatic management of Substack content, including creating, updating, and publishing draft posts, uploading images to Substack's CDN, posting short-form Notes, and managing live blogging sessions.
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 MCP Servercreate a new draft titled 'AI Trends' using my recent notes"
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.
Substack MCP Server
A Model Context Protocol (MCP) server for Substack integration with Claude Code and other MCP-compatible AI tools.
Features
Create and manage drafts - Create, update, and publish Substack posts programmatically
Image upload - Upload images to Substack's CDN with proper metadata
Live blogging - Real-time post updates with timestamps
Notes - Post short-form content to Substack Notes
Full ProseMirror support - Proper document structure for Substack's editor
Installation
# Clone the repo
git clone https://github.com/acolle/substack-mcp.git
cd substack-mcp
# Install dependencies
pip install -r requirements.txtTesting
python -m unittest discover -s testsSetup
1. Get your Substack credentials
Go to your Substack dashboard in Chrome/Safari
Open DevTools (Cmd+Option+I or F12)
Go to Application tab → Cookies → your-substack.substack.com
Find
substack.sidand copy its value
2. Create credentials file
# Create ~/.substackrc
cat > ~/.substackrc << 'EOF'
export SUBSTACK_PUBLICATION="your-publication.substack.com"
export SUBSTACK_SID="your-cookie-value-here"
EOF3. Add to Claude Code
# Add the MCP server to Claude Code
claude mcp add substack \
--command "bash" \
--args "-c" "source ~/.substackrc && python3 $(pwd)/substack_mcp/server.py"Or manually add to ~/.claude.json:
{
"mcpServers": {
"substack": {
"command": "bash",
"args": ["-c", "source ~/.substackrc && python3 /path/to/substack-mcp/substack_mcp/server.py"]
}
}
}Available Tools
Tool | Description |
| Create a new draft post |
| Update an existing draft |
| Append content (for live blogging) |
| Add a code block to a draft |
| Add an image to a draft |
| Publish a draft |
| Post a short note |
| List all drafts |
| List published posts |
| Start a live blogging session |
| End live blogging session |
Usage Examples
Create a post with Claude Code
You: Create a new Substack post about AI tools
Claude: I'll create a draft for you...
[Uses substack_create_draft tool]
Created draft 12345. Edit at: https://your-pub.substack.com/publish/post/12345Upload and embed images
You: Add this diagram to my post [image path]
Claude: I'll upload the image and add it to your draft...
[Uses substack_add_image tool]
Image added successfully.Live blogging
You: Start a live blog for the product launch
Claude: Starting live blog session...
[Uses substack_live_blog_start tool]
Live blog started. I'll append updates as they happen.API Reference
SubstackClient
The core client for interacting with Substack's API.
from substack_client import SubstackClient, SubstackDocument
# rate_limit is seconds between requests; timeout is per-request timeout.
client = SubstackClient(token="your-sid", publication="your-pub.substack.com", rate_limit=0.5, timeout=30.0)
# Upload an image
img = client.upload_image("/path/to/image.png")
# Returns: {"url": "https://...", "width": 800, "height": 600, "bytes": 12345, "contentType": "image/png"}
# Create a document
doc = SubstackDocument()
doc.heading("My Post", level=2)
doc.paragraph("Hello world!")
doc.image(src=img['url'], width=img['width'], height=img['height'],
bytes_size=img['bytes'], content_type=img['contentType'])
# Create and publish
draft = client.create_draft(title="My Post", body=doc)
client.publish_draft(draft.id, send_email=False)Key Technical Details
Image Node Structure
Substack uses ProseMirror and requires specific attributes for images:
{
"type": "captionedImage",
"content": [{
"type": "image2",
"attrs": {
"src": "https://substack-post-media.s3.amazonaws.com/...",
"width": 800,
"height": 600,
"bytes": 12345,
"type": "image/png",
"internalRedirect": "https://pub.substack.com/i/{draft_id}?img={encoded_url}",
"belowTheFold": false,
"topImage": false,
"isProcessing": false
}
}]
}The internalRedirect field is required - without it, Substack's editor fails to render the document.
Image Handling Notes
create_draftandupdate_draftautomatically add missinginternalRedirectvalues for any image nodes.Image captions are emitted as separate italic paragraphs (not
imageCaptionnodes) to avoid editor rendering issues.For best rendering results, upload images through
upload_image()and use the returned metadata.
Credits
License
MIT
Disclaimer
This uses Substack's unofficial/internal API which may change without notice. Use at your own risk.
This server cannot be installed
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/jessicaruthabbott/my-substack-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server