AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Substack Ops

mcp-06ketan-substack-ops · by 06ketan

Substack CLI + 26-tool MCP server. Your IDE drafts replies via propose_reply. No API keys.

— No reviews yet
0 installs
32 views
0.0% view→install

Install

$ agentstack add mcp-06ketan-substack-ops

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.3.1 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ● Network access Used
  • ✓ Filesystem access No
  • ● Shell / process execution Used
  • ● Environment & secrets Used
  • ✓ Dynamic code execution No

From automated source analysis of v0.3.1. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-06ketan-substack-ops)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
○ 4mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Substack Ops? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

substack-ops

[](https://pypi.org/project/substack-ops/) [](https://pypi.org/project/substack-ops/) [](https://www.python.org/downloads/) [](LICENSE) [](https://modelcontextprotocol.io) [](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.06ketan/substack-ops) [](https://github.com/06ketan/substack-ops/releases/latest) [](https://glama.ai/mcp/servers/06ketan/substack-ops) [](https://lobehub.com/mcp/06ketan-substack-ops) [](https://github.com/06ketan/substack-ops/actions/workflows/test.yml)

> Standalone Substack CLI + 26-tool MCP server for Cursor MCP, Claude MCP, OpenCode MCP, and any stdio MCP host. Your IDE drafts the replies. Zero AI API keys.

Site → substack-ops.chavan.in · Source → 06ketan/substack-ops · Glama → mcp/servers/06ketan/substack-ops

Posts, notes, comments, replies, reactions, restacks, recommendations, search, profiles, feeds, automations, MCP server, Textual TUI. One Python install, one binary, MIT licensed.

TL;DR — MCP-native (no API key, one command)

uvx substack-ops mcp install cursor          # or claude-desktop, claude-code, opencode, print
# Restart your host. Then in chat:
#   "list unanswered comments on post 193866852"
#   "draft a warm reply to comment 12345"
#   "post that draft"

Your host's LLM (Cursor's, Claude's) does the drafting via the propose_reply / confirm_reply tools. No ANTHROPIC_API_KEY / OPENAI_API_KEY needed.

Wrong install?

This project is substack-ops on PyPI — install with uv / uvx, not unrelated npx packages that appear when searching “Substack MCP”. Canonical listing: Glama — 06ketan/substack-ops.

Works with (MCP)

These rows help discovery (search keywords); confirm each host’s current MCP docs before upgrading.

Open source–oriented hosts

| Host | Documentation | Typical wire-up | |------|---------------|-----------------| | OpenCode | OpenCode MCP servers | uvx substack-ops mcp install opencode | | Continue | Continue | uvx substack-ops mcp install print — paste the snippet into Continue’s MCP settings | | Zed | Zed | Configure stdio MCP per Zed’s docs | | Cline | Cline | MCP setup per extension / marketplace docs | | Goose | Goose | MCP extensions per Goose docs |

Large commercial stacks

| Host | Documentation | Typical wire-up | |------|---------------|-----------------| | Cursor | Cursor MCP | uvx substack-ops mcp install cursor | | Claude (Desktop / Code) | Claude Desktop, Claude Code | mcp install claude-desktop / claude-code | | GitHub Copilot | Copilot | MCP in VS Code / Copilot where supported — use print + host docs | | ChatGPT | OpenAI | Developer / connector flows — often REST (Slideshot API) for tools without MCP | | Google Gemini | Gemini | Gemini CLI / IDE features per Google docs — stdio where supported |

OpenCode (copy-paste)

Auto-install:

uvx substack-ops mcp install opencode

Manual (~/.config/opencode/opencode.json):

{
  "mcp": {
    "substack-ops": {
      "type": "local",
      "command": ["uvx", "substack-ops", "mcp", "serve"],
      "enabled": true
    }
  }
}

Optional version pin: use ["uvx", "substack-ops==0.3.5", "mcp", "serve"] (replace with current PyPI release).

Setup (dev / from source)

git clone https://github.com/06ketan/substack-ops && cd substack-ops
uv sync
uv sync --extra mcp     # mcp SDK for the MCP server (recommended)
uv sync --extra tui     # textual for the TUI
uv sync --extra chrome  # pycryptodome + keyring for Chrome cookie auto-grab

Auth defaults to ~/.cursor/mcp.json's mcpServers.substack-api.env. Override with env or .env. Or use one of the auth flows in auth login / auth setup.

uv run substack-ops auth verify
uv run substack-ops quickstart   # 20-step tour

Command surface

Grouped by intent. Every write defaults to --dry-run; flip with --no-dry-run (and --yes-i-mean-it for the irreversible ones). All writes land in .cache/audit.jsonl and are dedup-checked against .cache/actions.db.

Auth (4)

| Command | What it does | |---|---| | auth verify | Confirm the cookie works; print authed user/pub. | | auth test | Same as verify, exit non-zero on failure (CI-friendly). | | auth login --browser chrome\|brave | Auto-grab cookie from local Chromium browser via macOS Keychain. | | auth login --email me@x.com | Email magic-link → paste-the-link interactive flow. | | auth setup | Interactive paste of connect.sid cookie. |

Read — Posts (8)

| Command | What it does | |---|---| | posts list [--pub] [--limit] [--sort new\|top] | List posts from a publication (yours by default). | | posts show [--pub] | Post metadata (title, dates, reactions, comment count). | | posts get --slug [--pub] | Same as show but slug-only. | | posts content [--md] [--pub] | HTML body (auth-aware for paywalled). --md converts to Markdown. | | posts stats | Engagement counts — reactions, comments. | | posts search [--pub] [--limit] | Substack-side full-text search. | | posts paywalled [--pub] | Boolean: is this post paywalled? | | posts react [--off] [--pub] | Add (or remove with --off) a reaction. Defaults to ❤. | | posts restack [--off] | Restack a post (Substack does not support unrestack). |

Read — Notes (5)

| Command | What it does | |---|---| | notes list [--limit] | Your published Notes. | | notes show | One note + its reply tree. | | notes publish [--no-dry-run] | Publish a top-level Note. | | notes react [--off] | React on any Note. | | notes restack [--off] | Restack a Note. |

Read + Write — Comments (5)

| Command | What it does | |---|---| | comments tree [--pub] | Full nested comment tree as table. | | comments export --out file.json [--pub] | Same tree as JSON. | | comments add [--pub] [--no-dry-run] | New top-level comment. | | comments react --kind post\|note [--off] | React on a comment. | | comments delete --kind post\|note [--no-dry-run] | Destructive — your own comments only. |

Reply engine (6)

| Command | What it does | |---|---| | reply template --template thanks | Rule-based replies (no LLM). | | reply review | LLM drafts each, you [a]ccept / [e]dit / [s]kip / [q]uit. | | reply bulk --out drafts.json | Draft every comment to a file. Edit, set action: "approved". | | reply note-bulk --out drafts.json | Same for replies under a Note. | | reply bulk-send drafts.json [--no-dry-run] | Posts only approved rows. Dedup-checked. | | reply auto --no-dry-run --yes-i-mean-it | Draft + post immediately. 30s rate limit. |

Read — Discovery (8)

| Command | What it does | |---|---| | feed list --tab for-you\|subscribed\|category-{slug} | Reader feed (the Substack app feed). | | profile me / profile get | Profile. | | users get / users subscriptions | Public user info + their subs. | | podcasts list [--pub] | Audio posts. | | recommendations list [--pub] | Pub's recommended publications. | | authors list [--pub] | Pub's contributor list. | | categories list / categories get --name | Substack's category taxonomy. |

Automations (3)

| Command | What it does | |---|---| | auto presets | List built-in YAML rules. | | auto run | One-shot run a preset. | | auto daemon --interval 60 | Loop forever; logs to audit. |

Operations + safety (3)

| Command | What it does | |---|---| | audit search [--kind] [--target] [--status] [--since 7d] | Query the JSONL audit log. | | audit dedup-status | Counts in the dedup SQLite DB. | | quickstart | 20-step interactive tour. |

MCP server (3)

| Command | What it does | |---|---| | mcp install [--dry-run] | Auto-merge config into your host. | | mcp serve | stdio MCP server (26 tools). | | mcp list-tools | Print the tool registry. |

Other (1)

| Command | What it does | |---|---| | tui | Textual TUI — 6 tabs (Notes, Posts, Comments, Feed, Auto, Profile). |

Multi-publication

Every read command accepts --pub . Defaults to your own publication.

substack-ops posts list --pub stratechery --limit 5
substack-ops posts search "ai" --pub stratechery
substack-ops recommendations list --pub stratechery

Reply modes

| Mode | What it does | Safety | |------|--------------|--------| | template | YAML keyword/regex rules under src/substack_ops/templates/*.yaml | dry-run default | | review | LLM drafts each reply, you [a]ccept / [e]dit / [s]kip / [q]uit | dry-run default + manual gate per comment | | bulk | LLM drafts every comment to drafts.json. Edit file, set action: "approved" | offline review, dedup-checked on send | | bulk-send | Posts only items with action: "approved" | dry-run default; dedup DB prevents the M2 31-dup-replies regression | | auto | LLM drafts and posts immediately | requires --no-dry-run --yes-i-mean-it, 30s rate limit |

After every live note-reply the engine re-fetches the new comment and asserts ancestor_path is non-empty. If empty, the audit row's result_status is flipped to "orphaned" (the M2 bug where parent_comment_id was silently dropped — now caught).

Automations

Built-in presets (auto presets):

  1. like-back — when someone reacts to your note, react to their latest note.
  2. auto-reply — same trigger, but post a templated thank-you.
  3. auto-restack — when a watchlist handle posts a new note, restack it.
  4. follow-back — when someone follows you, follow them back.

Custom YAML rules under ~/.config/substack-ops/auto/*.yaml. Loop with auto daemon --interval 60.

MCP server

substack-ops mcp install opencode          # auto-add to ~/.config/opencode/opencode.json
substack-ops mcp install cursor              # auto-add to ~/.cursor/mcp.json
substack-ops mcp install claude-desktop      # auto-add to claude_desktop_config.json
substack-ops mcp install claude-code         # uses `claude mcp add` under the hood
substack-ops mcp install print               # print the snippet only
substack-ops mcp install cursor --dry-run    # preview without writing
substack-ops mcp serve                       # stdio server
substack-ops mcp list-tools                  # 26 tools

Manual config snippet (if you prefer):

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

If the mcp SDK is not installed, the server falls back to a minimal stdin/stdout JSON-line dispatcher that's still useful for scripting:

echo '{"tool":"list_posts","args":{"limit":3}}' | substack-ops mcp serve

MCP-native draft loop (no API key)

3 tools designed to let your host LLM draft for you:

| Tool | What it does | |------|--------------| | get_unanswered_comments | Returns the worklist: comments where you have not yet replied (any depth). | | propose_reply | Dry-run only. Returns a token + payload preview. No write. | | confirm_reply | Posts a previously-proposed reply by token. Idempotent via dedup DB. Token TTL 5 min. |

Differentiator tools (the safety + drafting stack that makes the unattended mode safe): bulk_draft_replies, send_approved_drafts, audit_search, dedup_status, get_unanswered_comments, propose_reply, confirm_reply.

LLM strategy

Two layers, both free:

  1. MCP-native (default). Host LLM drafts via propose_reply /

confirm_reply. No env vars, no API key. Use this for interactive replies.

  1. Subprocess CLI (daemon path). For reply auto / auto daemon when

no human is in the loop. Auto-detects claude (Claude Code), cursor-agent, or codex on PATH. Override with SUBSTACK_OPS_LLM_CMD.

There is no paid-API-key path. If you want one, vendor the old _anthropic / _openai methods from substack-ops v0.2.0 yourself.

Textual TUI

substack-ops tui

6 tabs: Notes / Posts / Comments / Feed / Auto / Profile. Sub-tabs: 1=mine, 2=following, 3=general. Keys: tab, 1-3, ↑/↓, enter, r, l, s, o, q/esc.

Auth methods

substack-ops auth verify                  # uses mcp.json or env
substack-ops auth login                   # auto-grab cookies from Chrome (macOS Keychain)
substack-ops auth login --browser brave
substack-ops auth login --email me@x.com  # email magic-link, paste-the-link mode
substack-ops auth setup                   # interactive paste cookies

Architecture

mcp.json | env | Chrome | OTP  →  auth.py / auth_chrome.py / auth_otp.py
                                            │
                                  .cache/cookies.json
                                            │
                                  SubstackClient (httpx)
                                            │
   ┌──────┬──────┬───────┬───────┬───────┬──────┬──────┬─────┬──────┐
   ▼      ▼      ▼       ▼       ▼       ▼      ▼      ▼     ▼      ▼
 posts  notes  comments  feed  profile  users  recs  cats  ...   reply_engine
                                                                       │
                                                       ┌───────────────┼────────────┐
                                                       ▼               ▼            ▼
                                                  template       ai_review     ai_bulk + ai_auto
                                                       └───────────────┬────────────┘
                                                                       ▼
                                                            base.post_reply / post_note_reply
                                                                       │
                                                              ┌────────┼────────┐
                                                              ▼        ▼        ▼
                                                            dedup    audit  ancestor_path
                                                            (SQLite) (jsonl)  guardrail
   auto/engine.py ────────────────┐
   mcp/server.py  ──── 23 tools ──┼─── all share SubstackClient
   tui/app.py     ──── 6 tabs   ──┘

Endpoints used

| Action | Method + URL | |--------|--------------| | Auth check | GET https://substack.com/api/v1/subscriptions | | List posts | GET {pub}/api/v1/archive | | Post by id | GET {pub}/api/v1/posts/by-id/{id} | | Post by slug | GET {pub}/api/v1/posts/{slug} | | Post content | same as above; body_html field | | Post search | GET {pub}/api/v1/archive?search= | | Comments | GET {pub}/api/v1/post/{id}/comments?all_comments=true | | Reply to comment | POST {pub}/api/v1/post/{id}/comment body {body, parent_id} | | Add top-level comment | same with parent_id: null | | React to post | POST {pub}/api/v1/post/{id}/reaction body {reaction} | | Restack post | POST https://substack.com/api/v1/restack body {post_id} | | Restack note | POST https://substack.com/api/v1/restack body {comment_id} | | Delete post-comment | DELETE {pub}/api/v1/comment/{id} (PUB host) | | Delete note | DELETE https://substack.com/api/v1/comment/{id} (BARE host) | | My notes | GET https://substack.com/api/v1/reader/feed/profile/{user_id}

…

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.3.1 Imported from the upstream source.