AI Talk

从一句话到全平台草稿:用 ChatGPT、MCP 与 OAuth 搭建 Sky Publisher

今天,我把一个一直想要的工作流真正跑通了:在 ChatGPT 对话中说一句“把这次聊天整理后发布到全平台草稿”,系统便会自动整理内容、检查各平台状态,并在小红书、知乎、微博和 X 中创建草稿。

这篇文章记录完整的设计与实现过程:为什么最初选择 WordPress REST API,后来为什么改用远程 MCP;怎样设计草稿和公开发布的安全边界;OAuth 2.1 联调中遇到了什么问题;以及最终如何验证整条链路。

一、我想解决什么问题

我经常在 ChatGPT 中进行很长的讨论。其中一些内容已经接近一篇完整文章,但从“有价值的对话”到“真正发布”之间还有大量机械工作:

  • 整理对话,去掉重复内容;
  • 补充标题、摘要和结构;
  • 转换成适合不同平台的格式;
  • 分别打开 WordPress、小红书、知乎、微博和 X;
  • 复制、粘贴并保存草稿;
  • 记录每个平台是否成功。

真正想要的体验很简单:

把这次聊天整理成教程,发布到我的全平台草稿。

ChatGPT 负责理解内容和意图,我自己的发布系统负责可靠、安全地执行。

二、第一步:先打通 WordPress

WordPress 是最容易接入的一站,因为它有成熟的 REST API。只要完成认证,ChatGPT 就可以创建文章、编辑现有文章、设置分类,并选择保存为草稿或公开发布。

这一阶段验证了最核心的可行性:大模型不仅能生成文章,也能调用外部工具完成真实操作。随后我增加了一个名为 AI Talk 的分类,专门收录由人和 AI 对话整理出的内容。

但 WordPress 只是一个平台。小红书、知乎、微博和 X 的接口能力、草稿机制与登录方式各不相同,仅靠一组普通 REST API 很难统一处理。

三、最终架构:ChatGPT + Remote MCP + Local Worker

最终采用的架构如下:

ChatGPT
   │
   │ OAuth 2.1 + MCP
   ▼
Sky Publisher Gateway
   │
   │ Job Queue / Status / Idempotency
   ▼
Local Worker on Mac
   │
   ├── 小红书
   ├── 知乎
   ├── 微博
   ├── X
   └── Facebook

其中每一层职责非常明确:

  • ChatGPT:理解用户意图、整理文章、选择工具和目标平台;
  • Remote MCP Gateway:负责认证、校验、权限、任务创建、幂等性和状态查询;
  • Local Worker:运行在我自己的 Mac 上,通过已经登录的浏览器执行平台操作;
  • 平台适配器:把统一的文章结构转换成各个平台能够接受的内容。

这样做的好处是,ChatGPT 不需要直接持有各个平台的账号密码;Gateway 也不需要模拟每个平台的复杂登录。真正的浏览器会话保留在我自己的设备上。

四、七个 MCP 工具

Sky Publisher 最终提供七个工具:

  1. list_publish_targets:读取 Worker、平台登录状态以及草稿/公开发布能力;
  2. validate_publish_job:只校验,不产生副作用;
  3. create_draft_job:创建私有草稿;
  4. create_public_job:创建可能公开发布的任务;
  5. get_publish_job:查询任务及各平台结果;
  6. retry_publish_targets:重试指定的失败平台;
  7. cancel_publish_job:取消仍可取消的任务。

这里最重要的并不是工具数量,而是把“草稿”和“公开发布”拆成了两个完全不同的接口。

五、安全设计:草稿接口不能表达公开发布

最初的接口同时支持 draftpublish。这会带来一个问题:即使用户只想创建草稿,ChatGPT 也会因为接口具备公开发布能力而谨慎地重复确认。

最终的解决办法不是简单地把接口标记成“低风险”,而是从结构上消除风险:

  • create_draft_job 的请求中根本没有 mode 字段;
  • 服务端强制所有目标使用 draft
  • 即使调用方尝试注入 publish,Schema 也会直接拒绝;
  • create_public_job 单独保留,并继续要求明确确认;
  • 生产环境还有公开发布总开关,默认关闭。

这是一条很实用的 Agent 设计原则:不要只依赖 Prompt 约束危险行为,而要让低风险工具在数据结构层面无法表达高风险操作。

六、OAuth 2.1 与权限隔离

为了让 ChatGPT 网页版能够连接私人 MCP 服务,我为 Sky Publisher 增加了 OAuth 2.1,使用 Authorization Code Flow 和 PKCE S256。

权限被拆分为:

  • publisher.read:查看平台、校验任务和查询状态;
  • publisher.draft:创建草稿;
  • publisher.publish:公开发布;
  • publisher.retry:重试任务;
  • publisher.cancel:取消任务。

访问令牌采用短有效期,刷新令牌轮换;服务端验证签名、签发方、Audience、Resource、过期时间和 Scope。Owner 授权口令不会写入仓库,也不会出现在日志中。

这层 OAuth 不只是“能登录”,更重要的是把 ChatGPT 能做什么限制在可审计的权限集合中。

七、任务系统的可靠性设计

浏览器自动化不是同步 HTTP 请求:平台可能加载缓慢、要求重新登录,或者出现验证码。因此发布任务必须异步执行。

Gateway 创建 Job 后,Worker 获取任务并逐个平台处理。每个目标都有独立状态,例如:

  • queued
  • running
  • draft_created
  • needs_login
  • needs_captcha
  • failed

系统还加入了幂等键。相同请求即使重复调用,也会返回同一个 Job,而不是在平台中生成多份重复草稿。

在创建任务前,ChatGPT 必须先调用 list_publish_targetsvalidate_publish_job。只有当 Worker 在线、Inventory 新鲜、平台已登录,并且校验结果为 valid=trueside_effects=false 时,才创建草稿。

八、今天遇到的几个真实问题

1. OpenAPI 工具数量不完整

最初远程 OpenAPI 中的路径参数使用了部分客户端不兼容的 $ref,导致 ChatGPT 没有识别全部 Action。把路径参数内联后,工具清单才完整加载。

2. Inventory 过期

浏览器更新重启后,Chrome 的调试端口消失,Worker 仍然保留旧的登录状态快照。后来增加了主动刷新机制:

  • Inventory 超过阈值时,Gateway 请求 Worker 刷新;
  • Worker 重连后立即刷新;
  • Chrome/CDP 故障时返回新鲜的 available=false,而不是继续使用过期状态。

3. OAuth 页面本地能打开,云端却失败

OAuth 联调中还遇到了一个很典型的问题:本地浏览器可以打开授权页,但 ChatGPT 的云端浏览器收到 502 Bad GatewayConnection refused

这说明“我本地能访问”并不能证明公网所有访问路径都正常。需要同时检查 DNS、IPv4/IPv6、CDN 节点、反向代理配置和 upstream 监听端口。OAuth URL 中的 state 与 PKCE Challenge 还是一次性的,失败后不能反复复用旧链接,必须从 ChatGPT 重新发起连接。

九、最终生产验证

OAuth 修复并重新连接后,我通过 ChatGPT 发出了一条测试指令。系统完成了以下步骤:

  1. 读取平台状态;
  2. 排除不支持草稿的 Facebook;
  3. 验证小红书、知乎、微博和 X;
  4. 得到 valid=trueside_effects=false
  5. 调用专用草稿接口;
  6. 查询任务直到进入终态。

最终四个平台均返回 draft_created,实际模式全部是 draft,没有任何内容被公开发布。

十、最终使用体验

以后在任意支持该私人插件的 ChatGPT 会话中,只需要选择 Sky Publisher,然后说:

把这次聊天整理成一篇文章,保存到小红书、知乎、微博和 X 的草稿箱。不要公开发布。

如果要先发 WordPress,则可以说:

把这次聊天整理成一篇教程,发布到 WordPress,并归入 AI Talk 分类;同时生成一版适合短社交平台的摘要。

结语

这套系统表面上是“一键发布”,本质上是在建立一条由自然语言驱动、但具备严格权限和状态管理的内容流水线。

大模型负责理解和创作,MCP 负责标准化工具调用,OAuth 负责身份与授权,Gateway 负责任务与安全策略,本地 Worker 负责真实执行。把这些部分拆开之后,ChatGPT 就不再只是一个写作工具,而变成了我个人内容基础设施的统一入口。

最后更新于 2026年9月6日 by qlili

0 0 votes
Article Rating
guest

0 Comments
Newest
Oldest Most Voted
0
Would love your thoughts, please comment.x
()
x