Purpose
freshrss-mcp is a Model Context Protocol (MCP) server for connecting to the self-hosted RSS and Atom feed aggregator FreshRSS. It lets MCP clients such as Claude Code, Claude Desktop, and Codex operate on the user's subscription content: see what is unread, read articles, mark them, and manage feeds and categories.
Main capabilities
- Communicates via the Google Reader-compatible API that FreshRSS exposes at /api/greader.php.
- Provides sixteen tools by default, covering feeds, categories, labels, articles, read and starred status, and OPML import/export.
- Tool parameters use numeric feed ids, category and label names, ISO dates, and decimal article ids, rather than the Google Reader API's stream identifiers and hexadecimal item tags; returns plain text rather than raw HTML.
- Supports choosing which tools to load via FRESHRSS_ALLOW_TOOLS and FRESHRSS_DENY_TOOLS, supporting comma-separated tool names and whole-family matching with a trailing *; essential is a curated preset of seven tools: list_feeds, list_categories, get_unread_counts, list_articles, get_articles, mark_articles, mark_all_as_read.
- Each tool declares an outputSchema and returns structuredContent in addition to text blocks, so clients can use results directly without parsing text.
- Tools that report subscription content carry the fields untrusted: true and source: "freshrss".
- Provides a Docker image, published for linux/amd64 and linux/arm64, with SBOM and build provenance information, runs as an unprivileged node user, and contains no npm in the image.
- Via mcp-hub, clients that cannot start local processes (such as ChatGPT connectors, web-based Claude, Cursor, LibreChat) can access it over Streamable HTTP, whose /hub endpoint replaces all servers' tools with six meta-tools.
Usage
Requires Node.js 22 or later, and a FreshRSS instance with the API enabled (developed against version 1.29). Enabling steps: in Settings → Authentication, check "Allow API access"; in Settings → Profile → API management, set an API password for the user, which is different from the web login password. The server can also start without credentials so that tools remain listable, but every call will fail with these setup instructions.
When used via mcp-hub, its /config/mcp.json uses Claude Code's format, so existing entries can be reused directly.
Use cases
Suitable for users who use self-hosted FreshRSS and want to manage subscriptions, read, and organize articles conversationally through an MCP client. Also suitable for scenarios that need to connect clients that cannot start local processes, in which case mcp-hub can be used.
Limitations and security design
- No full-text search: FreshRSS's Google Reader API endpoints only filter by stream, read status, and date, so list_articles has no query parameter; you need to narrow the range with feed_id / category and since / until and then filter the returned articles yourself. There is no API endpoint behind the FreshRSS web interface's search.
- Does not return raw HTML: article bodies are converted to plain text, with limits per article and per response.
- Article text is untrusted input: all content from FreshRSS is written by third parties on the internet, and responses carrying article text, titles, or feed names are explicitly marked as data rather than instructions.
- Five irreversible tools ask a human first: mark_all_as_read, unsubscribe_feed, delete_category_or_label, import_opml, and mark_articles (only when about to mark content as read). When the client supports MCP elicitation, a real dialog pops up,The model cannot answer on its behalf; when dialogs are not supported, it falls back to a one-time token bound to the exact target and states this truthfully.
- Response budget: FreshRSS returns at most 500,000 characters of HTML per article; article text is converted to plain text, with caps set per article and per response, and article text in lists is optional. The budget is charged by the amount of markup read, not the amount of text output.
- Credentials are read only once, then removed from process.env and not written to disk; requests do not follow redirects; relaxed TLS verification is limited to that connection.
- Feed URLs are redacted: FreshRSS stores HTTP-authenticated feeds as https://user:password@host/feed,userinfo parts are stripped before entering tool results or OPML exports.
- subscribe_feed and import_opml reject internal targets: loopback and link-local addresses (including cloud metadata endpoints) are rejected, addresses are compared numerically, and hostnames are resolved before acceptance; private LAN addresses are still allowed. import_opml rejects <!DOCTYPE>.
- When FRESHRSS_READ_ONLY=true, write tools are not registered at all, rather than being rejected at call time.
The full guide, tool reference, and security notes are at freshrss-mcp.ni-c.de (source in docs/). The project is MIT licensed, by author Willi Thiel.