内容
# substack-ops
<!-- mcp-name: io.github.06ketan/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)
> **独立 Substack CLI + 26 工具 MCP 服务器,适用于 Cursor MCP、Claude MCP、OpenCode MCP 和任何 stdio MCP 主机。您的 IDE 负责草拟回复。无需 AI API 密钥。**
站点 → **[substack-ops.chavan.in](https://substack-ops.chavan.in)** · 源代码 → **[06ketan/substack-ops](https://github.com/06ketan/substack-ops)** · Glama → **[mcp/servers/06ketan/substack-ops](https://glama.ai/mcp/servers/06ketan/substack-ops)**
<a href="https://glama.ai/mcp/servers/06ketan/substack-ops">
<img width="380" height="200" src="https://glama.ai/mcp/servers/06ketan/substack-ops/badges/card.svg" alt="substack-ops MCP 服务器卡片在 Glama 上" />
</a>
帖子、笔记、评论、回复、反应、转发、推荐、搜索、个人资料、订阅源、自动化、MCP 服务器、Textual TUI。一个 Python 安装,一个二进制文件,MIT 许可。
## 快速概览 — MCP 原生(无需 API 密钥,一条命令)
```bash
uvx substack-ops mcp install cursor # 或 claude-desktop、claude-code、opencode、print
# 重启您的主机。然后在聊天中:
# "列出帖子 193866852 下的未回复评论"
# "为评论 12345 草拟一个温暖的回复"
# "发布该草稿"
```
您的**主机**的 LLM(Cursor 的、Claude 的)通过 `propose_reply` / `confirm_reply` 工具进行草拟。无需 `ANTHROPIC_API_KEY` / `OPENAI_API_KEY`。
### 错误安装?
该项目在 [PyPI](https://pypi.org/project/substack-ops/) 上名为 **`substack-ops`** — 使用 **`uv` / `uvx`** 安装,而不是不相关的 **`npx`** 软件包,在搜索“Substack MCP”时会出现。规范列表: **[Glama — 06ketan/substack-ops](https://glama.ai/mcp/servers/06ketan/substack-ops)**。
## 支持(MCP)
这些行有助于发现(搜索关键词);**在升级前,请确认每个主机的当前 MCP 文档**。
### 开源导向的主机
| 主机 | 文档 | 典型连接方式 |
|------|---------------|-----------------|
| **OpenCode** | [OpenCode MCP 服务器](https://open-code.ai/en/docs/mcp-servers) | `uvx substack-ops mcp install opencode` |
| **Continue** | [Continue](https://docs.continue.dev) | `uvx substack-ops mcp install print` — 将代码片段粘贴到 Continue 的 MCP 设置中 |
| **Zed** | [Zed](https://zed.dev/docs) | 按 Zed 文档配置 stdio MCP |
| **Cline** | [Cline](https://github.com/cline/cline) | 按扩展程序/市场文档配置 MCP |
| **Goose** | [Goose](https://block.github.io/goose/) | 按 Goose 文档配置 MCP 扩展程序 |
### 大型商业堆栈
| 主机 | 文档 | 典型连接方式 |
|------|---------------|-----------------|
| **Cursor** | [Cursor MCP](https://docs.cursor.com/context/model-context-protocol) | `uvx substack-ops mcp install cursor` |
| **Claude** (桌面版/代码版) | [Claude 桌面版](https://support.anthropic.com/en/articles/10065433-installing-claude-for-desktop), [Claude 代码版](https://docs.claude.com/en/docs/claude-code) | `mcp install claude-desktop` / `claude-code` |
| **GitHub Copilot** | [Copilot](https://docs.github.com/en/copilot) | 支持的 VS Code / Copilot 中使用 MCP — 使用 `print` + 主机文档 |
| **ChatGPT** | [OpenAI](https://platform.openai.com/docs) | 开发人员/连接器流程 — 通常使用 REST ([Slideshot API](https://slideshot.vercel.app)) 适用于没有 MCP 的工具 |
| **Google Gemini** | [Gemini](https://ai.google.dev/docs) | 按 Google 文档配置 Gemini CLI / IDE 功能 — 支持 stdio |
### OpenCode(复制粘贴)
自动安装:
```bash
uvx substack-ops mcp install opencode
```
手动(`~/.config/opencode/opencode.json`):
```json
{
"mcp": {
"substack-ops": {
"type": "local",
"command": ["uvx", "substack-ops", "mcp", "serve"],
"enabled": true
}
}
}
```
可选版本固定:使用 `["uvx", "substack-ops==0.3.5", "mcp", "serve"]`(替换为当前的 PyPI 版本)。
## 设置(开发版/源码)
```bash
git clone https://github.com/06ketan/substack-ops && cd substack-ops
uv sync
uv sync --extra mcp # MCP 服务器的 MCP SDK(推荐)
uv sync --extra tui # 文本界面
uv sync --extra chrome # pycryptodome + keyring,用于自动获取 Chrome cookie
```
身份验证默认为 `~/.cursor/mcp.json` 的 `mcpServers.substack-api.env`。使用环境变量或 `.env` 文件覆盖。或使用 `auth login` / `auth setup` 中的身份验证流程之一。
```bash
uv run substack-ops auth verify
uv run substack-ops quickstart # 20 步交互式教程
```
## 命令界面
按意图分组。每个写入操作默认为 `--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 me@x.com` | 邮箱魔术链接 → 粘贴链接交互式流程。 |
| `auth setup` | 交互式粘贴 `connect.sid` cookie。 |
### 读取 - 帖子(8)
| 命令 | 功能 |
|---|---|
| `posts list [--pub] [--limit] [--sort new\|top]` | 列出发布者的帖子(默认为您的帖子)。 |
| `posts show <id\|slug> [--pub]` | 帖子元数据(标题、日期、反应、评论数)。 |
| `posts get --slug <slug> [--pub]` | 与 show 相同,但仅限 slug。 |
| `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>` | 一个笔记 + 其回复树。 |
| `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` | 适用于笔记下的回复。 |
| `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`。 |
| `users get <handle>` / `users subscriptions <handle>` | 公共用户信息 + 订阅列表。 |
| `podcasts list [--pub]` | 音频帖子。 |
| `recommendations list [--pub]` | 推荐的发布者。 |
| `authors list [--pub]` | 发布者的作者列表。 |
| `categories list` / `categories get --name <X>` | Substack 的分类法。 |
### 自动化(3)
| 命令 | 功能 |
|---|---|
| `auto presets` | 列出内置 YAML 规则。 |
| `auto run <name>` | 单次运行一个预设。 |
| `auto daemon <name> --interval 60` | 循环运行;记录到审计日志。 |
### 操作 + 安全(3)
| 命令 | 功能 |
|---|---|
| `audit search [--kind] [--target] [--status] [--since 7d]` | 查询 JSONL 审计日志。 |
| `audit dedup-status` | 计数 SQLite 数据库中的重复检查。 |
| `quickstart` | 20 步交互式教程。 |
### MCP 服务器(3)
| 命令 | 功能 |
|---|---|
| `mcp install <cursor\|claude-desktop\|claude-code\|opencode\|print> [--dry-run]` | 自动合并配置到您的主机。 |
| `mcp serve` | 标准输入/输出 MCP 服务器(26 个工具)。 |
| `mcp list-tools` | 打印工具注册表。 |
### 其他(1)
| 命令 | 功能 |
|---|---|
| `tui` | 文本界面 - 6 个标签页(笔记、帖子、评论、订阅源、自动化、个人资料)。 |
## 多发布者
每个读取命令都接受 `--pub <subdomain|domain>`。默认为您自己的发布者。
```bash
substack-ops posts list --pub stratechery --limit 5
substack-ops posts search "ai" --pub stratechery
substack-ops recommendations list --pub stratechery
```
## 回复模式
| 模式 | 功能 | 安全 |
|------|--------------|--------|
| `template` | YAML 关键词/正则规则(位于 `src/substack_ops/templates/*.yaml`) | 默认情况下为 dry-run |
| `review` | LLM 草拟每个回复,您 `[a]ccept / [e]dit / [s]kip / [q]uit` | 默认情况下为 dry-run + 每条评论的手动门控 |
| `bulk` | LLM 草拟所有评论到 `drafts.json`。编辑文件,设置 `action: "approved"` | 离线审查,发送时重复检查 |
| `bulk-send` | 仅发布 `action: "approved"` 的项目 | 默认情况下为 dry-run;**重复数据库防止 M2 31 次回复回归** |
| `auto` | LLM 草拟并立即发布 | 需要 `--no-dry-run --yes-i-mean-it`,30 秒速率限制 |
每次实时笔记回复后,引擎会重新获取新的评论并断言 `ancestor_path` 为非空。如果为空,则审计行的 `result_status` 将更改为 `"orphaned"`(M2 错误,即 `parent_comment_id` 被静默删除 - 现已捕获)。
## 自动化
内置预设(`auto presets`):
1. **like-back** - 当有人对您的笔记做出反应时,对他们的最新笔记做出反应。
2. **auto-reply** - 相同的触发器,但发布模板化的感谢信。
3. **auto-restack** - 当关注列表中的用户发布新笔记时,转发该笔记。
4. **follow-back** - 当有人关注您时,关注他们。 |
自定义 YAML 规则位于 `~/.config/substack-ops/auto/*.yaml`。使用 `auto daemon <name> --interval ** 60` 循环运行。
## MCP 服务器
```bash
substack-ops mcp install opencode # 自动添加到 ~/.config/opencode/opencode.json
substack-ops mcp install cursor # 自动添加到 ~/.cursor/mcp.json
substack-ops mcp install claude-desktop # 自动添加到 claude_desktop_config.json
substack-ops mcp install claude-code # 使用 `claude mcp add` 作为底层操作
substack-ops mcp install print # 仅打印代码片段
substack-ops mcp install cursor --dry-run # 预览而不写入
substack-ops mcp serve # 标准输入/输出服务器
substack-ops mcp list-tools # 26 个工具
```
手动配置片段(如果您更喜欢):
```json
{
"mcpServers": {
"substack-ops": {
"command": "substack-ops",
"args": ["mcp", "serve"]
}
}
}
```
如果未安装 `mcp` SDK,服务器将回退到一个最小的 `stdin/stdout` JSON 行调度器,该调度器仍然对脚本编写很有用:
```bash
echo '{"tool":"list_posts","args":{"limit":3}}' | substack-ops mcp serve
```
### MCP 原生回复循环(无 API 密钥)
3 个工具设计用于让您的**主机** LLM 为您草拟:
| 工具 | 功能 |
|------|--------------|
| `get_unanswered_comments` | 返回工作列表:您尚未回复的评论(任意深度)。 |
| `propose_reply` | 仅限 dry-run。返回 `token` + 有效载荷预览。**无写入操作**。 |
| `confirm_reply` | 发布之前草拟的回复,标记为 token。具有重复检查,token TTL 为 5 分钟。 |
**区分工具**(安全 + 草拟堆栈,使无人值守模式安全):`bulk_draft_replies`、`send_approved_drafts`、`audit_search`、`dedup_status`、`get_unanswered_comments`、`propose_reply`、`confirm_reply`。
## LLM 策略
两层,均免费:
1. **MCP 原生(默认)。** 主机 LLM 通过 `propose_reply` / `confirm_reply` 草拟。无需环境变量,无需 API 密钥。请将此用于交互式回复。
2. **子进程 CLI(守护进程路径)。** 适用于 `reply auto` / `auto daemon`,当没有人类在循环中时。自动检测 `claude`(Claude 代码)、`cursor-agent` 或 `codex` 在 PATH 上。覆盖使用 `SUBSTACK_OPS_LLM_CMD`。
无付费 API 密钥路径。如果您想要一个,请自行开发旧版 `_anthropic` / `_openai` 方法。
## 文本界面
```bash
substack-ops tui
```
6 个标签页:笔记/帖子/评论/订阅源/自动化/个人资料。
子标签页:1=我的,2=关注的,3=一般。
按键:标签页,1-3,↑/↓,回车,R,L,S,O,Q/ESC。
## 身份验证方法
```bash
substack-ops auth verify # 使用 mcp.json 或环境变量
substack-ops auth login # 自动从 Chrome 获取 cookie(macOS 密钥链)
substack-ops auth login --browser brave
substack-ops auth login --email me@x.com # 电子邮件魔术链接,粘贴链接模式
substack-ops auth setup # 交互式粘贴 cookie
```
## 架构
```text
mcp.json | 环境变量 | 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 工具 ──┼─── 所有工具共享 SubstackClient
tui/app.py ──── 6 个标签页 ──┘
```
## 使用的端点
| 操作 | 方法 + URL |
|--------|--------------|
| 身份验证检查 | `GET https://substack.com/api/v1/subscriptions` |
| 列出帖子 | `GET {pub}/api/v1/archive` |
| 按 ID 获取帖子 | `GET {pub}/api/v1/posts/by-id/{id}` |
| 按 slug 获取帖子 | `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}`(发布者主机) |
| 删除笔记 | `DELETE https://substack.com/api/v1/comment/{id}`(裸主机) |
| 我的笔记 | `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](https://github.com/06ketan/slideshot)** — HTML → 幻灯片(PNG / PDF / PPTX);npm [`slideshot-mcp`](https://www.npmjs.com/package/slideshot-mcp)。
- **[medium-ops](https://github.com/06ketan/medium-ops)** — Medium 故事 + 回复 + MCP(PyPI `medium-ops`)。
## 测试
```bash
uv run pytest -q # 43 个测试,~0.6 秒,无网络请求
```
覆盖率:身份验证、客户端(读取+写入+互动+删除)、回复引擎、重复数据库、审计日志搜索、MCP 工具注册表和调度器、自动化引擎预设加载、M2 `parent_id` 回归测试、M2 主机不匹配回归测试。
## GSD 工作流
`.planning/` 位于 `~/.claude/skills/gsd-*` 下的 [Get Shit Done](https://github.com/khromov/get-shit-done) 框架。
在 `.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](LICENSE)。
`src/substack_ops/_substack/` 下的 vendored httpx-port 助手是从 MIT 许可的 `NHagar/substack_api` 包派生而来 — 保留在此仓库中,以便于零运行时依赖于第三方 Substack 库。每个文件的模块文档字符串中保留了属性。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器