Skip to main content
Glama
flap4fun

substack-vault

by flap4fun

Substack Vault

English · 中文

Collect Substack newsletters from Zoho Mail, archive them locally, and analyze via MCP Streamable HTTP with cross-author search.

v0.1.0 — Initial release: Zoho sync, Web UI, article library, and MCP tools.

Features

Module

Description

Mail ingestion

Zoho Mail OAuth (Self Client + Grant Code), full Substack email body

Session archive

Paste your own Substack session cookie to import subscriptions and pull historical (including paid) posts you already subscribe to

Subscriptions

Enable/disable feeds, inbox scan for new authors, link orphans by sender_email

Article library

List/card views, filter by author/date/keyword; drawer reader, copy, export Markdown

AI analysis

DeepSeek (deepseek-v4-flash): saved schemes, date range + authors + keywords, cross-author comparison

Sync engine

Manual/scheduled incremental sync, configurable lookback, sync log

Web UI

Dashboard, subscriptions, articles, AI analysis, accounts, sync log, settings; light/dark theme

MCP

Streamable HTTP endpoint for Cursor and other agents; cross-author topic search

Local-first

SQLite storage, encrypted OAuth/LLM tokens on disk, binds to 127.0.0.1 by default

Related MCP server: MailMesh MCP

Requirements

Quick start

git clone https://github.com/flap4fun/substack-vault.git
cd substack-vault

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
# Optional: OCR for image-only Substack emails (e.g. weekly image posts)
pip install -e ".[ocr]"

cp .env.example .env               # Windows: copy .env.example .env

Optional: image OCR (Tesseract)

Some paid newsletters put the body in images. Vault OCRs those from Zoho email HTML (not the public Substack site, which may be paywalled).

  1. Install Tesseract with language packs chi_tra and eng

  2. pip install -e ".[ocr]"

  3. Re-sync articles to re-fetch email HTML when needed and OCR images

Email sync only sees recent inbox mail. To pull older posts from publications you already pay for:

  1. Sign in to Substack in your browser

  2. Copy connect.sid / substack.sid (DevTools → Application → Cookies) or export a JSON cookie array

  3. In Settings, paste the cookie and save (Vault probes profile/self and encrypts it locally)

  4. In Subscriptions, use Import from Substack then Pull history

Do not commit cookies. This version has no password / OTP auto-login. Use only your own subscribed content.

Start the server:

substack-vault

Open http://127.0.0.1:8765 in your browser. Use this URL directly — do not serve web/ with Live Server or another static file server.

Docker (optional)

Run the whole app (including Tesseract OCR) in a container — no Python, venv, or Tesseract install on the host:

cd substack-vault
cp .env.example .env        # compose reads secrets from this file
docker compose up -d --build

Open http://127.0.0.1:8765. The SQLite database and encrypted keys live in the Docker named volume substack-vault_vault-data, so data survives image rebuilds.

Useful commands:

docker compose logs -f        # follow logs
docker compose restart         # restart the app
docker compose down            # stop (data kept)
docker compose down -v         # stop AND delete all data

Notes:

  • The host port is bound to 127.0.0.1 only. Keep it that way — the MCP endpoint has no authentication.

  • Fill in VAULT_ZOHO_* (and optionally DeepSeek credentials in Settings) before connecting; compose passes the VAULT_ZOHO_* values from your .env into the container.

  • OCR (Tesseract chi_tra+eng) is already inside the image, so image-only posts work out of the box.

  • Substack outbound access uses VAULT_PROXY from .env (for example, http://host.docker.internal:7890); it does not depend on the Windows system-proxy toggle and tries direct access when the proxy is unavailable.

  • Linux users who prefer direct file access can bind-mount instead of the named volume: replace the volumes: block in docker-compose.yml with - ~/.substack-vault:/data, after sudo chown -R 1000:1000 ~/.substack-vault.

Connect Zoho Mail

Self Client apps do not support browser OAuth redirects. You must generate a Grant Code manually.

1. Create a Self Client in Zoho API Console

  • Type: Self Client

  • Redirect URI: http://localhost:8765/oauth/zoho/callback (must match .env)

  • Scopes (paste when generating code):

ZohoMail.messages.READ,
ZohoMail.accounts.READ,
ZohoMail.folders.READ,
offline_access

offline_access is required for refresh tokens; without it you must re-authorize when tokens expire.

2. Connect in the Web UI

  1. Open 邮箱账号 (Mail accounts) → 连接 Zoho Mail

  2. Select your data center (default: Global .com)

  3. Enter Client ID, Client Secret, and Grant Code

  4. After connecting, use 手动同步 (Sync now) in the top bar

Credentials can also go in .env (see Configuration). UI-saved credentials are stored locally as well.

3. Subscriptions and sync

  1. 订阅管理 (Subscriptions) → 扫描发现 (Scan inbox) to discover Substack senders

  2. Enable subscriptions you want to sync

  3. 手动同步 or wait for the background job (default: every 30 minutes)

Web UI

Page

Purpose

Dashboard

Article/subscription stats, recent sync activity

Subscriptions

Author list, enable toggle, inbox scan, article count & last update

Articles

Filters, resizable reading drawer, copy/export Markdown; Send to AI analysis

AI analysis

Saved schemes, authors/keywords/date range → DeepSeek Markdown report

Mail accounts

Zoho connection status, read-only sync policy

Sync log

Per-run counts, duration, errors

Settings

Theme, DeepSeek API base URL + key, compact list

AI analysis (DeepSeek)

  1. Open SettingsAI / DeepSeek, set API Key (default base URL https://api.deepseek.com)

  2. Open AI analysis, pick or edit a scheme (seeded: “跨作者观点对比”)

  3. Choose date range, 1–N authors, 1–N keywords (e.g. tickers), then Run

  4. Or from Articles, set filters and click Send to AI analysis

Model is fixed to deepseek-v4-flash. The API key is Fernet-encrypted locally (same as Zoho secrets).

Display timezone defaults to Asia/Shanghai (UTC+8); the database stores UTC.

Cursor MCP

With substack-vault running, add to Cursor MCP settings:

{
  "mcpServers": {
    "substack-vault": {
      "url": "http://127.0.0.1:8765/mcp"
    }
  }
}

Tools

Tool

Description

list_subscriptions

List all Substack subscriptions

list_articles

List articles by author slug or keyword

get_article

Full text and metadata by ID

search_articles

Search titles and bodies

find_topic_across_authors

Same topic across authors for viewpoint comparison

get_sync_status

Sync state and recent logs

Example: ask an agent to compare how different authors cover a topic, or summarize the past week’s posts.

Configuration

.env example (VAULT_ prefix):

# Zoho OAuth
VAULT_ZOHO_CLIENT_ID=
VAULT_ZOHO_CLIENT_SECRET=
VAULT_ZOHO_REDIRECT_URI=http://localhost:8765/oauth/zoho/callback

# Server
VAULT_HOST=127.0.0.1
VAULT_PORT=8765

# Optional Substack proxy fallback; direct Substack access is also built in
VAULT_PROXY=

# Sync (optional)
VAULT_SYNC_INTERVAL_MINUTES=30
VAULT_SYNC_LOOKBACK_DAYS=90
VAULT_SYNC_SUBSCRIBED_ONLY=true

Variable

Default

Description

VAULT_HOST

127.0.0.1

Bind address

VAULT_PORT

8765

Port

VAULT_SYNC_INTERVAL_MINUTES

30

Background sync interval (minutes). Can also be changed from Settings → Scheduled sync (30–1440) without restart; the UI value takes precedence

VAULT_SYNC_LOOKBACK_DAYS

90

Initial / lookback window (days)

VAULT_SYNC_SUBSCRIBED_ONLY

true

Sync only enabled subscriptions

VAULT_PROXY

empty

Optional proxy for Substack requests; failures automatically fall back to direct access

Data directory

Platform

Path

Windows

%USERPROFILE%\.substack-vault\

macOS / Linux

~/.substack-vault/

Contains vault.db (SQLite), encryption key, and OAuth credentials. Do not commit this directory.

Development

pip install -e ".[dev]"
pytest

Layout:

src/substack_vault/
  api/          FastAPI REST + static Web
  connectors/   Zoho Mail connector
  parsers/      Substack email parser
  sync/         Sync engine
  storage/      SQLAlchemy models & DB
  mcp/          MCP Streamable HTTP
web/            Frontend static assets
tests/          Unit & API tests
openspec/       Specs & change history (OpenSpec)

Roadmap

  • Outlook and other mail providers

  • RSS body enrichment

  • Article tags and advanced filters

  • Analysis run history / streaming UI / more LLM providers

  • Multi-user / remote deployment

Limitations

  • Zoho Mail only (international and regional data centers)

  • Single-machine local deployment; no multi-tenant or cloud sync

  • Substack HTML parsing depends on email templates; unusual layouts may lose formatting

  • Image-body posts need local Tesseract (chi_tra+eng); OCR is best-effort

  • Paid full text: recent mail via Zoho; older / paywalled posts via your own session cookie in Settings. Never commit cookies

  • In-app AI supports DeepSeek official only; model fixed to deepseek-v4-flash

  • MCP endpoint has no authentication — do not expose to the public internet

License

MIT © 2026 flap4fun

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

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

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    A private, single-user MCP server that unifies Gmail, Microsoft 365/Outlook, and IMAP mailboxes for LLMs to search and read emails live, without storing or caching mailbox contents.
    -
  • A
    license
    A
    quality
    A
    maintenance
    A local MCP server for managing saved Substack posts. Enables offline reading, searching, bookmarking, and unbookmarking of Substack content via CLI or MCP clients.
    17
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    MCP server for human-reviewed Zoho Mail inbox triage. It uses a two-pass proposal/execution model to propose actions (move, archive, mark-read) without touching the inbox until a human approves, and treats email content as untrusted data to prevent prompt injection.
    -

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/flap4fun/substack-vault'

If you have feedback or need assistance with the MCP directory API, please join our Discord server