1. 项目概述一个让AI帮你写Substack的“智能助手”如果你是一个内容创作者或者像我一样经常需要打理一个Substack或类似的邮件通讯那你肯定对“写作-排版-发布”这个循环不陌生。有时候灵感来了但打开编辑器面对空白的页面和一堆格式按钮那股劲儿可能就泄了一半。更别提还要考虑标题优化、标签分类、发布时间这些琐事了。最近在GitHub上看到一个叫playerbs1/substack-publisher-mcp的项目第一眼就被它的定位吸引了一个基于MCPModel Context Protocol的Substack发布工具。简单来说它不是一个独立的写作软件而是一个“桥梁”或“插件”。它的核心作用是让你能在支持MCP协议的AI助手比如Claude Desktop、Cursor等里直接通过自然语言对话来完成Substack文章的创建、编辑和发布。想象一下你对着AI说“帮我把这篇关于春季旅行的草稿发到我的Substack上标题要吸引人一点标签加上‘旅行’和‘生活方式’设定为明天上午10点发布。”然后AI就能帮你一站式搞定。这听起来是不是有点像科幻片里的场景但这个项目正在把它变成现实。这个项目解决的核心痛点正是内容创作流程中的“摩擦”。它将AI的文本生成与理解能力与Substack这个成熟的内容发布平台无缝连接起来把创作者从重复性的平台操作中解放出来更专注于内容本身。它适合所有使用Substack的创作者无论是个人博主、小型媒体还是希望用AI提升内容运营效率的团队。2. 核心思路与技术架构拆解2.1 为什么是MCP协议的选择决定了生态位要理解这个项目必须先搞懂MCP是什么。MCP全称Model Context Protocol是由Anthropic公司提出并开源的一套协议。它的目标很明确为各种AI模型如Claude、GPT等提供一个标准化的方式来“使用”外部工具、数据和能力。你可以把它想象成AI世界的“USB标准”或“插件系统”。在MCP出现之前如果你想给AI助手增加新功能比如查数据库、控制智能家居、发布文章往往需要针对特定的AI平台如OpenAI的GPTs、Claude的Custom Actions进行深度集成过程繁琐且不通用。MCP的出现改变了这一局面。它定义了一套标准的通信方式通常是基于JSON-RPC over stdio或SSE使得工具提供方比如这个Substack发布器和工具使用方比如Claude Desktop可以解耦。对于substack-publisher-mcp项目而言选择基于MCP开发带来了几个关键优势一次开发多处使用只要AI客户端支持MCP如Claude Desktop、Cursor、Windsurf等这个工具就能被调用无需为每个客户端单独适配。关注点分离项目开发者只需要专注于实现与Substack API交互的逻辑而无需关心AI模型内部的复杂逻辑。安全性MCP服务器即本项目通常运行在本地或受信任的服务器上API密钥等敏感信息无需发送给远端的AI服务商提升了隐私安全性。2.2 项目整体架构一个标准的MCP服务器这个项目的本质是一个实现了MCP协议的服务器程序。它的架构可以清晰地分为三层协议层这一层完全遵循MCP规范。它负责与AI客户端建立连接接收来自客户端的JSON-RPC请求例如“调用工具publish_to_substack”并将执行结果封装成MCP规定的格式返回。这一层是通用的任何MCP工具都类似。业务逻辑层这是项目的核心。它解析协议层传来的参数将其转化为对Substack平台的具体操作。这主要包括身份认证处理用户的Substack登录态或API密钥。文章管理实现创建新文章、获取文章列表、编辑已有文章、发布/取消发布文章等功能。媒体处理可能包含图片上传到Substack并返回链接的功能。元数据操作处理子站Publication选择、标签Tags管理、发布时间调度等。Substack API适配层Substack官方没有提供完整的公开API截至我了解的信息因此这一层很可能通过模拟浏览器操作使用Puppeteer、Playwright等无头浏览器工具或逆向工程其内部接口来实现。这是整个项目技术难度最高、也最需要维护的部分因为Substack前端的任何改动都可能导致这里的代码失效。注意由于Substack API的非公开性项目的实现方式可能存在变数。一种更稳定但权限受限的方式是如果用户能提供通过浏览器开发者工具获取的认证Cookie或Token项目可能直接调用其内部API。否则无头浏览器方案是更通用的选择但会带来更高的复杂性和运行开销。2.3 与AI客户端的协作流程一个完整的使用流程展现了MCP的协作之美用户在Claude Desktop中开启对话。用户输入“帮我在‘我的科技杂谈’子站上发布一篇文章标题是‘AI辅助写作的未来’内容就用我们刚才讨论的草稿。”Claude模型理解用户意图后发现需要调用一个外部工具。它检查本地配置的MCP服务器列表找到了substack-publisher-mcp提供的工具。Claude通过MCP协议向本地运行的substack-publisher-mcp服务器发送一个tools/call请求。MCP服务器即本项目收到请求解析参数通过业务逻辑层和API适配层登录Substack找到“我的科技杂谈”子站创建新文章填入标题和内容点击“发布”或“保存草稿”。操作完成后MCP服务器将结果如文章链接、文章ID或错误信息打包通过MCP协议返回给Claude。Claude将结果转化为自然语言回复给用户“已完成文章已发布链接是https://yourname.substack.com/p/ai-future。”整个过程对用户而言就是一次自然的对话。所有的技术细节包括认证、API调用、错误处理都被封装在了MCP服务器背后。3. 核心功能与实操要点解析3.1 核心工具Tools定义与使用一个MCP服务器通过“工具”来暴露其能力。substack-publisher-mcp项目预计会提供以下几个核心工具理解它们就理解了项目的全部功能边界。3.1.1 文章发布与编辑工具这是最核心的工具可能被命名为publish_post或create_post。它接受的参数通常包括publication_name或publication_id: 指定要发布到哪个Substack子站如果你有多个。title: 文章标题。content: 文章正文内容支持HTML或Markdown取决于Substack编辑器的支持情况。status: 发布状态如draft草稿、published立即发布、scheduled定时发布。schedule_time: 如果状态是scheduled则需要提供具体的发布时间戳。tags: 文章标签数组如[“AI”, “Writing”, “Productivity”]。subtitle: 文章副标题。cover_image_url: 封面图URL。实操要点内容格式处理Substack的编辑器比较特殊。直接粘贴复杂的HTML可能格式错乱。一个稳健的做法是工具内部将Markdown或简化的HTML转换为Substack编辑器兼容的格式。或者更直接的方法是工具模拟用户操作将内容粘贴到富文本编辑区域利用编辑器自身的能力进行格式化。错误处理网络超时、认证失效、Substack界面改版都会导致失败。工具必须返回明确、可读的错误信息给AI以便AI能向用户解释例如“登录失败请检查Substack凭据”或“发布按钮未找到可能Substack界面已更新”。3.1.2 文章列表获取工具工具名可能为list_posts或get_publications。用于让AI了解现有内容避免创建重复标题或为编辑已有文章提供上下文。参数可能包括publication_name,status筛选已发布、草稿等limit数量限制。返回一个文章列表包含每篇文章的ID、标题、状态、链接和修改时间。3.1.3 文章更新工具工具名可能为update_post。用于修改已存在的文章。关键参数post_id或post_url以及需要更新的字段如新的title,content,status。注意事项更新操作需要准确定位文章。使用post_id是最可靠的这通常需要在创建或列表获取时保存。通过标题匹配可能存在歧义。3.1.4 媒体上传工具工具名可能为upload_image。AI生成的描述可能需要配图此工具可将本地图片或网络图片上传至Substack的媒体库并返回可直接嵌入文章的内容链接。参数image_path本地路径或image_url。核心难点Substack的图片上传通常需要交互式表单。无头浏览器方案需要模拟文件选择对话框这是自动化测试中的经典难题。解决方案可能是预先将图片上传到图床然后直接提供网络链接给工具由工具处理嵌入但这增加了依赖。3.2 认证与安全如何管理你的Substack账号这是用户最关心也最需要谨慎处理的部分。项目需要访问你的Substack账号因此认证机制必须安全、灵活。3.2.1 认证方案分析Cookie/Token认证推荐如果可行用户手动登录Substack后从浏览器开发者工具的“网络”或“应用”标签中提取关键的认证Cookie如substack.sid或Bearer Token。将其配置到MCP服务器的设置文件中。这种方式直接、高效避免了存储明文密码且权限明确即当前登录会话的权限。项目需要提供清晰的文档指导用户如何安全获取这些信息。无头浏览器自动登录项目启动时打开一个不可见的浏览器导航到Substack登录页自动填入用户配置的邮箱和密码进行登录。这种方式对用户最方便但隐患最大安全风险用户需要将密码明文存储在配置文件中。可靠性问题容易遇到验证码CAPTCHA拦截导致登录失败。维护成本高登录页面的任何UI改动都可能破坏自动登录脚本。重要安全提示无论采用哪种方式都强烈建议为MCP工具创建一个专用的Substack账号或使用有限权限的账号。并确保配置文件包含敏感信息的访问权限严格受限如Unix系统的600权限。3.2.2 配置实操项目通常会需要一个配置文件如config.json或config.yaml位置在~/.config/mcp/servers/substack-publisher/或项目根目录。{ auth: { method: cookie, cookie: your_substack_session_cookie_here // 或 // method: login, // email: your-emailexample.com, // password: your-password // 高风险不推荐 }, default_publication: My Tech Blog }在Claude Desktop等客户端中你需要在设置里添加这个MCP服务器。例如在Claude Desktop的claude_desktop_config.json中{ mcpServers: { substack-publisher: { command: node, args: [ /path/to/substack-publisher-mcp/build/index.js ], env: { SUBSTACK_CONFIG_PATH: /path/to/your/config.json } } } }4. 本地部署与调试实操指南4.1 环境准备与项目初始化假设你是一个有一定开发经验的用户想要自己部署和运行这个项目以下是详细的步骤。4.1.1 基础环境检查首先确保你的系统已安装Node.js版本建议在18.x或以上。这是运行JavaScript MCP服务器的基础。npm或yarn或pnpmNode.js的包管理器。Git用于克隆代码仓库。打开终端通过命令验证node --version npm --version git --version4.1.2 获取项目代码从GitHub克隆项目仓库git clone https://github.com/playerbs1/substack-publisher-mcp.git cd substack-publisher-mcp进入项目目录后第一件事是查看README.md文件。这是获取最新、最准确安装和配置说明的权威来源。如果README中提到需要特定版本的Node或其他依赖请务必遵循。4.1.3 安装项目依赖运行包管理器的安装命令。通常使用npmnpm install这个过程会下载项目所有的JavaScript依赖包包括MCP协议库、HTTP请求库、无头浏览器驱动如Puppeteer等。根据网络情况可能需要一些时间特别是Puppeteer会下载一个Chromium浏览器。实操心得在国内网络环境下npm安装可能会很慢或失败。可以尝试以下方法使用淘宝镜像npm config set registry https://registry.npmmirror.com使用yarn或pnpm它们在某些场景下可能更快。如果Puppeteer下载失败可以设置环境变量跳过下载使用系统已安装的ChromePUPPETEER_SKIP_CHROMIUM_DOWNLOADtrue然后在代码中配置executablePath指向你的Chrome路径。4.2 配置与首次运行4.2.1 创建配置文件参照项目文档创建你的认证配置文件。如前文所述优先尝试Cookie认证方式。在浏览器中登录你的Substack账号。打开开发者工具F12切换到“网络”(Network)标签。刷新页面找到任意一个对substack.com域名的请求如api/v1/相关的。点击该请求在“请求头”(Headers)部分找到Cookie字段。复制整个Cookie字符串很长包含substack.sid等键值对。在项目根目录或指定配置目录创建config.json填入复制的Cookie。4.2.2 运行MCP服务器进行测试大多数MCP服务器可以直接用Node运行。在项目根目录尝试node index.js # 或 npm start如果服务器启动成功你可能会看到类似“MCP server running on stdio”的日志。此时它正在等待来自MCP客户端的连接。4.2.3 连接AI客户端以Claude Desktop为例找到你的Claude Desktop配置文件。在macOS上通常位于~/Library/Application Support/Claude/claude_desktop_config.json。在Windows上位于%APPDATA%\Claude\claude_desktop_config.json。编辑这个JSON文件添加MCP服务器配置如第3.2.2节所示。注意command和args要指向你本地项目的入口文件。保存配置文件完全重启Claude Desktop不是关闭窗口而是从任务栏/程序坞退出再重新启动。重启后新建一个对话。如果配置成功Claude的输入框上方可能会显示一个小工具图标或者你可以直接询问“你能用Substack发布工具吗” Claude应该能识别出可用的工具。4.3 核心功能测试与验证配置成功后需要进行系统性的测试确保每个功能都按预期工作。4.3.1 测试清单认证测试让AI执行一个最简单的操作如“列出我的Substack子站”。如果返回成功并显示了你的子站名称说明认证通过。发布草稿测试执行“在[你的子站名]下创建一篇草稿标题为‘测试文章’内容为‘这是一个MCP工具测试。’”。完成后立即手动登录Substack后台检查草稿箱是否存在该文章。发布正式文章测试谨慎操作可以先发布到一个小众或测试用的子站。指令“将刚才的测试文章发布。” 检查文章是否公开可见。编辑文章测试获取已存在文章的ID或标题指令“更新文章‘测试文章’在内容末尾加上‘已更新。’”。检查修改是否生效。定时发布测试指令“创建一篇文章标题‘定时测试’内容‘定时发布’设定在2小时后发布。” 检查Substack后台的“已计划”列表中是否有该文章且时间是否正确。4.3.2 常见问题与排查问题Claude提示“未找到可用工具”。排查检查Claude Desktop配置文件路径和格式是否正确检查MCP服务器进程是否在运行查看MCP服务器的启动日志是否有错误确认Claude Desktop已完全重启。问题操作失败返回“登录失效”或“认证错误”。排查Substack的会话Cookie可能过期通常有效期较长但可能失效。重新登录Substack获取新的Cookie并更新配置文件。如果使用密码登录检查是否触发了验证码。问题发布文章成功但格式混乱。排查检查工具处理内容格式的逻辑。尝试让AI提供纯文本或非常简单的Markdown如仅标题和段落看是否正常。这可能是内容转换环节的bug。问题无头浏览器启动失败或超时。排查如果是Puppeteer确保Chromium下载完整。可以尝试增加超时时间或在代码中配置headless: false以可视化模式运行观察卡在哪一步。5. 深入原理MCP协议通信与Substack接口逆向5.1 MCP协议通信流程详解要真正理解这个项目如何工作甚至想为其贡献代码就需要深入MCP协议的通信细节。MCP通信基于JSON-RPC 2.0这是一个轻量级的远程过程调用协议。通信传输层可以是标准输入输出stdio、WebSocket或服务器发送事件SSE。对于本地工具stdio是最常见的方式。5.1.1 初始化握手当AI客户端如Claude Desktop启动时它会根据配置启动指定的MCP服务器进程即我们的substack-publisher-mcp。启动后双方通过stdio进行通信。服务器启动后首先向客户端发送一个initialize请求告知自己的协议版本、名称、能力等。客户端回复initialize的响应并可能附带一些初始化参数。握手完成后客户端会发送一个tools/list请求。服务器响应列出自己提供的所有工具publish_post,list_posts等的名称、描述、参数schema。这个schema非常重要它告诉AI模型这个工具需要什么参数是什么类型从而让AI能在合适的时机、构造正确的参数来调用它。5.1.2 工具调用流程当用户向AI提出一个涉及Substack的请求时AI模型如Claude根据对话上下文判断需要调用substack-publisher-mcp的某个工具。AI客户端构造一个tools/call请求通过stdio发送给MCP服务器。这个请求包含toolName工具名和arguments一个JSON对象包含用户意图转化来的参数。{ jsonrpc: 2.0, id: 1, method: tools/call, params: { name: publish_post, arguments: { publication_name: 我的博客, title: AI写作体验, content: 今天试用了一个新工具..., status: draft } } }MCP服务器收到请求在业务逻辑层解析参数调用相应的Substack操作函数。操作执行完毕成功或失败服务器向客户端发送一个tools/call响应。{ jsonrpc: 2.0, id: 1, result: { content: [{ type: text, text: 文章已成功创建为草稿ID123456编辑链接https://substack.com/edit/123456 }] } }如果出错则返回错误信息。AI客户端收到响应将结果内容result.content呈现给AI模型模型再组织成自然语言回复给用户。5.2 与Substack“对话”无头浏览器 vs 内部API这是项目最技术性的部分决定了工具的稳定性、速度和隐蔽性。5.2.1 无头浏览器方案通用但笨重如果无法获取稳定的内部API使用Puppeteer或Playwright是唯一选择。优势模拟真实用户操作几乎可以完成任何在网页上能完成的操作通用性强。劣势性能差需要启动完整的浏览器实例加载所有页面资源速度慢占用内存多。脆弱高度依赖页面UI结构。Substack前端的一个CSS类名更改、一个按钮位置调整都可能导致脚本定位元素失败。容易被检测虽然可以设置一些参数来降低被识别为机器人的概率但无头浏览器仍有特征可循。实现示例片段伪代码const puppeteer require(puppeteer); async function publishWithBrowser(title, content) { const browser await puppeteer.launch({ headless: true }); // 无头模式 const page await browser.newPage(); // 设置Cookie以保持登录状态 await page.setCookie(...cookies); await page.goto(https://substack.com/editor); // 等待编辑器加载这是一个脆弱的环节 await page.waitForSelector([data-testideditor-title]); // 输入标题和内容 await page.type([data-testideditor-title], title); // 切换到内容编辑区可能更复杂 const editorFrame await page.$(iframe); // 编辑器可能在iframe里 const frame await editorFrame.contentFrame(); await frame.type(body, content); // 点击发布按钮 await page.click(button:has-text(Publish)); // 等待发布成功提示 await page.waitForSelector(.success-message); const url await page.evaluate(() window.location.href); await browser.close(); return url; }5.2.2 内部API逆向工程方案高效但需维护这是更优的方案。通过浏览器开发者工具观察在Substack网站上进行操作时浏览器实际向哪些后端接口发送了请求。登录Substack打开开发者工具的“网络”(Network)标签。进行“发布文章”操作。在网络请求列表中筛选XHR或Fetch请求寻找包含api、graphql、publish、post等关键词的请求。分析该请求的URL、方法POST/GET、请求头特别是Authorization头和请求体Payload。如果找到就可以在代码中直接用fetch或axios库模拟这个请求。优势速度快资源消耗低更稳定只要API接口不变。挑战Substack的API可能未公开随时可能变动请求可能需要特定的、难以生成的Token或签名API可能比较复杂涉及多个步骤如先创建草稿再上传图片最后发布。实操心得一个混合方案可能更实用。对于登录态使用Cookie从浏览器获取。对于核心操作如发布尽量使用逆向出的内部API。对于无法API化的操作如处理富文本编辑器中的复杂格式再回退到无头浏览器进行精确模拟。项目需要良好的错误处理和回退机制。6. 扩展思考与最佳实践6.1 项目潜在的应用场景与扩展方向substack-publisher-mcp的价值远不止于“发布文章”这个单一动作。结合AI的能力它可以衍生出许多强大的工作流自动化内容流水线你可以结合其他MCP工具或AI的代码解释能力构建一个完整流水线。例如先用AI分析RSS订阅总结热点再让AI基于热点撰写初稿最后调用本工具发布到Substack。整个过程可以通过一个复杂的提示词或简单的脚本串联起来。多平台同步发布可以开发或集成其他平台的MCP发布工具如WordPress、Medium、知乎专栏等。AI在完成内容创作后可以依次调用多个发布工具实现“一文多发”。数据驱动的内容优化结合分析工具AI可以获取历史文章的打开率、点赞数等数据。在发布新文章时AI可以建议“根据历史数据带有‘教程’标签、在周二上午发布的文章打开率更高建议调整发布时间和标签。”智能草稿管理与重构AI可以定期扫描你的草稿箱对长期未完成的草稿进行摘要甚至建议续写方向或将其拆解为更短的内容。6.2 使用中的注意事项与避坑指南基于这类工具的开发和使用经验以下是一些关键的注意事项权限最小化原则务必使用一个专用的Substack账号来连接此工具不要使用你的主账号。如果支持在Substack内创建一个只有发布权限的子账户。内容审查不可省虽然AI能直接发布但强烈建议将首次发布状态设为“草稿”。发布前人工审查标题、内容、标签和封面图。AI可能会误解指令或产生不合时宜的内容。做好版本备份工具可能会出错误覆盖或删除文章。定期导出你的Substack内容备份。或者在本地用Git管理你的文章Markdown源文件将其作为唯一真相源发布只是最后一步。关注项目更新Substack前端和潜在的内部API会变化。关注GitHub仓库的Issues和Release及时更新工具版本避免某天突然失效。提示词工程是关键你给AI的指令越清晰结果越好。不要只说“发一篇文章”。应该提供结构化指令“角色你是科技专栏作者。任务基于以下要点写一篇关于MCP协议的技术短文。要点1. MCP是什么2. 解决了什么问题3. 一个使用例子。风格口语化带点幽默。字数800字左右。然后将成品发布到‘我的技术博客’子站标签加上‘AI’、‘开发工具’保存为草稿。”网络与稳定性确保运行MCP服务器的环境网络稳定。如果使用无头浏览器方案服务器环境最好有图形界面支持或使用虚拟帧缓冲区以减少未知错误。6.3 对于开发者的启示如何构建自己的MCP工具如果你对这个模式感兴趣想为自己常用的其他服务如Notion、Trello、Jira、社交媒体构建MCP工具这里有一些快速上手的思路从模板开始Anthropic官方和社区提供了一些MCP服务器模板TypeScript/Python。使用模板可以快速搭建协议通信层你只需要关注业务逻辑。明确工具边界仔细设计你的“工具”。一个工具应该完成一个相对独立、完整的任务。例如“在Notion中创建一个页面”是一个好工具“向Notion数据库添加一行数据”也是一个好工具。避免设计一个“操作Notion”的庞然大物。设计清晰的参数Schema这是AI能正确调用你工具的关键。使用JSON Schema详细定义每个参数的类型、描述、是否必填、枚举值等。良好的schema能让AI更好地理解何时以及如何使用你的工具。错误信息要友好工具执行失败时返回的错误信息不仅要给开发者看更要能让AI理解并转化为用户能懂的语言。例如返回“ERR_AUTH_FAILED”不如返回“登录失败请检查提供的API密钥是否正确且未过期”。重视测试除了单元测试一定要进行“端到端”的集成测试启动MCP服务器使用一个模拟的MCP客户端或简单的脚本去调用工具验证整个流程。这能发现协议层和业务层对接的问题。这个项目是一个很好的范例展示了如何将一个具体的平台能力Substack发布封装成AI世界的一个通用“技能”。随着MCP协议的普及未来我们或许真的能像组装积木一样用自然语言指挥AI串联起互联网上各种服务构建高度个性化的自动化工作流。而这一切就从理解并用好一个具体的MCP工具开始。