substack-ops について
substack-ops は、Substack の投稿、ノート、コメントなどを扱う Python 製コマンドラインツール兼 MCP サーバーです。IDE での返信下書きにレビューや重複防止を組み合わせ、AI API キーを必要としません。
主な機能
- 01投稿、ノート、コメントの閲覧と管理
- 02返信の下書きとレビュー
- 03定期自動処理の設定
- 04書き込みの監査と重複防止
- 05Textual のターミナル UI
活用シーン
- 01未返信コメントを探して返信を準備
- 02送信前に承認済み下書きを確認
- 03リアクションや新規ノートへのルール実行
- 04出版物のフィードや活動を確認
MCP 対応
stdio MCP サーバーは 26 個のツールを提供し、対応ホストへのインストールまたは手動設定ができます。提案・確認型の返信ツールにより、別途 AI API キーを使わず、ホストの LLM で返信を下書きできます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx substack-opsSUBSTACK_PUBLICATION_URLYour Substack publication URL (e.g. https://you.substack.com/). Optional if set in ~/.cursor/mcp.json's mcpServers.substack-api.env.SUBSTACK_USER_IDYour Substack numeric user id. Optional if set in ~/.cursor/mcp.json.SUBSTACK_SESSION_TOKENシークレットYour Substack session cookie value (the s%3A... string). Required for authenticated calls. Easier path: run `substack-ops auth login --browser chrome` and the cookie is auto-grabbed.SUBSTACK_OPS_MCP_PATHOverride path to the mcp.json file the auth layer reads. Defaults to ~/.cursor/mcp.json.SUBSTACK_OPS_LLM_CMDOptional: override the host CLI used by the unattended daemon path (default: auto-detect claude / cursor-agent / codex on PATH). Use {prompt} placeholder if your CLI takes the prompt as an arg.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
substack-ops
Cursor MCP、Claude MCP、OpenCode MCP、および任意のstdio MCPホスト向けの、スタンドアロンSubstack CLI+26ツールのMCPサーバーです。返信の下書きはIDEが作成します。AI APIキーは不要です。
サイト → substack-ops.chavan.in · ソース → 06ketan/substack-ops · Glama → mcp/servers/06ketan/substack-ops
投稿、ノート、コメント、返信、リアクション、リスタック、おすすめ、検索、 プロフィール、フィード、自動化、MCP サーバー、Textual TUI。Pythonを1回インストールするだけで、1つの バイナリを利用できます。MITライセンスです。
TL;DR — MCPネイティブ(APIキー不要、1コマンド)
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"
下書きは、ホストのLLM(CursorやClaude)が
propose_reply/confirm_replyツールを使って作成します。ANTHROPIC_API_KEY/
OPENAI_API_KEYは不要です。
インストール先を間違えていませんか?
このプロジェクトは、PyPI上のsubstack-opsです。「Substack MCP」を検索したときに表示される、無関係なnpxパッケージではなく、uv/uvxでインストールしてください。正式な掲載先:Glama — 06ketan/substack-ops。
対応環境(MCP)
以下の行は検索キーワードとして見つけやすくするためのものです。アップグレードする前に、各ホストの最新MCPドキュメントを必ず確認してください。
オープンソース志向のホスト
| ホスト | ドキュメント | 一般的な接続方法 |
|---|---|---|
| OpenCode | OpenCode MCPサーバー | uvx substack-ops mcp install opencode |
| Continue | Continue | uvx substack-ops mcp install print — スニペットをContinueのMCP設定に貼り付けます |
| Zed | Zed | Zedのドキュメントに従ってstdio MCPを設定します |
| Cline | Cline | 拡張機能/マーケットプレイスのドキュメントに従ってMCPを設定します |
| Goose | Goose | Gooseのドキュメントに従ってMCP拡張機能を設定します |
大規模な商用スタック
| ホスト | ドキュメント | 代表的な接続方法 |
|---|---|---|
| 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 | サポートされている場合は、VS Code / Copilot で MCP を使用してください。対応していない場合は print とホストのドキュメントを使用してください |
| ChatGPT | OpenAI | 開発者向け/コネクターのフロー。MCP に対応していないツールでは、多くの場合 REST を使用します(Slideshot API) |
| Google Gemini | Gemini | Google のドキュメントに従って Gemini CLI / IDE の機能を使用してください。サポートされている場合は stdio を使用します |
OpenCode(コピー&ペースト)
自動インストール:
uvx substack-ops mcp install opencode
手動(~/.config/opencode/opencode.json):
{
"mcp": {
"substack-ops": {
"type": "local",
"command": ["uvx", "substack-ops", "mcp", "serve"],
"enabled": true
}
}
}
任意のバージョン固定:["uvx", "substack-ops==0.3.5", "mcp", "serve"] を使用します(現在の PyPI リリースに置き換えてください)。
セットアップ(開発/ソースから)
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
認証では、デフォルトで ~/.cursor/mcp.json の mcpServers.substack-api.env が使用されます。環境変数または .env で上書きできます。または、auth login / auth setup の認証フローを使用してください。
uv run substack-ops auth verify
uv run substack-ops quickstart # 20-step tour
コマンド一覧
目的別に分類しています。書き込みコマンドはすべてデフォルトで --dry-run になります。--no-dry-run で切り替えてください(取り消せない操作には --yes-i-mean-it も指定します)。すべての書き込みは .cache/audit.jsonl に記録され、.cache/actions.db に照らして重複チェックされます。
認証(4)
| コマンド | 機能 |
|---|---|
auth verify | Cookie が有効か確認し、認証済みのユーザー/出版物を表示します。 |
auth test | verify と同じですが、失敗時にゼロ以外の終了コードを返します(CI 向け)。 |
auth login --browser chrome|brave | macOS Keychain を介して、ローカルの Chromium ブラウザーから Cookie を自動取得します。 |
auth login --email [email protected] | メールのマジックリンクを送信し、リンクを貼り付ける対話型フローを開始します。 |
auth setup | connect.sid Cookie を対話形式で貼り付けます。 |
読み取り — 投稿(8)
| コマンド | 機能 |
|---|---|
posts list [--pub] [--limit] [--sort new|top] | 出版物の投稿一覧を表示します(デフォルトでは自分の出版物)。 |
posts show <id|slug> [--pub] | 投稿のメタデータ(タイトル、日付、リアクション、コメント数)を表示します。 |
posts get --slug <slug> [--pub] | show と同じですが、スラッグのみを指定します。 |
posts content <id> [--md] [--pub] | HTML 本文を取得します(有料記事では認証状態を考慮します)。--md を指定すると Markdown に変換します。 |
posts stats <id> | リアクションやコメントなどのエンゲージメント数を表示します。 |
posts search <query> [--pub] [--limit] | Substack 側で全文検索します。 |
posts paywalled <id> [--pub] | 投稿が有料記事かどうかを真偽値で返します。 |
posts react <id> [--off] [--pub] | リアクションを追加します(--off を指定すると削除します)。デフォルトは ❤ です。 |
posts restack <id> [--off] | 投稿を再スタックします(Substack は再スタックの取り消しに対応していません)。 |
読み取り — ノート(5)
| コマンド | 機能 |
|---|---|
notes list [--limit] | 公開済みの自分のノートを表示します。 |
notes show <id> | 1 件のノートとその返信ツリーを表示します。 |
notes publish <body> [--no-dry-run] | トップレベルのノートを公開します。 |
notes react <id> [--off] | 任意のノートにリアクションします。 |
notes restack <id> [--off] | ノートを再スタックします。 |
読み取り+書き込み — コメント(5)
| コマンド | 機能 |
|---|---|
comments tree <post_id> [--pub] | ネストされたコメントツリー全体を表形式で表示します。 |
comments export <post_id> --out file.json [--pub] | 同じツリーを JSON 形式で出力します。 |
comments add <post_id> <body> [--pub] [--no-dry-run] | 新しいトップレベルのコメントを追加します。 |
comments react <id> --kind post|note [--off] | コメントにリアクションします。 |
comments delete <id> --kind post|note [--no-dry-run] | 破壊的な操作です。自分のコメントのみ削除できます。 |
返信エンジン(6)
| コマンド | 機能 |
|---|---|
reply template <post_id> --template thanks | ルールベースの返信です(LLM は使用しません)。 |
reply review <post_id> | LLM が返信をそれぞれ作成し、[a]ccept / [e]dit / [s]kip / [q]uit を選択できます。 |
reply bulk <post_id> --out drafts.json | すべてのコメントへの返信をファイルに下書きします。編集して、action: "approved" を設定します。 |
reply note-bulk <note_id> --out drafts.json | Note への返信にも同じ処理を行います。 |
reply bulk-send drafts.json [--no-dry-run] | approved の行のみを投稿します。重複チェック済みです。 |
reply auto <post_id> --no-dry-run --yes-i-mean-it | 下書きしてすぐに投稿します。レート制限は30秒です。 |
読み取り — 検索(8)
| コマンド | 機能 |
|---|---|
feed list --tab for-you|subscribed|category-{slug} | リーダーフィード(Substack アプリのフィード)です。 |
profile me / profile get <handle> | プロフィールです。 |
users get <handle> / users subscriptions <handle> | ユーザーの公開情報と購読内容です。 |
podcasts list [--pub] | 音声投稿です。 |
recommendations list [--pub] | Pub のおすすめ出版物です。 |
authors list [--pub] | Pub の寄稿者一覧です。 |
categories list / categories get --name <X> | Substack のカテゴリー分類です。 |
自動化(3)
| コマンド | 機能 |
|---|---|
auto presets | 組み込みの YAML ルールを一覧表示します。 |
auto run <name> | プリセットを1回実行します。 |
auto daemon <name> --interval 60 | 監査ログに記録しながら、無期限にループします。 |
運用と安全性(3)
| コマンド | 機能 |
|---|---|
audit search [--kind] [--target] [--status] [--since 7d] | JSONL 監査ログを検索します。 |
audit dedup-status | 重複排除用 SQLite DB の件数を表示します。 |
quickstart | 20ステップの対話型ガイドです。 |
MCP サーバー(3)
| コマンド | 機能 |
|---|---|
mcp install <cursor|claude-desktop|claude-code|opencode|print> [--dry-run] | ホストの設定に自動でマージします。 |
mcp serve | stdio MCP サーバー(26個のツール)です。 |
mcp list-tools | ツールのレジストリを表示します。 |
その他(1)
| コマンド | 機能 |
|---|---|
tui | Textual TUI — 6つのタブ(Notes、Posts、Comments、Feed、Auto、Profile)です。 |
複数の出版物
すべての読み取りコマンドで --pub <subdomain|domain> を指定できます。デフォルトでは
自分の出版物が対象になります。
substack-ops posts list --pub stratechery --limit 5
substack-ops posts search "ai" --pub stratechery
substack-ops recommendations list --pub stratechery
返信モード
| モード | 機能 | 安全性 |
|---|---|---|
template | src/substack_ops/templates/*.yaml にある YAML キーワード/正規表現ルールです | デフォルトでドライラン |
review | LLM が返信をそれぞれ作成し、[a]ccept / [e]dit / [s]kip / [q]uit を選択できます | デフォルトでドライラン+コメントごとの手動承認 |
bulk | LLM がすべてのコメントへの返信を drafts.json に下書きします。ファイルを編集し、action: "approved" を設定します | オフラインでレビュー可能。送信時に重複チェック |
bulk-send | action: "approved" の項目のみを投稿します | デフォルトでドライラン。重複排除 DB により、M2 の31件の重複返信の再発を防止します |
auto | LLM が返信を作成してすぐに投稿します | --no-dry-run --yes-i-mean-it が必要です。レート制限は30秒です |
ライブで Note に返信するたびに、エンジンは新しいコメントを再取得し、
ancestor_path が空でないことを確認します。空の場合は、監査行の result_status が
"orphaned" に切り替わります(parent_comment_id が気づかれないまま
破棄されていた M2 のバグを、現在は検出できます)。
自動化
組み込みのプリセット(auto presets):
- like-back — 誰かがあなたの Note にリアクションしたら、その人の最新の Note にリアクションします。
- auto-reply — 同じトリガーで、テンプレート化されたお礼を投稿します。
- auto-restack — ウォッチリストのハンドルが新しい Note を投稿したら、その Note を restack します。
- follow-back — 誰かがあなたをフォローしたら、フォローバックします。
カスタム YAML ルールは ~/.config/substack-ops/auto/*.yaml に配置します。
auto daemon <name> --interval 60 でループを実行します。
MCP サーバー
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
手動で設定する場合のスニペット:
{
"mcpServers": {
"substack-ops": {
"command": "substack-ops",
"args": ["mcp", "serve"]
}
}
}
mcp SDK がインストールされていない場合、サーバーは最小限の
stdin/stdout JSON 行ディスパッチャーにフォールバックします。スクリプト作成には引き続き便利です。
echo '{"tool":"list_posts","args":{"limit":3}}' | substack-ops mcp serve
MCP ネイティブの下書きループ(API キー不要)
ホスト LLM が下書きを作成するために設計された 3 つのツールです。
| ツール | 内容 |
|---|---|
get_unanswered_comments | 対応待ちリストを返します。まだ返信していないコメント(深さを問わず)が含まれます。 |
propose_reply | ドライランのみです。token とペイロードのプレビューを返します。書き込みは行いません。 |
confirm_reply | トークンを使って、事前に提案された返信を投稿します。重複排除 DB による冪等性を備えています。トークンの有効期間は 5 分です。 |
差別化につながるツール(無人モードを安全にする安全性と下書き作成の仕組み):bulk_draft_replies、send_approved_drafts、audit_search、dedup_status、get_unanswered_comments、propose_reply、confirm_reply。
LLM 戦略
どちらも無料の 2 つのレイヤーがあります。
- MCP ネイティブ(デフォルト)。 ホスト LLM が
propose_reply/confirm_replyを使って下書きを作成します。環境変数も API キーも不要です。対話形式の返信にはこちらを使用してください。 - サブプロセス CLI(デーモン経由)。 人が介在しない
reply auto/auto daemon用です。PATH 上のclaude(Claude Code)、cursor-agent、またはcodexを自動検出します。SUBSTACK_OPS_LLM_CMDで上書きできます。
有料 API キーを使う方法はありません。必要な場合は、substack-ops v0.2.0 の古い _anthropic /
_openai メソッドをご自身で取り込んでください。
テキスト TUI
substack-ops tui
6 つのタブ:ノート / 投稿 / コメント / フィード / 自動化 / プロフィール。 サブタブ:1=自分、2=フォロー中、3=全般。 キー:tab、1-3、↑/↓、enter、r、l、s、o、q/esc。
認証方法
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 [email protected] # email magic-link, paste-the-link mode
substack-ops auth setup # interactive paste cookies
アーキテクチャ
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 ──┘
使用するエンドポイント
| 操作 | メソッド + URL |
|---|---|
| 認証チェック | GET https://substack.com/api/v1/subscriptions |
| 投稿一覧 | GET {pub}/api/v1/archive |
| ID で投稿を取得 | GET {pub}/api/v1/posts/by-id/{id} |
| スラッグで投稿を取得 | GET {pub}/api/v1/posts/{slug} |
| 投稿コンテンツ | 上記と同じ。body_html フィールド |
| 投稿検索 | GET {pub}/api/v1/archive?search= |
| コメント | GET {pub}/api/v1/post/{id}/comments?all_comments=true |
| コメントへの返信 | POST {pub}/api/v1/post/{id}/comment ボディ {body, parent_id} |
| トップレベルのコメントを追加 | parent_id: null を指定して同様に実行 |
| 投稿にリアクション | POST {pub}/api/v1/post/{id}/reaction ボディ {reaction} |
| 投稿をリスタック | POST https://substack.com/api/v1/restack ボディ {post_id} |
| ノートをリスタック | POST https://substack.com/api/v1/restack ボディ {comment_id} |
| 投稿コメントを削除 | DELETE {pub}/api/v1/comment/{id}(PUB ホスト) |
| ノートを削除 | DELETE https://substack.com/api/v1/comment/{id}(BARE ホスト) |
| 自分のノート | GET https://substack.com/api/v1/reader/feed/profile/{user_id} |
| ノートのスレッド | GET https://substack.com/api/v1/reader/comment/{note_id} |
| ノートへの返信 | GET https://substack.com/api/v1/reader/comment/{note_id}/replies |
| ノートを公開 | POST https://substack.com/api/v1/comment/feed ボディ {bodyJson} |
| ノートに返信 | {bodyJson, parent_id} を指定して同様に実行(parent_comment_id ではありません。既知の M2 バグです) |
| コメントにリアクション | POST {host}/api/v1/comment/{id}/reaction(ホストは投稿コメントの場合は pub、ノートの場合は substack.com) |
| おすすめ | GET {pub}/api/v1/recommendations/from/{publication_id} |
| 著者 | GET {pub}/api/v1/publication/users/ranked?public=true |
| カテゴリー | GET https://substack.com/api/v1/categories |
| ユーザープロフィール | GET https://substack.com/api/v1/user/{handle}/public_profile(404 の場合は自動でリダイレクト) |
| リーダーフィード | GET https://substack.com/api/v1/reader/feed/{recommended|subscribed|category/{slug}} |
関連する MCP
- slideshot — HTML → スライド(PNG / PDF / PPTX)。npm
slideshot-mcp。 - medium-ops — Medium の記事、返信、MCP(PyPI
medium-ops)。
テスト
uv run pytest -q # 43 tests, ~0.6s, no live network
現在のカバレッジ:認証、クライアント(読み取り+書き込み+エンゲージメント+削除)、返信エンジン、
重複排除 DB、監査ログ検索、MCP ツールレジストリとディスパッチャー、自動化エンジンの
プリセットローダー、M2 の parent_id 回帰テスト、M2 のホスト不一致
回帰テスト。
GSD ワークフロー
Get Shit Done 用の .planning/ スキャフォールドは、
~/.claude/skills/gsd-* の下にあります。ロードマップは .planning/ROADMAP.md、
フェーズごとの計画は .planning/phases/M*/PHASE.md にあります。
既知の不足点
- メールの全統計(開封数/クリック数/閲覧数)— ダッシュボードの CSRF フローが必要です。代替策:Playwright MCP によるスクレイピング。
- POST/DELETE のリアクションエンドポイントの形式は、まだ実環境で確認できていません。現在の形式は、上流のツールカタログをもとにした推測です。
- 自動エンジンの
new_follower/new_note_fromトリガーはスタブの状態です(note: "trigger not yet implemented"を返します)。 - TUI のサブタブ(1/2/3)と、返信/いいね/再投稿のキー割り当ては用意されていますが、まだクライアントに接続されていません。
- Chrome の Cookie 自動取得は macOS 版 Chrome でのみテスト済みです。Brave のパスも含まれていますが、Linux/Windows はサポートされていません。
ライセンス
MIT。LICENSE を参照してください。
src/substack_ops/_substack/ にあるベンダー同梱の httpx-port ヘルパーは、MIT ライセンスの NHagar/substack_api パッケージをベースにしています。このリポジトリがサードパーティ製 Substack ライブラリへの実行時依存を一切含まないよう、ここに保持しています。各ファイルのモジュール docstring に著作権表示を残しています。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。