substack-publisher-mcp
This server lets you query and analyze Substack publication data using the official Publisher API. It supports the following capabilities:
List Publications – View all configured Substack publications (useful when managing multiple).
List Posts – Browse published posts with filtering by date range, post type (newsletter, podcast, video), and sort order; supports pagination.
Get Post Details – Retrieve full metadata for a specific post (title, subtitle, audience, publish date, etc.) using its URL slug.
Get Post Stats – Fetch engagement analytics for a specific post, including opens, clicks, views, recipients, new free/paid subscriptions, and estimated revenue.
Get Subscriber Counts – Pull daily subscriber counts broken down by subscription type (free, paid, trial, comp, gift, lifetime, founding) over a specified date range — useful for tracking growth and churn.
Look Up a Subscriber – Search for an individual subscriber by email to see their subscription type, status, and social handles.
All tools (except list_publications) support an optional publication parameter for targeting a specific publication when multiple are configured.
Provides tools for managing and analyzing Substack publications via the official Publisher API, including listing posts, retrieving subscriber counts, and fetching post engagement stats.
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-publisher-mcpShow my recent posts with stats"
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-publisher-mcp
MCP server for Substack's official Publisher API
Note: This is an unofficial, community-developed tool and is not affiliated with, endorsed by, or supported by Substack, Inc.
The first MCP server for Substack's official Publisher API. Query post analytics, subscriber counts, and publication data directly from Claude, Cursor, or any MCP client.

Why this server?
substack-publisher-mcp | Other Substack MCP servers | |
API | Official Publisher API | Unofficial internal API |
Auth | API key (stable) | Browser cookies (fragile) |
Stability | Official, documented API | Breaks when Substack changes internals |
Multi-publication | Built-in support | Not available |
Related MCP server: substack-mcp
Prerequisites
Node.js 18+. Check with
node --version; install from nodejs.org if missing.Substack Publisher API key. Generate one from your publication's Substack dashboard. If you don't see a Publisher API option there, it may not be enabled for your publication yet; see the Publisher API docs for availability.
Quick Start
1. Install
git clone https://github.com/dkships/substack-publisher-mcp.git
cd substack-publisher-mcp
npm install && npm run build2. Configure your MCP client
Add to your client's MCP config file (create the file if it doesn't exist):
Client | Config file |
Claude Desktop (macOS) |
|
Claude Desktop (Windows) |
|
Claude Code |
|
Cursor |
|
{
"mcpServers": {
"substack": {
"command": "node",
"args": ["/path/to/substack-publisher-mcp/dist/index.js"],
"env": {
"SUBSTACK_API_KEY": "your-api-key-here"
}
}
}
}Claude Code users: Add
"type": "stdio"to the server config.
Restart your MCP client after editing the config — servers load at startup.
3. Start using it
Ask Claude (or your MCP client):
"Which Substack publications do I have configured?"
"Show me my posts from the last month"
"Pull up my post with the slug my-latest-post"
"How many opens and clicks did my latest post get?"
"What are my subscriber counts for the last 30 days?"
"Look up subscriber jane@example.com"
Installing through an AI agent or registry? See llms-install.md for a condensed, machine-readable setup guide.
Tools
Tool | Description | Key Parameters |
| List configured publications | None |
| List published posts |
|
| Get a specific post by URL slug |
|
| Get engagement stats for a post |
|
| Get daily subscriber counts by type |
|
| Look up a subscriber by email |
|
All tools except list_publications accept an optional publication parameter when multiple publications are configured.
Example responses
[
{
"date": "2025-01-15",
"total_email_subscribers": 25000,
"paid_subscribers": 500,
"free_trial_subscribers": 10,
"comp_subscribers": 50,
"gift_subscribers": 15,
"lifetime_subscribers": 0,
"founding_subscribers": 25
}
]{
"clicks": 320,
"opens": 5400,
"post_id": 12345678,
"recipients": 10000,
"views": 6100,
"new_free_subscriptions": 80,
"new_paid_subscriptions": 5,
"estimated_revenue_increase": 400
}{
"posts": [
{
"title": "My Latest Post",
"audience": "only_paid",
"subtitle": "A deep dive into the topic",
"postDate": "2025-01-15T12:00:00.000Z",
"urlSlug": "my-latest-post",
"coverImage": "https://substackcdn.com/image/..."
}
],
"next": "abc123cursor"
}Multiple publications
If you manage multiple Substack publications, configure a separate API key for each using the SUBSTACK_API_KEY_<NAME> pattern:
{
"mcpServers": {
"substack": {
"command": "node",
"args": ["/path/to/substack-publisher-mcp/dist/index.js"],
"env": {
"SUBSTACK_API_KEY_MAIN": "your-main-blog-key",
"SUBSTACK_API_KEY_TECH": "your-tech-newsletter-key",
"SUBSTACK_API_KEY_COMPANY": "your-company-updates-key"
}
}
}
}Then specify which publication to query:
"Show me subscriber counts for main" "List recent posts from the tech publication"
Use list_publications to see all configured publication names.
Troubleshooting
Issue | Solution |
| Verify your API key is correct. The key goes directly in the |
| Only configure env vars for publications you have keys for. Remove the rest. |
Server won't start | Make sure you ran |
| Set |
Server doesn't appear in your client | Check the config file is valid JSON (no trailing commas), then restart the client. |
| Node.js isn't installed or isn't on your PATH. Check |
Still stuck | Check your client's MCP logs. Claude Desktop on macOS: |
API Reference
This server wraps the Substack Publisher API. See Substack's documentation for details on available data and rate limits.
Contributing
See CONTRIBUTING.md for guidelines.
License
MIT License. See LICENSE for details.
Substack is a trademark of Substack, Inc. This project is not affiliated with Substack, Inc. Use of the Substack name is for descriptive purposes only.
Available Tools
6 toolsget_postGet PostARead-onlyIdempotent
Get detailed information about a specific post by its URL slug. Returns full post metadata including title, subtitle, audience, publish date, and content details.
| Name | Required | Description | Default |
|---|---|---|---|
| urlSlug | Yes | The URL slug of the post (from list_posts results or the post URL). | |
| publication | No | Publication name (e.g., 'ny', 'la'). Required if multiple publications are configured. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, openWorldHint, idempotentHint. Description adds that it returns full post metadata but no additional behavioral traits like auth needs or rate limits. Adequate but not enhanced beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, front-loaded with purpose. No filler, every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers main use case well. Missing details about when publication parameter is required versus optional, and no error scenarios. With no output schema, could be more complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters with descriptions. Description adds 'by its URL slug' and mentions slug origin, but no new meaning beyond schema. Baseline 3 justified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Get detailed information about a specific post by its URL slug', specifying verb and resource. Distinguishes from siblings like 'get_post_stats' (stats) and 'list_posts' (multiple posts).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Mentions using URL slug from list_posts or URL, providing context. Does not explicitly state when not to use or compare with alternatives like get_post_stats, lacking exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_post_statsGet Post StatsARead-onlyIdempotent
Get engagement statistics for a specific post by its URL slug. Returns metrics like opens, clicks, and other engagement data.
| Name | Required | Description | Default |
|---|---|---|---|
| urlSlug | Yes | The URL slug of the post (from list_posts results or the post URL). | |
| publication | No | Publication name (e.g., 'ny', 'la'). Required if multiple publications are configured. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint as true. The description adds that it returns metrics like 'opens, clicks', but this is minimal extra value beyond annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with verb and resource, no wasted words. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (2 params, no output schema, rich annotations), the description is largely complete. It could optionally mention that the slug comes from list_posts, but this is implied by the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameters are already well-documented. The description mentions 'URL slug' and 'publication' implicitly but does not add significant meaning beyond what the schema provides, meriting the baseline score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Get'), the resource ('engagement statistics'), and the method ('by its URL slug'). It distinguishes itself from sibling tools like get_post and get_subscriber by specifically focusing on engagement data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when engagement metrics are needed but lacks explicit when-to-use, when-not-to-use, or alternative tool comparisons. No guidance on prerequisites or context for invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_subscriberGet SubscriberARead-onlyIdempotent
Look up a specific subscriber by email address. Returns their subscription details including type, status, and social handles.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | The subscriber's email address. | ||
| publication | No | Publication name (e.g., 'ny', 'la'). Required if multiple publications are configured. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint. Description adds value by specifying the return fields (type, status, social handles), exceeding the safety profile provided by annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no wasted words. Front-loaded with purpose, followed by output description. Efficient and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 2 parameters, no output schema, and rich annotations, the description covers the main functionality and return values. Slight gap on publication parameter meaning, but overall sufficient for a lookup tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, baseline 3. Description mentions lookup by email but does not explain the optional publication parameter beyond what the schema provides. No additional semantic clarity added.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the action (look up) and resource (subscriber by email), and lists the returned information (subscription details including type, status, social handles). Distinguishes from sibling tools like get_post and get_subscriber_counts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use vs alternatives. While lookup intent is clear, there are no exclusions or references to sibling tools (e.g., get_subscriber_counts) that perform similar but distinct functions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_subscriber_countsGet Subscriber CountsARead-onlyIdempotent
Get daily subscriber counts broken down by subscription type (free, paid, etc.). Useful for tracking growth and churn over time.
| Name | Required | Description | Default |
|---|---|---|---|
| endDate | No | End of date range (YYYY-MM-DD). | |
| startDate | No | Start of date range (YYYY-MM-DD). | |
| publication | No | Publication name (e.g., 'ny', 'la'). Required if multiple publications are configured. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the description adds the behavioral detail of returning daily counts broken by subscription type. This adds some context but is not extensive; no contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose. No redundant words, and the second sentence adds useful context. Highly concise and structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 parameters and no output schema, the description explains what the output looks like (daily counts by type) and its utility. It does not mention pagination or limits, but given the openWorldHint and readOnlyHint, this is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description does not add any meaning beyond what the schema provides for the parameters (startDate, endDate, publication).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and resource 'daily subscriber counts broken down by subscription type', and distinguishes it from sibling tools like get_post and get_post_stats which are focused on posts rather than subscriber analytics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Useful for tracking growth and churn over time' provides clear context for when to use the tool. While it does not explicitly mention alternatives or when not to use, the context is sufficient to guide the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_postsList PostsARead-onlyIdempotent
List posts published by a Substack publication. Returns post metadata including title, URL slug, audience, publish date, and type. Use the urlSlug from results with get_post or get_post_stats for details.
| Name | Required | Description | Default |
|---|---|---|---|
| next | No | Pagination cursor from a previous list_posts response. Pass this to get the next page of results. | |
| type | No | Filter by post type. | |
| sortBy | No | Sort order. Defaults to newest. | |
| endDate | No | Filter posts published on or before this date (YYYY-MM-DD). | |
| startDate | No | Filter posts published on or after this date (YYYY-MM-DD). | |
| maxResults | No | Maximum number of posts to return. Default 100. | |
| publication | No | Publication name (e.g., 'ny', 'la'). Required if multiple publications are configured. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint. The description adds behavioral context by listing returned metadata (title, URL slug, etc.) and implying pagination via 'next' parameter. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no unnecessary words. First sentence states purpose and return info, second gives actionable guidance. Highly efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description adequately covers return values (title, URL slug, etc.) and hints at pagination. For a list tool with well-documented parameters, this is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the description does not need to repeat parameter details. It mentions urlSlug in context but does not add new semantic meaning beyond the schema, earning the baseline score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'List posts published by a Substack publication' with a specific verb ('List') and resource ('posts'). It distinguishes from sibling tools like get_post and get_post_stats by implying it returns multiple posts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly recommends using urlSlug from results with get_post or get_post_stats for details, providing clear context for follow-up. However, it does not explicitly state when to use this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_publicationsList PublicationsARead-onlyIdempotent
List all configured Substack publications and their names. Use these names as the 'publication' parameter in other tools.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint. The description adds no further behavioral details beyond stating it lists names, which is adequate but not extra.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no wasted words, front-loaded with purpose. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with no output schema, the description adequately explains what is returned (publication names) and how to use them, making it complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so baseline 4 applies. The description adds no param info, but none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists all configured Substack publications and their names, with a specific verb 'list' and resource 'publications'. It distinguishes from sibling tools focused on posts, stats, and subscribers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells agents to use the output names as the 'publication' parameter in other tools, providing clear usage context. It doesn't mention when not to use, but the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
5 tool updates
v1.1.0- Changed
get_post1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_post_stats1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_subscriber3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / email / formatAdded value: +"email" - added
Input schema / properties / email / patternAdded value: +"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
- Changed
get_subscriber_counts3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / endDate / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / startDate / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
list_posts5 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / endDate / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / maxResults / maximumAdded value: +9007199254740991 - added
Input schema / properties / maxResults / minimumAdded value: +1 - added
Input schema / properties / startDate / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
6 tool updates
v1.0.0- First observed
get_post - First observed
get_post_stats - First observed
get_subscriber - First observed
get_subscriber_counts - First observed
list_posts - First observed
list_publications
TDQS
Each tool targets a distinct resource or aspect: post metadata vs. stats, individual subscriber vs. counts, and listing posts vs. publications. No overlap.
All tools follow a consistent verb_noun pattern (get/list + noun), with singular/plural used appropriately. No mixing of conventions.
6 tools is well-scoped for a read-only Substack publisher tool: covers publications, posts, subscribers, and stats without being overwhelming.
Read operations are well-covered (list, get details, get stats, get subscriber, counts), but lacks write operations (create, update, delete) which may be expected for a 'publisher' server. Minor gap.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
- SupabaseOAuthcom.supabase
MCP server for interacting with the Supabase platform
MCP server for structured access to Lenny Rachitsky podcast transcripts. For content creators.
MCP server for querying and analyzing data from ad platforms, analytics tools, and spreadsheets
Official Microsoft MCP Server to query Microsoft Entra data using natural language
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceAn MCP server that enables AI assistants like Claude to interact with Substack newsletters, allowing for post retrieval, content searching, and author information access through a standardized interface.-
- AlicenseAqualityDmaintenanceMCP server for Substack that lets Claude Code create drafts, upload images, set cover thumbnails, schedule, and publish posts on your Substack publication.1115MIT
- AlicenseAqualityDmaintenanceA tool that connects to Substack's official Publisher API to access posts, newsletters, analytics, and subscribers, compatible with MCP clients like Claude and Cursor.63MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for Substack that enables reading articles, comments, feed, and subscriptions from AI clients like Cursor and Claude, with optional authentication for paid content.353MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/dkships/substack-publisher-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server