mcpField
S
Substack MCP Server

Substack MCP Server

本地服务
github.com社交媒体441 天前更新

关于 Substack MCP Server

Substack MCP Server 可让 AI 助手或终端管理 newsletter 内容和账户数据。长文仅保存为草稿,须手动审核并发布;Notes 则会立即发布。

主要功能

  1. 01创建和更新长文草稿
  2. 02搜索并导出文章
  3. 03发布短篇 Notes
  4. 04查看分析数据
  5. 05管理明确同意的免费订阅者

适用场景

  1. 01在 Substack 准备文章以供审核
  2. 02查找并导出存档文章
  3. 03发布 Note
  4. 04查看 newsletter 数据或管理主动订阅者

MCP 相关

它通过本地 stdio 或自托管 HTTP 向 MCP 客户端提供 Substack 操作。长文工具只能创建或编辑草稿;Note 工具会立即公开发布。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"conorbronsdon-substack": {
"command": "npx",
"args": [
"-y",
"@conorbronsdon/substack-mcp"
],
"env": {
"SUBSTACK_PUBLICATION_URL": "<SUBSTACK_PUBLICATION_URL>",
"SUBSTACK_SESSION_TOKEN": "<SUBSTACK_SESSION_TOKEN>",
"SUBSTACK_USER_ID": "<SUBSTACK_USER_ID>"
}
}
}
}
启动命令npx -y @conorbronsdon/substack-mcp
需要配置的环境变量
SUBSTACK_PUBLICATION_URLYour Substack publication URL (e.g., https://yourblog.substack.com)
SUBSTACK_SESSION_TOKEN密钥connect.sid cookie value from your Substack session
SUBSTACK_USER_IDYour Substack user ID

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@conorbronsdon/substack-mcp1.3.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

substack-mcp

通过 AI 助手或终端创建和管理你的 Substack 新闻简报。准备丰富的草稿、搜索存档、发布 Notes、查看分析数据,并管理在明确同意后订阅的免费订阅者。审核并在 Substack 中发布长篇文章。

License: MIT Language: TypeScript npm version MCP HOL Plugin Security Scan Podcast X


使用 substack-mcp 创建、搜索、导出、规划并审核草稿

演示会使用离线示例数据运行实际的 MCP 处理程序,不会进行实时 API 调用,也不会发布内容。按照草稿工作流创建、查找、导出并审核文章。

**长篇文章仅能创建草稿;公开操作须明确进行:**此服务无法发布或删除长篇文章。文章工具只能创建和编辑草稿;你需要通过 Substack 编辑器手动审核并发布。公开社区评论/restack 操作则是独立的实验性功能,且需征得同意。Substack Notes 也会公开发布:create_note 和 create_note_with_link 会立即发布短篇 Notes,因为 Substack 不提供 Notes 草稿状态。请将 Note 工具视为公开发布操作——没有预览步骤,也无法通过此服务撤销。这样的区分是与风险相称的审核机制,也是此服务最重视的 Agent 信任基础设施:高风险操作设有人为审核关卡,并明确说明例外情况。

此服务不要求账号具备畅销书作者身份。请使用有权管理该出版物的已认证账号;具体操作取决于你的 Substack 访问权限。可通过本地 stdio 或可自托管的 HTTP 连接。

substack-mcp MCP 服务

有关 1.0 版本的设置支持范围和账号资格,请参阅兼容性。运行 substack-mcp compatibility report 可生成离线、可分享的诊断报告;另请参阅报告指南。维护者可使用发布清单和分发清单。

目录:快速开始 · 设置 · 工具 · 操作员 CLI · 草稿工作流 · 从分析数据到草稿 · 导出 · Markdown · 多个出版物 · 传输方式 · 兼容性

快速开始

  1. 安装并登录。 浏览器登录需要可选的 Playwright 依赖:

    npm install @conorbronsdon/substack-mcp playwright
    npx playwright install chromium
    npx substack-mcp login https://yourblog.substack.com --user-id 12345
    

    使用你自己账号的用户 ID(如何查找)。只有在成功完成一次有界的 身份验证读取后,才会保存会话。如要改为粘贴凭据,请参阅 选项 B。

  2. 验证读取。 npx substack-mcp doctor --json --check-auth 会针对每个出版物执行一次 有界读取。它确认你有读取权限,但不会确认你的用户 ID 或写入权限。

  3. 连接 MCP 客户端。 将服务添加到 Claude Desktop 或 Claude Code,或使用 Codex 插件。环境变量优先级更高;省略它们即可使用已保存的浏览器登录会话。然后询问你的助手: “我有多少 Substack 订阅者?”

  4. 准备草稿以供审核。 按照草稿工作流操作: create_draft、search_posts、export_draft、preflight_draft,然后 执行 plan_draft_update 和 update_draft。长篇文章会保持为未发布草稿,直到你在 Substack 编辑器中发布。 create_note 和 create_note_with_link 会立即发布。

社区实践指南

Jonathan Price 的我用 Codex 将 ChatGPT 连接到 Substack。然后它起草了这篇文章。 介绍了如何使用 Codex 在本地安装 MCP,通过 OpenAI 的 Secure MCP Tunnel 连接 ChatGPT,以及创建私密草稿以供手动发布。 他使用该连接创建了这篇指南的草稿。

该指南记录了他在 2026 年 9 月 18 日使用 1.2.0 版本进行的配置。报告的 get_post 404 问题已在 1.2.1 版本中修复。客户端界面和访问要求可能会发生变化;有关此软件包的当前配置,请参阅下方的设置说明。 这是社区实践指南,并非本项目提供的托管服务。

设置

需要 Node.js 22 或更高版本(CI 覆盖 Node 22 和 24)。浏览器登录还需要 Playwright。

你可以通过两种方式提供凭据:将它们粘贴为环境变量(见下文),或运行可选的浏览器登录,由它为你捕获并保存凭据。

选项 A — 浏览器登录(可选,无需手动复制 Cookie)

在本地工具目录中同时安装服务和可选的 Playwright 依赖,然后登录:

npm install @conorbronsdon/substack-mcp playwright
npx playwright install chromium
npx substack-mcp login https://yourblog.substack.com --user-id 12345

substack-mcp-login 仍是受支持的别名。系统会提示输入缺失的出版物 URL 和用户 ID。请提供你自己账户的用户 ID(步骤见下文);文章作者署名不能证明你的身份。浏览器会打开供你登录,包括处理任何 CAPTCHA。 登录后,浏览器会打开 <publication>/publish/home,并等待出版物会话 Cookie;在自定义域名上,该 Cookie 是自定义域名下的 connect.sid。 保存前,必须成功完成有范围限制的身份验证读取。默认流程会验证读取权限,不会验证配置的用户 ID 或写入权限。

若要从所选出版物的已验证会话中推导用户 ID,而不是手动输入,请使用:

npx substack-mcp login https://yourblog.substack.com --verify-identity --profile work

--verify-identity 会使用该主机的 Cookie 请求出版物主机上的 /api/v1/user/profile/self,要求顶层 ID 为正的安全整数,然后在保存前执行现有的已验证身份草稿列表检查。如果同时提供 --user-id,该参数就会作为断言:若不匹配,则停止操作,不保存也不替换配置文件,即使使用 --force 也一样。不会将公开个人资料、文章作者署名、其他主机的 Cookie 或其他主机的端点作为备用来源。已验证模式的 JSON 结果会报告 user_identity: "verified" 和 identity_source: "authenticated_publication_self_profile";不会打印 ID。这只是登录时的观测结果,并非持久化的身份证明,也不能证明拥有写入权限。普通的 doctor 仍会将身份报告为未验证。

尚未在所有 Substack/自定义域名配置中实测验证出版物主机对个人资料端点的支持情况。如果端点不可用、已过期、发生重定向或格式异常,已验证模式会安全失败,不保存任何内容。仍可使用现有的手动配置 ID 流程,但该流程会明确标记为未验证。对于 #150,仍需进行真实浏览器测试;fixture 测试不能证明当前登录界面的实际情况。

如果未指定 --profile,登录会保存到 ~/.substack-mcp/session.json(目录覆盖变量:SUBSTACK_MCP_HOME)。当出版物凭据环境变量和 SUBSTACK_PROFILES 均未设置时,服务会使用此旧版会话。

默认存储(SUBSTACK_CREDENTIAL_STORE=file): 会话使用 AES-256-GCM 加密,密钥根据操作系统账户和计算机派生。文件权限请求值为 0600;在 Windows 上,访问还取决于目录 ACL。这是绑定到计算机的文件,并非操作系统钥匙串或机密保险库。以你的操作系统用户身份运行的代码可以派生该密钥。如果 MCP 客户端会替你管理机密,请改用环境凭据。

可选的操作系统钥匙串: 在登录进程和 MCP 客户端的环境中均设置 SUBSTACK_CREDENTIAL_STORE=keychain。macOS 通过 /usr/bin/security 使用 Keychain;Linux 需要 libsecret 和 secret-tool,以及已解锁的 Secret Service;Windows 通过 PowerShell 的 PasswordVault 使用 Credential Manager。这三种方式都会在 GitHub 托管的运行器上通过 keychain CI 工作流使用合成凭据进行测试(macOS 使用已解锁的临时钥匙串,Linux 使用 gnome-keyring 会话);桌面环境中锁定的钥匙串仍可能触发提示。登录会将所选账户写入钥匙串,服务则从钥匙串读取。明确选择钥匙串后,绝不会将加密文件用作回退来源。钥匙串有助于防范其他操作系统用户、复制的磁盘,以及某些仅能访问文件的恶意软件。以你的用户身份运行的代码通常可以查询钥匙串。请确保操作系统账户和运行中的代码值得信任。 在 Linux 上,对于条目不存在或密钥环已锁定这两种情况,secret-tool lookup 都可能在没有错误消息的情况下以状态码 1 退出。不使用 --force 的具名写入会先搜索并解锁;如果发现已有条目,则拒绝覆盖。

命名配置文件与迁移
npx substack-mcp login https://yourblog.substack.com --user-id 12345 --profile work
npx substack-mcp profiles list
# Copy an existing legacy session without changing its file:
npx substack-mcp profiles migrate --name personal
# Copy a file session or named file profile into the keychain; source remains:
npx substack-mcp profiles migrate --to keychain
npx substack-mcp profiles migrate --to keychain --name work

键必须以小写 ASCII 字母开头,且只能包含小写字母、数字和连字符,最多 64 个字符。替换现有配置文件需要显式指定 --force。列表输出包含键、可读性状态、发布来源和文件保存时间,不包含 Cookie 和用户 ID。不可读的配置文件仍会显示,但无法选用。保存时间记录的是本地持久化时间(包括迁移),并非令牌签发或过期时间。列表最多显示 32 个配置文件。

配置文件存储要求本地文件系统支持硬链接(例如 NTFS 或常见的 Linux 文件系统),以便创建时能够安装完整的加密文件,而不覆盖现有名称。不支持 FAT/exFAT 和某些网络挂载:请将 SUBSTACK_MCP_HOME 设为合适的本地目录。请勿使用 --force 来绕过不受支持的文件系统。

在 MCP 客户端的环境中设置 SUBSTACK_PROFILES=work,personal,即可选择最多 32 个不同的配置文件。请先移除所有发布凭据变量:同时使用配置文件选择和旧版或命名凭据变量会导致错误,即使变量值为空也不例外。所选配置文件缺失、损坏或无效时,启动会停止;绝不会回退到其他账号。发现过程中绝不会激活磁盘上的配置文件。使用多个配置文件时,工具需要显式指定发布键,CLI 读取操作需要 --publication。

如需回滚,请取消设置 SUBSTACK_PROFILES 并恢复之前的环境配置。迁移会逐字节保留旧版会话。这些文件使用现有的加密格式。profiles list 会列出文件配置文件;迁移或登录后,可通过 SUBSTACK_PROFILES 显式选择密钥链配置文件。运行 substack-mcp status --json 可进行离线配置诊断,或运行 substack-mcp doctor --check-auth --json,对每个所选账号执行有界读取。

选项 B — 手动获取凭据

在浏览器中打开 Substack,然后:

  1. 会话令牌: 对于自定义域名,打开开发者工具 → Application → Cookies → https://your-custom-domain,并从发布内容自己的域名复制 connect.sid(以 s%3A 开头的 URL 编码字符串)。请勿从 substack.com 复制 substack.sid:这是另一个会话,自定义域名的管理 API 会以 403 拒绝它。对于 *.substack.com 发布内容,请使用该主机上的 connect.sid,或 .substack.com 上的 substack.sid。令牌必须与 SUBSTACK_PUBLICATION_URL 的主机匹配;只有由 Substack 托管的发布内容才可使用 .substack.com 作为备用。
  2. 用户 ID: 按照查找你的账号用户 ID中的步骤操作。请勿使用发布文章署名中的 ID:一个发布内容可能有多个作者。此服务不会独立验证所提供的 ID。
  3. 发布 URL: 你的 Substack URL;如果有自定义域名,请包含该域名(例如,https://newsletter.yourdomain.com 或 https://yourblog.substack.com)
查找你的账号用户 ID
  1. 在 Substack 中,打开你自己的账号个人资料并复制其用户名(即 https://substack.com/@your-handle 中 @ 后面的部分)。发布 URL 或其他作者的个人资料都不是你的账号用户名。
  2. 将 your-handle 替换为你的用户名,然后打开 https://substack.com/api/v1/user/your-handle/public_profile。读取 JSON 响应顶层的数字 id;不要使用嵌套在发布内容或文章署名下的 ID。此服务也会使用该公开个人资料端点进行匿名个人资料查询。
  3. 确认响应中的 handle 和姓名与将用于登录的账号相符。将顶层的 id 提供给 login --user-id 或 SUBSTACK_USER_ID。公开个人资料查询只能确认你输入的用户名;浏览器登录读取检查不能证明 Cookie 属于该 ID。执行任何写入操作前,请再次确认账号。
2. 配置 MCP 客户端
Claude Desktop

添加到 claude_desktop_config.json:

{
  "mcpServers": {
    "substack": {
      "command": "npx",
      "args": ["-y", "@conorbronsdon/substack-mcp"],
      "env": {
        "SUBSTACK_PUBLICATION_URL": "https://yourblog.substack.com",
        "SUBSTACK_SESSION_TOKEN": "your-session-token",
        "SUBSTACK_USER_ID": "your-user-id"
      }
    }
  }
}

除了手动配置 MCP 外,还可使用 Claude Code 和 Codex 插件设置。仓库插件市场和本地插件与精选目录收录或托管的 ChatGPT 支持无关。

Claude Code

添加到 .mcp.json:

{
  "mcpServers": {
    "substack": {
      "command": "npx",
      "args": ["-y", "@conorbronsdon/substack-mcp"],
      "env": {
        "SUBSTACK_PUBLICATION_URL": "https://yourblog.substack.com",
        "SUBSTACK_SESSION_TOKEN": "your-session-token",
        "SUBSTACK_USER_ID": "your-user-id"
      }
    }
  }
}
3. 验证

向 AI 助手询问:“我有多少位 Substack 订阅者?”

工具契约中记录了工具输出兼容性、响应限制和版本管理。

运维诊断

CLI 通过与服务端相同的 MCP 处理程序和凭据解析,提供运维命令和配置检查。drafts create 会创建一个私有草稿;其他运维命令会读取:

substack-mcp status --json
substack-mcp doctor --json --check-auth
substack-mcp drafts list --limit 10

运维 CLI 和诊断中记录了命令、JSON 信封、退出代码、请求截止时间和响应限制。

工具

每个工具都会声明明确的 MCP 副作用注释;请参阅工具注释。工具描述是权威措辞。

读取
工具描述
get_subscriber_count获取你的刊物当前的订阅者数量
list_subscribers读取一页范围受限的私人订阅者记录
search_subscribers筛选并分页读取私人订阅者记录;可选活动、日期、标记和收入字段
get_subscriber按确切邮箱查找会员身份;核对待处理的新增记录
list_published_posts分页列出已发布的文章
get_publication读取预计的刊物身份信息/设置,验证已配置的主机,并报告缺失字段;不验证账户身份或角色
list_publication_tags读取标记定义,默认包含隐藏标记,并进行范围受限的本地分页
get_post_tags解析文章的标记关联;保留无法解析的 ID,并报告空结果中的身份不确定性。目前仅针对空响应实时验证草稿覆盖情况
search_posts按查询和状态搜索刊物档案;提供范围受限的分页及续页元数据
plan_draft_update审核拟议更改、预检和用于尽力检测过时状态的回执;不写入数据
export_draft可编辑的 Markdown、精确的原始正文、转换诊断、预检和编辑器链接
preflight_draft只读检查标题、受众、正文结构、图片和付费墙,并提供编辑器链接
list_drafts列出草稿文章
get_post按 ID 获取已发布文章的完整内容
get_draft按 ID 获取草稿的完整内容
get_post_comments获取已发布文章的评论
get_sections列出你的刊物版块(分类)及其 ID
get_post_analytics按 ID 获取已发布文章的统计数据(浏览量、打开量、注册量、订阅量、互动量)
rank_posts按浏览量、打开量、发送量、比率、注册量、订阅量、估算价值或日期对文章进行排名,并区分 null 值和缺失值
get_publication_stats读取仪表板摘要和指定范围内的刊物指标,并区分缺失和不可用状态
get_growth_sources读取范围受限的增长来源归因和可选事件
list_incoming_recommendations列出推荐你的刊物,包括开始日期、活跃状态和由仪表板归因的订阅者
list_outgoing_recommendations列出你的刊物推荐的对象(可能不完整)。这并非推荐你的对象;如需查询,请使用 list_incoming_recommendations
list_outgoing_recommendation_stats列出你的刊物为其推荐的刊物带来的订阅者
list_scheduled_posts列出计划未来发布的文章(只读;排期仍需在 Substack 的编辑器中进行)
get_user_profile匿名读取按用户名查找的最简公开用户资料
get_profile_feed匿名读取一页公开用户动态,支持游标续页
get_note_thread匿名读取公开 Note、其上级内容以及一页回复
list_public_posts匿名读取一页范围受限的公开档案
get_public_post按 URL 匿名读取公开文章,并附带正文状态和截断标记
公开读取

这五个工具使用独立的匿名读取器。它只发送 User-Agent 和 Accept,绝不会发送已配置的 publication cookie 或其他凭据。已配置的 publication 用于选择默认归档源;调用方可以提供列入许可名单的 HTTPS publication 源。允许的主机包括 substack.com、单标签 *.substack.com、已配置的 publication 源,以及 SUBSTACK_PUBLIC_READ_ORIGINS 中列出的精确源(以逗号分隔的 HTTPS 源,不含端口、 路径或用户信息)。重定向会被拒绝。*.substack.com publication 可能会 重定向到其自定义域名(例如 lenny.substack.com);JSON 读取不会跟随该重定向。 请将自定义 HTTPS 源添加到 SUBSTACK_PUBLIC_READ_ORIGINS,并通过该源读取。配置了多个 publication 时,每个 publication 工具都必须提供 publication 键。

个人资料动态页面的大小由上游决定;has_more: null 表示上游未提供 续页元数据。若存在 more_branches 或 next_cursor,话题串页面可能会省略回复; completeness: "unknown" 表示上游未提供续页元数据。 完整归档页面的 has_more: null 是因为未返回总数。公开文章的 body_status 是基于受众和正文是否存在的启发式判断;它不能证明具有完整访问权限。 匿名读取器不会使用订阅权益。暂不支持读取器订阅和收件箱:已配置的 publication 会话访问 substack.com 读取器账户路由时收到 401;这些路由 需要单独的读取器会话,而此服务不会管理该会话。

归档搜索和草稿审查

search_posts 接受 query(1–500 个字符)、status(published、drafts 或 scheduled,默认为 published)、offset(默认为 0)和 limit(1–50, 默认为 25)。它会发起一次经过身份验证的归档请求,并返回投影后的元数据、 returned、total、has_more 和 next_offset。请使用 next_offset 和相同的 query/status 继续获取结果。当 Substack 未提供总数且页面已满时, has_more 为 null(未知);下一页可能为空。匹配和索引由 Substack 控制: 这并不保证会完整扫描全文。请使用 get_post 或 get_draft 获取完整内容。 分页不是快照;并发编辑可能会导致结果在不同页面间移动。

preflight_draft 接受 draft_id,读取一次草稿,并返回 checks_passed、 包含严重性、代码和消息的发现项、内容计数以及编辑器链接。它会检查标题、 受众、JSON/正文结构、图片包装器和 HTTPS 来源,以及付费墙数量和边界位置。 未知节点和外部图片会生成审查警告。超过两百万个字符、10,000 个节点或深度 100 的正文 不会被完整检查;counts.complete 为 false,达到扫描限制后会跳过聚合检查。 未知节点警告最多列出五种类型,供编辑器审查。这是有针对性的静态检查, 并非完整的 ProseMirror 验证或发布批准。它不会获取链接/图片、验证访问设置, 也不能证明最终渲染效果。请在 Substack 中审查草稿;不会修改任何内容。

配置了多个 publication 时,这两个工具都必须提供 publication。

写入(私有草稿;图片上传会返回公开 URL)
工具说明
create_draft根据 markdown 创建新草稿(私有)
update_draft应用经过审查的变更回执;重新检查未发布状态并报告回读结果
update_draft_tags规划或更改草稿标签;默认试运行,仅限草稿,写入后回读一次
upload_image从文件、数据 URI 或公开 HTTPS URL将图片上传到 Substack 的 CDN——返回可公开获取(未列出)的 URL
更改草稿前先审阅

在 0.9 中,先调用 plan_draft_update 并审阅其输出,再使用相同的字段和返回的回执调用 update_draft。已发布的草稿或已知过时的草稿会被拒绝。读写竞态仍然存在;请检查读取回显结果,并在 Substack 中审阅。CLI 通过 drafts plan 和 drafts apply 使用相同的流程。示例和限制请参阅草稿更改和迁移。

公开社区写入(实验性)
工具说明
create_post_comment在已配置的出版物中发表评论;默认预览,启用实时模式时会立即发布
restack以独立读者账号重置一篇文章或 Note;默认预览,启用实时模式时会立即发布

实时尝试需要设置 SUBSTACK_EXPERIMENTAL_COMMUNITY_WRITES=1、 dry_run=false、confirm_publish=true,并明确批准具体账号、目标和文本。 Restack 操作还需要单独的读者会话。两个工具都会在写入前检查已认证身份,尝试发送一次 POST,并报告范围受限的读取回显结果,不会自动重试。端点有来源证据;实时验证仍待完成。请参阅设置、凭据路由、同意和限制。

发布(Notes——立即公开)
工具说明
create_note发布 Substack Note(短篇内容,立即发布)
create_note_with_link发布附带链接卡片的 Note(立即发布)

Substack 上的 Notes 没有草稿状态,因此这两个工具都不提供先创建草稿的选项。

订阅者管理

add_free_subscriber 会将一位已同意的读者添加到免费新闻通讯中。这会更改分发设置:该读者可能会收到之后发送的新闻通讯邮件。可以通过 send_welcome_email: true 请求发送欢迎邮件(默认关闭)。此操作不会授予付费访问权限,也不会绕过 Substack 对之前已退订地址的屏蔽。其 MCP 注解将该操作标记为外部写入(readOnlyHint: false、openWorldHint: true)。

{"email":"[email protected]","consent_confirmed":true,"consent_evidence":{"source":"booking:message-id","recorded_at":"2026-09-01T00:00:00Z"},"dry_run":true}

默认采用试运行模式。在确认实际的新闻通讯订阅同意后,将 dry_run: false 设为执行模式。实时添加需要在 consent_evidence 中提供来源引用和时间戳;此证明会与出版物密钥一并回显以供审计,但不能替代对底层同意记录的检查。多出版物配置还必须指定 publication 选择器,与其他所有工具相同。

结果分为 existing、dry_run、verified、blocked 和 unverified、busy、retryable。busy 表示未执行写入;请等待其他操作完成。retryable 表示请求因身份验证或速率限制而被拒绝;请先解决该问题,再明确重试。空的 API 确认不能证明订阅者已添加。 verified 表示请求后精确的成员资格查询成功;但这不能证明本次请求最初创建了该成员资格。仪表板数据可能会延迟更新。缺失的读者也可能之前已退订。

对于 unverified,请使用 get_subscriber 重新检查;切勿自动重复添加。对于 blocked,请在 Substack 中审查,不要绕过屏蔽。自动化调用方必须在发送每个实时请求前持久化尝试记录。客户端的内存重复操作防护在重启或单独的 HTTP 会话之间不会保留。不要将订阅者身份和同意证据存入共享代码库、提交给未经批准的公共服务的提示词或常规日志。

实现和实时验证说明:订阅者 API。

对于 Google Calendar 预约选择加入流程,日历同步助手提供有范围限制的 Gmail 扫描、最新回答选择、私有持久化尝试记录,以及在写入结果不确定时进行只读核对。计划安排是明确的本地设置步骤;安装 MCP 不会启动后台任务。

有意排除的功能
  • 发布文章 — 发布长篇文章应由人类审慎决定(上文提到的 Notes 是已记录的例外)
  • 删除 — 对 AI 工具来说破坏性太大
  • 安排发布时间 — 使用 Substack 编辑器安排发布时间。list_scheduled_posts 会读取 你在编辑器中排队的内容,但此服务绝不会创建、编辑或取消任何安排。

如需使用具备持久云端状态和每周邮件报告的常驻调度器,请参阅 Cloud Calendar sync。

多个出版物

要在单个服务后运行多个出版物?为每个出版物设置一组三个 SUBSTACK_PUB_<KEY>_* 变量,而不是普通的 SUBSTACK_* 变量。<KEY> 可以是你选择的任意名称(字母、数字、下划线),它会转换为小写并以连字符分隔的出版物键,例如 KEVIN_MULDOON → kevin-muldoon。

"env": {
  "SUBSTACK_PUB_KEVIN_MULDOON_PUBLICATION_URL": "https://kevinmuldoon.substack.com",
  "SUBSTACK_PUB_KEVIN_MULDOON_SESSION_TOKEN": "token-1",
  "SUBSTACK_PUB_KEVIN_MULDOON_USER_ID": "111",
  "SUBSTACK_PUB_SAPERE_PUBLICATION_URL": "https://sapere.substack.com",
  "SUBSTACK_PUB_SAPERE_SESSION_TOKEN": "token-2",
  "SUBSTACK_PUB_SAPERE_USER_ID": "222"
}

每组三个变量相互独立,设置任意一个 SUBSTACK_PUB_<KEY>_* 变量都会声明该出版物。变量组不完整——缺少变量、值为空,或只包含空白字符——都会导致启动失败,并显示包含该键的错误,而不会静默忽略该出版物。这一点很重要,因为被忽略的出版物并不只是“少了一个出版物”:如果忽略的是唯一的出版物,服务就会回退到已存储的浏览器登录会话;如果忽略的是两个出版物中的一个,所有工具都会失去 publication 参数,因此原本要调用被忽略出版物的请求会静默转到剩下的那个出版物。

键的比较不区分大小写,且 _ 会转换为 -。两个会解析为同一键的名称(SUBSTACK_PUB_ALPHA_* 和 SUBSTACK_PUB_Alpha_*)也会导致启动错误——静默合并它们会使一个出版物的 URL 与另一个出版物的会话令牌配对。

<KEY> 只能包含 ASCII 字母、数字和下划线;三个后缀必须为大写,且整个变量名不得包含多余的空白字符。任何以 SUBSTACK_PUB_ 开头但不符合此格式的变量名——键中包含连字符、后缀为小写、包含带重音符号的字符、末尾有空格——都会导致启动错误,并指出变量名,而不会被悄悄忽略。原因与上文相同:被忽略的出版物并不只是少了一个出版物,而是会静默转到另一个出版物。

配置了两个或更多出版物时,每个出版物工具都会增加一个必填的 publication 参数,值必须是你配置的键之一(例如上文的 kevin-muldoon、sapere)。调用模型必须在每次出版物调用中指定其中一个;未识别的值会在进行任何 Substack API 调用之前被拒绝,因此误操作不会将内容写入错误的出版物。如果只配置了一个出版物——无论是常见的普通 SUBSTACK_* 变量配置,还是仅配置一组三个 SUBSTACK_PUB_<KEY>_* 变量——都不会添加 publication 参数;所有工具的架构都与单出版物模式一致。

不要混用这两种方式:只要设置了任意 SUBSTACK_PUB_<KEY>_* 变量,普通的 SUBSTACK_* 变量就会被忽略(并显示启动警告),而不会被当作一个未命名的额外出版物。

账户级的 restack 工具使用显式指定的读者 account_user_id,而不是 publication 参数。其读者凭据单独配置;它绝不会使用出版物会话。

SUBSTACK_USER_AGENT 和 SUBSTACK_REQUEST_TIMEOUT_MS 适用于每个已配置的出版物,并非针对单个出版物。浏览器登录也支持显式命名的配置文件;请参阅 命名配置文件与迁移。

令牌过期

Substack 会话令牌会定期过期(通常约 90 天)。如果遇到身份验证错误,请重新运行 substack-mcp login 以刷新已存储的会话,或从匹配的发布站点主机的 DevTools 中复制新的 Cookie,并更新环境变量。自定义域名需要使用自己的 connect.sid,而不是 substack.com 的另一个会话 substack.sid(自定义域名会以 403 拒绝该会话)。对于 *.substack.com 发布站点,请在该主机上使用 connect.sid,或在 .substack.com 上使用 substack.sid。然后运行 substack-mcp doctor --check-auth 验证访问权限。

自定义域名与 Cloudflare

本节介绍经过身份验证的创作者 API 调用。匿名公开阅读 使用上文公开阅读中的源站规则。

通过自定义域名(例如 blog.example.com)提供服务的 Substack 发布站点位于 Cloudflare 后方,Cloudflare 可能会以 403 error code: 1010 拒绝非浏览器请求。为避免此问题,服务默认发送浏览器 User-Agent 和 Referer,并使用已配置的发布站点 URL。

  • 匹配主机和 Cookie。 如果使用规范的 *.substack.com URL,请使用该主机的会话或 .substack.com 备用会话。自定义域名的 connect.sid 应与该自定义域名的 SUBSTACK_PUBLICATION_URL 配套使用。
  • 覆盖 User-Agent(可选):如果需要不同的浏览器标识,可通过 SUBSTACK_USER_AGENT 设置:
"env": {
  "SUBSTACK_PUBLICATION_URL": "https://yourblog.substack.com",
  "SUBSTACK_SESSION_TOKEN": "your-session-token",
  "SUBSTACK_USER_ID": "your-user-id",
  "SUBSTACK_USER_AGENT": "Mozilla/5.0 ..."
}

请求超时

每个发往 Substack 的请求都设有 30 秒的截止时间。Node 不会自行设置请求超时——只有 10 秒的连接超时——因此,如果主机接受连接后便不再响应(例如代理丢弃数据包而不是拒绝连接),工具调用就可能无限期挂起。达到截止时间的请求会失败,并返回一个指明端点和时限的 TimeoutError。

可通过 SUBSTACK_REQUEST_TIMEOUT_MS 调高或调低超时时间(单位为毫秒;如果值不是数字或不大于 0,则会发出警告并使用默认值):

"env": {
  "SUBSTACK_REQUEST_TIMEOUT_MS": "60000"
}

传输方式

默认情况下,服务通过 stdio 使用 MCP 通信,上述客户端配置也以此为前提。对于持久运行的可自托管部署,可设置 MCP_TRANSPORT=http,启用无状态 Streamable HTTP 服务(POST /mcp、GET /health)。设置方法、监听器变量和安全模型请参阅 HTTP 传输。

此监听器接受的请求

HTTP 监听器启动时处于关闭状态:默认仅允许回环 Host 和 Origin,可选设置 bearer 令牌(MCP_HTTP_TOKEN),请求正文上限为 10 MiB。Host 和 Origin 检查不属于身份验证;只要其他进程能够访问该端口,就应设置令牌。请参阅监听器策略。

带版本的 GHCR 镜像和传输验证:容器分发。

类型化错误

API 失败会映射为类型化错误(AuthenticationError、RateLimitError、 ValidationError、NotFoundError、ServerError、TimeoutError 和基类 SubstackAPIError)。状态映射和错误正文解析的说明请参阅类型化错误。

草稿导出

使用 export_draft 导出只读 Markdown/JSON 文件包,或运行:

substack-mcp export 42 --output draft-export.json
substack-mcp export 42 --format markdown --output draft.md

Markdown 导出会在 .source.json 旁置文件中保留完全一致的原始正文。重新使用前请检查 unsupported_nodes。已存在的文件需要使用 --force。有关发布站点选择、限制、部分导出和文件恢复,请参阅导出与 CLI 行为。

Markdown 支持

草稿支持 CommonMark/GFM Markdown:标题、嵌套的粗体/斜体/删除线、 链接和引用链接、带标题和链接目标的图片、带起始编号的嵌套 列表、代码、引用块、分隔线和硬换行。独立的 `` 块会为长篇草稿添加一个付费墙。

不支持的内容会在写入前返回 unsupported_nodes。查看这些诊断信息后, 草稿调用方可以明确设置 allow_unsupported: true,以保留字面形式的回退内容。表格仍以 Markdown 形式保留在代码块中;原生 表格、标注和任意嵌入内容均不属于支持范围。长篇草稿中,顶层段落里的脚注会映射为编辑器的原生脚注。 笔记在发布或创建附件之前都会拒绝不支持的转换,且没有回退选项。

有关映射、限制、兼容性变更,以及离线测试样例与实时编辑器检查之间的区别,请参阅 Markdown 编写指南。

重要说明

  • 此服务使用 Substack 的非官方 API。如果 Substack 更改其端点,服务可能会失效。
  • 会话令牌以 Cookie 形式发送。请妥善保管你的 SUBSTACK_SESSION_TOKEN。
  • 服务会在启动时检查你的凭据,且检查发生在 MCP 握手完成之后;它只会发出警告,不会因网络调用而阻止启动。如果令牌已过期,各工具仍会分别报错,便于针对实际故障采取措施。
  • 服务会处理 SIGTERM 和 SIGINT:关闭传输并以状态码 0 退出,因此 docker stop 会及时返回,而不是一直等待宽限期结束。

开发

如需选择性地执行实时读取检查,请参阅实时契约验证材料。 该探测在常规 CI 中处于禁用状态,且绝不会发布或写入内容。

发布前,请运行 npm run test:package。它会在干净的临时目录中安装包含生产依赖的构建归档包,检查两个可执行入口,并在不使用真实凭据的情况下验证 MCP 版本和完整的已注册工具目录。

git clone https://github.com/conorbronsdon/substack-mcp.git
cd substack-mcp
npm install
npm run build

在本地运行:

SUBSTACK_PUBLICATION_URL=https://yourblog.substack.com \
SUBSTACK_SESSION_TOKEN=your-token \
SUBSTACK_USER_ID=your-id \
npm start

参与贡献

欢迎提交问题和拉取请求。由于此服务使用 Substack 的非官方 API,最有帮助的贡献是在端点变更后修复问题。如果某个工具停止工作,请提交问题,并注明工具名称和错误信息。安全优先的边界始终不变:不发布、不删除、不安排长篇帖子发布。笔记会按设计立即发布,其描述中必须继续醒目地说明这一点。

关于

由 Conor Bronsdon 为 Chain of Thought 播客制作工作流构建并维护;该工作流用于起草和审阅简报帖子,再由人工点击发布。Conor 主持 Chain of Thought,这是一档探讨 AI 基础设施以及从业者如何实际构建相关技术的节目。创作者可使用的更多工具见 ai-tools-for-creators。可在 X 上通过 @ConorBronsdon 联系 Conor。

配套工具:

  • Transistor MCP:Transistor.fm 的官方 MCP 服务。提供节目、发布和分析功能。
  • podcastindex-mcp:搜索 Podcast Index 并跟踪嘉宾出演记录
  • op3-mcp:报告 OP3 的下载量、听众地域分布和应用信息
  • apple-podcasts-mcp:从 Apple Podcasts Connect 获取播放量、关注者数量和单集收听数据
  • gsc-mcp:在 Google Search Console 中查询搜索表现、关键词和站点地图
  • podcast-benchmark:仅使用公开数据,将节目与同类节目进行对比

免责声明

这是一个独立的个人项目,与任何公司均无关联,也未获得任何公司的赞助或认可。文中表达的所有观点均为我个人观点。

Codex 插件

此代码库包含位于 .codex-plugin/plugin.json 的 Codex 清单,以及位于 .mcp.json 的 MCP 配置。它使用 npx 通过标准输入/输出运行已发布的 npm 软件包; 必须安装 Node.js 和 npm。.mcp.json 中固定了软件包版本,因此升级插件的服务 需要显式修改配置。

请按照上文所述,使用环境变量或浏览器登录会话,在插件之外配置你的 Substack 凭据。 切勿提交会话令牌。安装不会验证账户身份,也不会授予发帖权限。 长篇文章仍会保存为草稿;Notes 会立即发布。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。