关于 FeedKeeper Cloud
FeedKeeper Cloud 是面向自托管用户的 RSS 和 Atom 阅读器,使用 SQLite 保存订阅与阅读记录。它内置远程 MCP 接口,可让客户端搜索、整理和阅读文章,并支持全文搜索与离线使用。
主要功能
- 01RSS 和 Atom 订阅管理
- 02全文搜索与文章笔记
- 03收藏文章并归档全文
- 04分类、筛选与静音关键词
- 05远程 MCP 读写访问
- 06离线阅读与同步
适用场景
- 01在自有服务器管理新闻订阅
- 02通过 MCP 搜索和整理未读文章
- 03保存文章全文以便日后查阅
- 04离线时阅读已缓存文章
MCP 相关
提供支持 Streamable HTTP 的远程 MCP 接口,允许客户端读取、搜索、收藏和整理订阅内容。支持只读或读写令牌,以及 OAuth 登录。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://feedkeeper.cloud/mcpclaude mcp add --transport http visualfusion-feedkeeper https://feedkeeper.cloud/mcp{"mcpServers":{"visualfusion-feedkeeper":{"type":"http","url":"https://feedkeeper.cloud/mcp"}}}在 Cursor 中打开{"servers":{"visualfusion-feedkeeper":{"type":"http","url":"https://feedkeeper.cloud/mcp"}}}在 VS Code 中打开{"mcpServers":{"visualfusion-feedkeeper":{"type":"http","url":"https://feedkeeper.cloud/mcp"}}}{"mcpServers":{"visualfusion-feedkeeper":{"serverUrl":"https://feedkeeper.cloud/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://feedkeeper.cloud/mcp需要授权工具
详细介绍
FeedKeeper
一款轻量、可自托管的 RSS 阅读器和远程 MCP 服务,适用于新闻、博客和 AI 工作流。
FeedKeeper 是一款独立的 RSS 和 Atom 订阅源管理器,面向希望完全掌控自己订阅内容的用户。它可以安静地运行在你自己的服务器或 Raspberry Pi 上,将所有内容存储在本地 SQLite 数据库中,无需任何云账户。
除了简洁的网页阅读器,FeedKeeper 还内置了原生的、经过身份验证的 Model Context Protocol (MCP) 端点。它已列入官方 MCP Registry(io.github.visualfusion/feedkeeper),并通过了 Anthropic Claude Directory 的验证,可让 MCP 客户端通过远程连接读取、搜索、收藏和整理你的订阅源。你的订阅和阅读历史都保存在自己的 SQLite 数据库中。
它默认支持多用户,提供相互隔离的账户、个人访问令牌,以及三语界面(英语、德语和日语)。
为什么选择 FeedKeeper?
已有一些不错的可自托管阅读器,例如 Miniflux 和 FreshRSS。如果你希望将订阅源融入 AI 工作流,同时又不放弃对数据的掌控,FeedKeeper 就适合你:
- 内置 MCP。 Claude、ChatGPT 和其他 MCP 客户端可直接连接到
/mcp,支持通过 OAuth 登录或使用个人访问令牌,并可选择只读或读写模式。FeedKeeper 已列入官方 Model Context Protocol Registry(io.github.visualfusion/feedkeeper),并通过了 Claude 连接器目录的验证。你可以让它生成每日简报、让 Agent 筛选未读文章,或让它策划一期内容。无需运行单独的桥接服务。 - 运行开销小。 一个 Node 进程和一个 SQLite 文件,并内置全文搜索。无需 PostgreSQL,也无需 Redis。它可以运行在 Raspberry Pi 上,也可以运行在 Uberspace 这类共享主机上。
- 开放 API。
/api/v1下的 REST API 在 OpenAPI 文件中有详细说明,并支持离线同步、笔记和内容专辑,方便第三方构建自己的客户端。 - 便于扩展。 管理员无需创建分支,即可为网页应用添加设置、页脚链接或单点登录表单,详见扩展网页应用。
如果你只需要一款朴素、成熟且集成丰富的阅读器,那么成熟的项目会是更稳妥的选择。FeedKeeper 还很年轻(版本 0.x),因此可能存在一些不够完善之处。
快速开始
大约一分钟即可启动。我们已将适用于 amd64 和 arm64(包括 Raspberry Pi)的预构建镜像发布到 GitHub Container Registry。你只需要 Docker,无需克隆或构建:
mkdir feedkeeper && cd feedkeeper
curl -fsSLO https://raw.githubusercontent.com/visualfusion/feedkeeper/main/compose.yaml
echo "SESSION_SECRET=$(openssl rand -hex 32)" > .env
docker compose up -d
打开 http://localhost:3000,通过网页引导界面完成初始设置。若使用公共域名,还需在 .env 中添加 PUBLIC_URL=https://your.domain(所有选项请参阅 .env.example)。
只想先看看?运行 npx feedkeeper 即可启动,无需 Docker(需要受支持的 Node.js 版本,参阅使用 Node.js 运行 FeedKeeper);数据会保存在 ~/.feedkeeper 中。
要更新,请拉取新镜像并重启:
docker compose pull
docker compose up -d
更改 SESSION_SECRET 会使当前浏览器会话退出,并导致已存储的双重验证密钥无法读取(参阅账户安全);订阅源和账户仍会保留在数据库中。想自行构建镜像?克隆代码库,然后运行 docker compose -f compose.yaml -f compose.build.yaml up -d --build。
如果启动时未设置 SESSION_SECRET(例如使用下方的某个模板),镜像会在首次启动时生成一个密钥,并将其保存在数据卷中。
使用 AI Agent 设置(Claude Code、Cursor、Codex)
如果你在服务器或本地计算机上使用 AI 编码助手,可以粘贴以下提示词:
“使用 Docker Compose 在这台计算机上设置并启动 FeedKeeper。下载或参照 https://raw.githubusercontent.com/visualfusion/feedkeeper/main/compose.yaml 中的模板,生成一个安全的 64 字符
SESSION_SECRET,将PUBLIC_URL设置为这台计算机可访问的地址,确保feedkeeper_data卷持久化,启动容器,并确认网页引导界面可通过端口 3000 响应。”
其他运行方式
| 位置 | 方式 |
|---|---|
| Raspberry Pi | Docker 分步指南,包含 HTTPS 和备份。 |
| HTTPS 反向代理 | Caddy、nginx 和 Traefik 配置,包含转发客户端 IP 和 MCP 客户端设置。 |
| Coolify、Unraid、CasaOS、Portainer | 适用于可自托管和家庭实验室平台的现成模板。 |
| Node.js,无需 Docker | 运行 npx feedkeeper 即可启动,无需克隆或构建,参阅使用 Node.js 运行 FeedKeeper。 |
| Uberspace 或任何 SSH 主机 | 部署到 Uberspace。 |
功能
- 分类和订阅源排序 — 将订阅源分组到不同分类中,搜索和筛选订阅源列表,就地重命名分类,并通过拖动调整订阅源顺序。
- 智能发现订阅源 — 粘贴直接订阅源链接或网站地址(如
example.com/blog);FeedKeeper 会查找 RSS 和 Atom 订阅源,包括列在网站订阅源概览页中的订阅源,并在订阅前逐一检查。 - 可靠的订阅源更新 — 同时获取多个订阅源,并限制每个来源的并发数。响应缓慢的订阅源和临时故障不会拖慢其他更新;未完成的工作会在重启后继续。
- 自动字符编码 — 既能解析标准 UTF-8,也能解析旧版 ISO-8859-1/Windows-1252 订阅源,不会出现变音符号乱码或符号损坏。
- 将已保存文章作为持久档案 — 为文章加星标即可保存:FeedKeeper 会保留文章全文,并将图片存储在数据库旁边,因此即使来源发生变化,文章仍然可读。已保存的文章不会因清理或取消订阅而消失,不受关键词筛选影响,且全文可搜索。
- 全文搜索 — 使用 SQLite FTS5 对标题、摘要、缓存的全文和个人笔记建立索引。按 BM25 相关性排序,支持不区分变音符号的匹配和短语搜索。
- 文章笔记与持久知识 — 为任意文章添加个人 Markdown 笔记。笔记可跨设备同步,可导出为独立的 Markdown 文件,并永久保护文章免受保留策略清理。
- 权威订阅源图标 — 图标会缓存在服务器上,并使用 SHA-256 哈希和条件 ETag,因此设备加载图标更快,也无需向第三方发出请求。
- 关键词屏蔽筛选器 — 在文章进入信息流之前,筛除匹配特定关键词的文章,减少信息过载。
- 过滤空图库内容 — 没有编辑文本的图库链接(只有图片或“阅读更多”提示)不会出现在文章列表、搜索结果、通知和精选内容中。简短新闻和图片说明仍会显示;已保存或添加注释的内容仍可访问。不会删除任何内容。
- 健康状态监控 — 清晰的状态指示器会显示轮询状态、连续获取错误次数和时间戳,让你立即发现失效的订阅源。
- 通用收件箱(稍后阅读) — 可通过任何浏览器、分享扩展或 MCP 客户端,将网页摘录、URL 和个人笔记直接保存到个人收件箱。系统会自动提取文章全文和主图,并离线存档。
- 精选专刊与每日简报 — 提供篇幅固定的早间、午间和晚间专刊。由外部 Agent 通过 MCP(例如 Claude、本地大模型或自定义脚本)策划,并附有结构化、带链接的编辑概览。最新一期会一直保留,直到后续一期发布。 候选内容和发布内容都必须包含可读的正文文本,不能只有重复标题或“阅读更多”/播放器提示,无论发布者或 URL 是什么。仅含视频/音频的条目会留在资料库中,但不会进入新的专刊;简短报道、摘要和文字稿仍符合条件。现有专刊不会更改。
- 自动数据库维护 — 合理的默认设置会清理已读文章、限制保留条目数量,并按计划运行 SQLite
VACUUM,以保持存储占用精简。 - 远程 MCP 访问 — 通过标准 Streamable HTTP,将条目直接传入 Claude 或任何兼容 MCP 的环境。支持只读或读写令牌、用于 ChatGPT 和 Claude 等连接器的 OAuth 登录(含同意页面、PKCE,以及可在设置中撤销),并支持基于游标的分页以进行增量同步。
- 优先保护隐私与支持自托管 — 仅需一个 Node.js 进程和一个 SQLite 文件。无需外部数据库引擎,不进行遥测或跟踪。
- OPML 2.0 导入与导出 — 可随时在 Feedly、NetNewsWire、Inoreader 或 Reeder 之间切换。
- 文章阅读器与后台预处理 — 在应用中阅读订阅源内容,采用共享且有界的全文提取机制,支持可靠重试和来源主机限制。可为每个订阅单独调整全文获取设置。阅读器内容会去除重复的作者和日期行,包括独立的行内署名;若未单独提供作者信息,则保留来源标注。视频、社交帖子和音频播放器(包括被同意插件拦截的内容)会转换为一个链接,由客户端显示为卡片;文章内的相关文章或热门文章列表会被移除。清理规则由一组简单的内容规则组成,社区可以对其进行扩展。设置和运行限制请参阅全文获取。
- 列表视图和报纸视图 — 可在紧凑列表和编辑式版面之间切换;后者采用宽幅头条和较长的预览。手机始终使用报纸视图。
- 适合移动设备的 Web 应用 — 响应式布局,支持标签页导航和下拉刷新,可安装到主屏幕,并提供浅色、深色和系统主题。
- 支持离线使用 — Service Worker 可让已安装的应用在无网络连接时启动。应用会在设备上保存已保存的文章和最新的未读文章及其全文和图片,因此你可以在火车上阅读、搜索和筛选。标记为已读或保存等更改会先保留,待重新联网后再发送。可在设置中关闭此功能;注销时会移除缓存数据。
- 通知和主屏幕快捷方式 — 可选的新文章推送通知,适用于你选择的订阅源(在 iPhone 和 iPad 上,需先将应用添加到主屏幕);应用图标可显示你选择的订阅源的未读文章数量;提供跳转到已保存文章和添加订阅源的快捷方式;还可将其他应用中的网址直接分享到添加订阅源对话框。通知采用端到端加密,并通过浏览器厂商的推送服务发送;服务器会在首次启动时创建推送密钥,并将其保存在数据库中。
- 个人资料 — 每个账户都可以设置显示名称和个人头像。
- 在线备份 — 服务持续运行时,可创建经过验证的 SQLite 备份。
- 引导式入门与入门包 — 通过按兴趣精选的订阅源列表(新闻、技术、Apple、开发、科学、设计、游戏、商业、体育、文化)立即开始使用。每个订阅源都附有简短说明;可一次性订阅多个列表中的订阅源,也可发现单个网站,或在设置空账户时导入 OPML。原生应用也可获取这些列表(
GET /api/v1/feed-lists)。 - 支持浏览器自动填充和敏感操作再次验证的通行密钥 — 通过 WebAuthn 浏览器自动填充,在电子邮件输入框中即可轻松登录,无需密码。可通过模态框中的生物识别确认来保护敏感安全操作(注册通行密钥、设置双重身份验证、恢复代码),无需输入密码。所有安装版本都支持可选的 TOTP 双重身份验证和一次性恢复代码;请参阅账户安全。
- 强化安全性 — 防止对内部网络进行探测的 SSRF 防护、身份验证速率限制,以及经哈希处理的 API 令牌。
工作原理
flowchart LR
WebUI(["Web reader"])
NativeApp(["Native app / clients<br/>(iOS, iPadOS, macOS)"])
MCPClient(["MCP client<br/>(e.g. Claude)"])
subgraph Server["One Node process"]
direction TB
WebAPI["Web session API"]
NativeAPI["Native REST API (/api/v1)<br/>device & bearer tokens"]
MCPEP["MCP endpoint (/mcp)<br/>streamable HTTP"]
DB[("SQLite + FTS5<br/>feed poller & sync engine")]
WebAPI --- DB
NativeAPI --- DB
MCPEP --- DB
end
WebUI <--> WebAPI
NativeApp <--> NativeAPI
MCPClient <--> MCPEP
一个 Node 进程负责提供构建好的 Web 阅读器、开放 REST API(/api/v1)和 MCP 端点(/mcp,使用 Streamable HTTP transport)——它们都由同一个 SQLite 数据库、FTS5 搜索索引和订阅源轮询器支持。
Web 阅读器、原生应用和 MCP
FeedKeeper 使用单一后端,并针对不同场景提供相应的客户端:
- Web 阅读器是简洁易用的浏览器界面,适合日常阅读、订阅源分类和信息流筛选。
- **原生应用(iOS、iPadOS、macOS)**充分利用平台功能:通过 SQLite 更改日志进行离线同步、为每篇文章添加个人 Markdown 笔记,以及每日新闻版。
- 远程 MCP 访问让 AI 工具能够整理阅读列表、搜索过往内容,并使用相同的 API 检查候选文章。
为原生应用开发的功能(例如文章笔记和新闻版排期)也通过开放 API(/api/v1)提供,以便第三方客户端使用。
备份与恢复
在 FeedKeeper 运行时创建一致的 SQLite 备份:
npm run db:backup -- /safe/location/feedkeeper.sqlite
如果不使用 Docker,请先运行一次 npm run build,再使用备份命令。该命令不会覆盖现有备份,并会验证备份的完整性。已保存文章的图片存放在数据库旁边的 archive 文件夹中(可通过 ARCHIVE_PATH 配置);备份时会将其复制到 <backup>.archive,恢复时则会将其放回。备份包含数据库和归档文件,不包含 SESSION_SECRET:请将该密钥与备份一同保存,因为它也用于保护数据库中的双重验证密钥(请参阅账户安全)。请将备份保存在应用程序目录之外,并复制到另一台机器或存储设备上。
使用 Docker Compose 时,在挂载的数据卷中创建备份,然后将其复制到主机:
docker compose exec feedkeeper node server/dist/feedkeeper.js backup /app/data/feedkeeper-backup.sqlite
docker compose cp feedkeeper:/app/data/feedkeeper-backup.sqlite ./feedkeeper-backup.sqlite
# only present if you have saved articles with images:
docker compose cp feedkeeper:/app/data/feedkeeper-backup.sqlite.archive ./feedkeeper-backup.sqlite.archive
恢复前,请先停止 FeedKeeper,然后运行:
npm run db:restore -- /safe/location/feedkeeper.sqlite --force
恢复操作会替换已配置的数据库。命令成功后,重新启动 FeedKeeper。如果现有备份是在较旧版本中创建的,启动时可能需要迁移数据库。
使用 Docker Compose 时,请停止服务,并在一次性容器中运行恢复命令,同时以只读方式挂载备份:
docker compose stop feedkeeper
docker compose run --rm --no-deps -v "$PWD/feedkeeper-backup.sqlite:/restore.sqlite:ro" feedkeeper node server/dist/feedkeeper.js restore /restore.sqlite --force
docker compose up -d feedkeeper
快速开始(本地开发)
需要 Node.js 22.22.2+(22.x)、24.15+(24.x)或 26+。
git clone https://github.com/visualfusion/feedkeeper.git
cd feedkeeper
npm install
cp .env.example .env
# edit .env — at minimum, set SESSION_SECRET (see the comment in the file)
npm run dev:server # terminal 1
npm run dev:web # terminal 2
打开 http://localhost:5173,按照引导界面创建第一个管理员账户。(更喜欢使用终端?npm run setup 可以完成相同操作,无需浏览器。)
部署
请参阅逐步指南,了解如何在 Uberspace 上运行 FeedKeeper。相同步骤也适用于任何可通过 SSH 访问且支持相应 Node.js 版本的 Linux 主机。
用于生产环境时,请构建一次并运行编译后的服务:
npm run build
npm run start
托管选项
如果您不想自行运维服务器,FeedKeeper Cloud 是由同一批维护者运营的托管版本。本仓库仍采用 MIT 许可证,并且完全支持自托管。
连接 MCP 客户端 
**本地 stdio 模式(Claude Desktop 和本地工具)。**运行 feedkeeper mcp(或 node server/dist/mcp-stdio.js)即可启动由 SQLite 数据库提供支持的本地 stdio MCP 服务,无需开放端口或配置网络。
使用 OAuth(ChatGPT、Claude 和其他连接器)。将 https://<your-domain>/mcp 添加为远程 MCP 服务或自定义连接器。客户端会自动发现登录流程:你登录 FeedKeeper,在授权页面选择只读或读取和写入,然后客户端会获得一个短期令牌(有效期为 1 小时,可在 30 天内刷新)。已连接的 AI 助手会列在设置 → MCP 下,随时可以断开连接。OAUTH_ALLOWED_REDIRECT_HOSTS 可限制允许注册的主机。将 PUBLIC_URL 设置为客户端访问服务所用的地址;参见 docs/design/mcp-oauth.md。
使用个人访问令牌(用于脚本和不支持 OAuth 的客户端)。
- 登录 FeedKeeper 网页界面,然后前往设置 → 个人访问令牌。
- 创建令牌并立即复制——它只会显示一次。对于只需浏览文章的客户端,选择只读;若要允许客户端更改订阅源或阅读状态,则选择读取和写入。现有令牌会保留此前的写入权限。
- 添加一个指向
https://<your-domain>/mcp的 MCP 服务条目,并在标头中发送Authorization: Bearer <token>。设置 → MCP 还提供了现成的 Claude Desktop 配置。
每次工具调用都限定于已登录用户——客户端只能查看和管理该用户自己的订阅源和条目。OAuth 令牌仅适用于 /mcp。
通过 AI 助手提示词进行连接
如需让 AI 助手为你配置 MCP 连接,请在设置 → 个人访问令牌中创建个人访问令牌,然后运行:
“将 FeedKeeper 添加为远程 HTTP MCP 服务,地址为 https:///mcp,使用 Authorization: Bearer ,并将其写入我的 MCP 配置(例如 claude_desktop_config.json 或 Cursor MCP 设置)。通过列出我的订阅源来验证连接。”
可用的 MCP 工具
| 工具 | 描述 |
|---|---|
list_feeds | 列出已订阅的源及其未读数量和健康状态,也可仅列出存在错误的源 |
get_feed | 查看单个已订阅源的元数据、订阅设置、未读数量和健康状态 |
subscribe_feed | 订阅源 URL 或网站 URL(自动发现源) |
discover_feeds | 在网站 URL 上发现可用的 RSS/Atom 源 |
save_to_inbox | 将网页剪藏、URL 或个人笔记保存到收件箱,并自动归档全文和图片 |
unsubscribe_feed | 取消订阅 |
update_feed | 更改订阅的源 URL、名称、轮询间隔、全文设置、推送通知或应用图标计数;新 URL 会在替换旧 URL 前进行验证 |
list_folders | 列出文件夹及其源数量和未读数量 |
create_folder | 创建文件夹 |
rename_folder | 重命名文件夹 |
delete_folder | 删除文件夹;其中的源仍保持订阅状态 |
move_feed_to_folder | 将订阅移入或移出文件夹 |
refresh_feed | 请求更新已订阅的源;遵循源的暂停设置并报告待处理工作 |
get_digest | 按源分组显示未读文章及简短摘要,这是查看新内容最省事的方式 |
get_overview | 查看整个账户的统计信息:未读和已保存文章、热门源、文件夹及故障源 |
get_new_items | 获取未读条目,可按源、搜索词或书签筛选;也可省略文章 HTML 并缩短摘要 |
list_items | 按添加时间分页浏览精简条目;使用游标获取较早或新添加的条目 |
get_item | 获取一篇文章及其缓存内容(HTML 或纯文本),可选择分页(offset、nextOffset、revision) |
fetch_full_text | 当源仅提供文章预览时,下载并缓存全文;后续分页部分请使用 get_item |
search_items | 搜索所有条目的标题和摘要(可选按书签筛选) |
mark_read | 将一个或多个条目标记为已读 |
mark_unread | 将一个或多个条目标记为未读 |
mark_all_read | 将所有已订阅条目标记为已读,也可限定在某个源或文件夹内 |
bookmark_item | 保存一个或多个条目;已保存的条目会连同全文和图片一起归档 |
unbookmark_item | 移除一个或多个条目的书签 |
list_muted_keywords | 列出用户当前启用的屏蔽关键词 |
add_muted_keyword | 添加关键词,以自动筛除匹配的文章 |
unmute_keyword | 移除屏蔽关键词规则 |
export_opml | 将所有已订阅的源导出为 OPML 2.0 XML 字符串 |
import_opml | 从 OPML 2.0 XML 字符串导入源 |
get_edition | 读取当前期刊、来源和修订版本,包括已过期或已忽略的状态 |
get_edition_candidates | 获取符合应用版块偏好和屏蔽关键词设置的精简候选条目 |
publish_edition | 发布经过排序的精选期刊,并可选择包含结构化主题概述、展示布局、过期时间、修订版本检查和安全重试 |
dismiss_edition | 忽略共享期刊,并提供修订版本和重放保护 |
除了工具,服务还提供提示词(daily_briefing、catch_up_on_topic、saved_reading_list、triage_unread)和资源(feedkeeper://feeds、opml、saved、digest 及 feedkeeper://items/{id}),客户端可将其显示为现成操作。
只读令牌仅开放不会更改 FeedKeeper 数据的工具。get_item 返回已存储的源内容或阅读器内容;fetch_full_text 会从文章所在网站下载文章,因此需要读写令牌。条目操作可接受单个 itemId 或最多 200 个 itemIds。get_new_items、search_items 和 list_items 接受 since 和 until(ISO 日期或日期时间),用于按发布日期筛选。进行增量同步时,请保存 newestCursor,下次将其作为 after 传入,并使用 nextCursor 作为 before 继续获取,直到没有更多页面。
原生应用
随时随地阅读和离线阅读,可使用官方 FeedKeeper 应用。该应用可在 App Store 下载,适用于 iOS、iPadOS 和 macOS。只需在网页阅读器中扫描 Settings → Devices 下的配对二维码,即可在几秒内直接连接到你的自托管实例。
该应用基于 FeedKeeper 开放的原生 API(/api/v1)构建,提供以下功能:
- 增量差异同步和离线文章缓存
- 离线操作排队(阅读状态、星标和文件夹会自动同步回来)
- 由 SQLite FTS5 驱动的快速全文搜索
- 每篇文章同步的个人 Markdown 笔记
- 阅读版式偏好和每日报纸版次
内置网页阅读器仍然完全免费,并持续获得全面支持。原生同步 API 已开放并记录在 docs/openapi.yaml 中,欢迎第三方和社区客户端基于同一组端点构建(入门指南请参阅 docs/building-clients.md)。
安全
- 默认关闭注册(
ALLOW_SIGNUP=false)。管理员可在 Settings 中创建其他账户。 - SSRF 防护:抓取前及连接时都会检查订阅源 URL 和重定向。默认会阻止私有/内部地址。对于需要访问本地订阅源的可信实例,请设置
ALLOW_PRIVATE_FEEDS=true。 - 屏蔽来源:在
BLOCKED_FEED_HOSTS中列出域名(以逗号分隔,包含子域名),即可禁止它们进入你的实例。系统会拒绝订阅、轮询以及获取文章文本和图片,并返回错误feed_blocked。已存储的订阅源将停止更新并移除其文章,但已保存的文章、带有笔记的文章以及已发布版次中的文章除外。更改列表后,请重启服务。 - 速率限制适用于登录和通用 API。
- 个人访问令牌以加盐哈希形式存储,绝不以明文存储。
- MCP 的 OAuth 2.1要求使用 PKCE,令牌会过期,刷新令牌会轮换并检测重复使用,且每次都会显示征求同意的页面。
- 位于代理或 CDN 后方:
TRUST_PROXY和CLIENT_IP_HEADER可确保速率限制使用客户端的真实地址。 - 按用户隔离数据:每个查询都限定为已通过身份验证的用户;订阅源在底层按 URL 去重,但订阅、阅读状态和令牌始终按用户区分。
FeedKeeper 服务会提供订阅源图标和已保存文章的图片,因此浏览这些内容时不会联系第三方网站;其他文章的图片仍从其来源网站加载。为查找订阅源的图标,服务大约每周会抓取一次网站首页。通过阅读器打开完整文章时,FeedKeeper 服务也会抓取该页面。
发现安全问题?请按照 SECURITY.md 中的说明私下报告,而不要公开提交问题。
配置
所有可用的环境变量请参阅 .env.example。
订阅源更新
默认情况下,FeedKeeper 一次最多检查四个订阅源,每个来源主机名最多发出两个请求。定时更新和手动更新、新订阅、OPML 导入以及 MCP 共用同一个队列。当来源繁忙或要求暂停时,手动刷新可能会处于等待状态;遇到这种情况时,网页阅读器会告知你。
每个数据库只运行一个应用进程。在内存较少的主机上,可从 POLL_CONCURRENCY=2 和 POLL_HOST_CONCURRENCY=1 开始。关停时请预留 45 秒;提供的 Docker Compose 文件已设置好此项。有关设置、日志和升级指南,请参阅订阅源轮询。
阅读器清理
提供阅读器 HTML 时会对其进行清理,不会改写存储的发布方内容。完全相邻的图片副本(例如分别用于桌面端和移动端的元素)会合并为一个;来源不同的图片、链接、响应式图片来源、说明文字,以及被文本隔开的重复图片,都会保持独立。空的商品卡片标题和广告位会根据其容器结构以及德语、英语和日语标签移除。现有广告内容、联盟营销披露和赞助文章标签仍会保留并可读。再次请求时,这些规则也适用于先前存储的文章;下载到客户端的副本需要刷新,才能反映服务端更新。
文章图片
图片代理会在同一订阅源的订阅者之间共享下载内容和缓存图片。这适用于请求代理图片的原生客户端,也适用于 Web 应用的离线副本;直接从发布方加载的图片不会经过此缓存。每次请求仍会检查对文章及其图片的访问权限。不同订阅源和不同来源 URL(包括查询参数)会使用独立的缓存条目。
此临时缓存默认上限为 256 MiB、2,000 张图片和六小时,最多同时处理四个任务,等待任务不超过 32 个。队列已满时会返回 503 image_busy,并附带 Retry-After: 1。下载仍遵循现有的 HTTP 限制、大小限制、SSRF 检查和重定向规则;POLL_REQUEST_TIMEOUT_MS 也会限制在图片队列中的等待时间。缺失图片(HTTP 404/410)和不支持的格式会记忆 60 秒;其他失败不会缓存。来源缓存指令可以缩短或禁止磁盘缓存。
Web 阅读器会将离线文章快照和排队中的更改绑定到经过身份验证的账户。切换账户时,会使私有 Service Worker 响应失效;即使之前的会话已过期且未明确登出,也会如此;正在进行的响应无法填充后续会话的缓存。没有账户归属信息的旧版快照会被丢弃并重新下载。另一个标签页中的更改会撤销该标签页的离线账户绑定,直到重新完成身份验证。
普通代理文章图片使用最长六小时的私有缓存时长,并带有内容 ETag。浏览器和 Web 离线缓存会重新验证这些图片;归档图片则保留其固定版本。新的代理 URL 版本可让现有客户端摆脱此前长达一年的不可变缓存策略。
如需更改这些限制,请参阅 .env.example 中的 IMAGE_CACHE_*。IMAGE_CACHE_PATH 默认指向数据库旁的 image-cache。每个缓存目录只能由一个进程使用,并应与 ARCHIVE_PATH 分开。过期条目和最近最少使用的条目会自动移除。缓存使用哈希键而非来源 URL,采用异步文件操作,且缓存命中时不会写入 SQLite。缓存启用后,每分钟会记录一次汇总的 image_cache 计数器:命中、未命中、共享任务、负缓存命中、错误、过载、淘汰、字节数、条目数、活动任务数和等待任务数。
已保存文章仍保留其永久归档。如果缓存和归档文件位于同一文件系统,它们会通过硬链接共享磁盘空间;否则,保存文章时会复制其图片。淘汰缓存不会删除已保存的副本。现有归档可在不联系来源的情况下重新填充缓存;这些快照仍与所属文章绑定,因此较旧的已保存图片不会替换同一来源 URL 上较新的图片。照常备份数据库和归档;临时缓存无需备份。
无需迁移数据库。如需回滚,请停止应用并恢复到先前版本。或者,设置 IMAGE_CACHE_MAX_BYTES=0 并重启,以停用磁盘缓存;设置 IMAGE_CACHE_NEGATIVE_TTL_SECONDS=0 也会停用失败记忆功能。应用停止时,可以删除现有临时文件。请保留归档。
扩展
基于 FeedKeeper 构建的运营方和产品,无需修改代码,即可通过 window.feedkeeperExtensions 为 Web 应用添加设置分区、页脚链接、页面标题和自定义登录。FeedKeeper Cloud(托管版)使用此功能管理会员设置。请参阅扩展 Web 应用。
技术栈
- 服务端:Node.js、TypeScript、Express、better-sqlite3、
@modelcontextprotocol/sdk - Web:React、Vite、Tailwind CSS、react-i18next
贡献
欢迎提交问题和拉取请求——请参阅 CONTRIBUTING.md 了解如何开始。改进或添加语言是很好的入门贡献,请参阅 docs/translating.md。为新用户看到的列表提供更好的初始订阅源也是如此,请参阅 docs/feed-lists.md。重要变更列于更新日志。这是一个新项目,因此可能还有一些不完善之处。
许可证
由 visualfusion 构建
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。