mcpField
F
FreshRSS

FreshRSS

本地服务
freshrss-mcp.ni-c.de生产力3今天更新

关于 FreshRSS

FreshRSS 的 MCP 服务,让 MCP 客户端读取和管理自托管 RSS 订阅。它将 Google Reader API 转换为易用工具,并以纯文本返回文章内容。

主要功能

  1. 01查看订阅、分类和未读数
  2. 02列出并读取文章
  3. 03标记文章状态和标签
  4. 04管理订阅与分类
  5. 05导入和导出 OPML

适用场景

  1. 01汇总各订阅源的未读文章
  2. 02阅读指定订阅或日期范围内的文章
  3. 03批量标记文章为已读
  4. 04导入或导出订阅列表

MCP 相关

向 MCP 客户端提供 FreshRSS 订阅、分类和文章的读取及管理工具。支持只读模式、工具筛选,并为不可逆操作请求确认。

配置

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

mcp.json · 通用配置
{
"mcpServers": {
"ni-c-freshrss": {
"command": "npx",
"args": [
"-y",
"@ni-c/freshrss-mcp"
],
"env": {
"FRESHRSS_URL": "<FRESHRSS_URL>",
"FRESHRSS_USER": "<FRESHRSS_USER>",
"FRESHRSS_API_PASSWORD": "<FRESHRSS_API_PASSWORD>",
"FRESHRSS_READ_ONLY": "<FRESHRSS_READ_ONLY>",
"FRESHRSS_INSECURE_TLS": "<FRESHRSS_INSECURE_TLS>",
"FRESHRSS_ALLOW_TOOLS": "<FRESHRSS_ALLOW_TOOLS>",
"FRESHRSS_DENY_TOOLS": "<FRESHRSS_DENY_TOOLS>"
}
}
}
}
启动命令npx -y @ni-c/freshrss-mcp
需要配置的环境变量
FRESHRSS_URLRoot URL of the FreshRSS instance, e.g. https://rss.example.com
FRESHRSS_USERFreshRSS user name
FRESHRSS_API_PASSWORD密钥API password from Settings -> Profile -> API management, not the web login password
FRESHRSS_READ_ONLYSet to true to register only the read tools
FRESHRSS_INSECURE_TLSSet to true to accept a self-signed certificate for this connection only
FRESHRSS_ALLOW_TOOLSComma-separated tool names or list_* prefixes to register; 'essential' selects a curated preset (default: all tools)
FRESHRSS_DENY_TOOLSComma-separated tool names or list_* prefixes to remove from whatever FRESHRSS_ALLOW_TOOLS left

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

安装包
npm@ni-c/freshrss-mcp0.3.2
ocighcr.io/ni-c/freshrss-mcp:0.3.2

工具

16

收录的工具列表 · 更新于 2 周前

此工具无需参数。

详细介绍

freshrss-mcp

CI OpenSSF Scorecard Socket Badge Glama score
npm version container image HTTP via mcp-hub
docs sponsor

一个用于 FreshRSS 的 Model Context Protocol(MCP)服务。FreshRSS 是一款可自托管的 RSS 和 Atom 订阅源聚合器。

它让 Claude Code、Claude Desktop 或 Codex 等 MCP 客户端能够处理你的订阅源:查看未读内容、阅读文章、标记文章,以及管理订阅和分类。

16 个工具只是上限,并非最低要求:设置 FRESHRSS_ALLOW_TOOLS=essential 即可改为注册精心挑选的 7 个工具。与 16 个工具相比,模型从 7 个工具中选择正确工具的可靠性高得多——详见选择要加载的工具。

它使用 FreshRSS 在 /api/greader.php 提供的 Google Reader 兼容 API,并通过工具参数屏蔽该 API 的种种特性,让助手能够直接使用:数字订阅源 ID、分类和标签名称、ISO 日期以及十进制文章 ID,无需处理 user/-/state/com.google/… 订阅流标识符和十六进制条目标签。

MCP 客户端通过标准输入/输出与 freshrss-mcp 通信;后者使用 GoogleLogin 身份验证令牌,通过 HTTPS 调用 FreshRSS 的 Google Reader 兼容 API

演示:通过 MCP Inspector CLI 列出工具、已订阅的订阅源和最新文章

有何不同

16 个工具,无需订阅流 ID。 Google Reader API 使用订阅流标识符和十六进制条目标签。这些工具使用数字订阅源 ID、分类和标签名称、ISO 日期以及十进制文章 ID,并返回纯文本,而非原始 HTML。

专为不可信订阅源打造。 每篇文章都来自互联网上的陌生人,因此响应会标记为数据,订阅源 URL 会移除凭据,文章文本也会按单篇文章和单次响应限制长度。5 个不可逆工具会先通过 MCP elicitation 征求用户确认。

要求

  • Node.js 22 或更高版本
  • FreshRSS 实例(基于 1.29 开发),并满足以下条件:
    • 已启用 API:设置 → 身份验证 → “允许 API 访问”
    • 已为用户设置 API 密码:设置 → 个人资料 → API 管理。 该密码与 Web 登录密码不同。

配置

变量必填说明
FRESHRSS_URL是实例的根 URL,例如 https://rss.example.com。系统会自动追加 API 路径 /api/greader.php。
FRESHRSS_USER是FreshRSS 用户名。
FRESHRSS_API_PASSWORD是个人资料页面中的 API 密码,而非网页登录密码。
FRESHRSS_READ_ONLY否设置为 1、true 或 yes 时,仅注册读取工具。
FRESHRSS_INSECURE_TLS否设置为 true 时,仅对此连接接受自签名证书。
FRESHRSS_ALLOW_TOOLS否以逗号分隔的工具名称、list_* 前缀,或精选预设 essential
FRESHRSS_DENY_TOOLS否语法相同;从 FRESHRSS_ALLOW_TOOLS 筛选后的结果中移除指定工具
ELICITATION否设置为 false 时,以双调用令牌取代审批对话框。不带前缀。

服务器无需凭据即可启动,因此其工具仍可列出;但每次调用都会失败,并显示这些设置说明。

选择要加载的工具

FRESHRSS_ALLOW_TOOLS 和 FRESHRSS_DENY_TOOLS 接受以逗号分隔的工具名称;末尾的 * 可匹配整个工具系列。essential 是包含以下七个工具的精选预设:list_feeds、list_categories、get_unread_counts、list_articles、get_articles、mark_articles、mark_all_as_read。

FRESHRSS_ALLOW_TOOLS=essential
FRESHRSS_ALLOW_TOOLS=list_feeds,list_articles,mark_articles
FRESHRSS_DENY_TOOLS=delete_*

如果某个条目与任何工具都不匹配,启动就会中止并指出该条目,因此拼写错误不会悄悄隐藏工具——没人会想到要从环境变量中排查某个缺失的工具。经过筛选的工具不会被注册,因此它既不会出现在 tools/list 中,也无法通过 tools/call 调用,这与 FRESHRSS_READ_ONLY 下的写入工具完全一样。

如果你同时运行多个此类服务器,mcp-hub 是另一种解决方案——它的 /hub 端点会将每个服务器的工具替换为六个元工具。

安装

Claude Code
claude mcp add freshrss -- npx -y @ni-c/freshrss-mcp
Claude Desktop
{
  "mcpServers": {
    "freshrss": {
      "command": "npx",
      "args": ["-y", "@ni-c/freshrss-mcp"],
      "env": {
        "FRESHRSS_URL": "https://rss.example.com",
        "FRESHRSS_USER": "alice",
        "FRESHRSS_API_PASSWORD": "…"
      }
    }
  }
}
Codex
[mcp_servers.freshrss]
command = "npx"
args = ["-y", "@ni-c/freshrss-mcp"]
env = { FRESHRSS_URL = "https://rss.example.com", FRESHRSS_USER = "alice", FRESHRSS_API_PASSWORD = "…" }
Docker
docker run --rm -i \
  -e FRESHRSS_URL=https://rss.example.com \
  -e FRESHRSS_USER=alice \
  -e FRESHRSS_API_PASSWORD=... \
  ghcr.io/ni-c/freshrss-mcp:latest

此镜像面向 linux/amd64 和 linux/arm64 发布,并附带 SBOM 和构建来源证明。它以非特权用户 node 运行,且不包含 npm,因此镜像中只有 Node、运行时依赖项和 dist/。

通过 mcp-hub

无法启动本地进程的客户端——ChatGPT connectors、Claude on the web、Cursor、LibreChat——可通过 mcp-hub 访问 freshrss-mcp:一个容器通过 Streamable HTTP 为许多 stdio MCP 服务器提供服务,并使用单一密码进行 OAuth 2.1 登录,同时为无法使用 OAuth 的客户端提供长期有效的令牌。它的 /hub 端点会将每个服务器置于六个元工具之后,因此一个连接器即可访问所有服务器,无需在模型上下文中加入 N×tool 模式;它还支持两个协议修订版本——本服务器提出的问题会经由它传递给另一端的人。

它的 /config/mcp.json 使用 Claude Code 的格式,因此配置项就是你已有的那一项:

{
  "mcpServers": {
    "freshrss": {
      "command": "npx",
      "args": ["-y", "@ni-c/freshrss-mcp"],
      "env": { "FRESHRSS_ALLOW_TOOLS": "essential" },
      "denyTools": ["delete_*"]
    }
  }
}

其中的 allowTools 和 denyTools 是 hub 自身针对每个服务器的筛选项,不同于 env 中的 *_ALLOW_TOOLS——两者的区别及其可能导致的误用,详见客户端指南。

工具

阅读
工具说明
get_user_info已通过身份验证的账户——快速检查凭据。
list_feeds所有订阅及其分类和未读数量。
list_categories分类(订阅源文件夹)和用户标签(文章标签)。
get_unread_counts按排序列出的未读总数,以及各订阅源/分类的未读数量。
list_articles订阅源、分类、标签或内置信息流中的文章,可提供摘要或有长度限制的全文。
get_articles按 ID 获取指定文章的全文。
list_article_ids仅返回 ID——这是为 mark_articles 收集一组 ID 的简便方法。
export_opml将所有订阅导出为 OPML 文档。
写入

当 FRESHRSS_READ_ONLY=true 时不会注册。

工具说明确认
mark_articles设置指定文章的已读状态、星标和标签。—
mark_all_as_read将整个订阅源、分类、标签或信息流标记为已读。是
subscribe_feed订阅订阅源或网站 URL。—
update_feed重命名订阅源或将其移至其他分类。—
unsubscribe_feed删除订阅源及其所有已存储文章。是
rename_category_or_label重命名分类或用户标签。—
delete_category_or_label删除分类或用户标签。是
import_opml订阅 OPML 文档中的所有订阅源。是
结构化输出

每个工具都声明了 outputSchema,并在文本块之外通过 structuredContent 返回结果,因此客户端无需解析散文即可使用结果:

{
  "untrusted": true,
  "source": "freshrss",
  "articles": [{ "id": "1234", "title": "…", "read": false, "starred": false }],
  "continuation": "1699999999",
  "notes": ["…"],
}

每个报告订阅源内容的工具都会带有 untrusted: true 和 source: "freshrss" 字段。该服务一直在 notes 中说明这一点——以列表形式呈现的散文,客户端可以读取但无法验证;而这些字段则让它可以验证。另有八个工具不带这些字段,因为它们的回答完全是该服务自己的内容:传入的 ID、根据参数生成的句子,以及它通过身份验证的账户。

以前有六个工具会用一句话作答(“Feed 9 deleted.”);现在它们也会返回字段,而这句话仍保留在文本块中。 export_opml 返回 {opml},而不是将文档作为整个结果返回:如果根节点为字符串的架构提供给 2025 年代的客户端,就会被改写为 {result: …};无论如何,truncated 都需要一个存放位置。

不支持搜索

FreshRSS 的 API 不提供全文搜索——Google Reader 端点只能按信息流、已读状态和日期筛选。因此,list_articles 没有查询参数;请使用 feed_id/category 和 since/until 缩小结果范围,然后自行筛选返回的文章。

有意不提供的功能

不提供全文搜索,因为 FreshRSS 的 Google Reader API 不支持全文搜索: 其端点只能按信息流、已读状态和日期筛选。请使用 feed_id、 category、since 和 until 缩小范围,然后自行筛选返回的文章。 FreshRSS 网页界面中的搜索没有对应的 API 端点。

不提供原始 HTML。 文章正文会转换为纯文本,并限制每篇文章和每次响应的长度, 以免单次列表响应中的内容占满整个上下文。

安全

  • 文章文本是不可信输入。 此服务从 FreshRSS 返回的所有内容都由互联网上的第三方撰写,因此,包含文章文本、标题或订阅源名称的响应都会明确标记为数据,而非指令。
  • 需要征得用户同意,而不只是告知。 如果客户端支持 MCP 征询,五个不可逆工具会弹出一个真正的对话框,模型无法代替用户作答。布尔值可能在首次调用时就被设为真,也可能被订阅源中隐藏的文本诱导为真。如果客户端无法显示对话框,这些工具会改用绑定到确切目标的一次性令牌,并明确说明这一点,而不会暗示有人已批准。消息会刻意避免引用来自 API 的标题或名称。请参阅征求用户同意。
  • 响应预算。 FreshRSS 为每篇文章最多返回 500 000 个字符的 HTML。文章文本会转换为纯文本,并受到单篇文章上限和单次响应预算的限制;在列表中,只有明确选择后才会包含文章文本。预算按读取的标记语言计费,而不是按转换后的文本计费,因此它限制的是转换工作量,而不仅仅是最终上下文——剥离后几乎不剩内容的标记语言最耗资源,而过去这类情况不计费。转换过程本身是一次从左到右的扫描,耗时与文章长度呈线性关系,与文章内容无关。
  • 凭据只读取一次,之后会从 process.env 中移除,并且绝不会写入磁盘。请求绝不跟随重定向,以免将授权标头重新发送到其他主机;放宽的 TLS 验证仅作用于此连接,而非整个进程。
  • 订阅源 URL 会进行脱敏。 FreshRSS 会以 https://user:password@host/feed 的形式存储使用 HTTP 身份验证的订阅源。在订阅源 URL 到达工具结果或 OPML 导出之前,userinfo 部分会被剥除,因此 list_feeds 不会将付费或私人订阅源的密码打印到对话记录中。
  • subscribe_feed 和 import_opml 会拒绝指向内部网络的目标。 FreshRSS 会在服务端获取这些 URL,因此,这两个工具都可能成为一种 SSRF 原语,可通过文章中的文本触发。环回地址和链路本地地址(包括云元数据端点)都会被拒绝;这既适用于订阅源 URL,也适用于 OPML 文档中的每个 xmlUrl/htmlUrl。地址会以数值形式比较,因此像 [::ffff:169.254.169.254] 这样的 IPv4 映射 IPv6 字面地址也会被拦截;主机名则会先解析再接受。读取 OPML 文档的方式与 XML 解析器一致,传给 FreshRSS 的就是经过检查的文档——因此,检查的 URL 就是实际获取的 URL。私有局域网地址仍然允许使用,因为可自托管的设置通常需要订阅自己网络上的订阅源。
  • import_opml 会拒绝 <!DOCTYPE>。 此进程不会解析 XML,但文档会交给 FreshRSS 处理,而文档类型声明可能被用于实体扩展攻击和外部实体攻击。OPML 根本不需要它。
  • FRESHRSS_READ_ONLY=true 不会注册写入工具,而不是等到调用时才拒绝它们。

会征求用户同意的工具:mark_all_as_read、unsubscribe_feed、delete_category_or_label、import_opml,以及 mark_articles,但仅限即将将文章标记为已读时。加星标、取消星标和添加标签都可以恢复;但哪些文章原先未读则无法恢复,而且 FreshRSS 不会记录这一状态。

文档

完整指南、工具参考和安全说明见 freshrss-mcp.ni-c.de(源文件位于 docs/)。

开发

npm install
npm run lint && npm run build && npm test
npm run test:coverage

请参阅 CONTRIBUTING.md,了解如何使用临时 FreshRSS 实例进行开发。完整文档见 freshrss-mcp.ni-c.de。

发布

  1. 将 CHANGELOG.md 中的 [Unreleased] 条目移到新版本下方,并更新 package.json 中的 version。
  2. npm run lint && npm run build && npm run test:coverage。
  3. 提交,然后打标签:git tag -s vX.Y.Z -m vX.Y.Z && git push origin main vX.Y.Z。

该标签会触发 release.yml,验证标签与 package.json 中的版本是否一致,通过 Trusted Publishing 发布到 npm 并附带来源证明(无需使用令牌),根据 CHANGELOG 对应章节创建 GitHub 发布,并将条目发布到 MCP Registry。如果只有 Registry 步骤失败,请在 main 上修复,然后手动重新运行 mcp-registry.yml——切勿重新运行已打标签的任务,因为它会检出旧代码树。

贡献

欢迎提交问题、参与讨论和发起拉取请求——请参阅 CONTRIBUTING.md。如需报告漏洞,请使用私密报告渠道,而非公开提交问题;相关政策见 SECURITY.md。

许可证

MIT © Willi Thiel

评论

支持 Markdown

第一次接触 MCP?

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

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