substack-mcp
Indexes and enables searching of Substack blog posts, providing tools for full-text search, filtering, citation generation, and markdown export.
Click on "Deploy 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-mcpsearch my recent posts about artificial intelligence"
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 that indexes and enables searching of Substack blog posts. Built for the Fejl 40 publication.
Overview
This MCP server fetches blog posts from a Substack RSS feed and provides tools for searching and querying the content through Claude Desktop. It includes full-text search, in-memory caching, and automatic refresh capabilities.
Related MCP server: substack-mcp-plus
Features
Full-text Search: Search across post titles, content, and descriptions using FlexSearch
Persistent Disk Cache: Saves posts to disk for instant startup (~/.cache/substack-mcp/)
Smart Caching: In-memory cache with configurable TTL (default: 30 minutes)
Auto-refresh: Automatically updates when cache expires
7 MCP Tools:
search_posts- Search by keywordslist_recent_posts- Get most recent postsget_post_by_title- Find by titleget_post_by_url- Get by URLget_posts_by_date_range- Filter by date rangegenerate_citation- Generate formatted citations (APA, MLA, Chicago, markdown)export_to_markdown- Export posts to markdown files
Installation
Prerequisites
Node.js 18 or higher
Claude Desktop app
npm
Setup
Clone or download this repository:
git clone https://github.com/andersschaffner/substack-mcp.git cd substack-mcpInstall dependencies:
npm installBuild the project:
npm run buildConfigure Claude Desktop:
Add this to your Claude Desktop config file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%/Claude/claude_desktop_config.json
{ "mcpServers": { "substack-mcp": { "command": "node", "args": ["/absolute/path/to/substack-mcp/index.js"], "env": { "SUBSTACK_FEED_URL": "https://fejl40.substack.com/feed" } } } }Important: Replace
/absolute/path/to/substack-mcp/with the actual path where you cloned the repo.Restart Claude Desktop
Configuration
Environment Variables
SUBSTACK_FEED_URL- The RSS feed URL for your Substack publication (required)CACHE_TTL_MS- Cache time-to-live in milliseconds (default: 1800000 = 30 minutes)
Using with a Different Substack
To use with a different Substack publication, simply change the SUBSTACK_FEED_URL in your Claude Desktop config:
"env": {
"SUBSTACK_FEED_URL": "https://your-publication.substack.com/feed"
}Usage
Once installed and configured, you can ask Claude questions about your blog posts:
"Search my blog posts about AI"
"What have I written about product management?"
"Show me my most recent blog posts"
"Find my post about [specific topic]"
"What did I write in December 2024?"
Claude will automatically use the MCP tools to search and retrieve your blog content.
Available Tools
search_posts
Search blog posts by keywords across title and content.
Parameters:
query(string, required) - Search querylimit(number, optional) - Maximum results (default: 10)
list_recent_posts
List the most recent blog posts.
Parameters:
limit(number, optional) - Number of posts (default: 10)offset(number, optional) - Posts to skip (default: 0)
get_post_by_title
Get a specific post by exact or partial title match.
Parameters:
title(string, required) - Post title or partial titleexact(boolean, optional) - Require exact match (default: false)
get_post_by_url
Retrieve a specific post by its URL.
Parameters:
url(string, required) - Full URL of the Substack post
get_posts_by_date_range
Get posts published within a date range.
Parameters:
start_date(string, required) - Start date (ISO 8601 format)end_date(string, required) - End date (ISO 8601 format)limit(number, optional) - Maximum results (default: 100)
generate_citation
Generate a formatted citation for a blog post.
Parameters:
url(string, required) - URL of the blog post to citestyle(string, optional) - Citation style: 'APA', 'MLA', 'Chicago', or 'markdown' (default: 'markdown')
Example output:
{
"citation": "[Post Title](https://fejl40.substack.com/...) by Anders Schaffner, December 15, 2024",
"style": "markdown",
"post": {
"title": "Post Title",
"link": "https://fejl40.substack.com/...",
"author": "Anders Schaffner",
"pubDate": "2024-12-15T..."
}
}export_to_markdown
Export blog posts to a markdown file.
Parameters:
output_path(string, required) - Output file path (e.g., ~/Desktop/posts.md)query(string, optional) - Search query to filter postsstart_date(string, optional) - Start date filter (ISO 8601 format)end_date(string, optional) - End date filter (ISO 8601 format)limit(number, optional) - Maximum posts to export (default: 100)
Example usage:
Export all posts:
export_to_markdown({ output_path: "~/Desktop/all-posts.md" })Export AI-related posts:
export_to_markdown({ output_path: "~/Desktop/ai-posts.md", query: "AI" })Export 2024 posts:
export_to_markdown({ output_path: "~/Desktop/2024.md", start_date: "2024-01-01", end_date: "2024-12-31" })
Development
Scripts
npm run build- Build the TypeScript projectnpm run dev- Build in watch modenpm start- Run the compiled server
Project Structure
.
├── src/
│ ├── index.ts # Main MCP server
│ ├── post-cache.ts # Caching and search logic with disk persistence
│ ├── rss-fetcher.ts # RSS feed parser
│ ├── citation.ts # Citation formatting (APA, MLA, Chicago, markdown)
│ ├── export.ts # Export to markdown/JSON
│ ├── types.ts # TypeScript interfaces
│ └── utils.ts # Helper functions
├── build.js # esbuild configuration
├── package.json
├── tsconfig.json
└── index.js # Compiled outputHow It Works
Server Startup: When Claude Desktop launches, it starts the MCP server
Disk Cache Load: Server attempts to load posts from disk cache (~/.cache/substack-mcp/posts.json)
RSS Fetch: If disk cache is missing or stale, fetches posts from the Substack RSS feed
Indexing: Posts are indexed with FlexSearch for fast searching
Disk Persistence: Posts are saved to disk cache for instant startup next time
Memory Caching: Posts are cached in memory with a 30-minute TTL
Auto-refresh: Cache automatically refreshes when it expires
Tool Calls: Claude calls the MCP tools when you ask about your blog
Performance: With disk cache, startup is nearly instant (< 1 second). Without disk cache, first startup takes 3-5 seconds to fetch RSS.
Troubleshooting
"Command not found" or server won't start
Ensure the path in
claude_desktop_config.jsonis absolute, not relativeVerify Node.js is installed:
node --versionCheck that
index.jsexists after runningnpm run build
No posts found
Verify the RSS feed URL is correct and accessible
Check Claude's MCP logs:
~/Library/Logs/Claude/mcp*.logEnsure the RSS feed has posts
JSON parse errors
Make sure you're using the latest build
All logging should go to stderr, not stdout
Technical Details
Language: TypeScript
Runtime: Node.js 18+
Build Tool: esbuild
Search Engine: FlexSearch
RSS Parser: rss-parser
MCP SDK: @modelcontextprotocol/sdk v1.25+
License
ISC
Author
Anders Schaffner
Contributing
Feel free to open issues or submit pull requests for improvements!
Available Tools
7 toolsexport_to_markdownC
Export blog posts to a markdown file
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of posts to export (default: 100) | |
| query | No | Optional search query to filter posts | |
| end_date | No | Optional end date filter (ISO 8601 format) | |
| start_date | No | Optional start date filter (ISO 8601 format) | |
| output_path | Yes | Output file path (e.g., ~/Desktop/posts.md) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It implies a file write to output_path but never states whether an existing file is overwritten or appended, whether the target directory must exist, whether this requires write permissions, or how multiple posts are combined into one markdown file.
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?
A single front-loaded sentence with zero filler. It is efficient, though its brevity borders on under-specification for a tool that writes to disk.
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 five-parameter tool with a filesystem side effect and no annotations or output schema, the description leaves key questions unanswered: overwrite behavior, file format layout, error handling, and whether the date/query filters apply to the export. It is too thin for a mutation 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 description coverage is 100%, so all five parameters (limit, query, dates, output_path) are already documented in the schema. The description adds no syntax, format, or interaction details beyond that, so the baseline 3 applies.
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?
States a specific verb (export) and resource (blog posts) plus the output form (markdown file), so the core action is unambiguous. However, it does nothing to distinguish itself from sibling read tools like list_recent_posts or search_posts, and it's unclear whether it exports all posts or a filtered set.
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 when-to-use guidance and no mention of alternatives. It doesn't tell the agent when to reach for this tool instead of search_posts or get_posts_by_date_range, or whether the filters (query, start_date, end_date) should be used to narrow the export.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_citationB
Generate a formatted citation for a blog post
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL of the blog post to cite | |
| style | No | Citation style: APA, MLA, Chicago, or markdown (default: markdown) | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden but discloses almost nothing beyond the action. It does not say whether the URL is fetched live, whether any network/auth is required, whether anything is persisted, or what the output looks like, which matters for a tool with no output schema.
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?
A single economical sentence with the core action and object front-loaded. Nothing extraneous; 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?
For a simple two-parameter generation tool this is minimally adequate, but with no output schema and no annotations it should clarify what 'formatted citation' returns (e.g. a string of citation text) and whether the URL is fetched. Those gaps leave the tool usable but under-specified.
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%, with the enum of styles and default already fully documented in the schema. The description adds no syntax, format, or behavior details beyond what the schema provides, so the baseline of 3 applies.
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?
States a specific verb ('Generate') and resource ('formatted citation for a blog post'), which is clearly distinct from the retrieval-focused siblings (search_posts, get_post_by_url, etc.). However, it does not explicitly name or contrast with any sibling to reinforce the distinction.
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 guidance on when to use this versus alternatives, no prerequisites, and no exclusions. The description only restates the action, leaving the agent to infer context from the name and siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_post_by_titleC
Get a specific post by exact or partial title match
| Name | Required | Description | Default |
|---|---|---|---|
| exact | No | Require exact match (default: false) | |
| title | Yes | Post title or partial title to search for |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It says nothing about case sensitivity, partial-match behavior, ambiguity handling when multiple posts match, or whether an exact-match result returns a single post versus a list. For a lookup tool with zero annotation coverage, these gaps matter.
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?
A single efficient sentence that front-loads the verb and resource. No filler, though it is arguably under-specified rather than minimalist.
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 two-parameter lookup with no annotations and no output schema, the description omits key behavioral details: ambiguity handling, match semantics, and return type. It is not complete enough for an agent to call it reliably without inferring behavior.
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 both parameters are documented in the schema (including the 'exact' boolean default). The description adds only a marginal restatement of 'exact or partial title match' and does not add syntax or format meaning beyond the schema baseline.
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 explicitly states a verb ('Get') and resource ('post by exact or partial title'), and clarifies the matching scope. It adequately distinguishes itself from get_post_by_url, but does not mention the pattern-matching versus list/search siblings like search_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?
No guidance on when to prefer this over search_posts, list_recent_posts, or get_post_by_url. An agent cannot tell whether this performs a lookup or a fuzzy search from the description alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_post_by_urlC
Retrieve a specific post by its URL
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Full URL of the Substack post |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, and it discloses almost nothing. It does not say what happens on an invalid/unresolvable URL, whether auth is required, or what is returned. The only implicit signal is that it is a read operation.
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?
A single efficient sentence with no filler, and the identifying detail (by its URL) is front-loaded. It is under-specified rather than verbose, which is a content problem rather than a structure problem.
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 one-parameter read tool with full schema coverage and no output schema, the description is just barely sufficient. It omits any return-shape or failure-mode context, which leaves an agent guessing about error handling.
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% and the single url parameter is already documented as the full URL of the Substack post. The description adds no format details (e.g. slug or canonical form requirements) beyond the schema, so the baseline 3 applies.
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?
States a specific verb (Retrieve) and resource (a specific post) plus the lookup key (URL), which implicitly separates it from the sibling get_post_by_title. No explicit sibling naming, so it falls short of a 5.
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 when-to-use guidance at all: it never says when a URL lookup is preferable to search_posts or get_post_by_title, nor does it mention prerequisites such as requiring the post to be public. The agent must infer all routing from the tool name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_posts_by_date_rangeC
Get posts published within a date range
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results (default: 100) | |
| end_date | Yes | End date (ISO 8601 format, e.g., 2024-12-31) | |
| start_date | Yes | Start date (ISO 8601 format, e.g., 2024-01-01) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, yet it says nothing about ordering, pagination behavior, whether the range is inclusive, or permissions required. Beyond confirming it is a read-style retrieval, no behavioral context is added.
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?
A single tight sentence with no filler and the core scope front-loaded. It is efficient, though arguably under-specified rather than truly concise given the tool's complexity.
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?
With no annotations, no output schema, and a default limit of 100, the description should clarify return shape and whether results are truncated, but it does neither. It is incomplete for an agent that needs to know what it gets back and whether to paginate.
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 start_date, end_date, and limit are already fully documented in the schema (including ISO 8601 format and the default). The description adds nothing beyond the date-range concept already conveyed by the name, so the baseline 3 applies.
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?
States a specific verb (Get) and resource (posts) with the scoping condition (published within a date range), so the agent knows it retrieves posts by publication date. It is distinguishable from list_recent_posts by the explicit date-range framing, though it never names or contrasts with any sibling.
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 when-to-use guidance, no exclusions, no mention of when search_posts or list_recent_posts would be preferable. The date-range constraint is implied by the name and description, but the agent must infer the selection criteria on its own.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_recent_postsC
List the most recent blog posts
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of posts to return (default: 10) | |
| offset | No | Number of posts to skip (default: 0) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. "List" implies a safe read, but nothing is said about ordering (is it newest-first?), whether results are paginated, or what the response contains.
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?
A single short sentence with zero waste and the resource front-loaded after the verb. It is arguably too terse to be maximally useful, but there is no filler.
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 two-parameter read tool with a fully documented schema, the description is minimally adequate. It still omits ordering behavior and any hint of default result size, which an agent calling a "recent posts" list would reasonably want.
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% and both limit and offset are documented in the schema with defaults. The description adds no syntax, range, or default detail, so the baseline of 3 applies.
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?
States a specific verb ("List") and resource ("blog posts") with a scope qualifier ("most recent"), so the agent knows the operation. It does not, however, distinguish itself from siblings like get_posts_by_date_range or search_posts, which could plausibly cover overlapping territory.
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 when-to-use or when-not-to-use guidance is given, and no alternative tool is named. The phrase "most recent" hints at a recency-based use case but leaves the agent to infer when this beats get_posts_by_date_range or search_posts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_postsB
Search blog posts by keywords across title, content, and description
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results (default: 10) | |
| query | Yes | Search query to find in posts |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It states what fields are searched but does not mention read-only nature, safety profile, matching semantics (e.g., AND/OR, fuzzy), ranking, pagination behavior, or authentication requirements, leaving key operational traits unspecified.
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?
The description is a single, well-structured sentence with no wasted words. The tool's purpose is front-loaded immediately, making it easy to parse.
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 low-complexity search tool with fully described parameters and no output schema, the description states the search scope but omits usage context relative to the many sibling retrieval tools and provides no behavioral details. It is minimally adequate but leaves clear gaps for an agent choosing among alternatives.
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 the schema already documents both parameters, including the default for 'limit'. The description adds some meaning by indicating that the query searches across title, content, and description, but it does not add syntax, format, or matching details beyond the schema. The baseline of 3 applies.
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 uses a specific verb ('Search') and resource ('blog posts'), and specifies the fields searched ('title, content, and description'). It clearly implies a full-text keyword search, which is distinct from siblings like get_post_by_title or get_posts_by_date_range, but it does not explicitly differentiate itself from those alternatives.
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 gives no explicit guidance on when to use this tool versus alternatives such as list_recent_posts or get_post_by_title. Usage is only implied by the word 'Search' and the search scope, with no stated conditions, exclusions, or alternative selection criteria.
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.
7 tool updates
v1.0.0- First observed
export_to_markdown - First observed
generate_citation - First observed
get_post_by_title - First observed
get_post_by_url - First observed
get_posts_by_date_range - First observed
list_recent_posts - First observed
search_posts
TDQS
Scored across 7 tools
The five retrieval tools differ by access pattern (keyword, recency, title, URL, date range), which is mostly clear. However, get_post_by_title and search_posts can overlap when a title is used as a keyword, and generate_citation vs export_to_markdown both consume posts, creating mild boundary blur.
All tools follow a consistent snake_case verb_noun pattern (search_posts, list_recent_posts, get_post_by_title, export_to_markdown). The convention is predictable and readable throughout.
Seven tools is well-scoped for a blog reading/search server, with each tool earning its place by covering a distinct retrieval or output mode.
Core read workflows (search, recency, by title, by URL, by date, cite, export) are well covered. Minor gaps exist around author/subscription or comment retrieval, but these are workable given the reading-focused scope.
Maintenance
Related MCP Connectors
Search Hacker News, Bluesky, and Substack from a single MCP interface
Search your Glasp web and Kindle highlights, notes, and AI memories from any MCP client. Read-only.
Search your newsletter and YouTube archive, drafted actions and working context from any MCP client.
Search, organize, and chat with your saved Reddit posts from Claude, Cursor, and any MCP client.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables programmatic management of Substack content, including creating drafts, publishing posts, and uploading images. It supports specialized features like live blogging and posting to Substack Notes through MCP-compatible AI tools.MIT
- AlicenseNot gradedqualityDmaintenanceCreate, manage, and publish Substack posts with full rich text formatting directly from Claude Desktop or any MCP-compatible client.40 npm23MIT
- 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.20 npm2MIT
- AlicenseAqualityAmaintenanceA local MCP server for managing saved Substack posts. Enables offline reading, searching, bookmarking, and unbookmarking of Substack content via CLI or MCP clients.17MIT