在 AI 代理逐渐成为人机交互主要入口的今天,一个核心矛盾日益突出:用户的订阅数据被困在第三方 Web UI 之后,AI 代理无法直接访问这些信息。Antenna 作为一款本地优先的 RSS 阅读器,通过将 MCP(Model Context Protocol)Server 直接嵌入阅读器核心,成功实现了订阅源数据向 AI 代理的开放输出。本文将从架构设计、工具注册机制、数据模型三个维度,解析这一整合的技术细节与工程价值。
核心问题:订阅数据为何需要「代理化」
传统 RSS 阅读器的数据流向是单向的:订阅源 Fetch 到本地存储,用户通过 Web 界面或客户端阅读。这一设计在 AI 时代暴露了两个根本性缺陷。首先,用户的订阅图谱(subscription graph)被困在阅读器的 Web UI 之后,AI 代理无法搜索、聚类或摘要这些内容。其次,主流阅读器逐渐走向商业化,广告侵入、数据追踪、导出困难等问题使得用户对数据的控制权持续流失。
Antenna 的设计哲学正是针对这两个痛点:把订阅图谱从封闭的 Web UI 中释放出来,使其同时服务于人类阅读和 AI 代理调用。该项目采用本地优先(local-first)策略,数据存储在用户自己的 SQLite 数据库中,不依赖任何 vendor cloud,也不存在数据锁定问题。
架构概览:SQLite + MCP stdio 的双输出模型
Antenna 的架构可以概括为「一个数据源,两个一流输出」。数据源是本地 SQLite 数据库,采用 WAL 模式以确保读写并发安全。输出之一是电子邮件投递,通过用户的 SMTP 配置(支持 Amazon SES、Postmark、Gmail App Password)发送单篇或摘要模式的 HTML 邮件。输出之二正是本文的核心 ——MCP Server,通过 stdio 协议与任意 MCP 客户端通信。
v0.1.0 版本仅支持 stdio 模式的 MCP 通信,这意味着它适合与本地运行的 AI 代理集成,例如 Claude Desktop。项目文档给出了典型的 Claude Desktop MCP 配置片段:通过指定 Python 解释器路径和配置文件路径,即可将 Antenna 的六个工具暴露给 AI 代理。这种设计避免了 HTTP 服务器的复杂性,同时也降低了安全风险 —— 所有数据都在本地文件系统内流动。
MCP 工具注册机制:六工具详解
Antenna 在 MCP 层暴露了六个工具,构成了 AI 代理操作订阅数据的完整原语集合。以下是每个工具的能力与适用场景分析。
list_sources 是健康检查类工具,返回每个订阅源的 last_polled_at(上次拉取时间)和 last_error(上次错误信息)。AI 代理可以据此判断哪些订阅源已经超时或失效,从而做出重试或告警决策。这个工具不返回具体内容,只返回元数据,适合用于代理的监控与巡检场景。
subscribe 接收一个 URL 参数,执行立即 Fetch 验证,并返回该订阅源的帖子数量。这个工具的核心价值在于「验证」——AI 代理在添加新订阅源之前,可以先用 subscribe 确认该 URL 可访问且包含有效内容,避免无效订阅污染数据库。
search_posts 是功能最强大的工具,基于 SQLite FTS5 虚拟表实现全文搜索。它返回带有高亮片段的搜索结果,支持布尔检索、短语匹配和前缀搜索。返回高亮片段的设计非常贴心 ——AI 代理可以直接从返回结果中提取上下文,无需二次请求获取完整内容。
get_post 是 search_posts 的补充,接收帖子 ID 或唯一标识符,返回完整的 HTML 内容以及纯文本版本。AI 代理可以用它获取具体文章的完整内容,用于深度分析或摘要生成。
recent_posts 提供最近一段时间内的新帖子列表,配合时间过滤条件使用。这个工具适合代理执行「每日简报」类任务 —— 拉取过去 24 小时的新内容并生成摘要。
unsubscribe 接收订阅源标识,执行退订操作。AI 代理可以基于预设规则自动清理失效或低质量的订阅源,实现订阅管理的自动化。
这六个工具的设计遵循了「最小完备集」原则:覆盖了增(subscribe)、删(unsubscribe)、查(search_posts、get_post、recent_posts)、监控(list_sources)的完整生命周期。
数据模型:FTS5 虚拟表与稳定 ID 去重
Antenna 的数据模型设计体现了「一次写入,多方查询」的思路。整个系统的数据存储在单一的 SQLite 数据库中,email 模块和 MCP 模块共享同一张_posts 表,没有任何同步延迟或索引分歧。这种设计的直接好处是:用户通过邮件阅读了一篇帖子后,AI 代理立即能知道这件事 —— 不存在「为什么代理没看到我刚读的帖子」这类问题。
搜索能力由 FTS5(Full-Text Search 5)虚拟表提供。FTS5 是 SQLite 内置的全文搜索引擎,支持倒排索引、布尔查询、短语匹配和前缀搜索。相比外部搜索服务,FTS5 的优势在于零额外依赖、查询速度快且完全本地化。Antenna 在写入帖子时自动同步到 FTS5 虚拟表,search_posts 直接查询该表并返回高亮片段。
去重机制是另一个关键设计点。Antenna 使用 feed 提供的 stable entry ID 进行去重,而非 URL 哈希。URL 哈希的缺陷在于,同一篇文章的 URL 可能因重定向或参数变化而改变,导致重复存储。stable entry ID 来自 RSS/Atom 规范的 <guid> 字段,是_feed 发布者提供的唯一标识,更可靠。这个设计确保了 AI 代理多次查询返回一致的结果,不会因为去重逻辑的细微差异而产生歧义。
集成配置与实际使用
将 Antenna 集成到 AI 代理的工作流中并不复杂。首先通过 pip 安装 Antenna,然后导入 OPML 文件(支持 Blogtrottr、Feedly、Inoreader 的导出格式)完成订阅迁移。之后配置 MCP 即可。
配置的关键在于理解 stdio 通信模式。MCP 客户端启动 Antenna 进程,通过标准输入输出传输 JSON-RPC 消息。这种模式适合桌面环境,但在服务器场景下有所局限 —— 项目文档明确提到,HTTP MCP 表面层将在 Phase 1 版本推出,届时将支持远程部署。
一个典型的使用场景是:AI 代理接收自然语言指令「搜索过去 7 天内所有标记为 robotics 且提及 Gemini 的帖子,总结最有趣的三篇」。代理内部调用 search_posts,传入时间范围过滤和关键词参数,获取高亮片段后生成摘要。整个过程无需人工干预,订阅数据从 SQLite 到 FTS5 搜索再到 MCP 工具返回,完全闭环。
局限与演进方向
当前 v0.1.0 版本存在几个明显的工程限制。首先,仅支持 stdio 模式决定了它目前适合个人桌面使用场景,不适合服务器部署或多用户共享。其次,没有 Web UI,所有配置通过 YAML 文件和 CLI 完成,对非技术用户有一定门槛。第三,单用户设计意味着没有认证和访问控制。
从路线图来看,Phase 0.5 将加入 Webhook 输出适配器和规则 UI,Phase 1 将推出托管服务和 HTTP MCP 表面。届时,Antenna 可能从个人工具演化为小型团队的订阅管理方案。
小结
Antenna 的核心贡献在于重新定义了 RSS 阅读器的数据出口:不再仅仅是人类阅读的终端,而是 AI 代理可以查询的数据库。通过 SQLite+FTS5 的本地存储方案、六工具的 MCP 注册机制、以及基于 stable entry ID 的可靠去重,它实现了「一次订阅,双重访问」的设计目标。对于希望将个人阅读数据融入 AI 工作流的开发者而言,Antenna 提供了一个值得参考的本地优先范式。