Skip to main content

Substack Saved Posts MCP & CLI

A local, stdio-based Model Context Protocol (MCP) server and sync engine for your saved/bookmarked Substack posts.

Features

  • Read & Search: Full-text search (SQLite FTS5) across saved post titles, excerpts, authors, and publications. Filter by publication, audience tier (e.g. everyone, only_paid), and date ranges (published_at vs saved_at). Search also covers a post's full body text, but only for posts whose content has already been fetched once via get-content / the get_post_content tool — a normal sync stores metadata and excerpts, not full bodies, so posts you haven't opened yet are matched on their title/excerpt/metadata only, not their full text.
  • Full Content for LLMs: Fetch a saved post's full content and get it back cleaned and formatted (headings, lists, links) for feeding directly to an LLM, with the result cached locally for next time.
  • Save & Unsave: Bookmark new Substack posts or unbookmark existing ones via authenticated browser sessions.
  • Offline First: Fast, offline queries directly from local SQLite cache.
  • Privacy & Security: Keeps session credentials local, redacting tokens from logs.
  • FastMCP Protocol: Stdio MCP interface with rich tool suite and resources.

Installation with uv

uv is the recommended fast Python package manager for installing and running substack-saved-mcp.

Option A: Install System-wide as a Tool (uv tool install)

Install directly from your local repository folder:

# Navigate to the repository
cd /path/to/substack-saved-mcp

# Install system-wide into an isolated uv environment
uv tool install .

# Or install directly from a remote Git repository:
# uv tool install git+https://github.com/your-username/substack-saved-mcp.git

After installation, substack-saved-mcp is immediately available in your PATH:

# Verify installation
substack-saved-mcp --help

To update or uninstall:

# Upgrade installed tool
uv tool upgrade substack-saved-mcp

# Uninstall tool
uv tool uninstall substack-saved-mcp

Option B: Local Development / Development Environment (uv sync)

If you are developing or modifying the codebase:

# Clone and enter directory
cd substack-saved-mcp

# Install dependencies and dev tools (pytest)
uv sync --extra dev

# Run CLI commands using uv run
uv run substack-saved-mcp --help

# Run tests
uv run pytest

Quick Start

# 1. Initialize local database
substack-saved-mcp init

# 2. Authenticate with Substack (opens interactive browser window once)
substack-saved-mcp login

# 3. Sync saved posts into local cache
substack-saved-mcp sync

# 4. Search saved posts via CLI
substack-saved-mcp search "artificial intelligence"

# 4b. Filter by publication or audience tier (see which tiers are cached with `audiences`)
substack-saved-mcp audiences
substack-saved-mcp list --audience only_paid
substack-saved-mcp search "artificial intelligence" --audience everyone

# 5. Save or unsave a post
substack-saved-mcp save "https://example.substack.com/p/post-slug"
substack-saved-mcp unsave "https://example.substack.com/p/post-slug"

# 6. Get a saved post's full content, cleaned up and ready for an LLM
substack-saved-mcp get-content "https://example.substack.com/p/post-slug"

# 7. Launch stdio MCP server
substack-saved-mcp serve

Configuring MCP Clients (Claude Desktop, Goose, Cursor, etc.)

Add substack-saved-mcp to your MCP client's configuration file (e.g. claude_desktop_config.json).

Using System-Wide Installed Tool (uv tool or global binary)

{
  "mcpServers": {
    "substack-saved": {
      "command": "substack-saved-mcp",
      "args": ["serve"]
    }
  }
}

Using uv directly from the Repository Path

If you prefer running directly from your repository path without installing system-wide:

{
  "mcpServers": {
    "substack-saved": {
      "command": "uv",
      "args": [
        "--directory",
        "/path/to/substack-saved-mcp",
        "run",
        "substack-saved-mcp",
        "serve"
      ]
    }
  }
}

Frequently Asked Questions (FAQ)

Where is the database saved?

By default, the SQLite database is saved in your OS application data directory:

  • Linux / macOS: ~/.local/share/substack-saved-mcp/saved_posts.sqlite
    (or $XDG_DATA_HOME/substack-saved-mcp/saved_posts.sqlite if XDG_DATA_HOME is set)

You can specify a custom database path or directory using environment variables:

export SUBSTACK_SAVED_DB_PATH="/path/to/my/custom_database.sqlite"
# or
export SUBSTACK_SAVED_DATA_DIR="/path/to/my/data_dir"

Will a browser window pop up when running as an MCP server?

No, a visible browser window will not open during normal MCP operations.

  • Read & Search Tools (search_saved_posts, list_saved_posts, get_saved_post, list_publications, saved_posts_status):
    Operate 100% offline using the local SQLite database. Zero browser activity.
  • Sync & Write Tools (sync_saved_posts, save_post, unsave_post, get_post_content):
    Run in headless background mode using the pre-authenticated session stored in storage_state.json.
  • Interactive Login:
    A visible browser window opens only when you manually run substack-saved-mcp login from your terminal. If your session expires while using an MCP client, the tool will return a clear error message instructing you to re-authenticate via substack-saved-mcp login instead of popping open a browser window unexpectedly.

What if I get a Playwright "Executable doesn't exist" error?

If you encounter an error like BrowserType.launch: Executable doesn't exist when running commands (especially login), it means Playwright hasn't installed its required browsers in the isolated environment.

To fix this, you need to run the playwright install command inside the environment where the tool is installed.

For a system-wide tool installation (via uv tool install), run:

~/.local/share/uv/tools/substack-saved-mcp/bin/playwright install

If you are using a local development environment (via uv sync), run:

uv run playwright install

I edited the source code, but the installed substack-saved-mcp command still behaves like the old version. Why?

uv tool install copies the package into its own isolated environment at install time — it does not track your working tree. If you edited files under src/ (or pulled new commits) after installing the tool system-wide, the globally installed copy is stale and keeps running the old code, even though uv run substack-saved-mcp ... from the repo would use the latest source.

Reinstall from your current working tree to pick up the changes:

uv tool install . --no-cache --force
  • --force replaces the existing installed version instead of skipping the install because a version is already present.
  • --no-cache ensures a fresh build rather than reusing a cached wheel/build artifact from before your edits.

Do this any time after modifying the codebase and before relying on the globally installed substack-saved-mcp binary (as opposed to uv run substack-saved-mcp, which always reflects the working tree).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

substack_saved_mcp-0.1.0.tar.gz (140.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

substack_saved_mcp-0.1.0-py3-none-any.whl (32.5 kB view details)

Uploaded Python 3

File details

Details for the file substack_saved_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: substack_saved_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 140.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for substack_saved_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2ad5b4725d7f5c4e44dbab13ad272d917137366d8aba907cbc13e3e4f8f804eb
MD5 ae1ad7b92ffebf751227cc7d3d47fe1a
BLAKE2b-256 a31b6d043e04ac24e98318843c4101487d5da6601c79a8e7641fb90b026b2238

See more details on using hashes here.

File details

Details for the file substack_saved_mcp-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for substack_saved_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2b123061f105c7d4ce195273a5fe020927b6ccaff85ae3fa8d0a4524db879acd
MD5 55b6845b139bfca36eb18db8971d8a8d
BLAKE2b-256 530f81110519ad21042c0cb1ce9944f364697211c72e7a7d2e1abb342a35cf18

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page