FeedKeeper RSS/Atom reader and remote MCP Server
You can use this MCP server to manage a self-hosted FeedKeeper RSS/Atom account, read and search articles, organize subscriptions, and curate newspaper editions.
List, inspect, subscribe to, discover, update, refresh, and unsubscribe from feeds.
Create, rename, delete, and list folders; move feeds into or out of folders.
Browse digests, account overviews, unread/new items, paginated item history, and individual article content.
Search articles with full-text filters and fetch full article text from publisher pages when needed.
Mark articles read/unread, mark all read, and bookmark/unbookmark items for permanent retention.
Save web clippings, URLs, HTML, text, or notes to the Universal Inbox.
Manage muted keyword filters and import/export OPML subscriptions.
Curate editions: get current edition, fetch candidates, publish, and dismiss with revision/idempotency controls.
Use read-only tools safely with read-only tokens, or read-write tools with write-scope tokens.
Provides tools for managing RSS/Atom feeds, including subscribing, unsubscribing, fetching unread items, searching, and marking items as read.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@FeedKeeper RSS/Atom reader and remote MCP Server Check my feeds and show me unread items from the last 24 hours."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
FeedKeeper
FeedKeeper is an independent RSS and Atom feed manager built for people who want full ownership over their subscriptions. It runs quietly on your own server or Raspberry Pi, stores everything in a local SQLite database, and requires zero cloud accounts.
Beyond a clean web reader, FeedKeeper includes a native, authenticated Model Context Protocol (MCP) endpoint. Listed in the official MCP Registry (io.github.visualfusion/feedkeeper) and verified for the Anthropic Claude Directory, it lets MCP clients read, search, bookmark, and organize your feeds over a remote connection. Your subscriptions and reading history stay in your own SQLite database.
It is multi-user by default, with isolated accounts, personal access tokens, and a trilingual interface (English, German, and Japanese).
Why FeedKeeper?
There are good self-hosted readers already, such as Miniflux and FreshRSS. FeedKeeper is for you if you want your feeds to be part of your AI workflows without giving up ownership:
MCP built in. Claude, ChatGPT and other MCP clients connect to
/mcpdirectly, with OAuth sign-in or personal access tokens, read-only or read and write. FeedKeeper is listed in the official Model Context Protocol Registry (io.github.visualfusion/feedkeeper) and verified in Claude's connector directory. Ask for a daily briefing, let an agent triage unread articles, or let it curate an edition. No separate bridge to run.Small to run. One Node process and one SQLite file, with full-text search built in. No PostgreSQL, no Redis. It runs on a Raspberry Pi or on shared hosting such as Uberspace.
An open API. The REST API under
/api/v1is described in an OpenAPI file, with offline sync, notes and editions, so third parties can build their own clients.Built to be extended. Operators can add settings, footer links or a single sign-on form to the web app without forking it, see Extending the web app.
If you only need a plain, mature reader with many integrations, the established projects are the safer choice. FeedKeeper is young (version 0.x), so expect some rough edges.
Related MCP server: RSS Feed MCP Server
Quick start
Up and running in about a minute. Prebuilt images for amd64 and arm64 (including Raspberry Pi) are published to the GitHub Container Registry. You only need Docker, no clone and no build:
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 -dOpen http://localhost:3000 to complete the initial setup via the web onboarding screen. For a public domain, also add PUBLIC_URL=https://your.domain to .env (see .env.example for all options).
Just want to look around? npx feedkeeper starts it without Docker (it needs a supported Node.js, see Running FeedKeeper with Node.js); the data stays in ~/.feedkeeper.
To update, pull the new image and restart:
docker compose pull
docker compose up -dChanging SESSION_SECRET signs out active browser sessions and makes stored two-factor keys unreadable (see Account security); feeds and accounts stay in the database. Want to build the image yourself? Clone the repository and run docker compose -f compose.yaml -f compose.build.yaml up -d --build.
Started without a SESSION_SECRET (for example from one of the templates below), the image creates one on the first start and keeps it in the data volume.
Set up with an AI agent (Claude Code, Cursor, Codex)
If you use an AI coding assistant on your server or local machine, you can paste this prompt:
"Set up and start FeedKeeper on this machine using Docker Compose. Download or reference the template from https://raw.githubusercontent.com/visualfusion/feedkeeper/main/compose.yaml, generate a secure 64-character SESSION_SECRET, set PUBLIC_URL to the address this machine is reachable at, ensure the feedkeeper_data volume is persistent, start the container, and verify that the web onboarding responds on port 3000."
Other ways to run it
Where | How |
Raspberry Pi | Step by step with Docker, including HTTPS and backups. |
HTTPS reverse proxy | Caddy, nginx and Traefik setup, including forwarded client IPs and MCP client setup. |
Coolify, Unraid, CasaOS, Portainer | Ready-made templates for self-hosting and home-lab platforms. |
Node.js, no Docker |
|
Uberspace or any SSH host |
Features
Categories and feed ordering — group subscriptions into categories, search and filter the feed list, rename categories in place, and reorder feeds by dragging.
Smart feed discovery — paste a direct feed link or a website address (like
example.com/blog); FeedKeeper finds RSS and Atom feeds, including ones listed on a site's feed overview page, and checks each one before subscribing.Reliable feed updates — fetch several feeds at once with limits per source. Slow feeds and temporary failures do not hold up other updates, and unfinished work resumes after a restart.
Automatic character encoding — parses standard UTF-8 as well as legacy ISO-8859-1/Windows-1252 feeds without garbled umlauts or broken symbols.
Saved articles as a lasting archive — star an article to save it: FeedKeeper keeps its full text and stores its images next to the database, so it stays readable even if the source changes. Saved articles survive cleanups and unsubscribing, ignore the word filter, and their full text is searchable.
Full-text search — indexed with SQLite FTS5 across titles, snippets, cached full text, and personal notes. Ranked by BM25 relevance with diacritic-insensitive matching and phrase support.
Article notes and lasting knowledge — attach personal Markdown notes to any article. Notes sync across devices, export to standalone Markdown files, and protect articles permanently from retention cleanups.
Authoritative feed icons — icons are cached on the server with SHA-256 hashes and conditional ETags, so devices load them fast without third-party requests.
Keyword mute filters — cut through information overload by filtering out articles matching specific keywords before they reach your stream.
Empty gallery filtering — gallery links with no editorial text (only an image or a read-more prompt) stay out of article lists, search, notifications and curation. Short news and captions remain visible; saved or annotated items remain accessible. Nothing is deleted.
Health monitoring — clear status indicators show polling health, consecutive fetch errors, and timestamps so you instantly spot dead feeds.
Universal Inbox (Read-it-Later) — save web clippings, URLs, and personal notes directly to your personal inbox from any browser, share extension, or MCP client. Full article contents and lead images are automatically extracted and archived offline.
Curated editions & daily briefings — finite morning, midday, and evening editions. Curated by external agents via MCP (e.g. Claude, local LLMs, or custom scripts), with structured, linked editorial overviews. The latest publication remains available until its successor is published. Candidates and publication require readable body text beyond a repeated headline or read-more/player prompt, regardless of publisher or URL. Video/audio-only entries stay in the library but out of new editions; short reports, summaries and transcripts remain eligible. Existing editions are unchanged.
Automated database housekeeping — sensible defaults prune read articles, enforce maximum item retention, and run SQLite
VACUUMon schedule to keep storage lean.Remote MCP access — stream items directly into Claude or any MCP-compatible environment via standard Streamable HTTP, with read-only or read-write tokens, OAuth sign-in for connectors such as ChatGPT and Claude (consent page, PKCE, revocable in Settings), and cursor-based paging for incremental sync.
Privacy & self-hosting first — a single Node.js process and one SQLite file. No external database engines, no telemetry, no tracking.
OPML 2.0 import & export — switch back and forth from Feedly, NetNewsWire, Inoreader, or Reeder at any time.
Article reader & background preparation — read feed content in the app, with shared, bounded full-text extraction, durable retries and source-host limits. Full-text fetching can be tuned per subscription. Reader content omits repeated author and date lines, including standalone inline bylines, while keeping attribution when no author is provided separately. Videos, social posts and audio players, including those held back by consent plugins, become one link that clients show as a card, and lists of related or popular articles inside an article are removed. The cleanup is a set of small content rules that the community can extend. See full-text fetching for settings and operating limits.
List and newspaper views — switch between a compact list and an editorial layout with wide lead stories and longer previews; phones always use the newspaper layout.
Mobile-friendly web app — responsive layout with tab navigation and pull to refresh, installable on the home screen, with light, dark and system themes.
Works offline — a service worker lets the installed app start without a connection. It keeps your saved articles and the newest unread ones on the device with their full text and images, so you can read, search and filter them on the train. Changes such as marking read or saving are kept and sent once you are back online. Switch it off in the settings; cached data is removed when you log out.
Notifications and home screen shortcuts — optional push notifications for new articles of the feeds you choose (on iPhone and iPad once the app is on the home screen), the number of unread articles of the feeds you choose on the app icon, shortcuts to saved articles and to adding a feed, and sharing a web address from another app straight into the add-feed dialog. Notifications are encrypted end to end and delivered through your browser vendor's push service; the server creates its push keys on first start and keeps them in the database.
Personal profiles — each account can set its display name and a profile photo.
Online backups — create verified SQLite backups while the service keeps running.
Guided onboarding & starter packs — get started instantly with curated feed lists by interest (News, Technology, Apple, Development, Science, Design, Gaming, Business, Sport, Culture), each feed with a short description and feeds from several lists in one go, single website discovery, or OPML import when setting up an empty account. The lists are served to the native apps too (
GET /api/v1/feed-lists).Passkeys with browser autofill & step-up reauthentication — sign in effortlessly without a password via WebAuthn browser autofill directly from the email input field. Protect security-sensitive actions (passkey registration, 2FA setup, recovery codes) with modal biometric confirmation without typing a password. Optional TOTP two-factor authentication and one-time recovery codes on every installation; see Account security.
Hardened security — SSRF protection against internal network probing, rate limiting on authentication, and hashed API tokens.
How it fits together
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 <--> MCPEPOne Node process serves the built web reader, the open REST API (/api/v1), and an MCP endpoint (/mcp, using the Streamable HTTP transport) — all backed by a single SQLite database, the FTS5 search index, and the feed poller.
Web reader, native apps, and MCP
FeedKeeper uses a single backend with clients tailored to different situations:
The web reader is a straightforward browser interface for day-to-day reading, categorizing feeds, and triaging your stream.
Native apps (iOS, iPadOS, macOS) build on platform features: offline sync via SQLite change logs, personal Markdown notes per article, and daily newspaper editions.
Remote MCP access lets AI tools curate reading lists, search past items, and inspect candidates using the same APIs.
Features developed for native apps (such as article notes and edition scheduling) are exposed through the open API (/api/v1) so third-party clients can use them too.
Back up and restore
Create a consistent SQLite backup while FeedKeeper is running:
npm run db:backup -- /safe/location/feedkeeper.sqliteWithout Docker, run npm run build once before using the backup commands. The command refuses to overwrite an existing backup and verifies its integrity. Images of saved articles live in an archive folder next to the database (configurable with ARCHIVE_PATH); the backup copies them to <backup>.archive and restore puts them back. A backup holds the database and the archive, not SESSION_SECRET: keep the secret with your backups, because it also protects the two-factor keys in the database (see Account security). Keep the backup outside the application directory and copy it to another machine or storage device.
With Docker Compose, create the backup in the mounted data volume and copy it to the host:
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.archiveTo restore, stop FeedKeeper first, then run:
npm run db:restore -- /safe/location/feedkeeper.sqlite --forceRestoring replaces the configured database. Start FeedKeeper again after the command succeeds. Existing backups may need a database migration on startup if they were created with an older version.
For Docker Compose, stop the service and run the restore command in a one-off container with the backup mounted read-only:
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 feedkeeperQuick start (local development)
Requires Node.js 22.22.2+ (22.x), 24.15+ (24.x), or 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 2Open http://localhost:5173 and follow the onboarding screen to create the first admin account. (Prefer the terminal? npm run setup does the same thing without a browser.)
Deploying
See docs/deployment-uberspace.md for a step-by-step guide to running FeedKeeper on Uberspace. The same steps work on any Linux host with SSH access and a supported Node.js version.
For production, build once and run the compiled server:
npm run build
npm run startHosted option
If you would rather not operate a server, FeedKeeper Cloud is a hosted edition run by the same maintainers. This repository stays MIT-licensed and fully self-hostable.
Connecting an MCP client 
Local stdio mode (Claude Desktop & local tooling). Run feedkeeper mcp (or node server/dist/mcp-stdio.js) to start a local stdio MCP server backed by your SQLite database without needing an open port or network configuration.
With OAuth (ChatGPT, Claude and other connectors). Add https://<your-domain>/mcp as a remote MCP server or custom connector. The client discovers the sign-in on its own: you log in to FeedKeeper, choose read only or read and write on the consent page, and the client gets a short-lived token (1 hour, refreshed for 30 days). Connected AI assistants are listed under Settings → MCP and can be disconnected at any time. OAUTH_ALLOWED_REDIRECT_HOSTS can limit which hosts may register. Set PUBLIC_URL to the address the client reaches the server at; see docs/design/mcp-oauth.md.
With a personal access token (scripts and clients without OAuth).
Log in to the FeedKeeper web UI and go to Settings → Personal access tokens.
Create a token and copy it immediately — it's only shown once. Choose Read only for clients that only need to browse articles; choose Read and write to let the client change feeds or reading state. Existing tokens retain their previous write access.
Add an MCP server entry pointing at
https://<your-domain>/mcp, sendingAuthorization: Bearer <token>as a header. Settings → MCP also offers a ready-made Claude Desktop configuration.
Every tool call is scoped to the signed-in user — a client can only see and manage that user's own feeds and items. OAuth tokens work only on /mcp.
Connect via AI assistant prompt
To have an AI assistant configure the MCP connection for you, create a Personal Access Token in Settings → Personal access tokens and run:
"Add FeedKeeper as a remote HTTP MCP server pointing to https:///mcp with Authorization: Bearer to my MCP configuration (e.g. claude_desktop_config.json or Cursor MCP settings). Verify the connection by listing my feeds."
Available MCP tools
Tool | Description |
| List subscribed feeds with unread counts and health status, optionally only feeds with errors |
| Inspect a single subscribed feed's metadata, subscription settings, unread count and health status |
| Subscribe to a feed URL or website URL (auto-discovering the feed) |
| Discover available RSS/Atom feeds on a website URL |
| Save a web clipping, URL, or personal note to your inbox with automatic full-text and image archiving |
| Remove a subscription |
| Change a subscription's feed URL, name, poll interval, full-text setting, push notifications or app icon count; a new URL is validated before it replaces the old one |
| List folders with feed and unread counts |
| Create a folder |
| Rename a folder |
| Delete a folder; its feeds stay subscribed |
| Move a subscription into or out of a folder |
| Request an update of a subscribed feed; respects source pauses and reports pending work |
| Unread articles grouped by feed with short snippets, the cheapest way to see what is new |
| Counts for the whole account: unread and saved articles, top feeds, folders and failing feeds |
| Fetch unread items, optionally filtered by feed, search, or bookmarks; can leave out article HTML and shorten summaries |
| Page through compact items by time added; use cursors to fetch older or newly added items |
| Fetch one article and its cached content (HTML or plain text) with optional pagination ( |
| Download and cache the full article when the feed only has a teaser; use |
| Search titles and summaries across all items (with optional bookmarks filter) |
| Mark one or more items as read |
| Mark one or more items as unread |
| Mark all subscribed items as read, optionally within a feed or folder |
| Save one or more items; saved items are archived with full text and images |
| Remove bookmarks from one or more items |
| List user's active muted keywords |
| Add a keyword to automatically filter out matching articles |
| Remove a muted keyword rule |
| Export all subscribed feeds as an OPML 2.0 XML string |
| Import feeds from an OPML 2.0 XML string |
| Read the current issue, source and revision, including expired or dismissed state |
| Get compact candidates respecting app section preferences and muted keywords |
| Publish an ordered curated issue with optional structured topic overviews and a presentation layout, expiry, revision checks and safe retries |
| Dismiss the shared issue with revision and replay protection |
Besides tools, the server offers prompts (daily_briefing, catch_up_on_topic, saved_reading_list, triage_unread) and resources (feedkeeper://feeds, opml, saved, digest and feedkeeper://items/{id}) that clients can show as ready-made actions.
Read-only tokens expose only the tools that leave FeedKeeper data unchanged. get_item returns stored feed or reader content; fetch_full_text downloads the article from its website and needs a read-and-write token. Item actions accept a single itemId or up to 200 itemIds. get_new_items, search_items and list_items accept since and until (ISO date or date-time) to filter by publish date. For incremental synchronization, save newestCursor, pass it as after next time, and follow nextCursor as before until there are no more pages.
Native apps
For reading on the go and offline, the official FeedKeeper app is available on the App Store for iOS, iPadOS, and macOS. It pairs directly with your self-hosted instance in seconds — just scan the pairing QR code under Settings → Devices in your web reader.
The app builds on FeedKeeper's open native API (/api/v1) to provide:
Incremental delta-sync and offline article caching
Offline action queuing (reading state, stars, and folders sync back automatically)
Fast full-text search powered by SQLite FTS5
Synchronized personal Markdown notes per article
Reading layout preferences and daily newspaper editions
The built-in web reader remains 100% free and fully supported. The native sync API is open and documented in docs/openapi.yaml — third-party and community clients are warmly encouraged to build on the same endpoints (see docs/building-clients.md for a getting-started guide).
Security
Closed signup by default (
ALLOW_SIGNUP=false). An admin creates additional accounts from Settings.SSRF protection: feed URLs and redirects are checked before fetching and again when connecting. Private/internal addresses are blocked by default. On trusted instances that need local feeds, set
ALLOW_PRIVATE_FEEDS=true.Blocked sources: list domains in
BLOCKED_FEED_HOSTS(comma-separated, subdomains included) to keep them out of your instance. Subscribing, polling, article text and images are refused for them with the errorfeed_blocked. Feeds already stored stop updating and lose their articles, except saved ones, ones with notes and ones in a published edition. Restart the server after changing the list.Rate limiting on login and the general API surface.
Personal access tokens are stored as salted hashes, never in plaintext.
OAuth 2.1 for MCP with required PKCE, expiring tokens, refresh-token rotation with reuse detection, and a consent page that asks every time.
Behind a proxy or CDN:
TRUST_PROXYandCLIENT_IP_HEADERmake sure rate limits see the real client address.Per-user data isolation: every query is scoped to the authenticated user; feeds are deduplicated by URL under the hood, but subscriptions, read state, and tokens are always per-user.
Feed icons and the images of saved articles are delivered by the FeedKeeper server, so browsing does not contact third-party sites for them; images of other articles still load from their source websites. To find a feed's icon, the server fetches the site's homepage about once a week. Opening a full article through the reader also fetches that page from the FeedKeeper server.
Found a security issue? Please report it privately as described in SECURITY.md instead of opening a public issue.
Configuration
See .env.example for all available environment variables.
Feed updates
By default, FeedKeeper checks up to four feeds at once, with at most two requests per source hostname. Scheduled and manual updates, new subscriptions, OPML imports and MCP share the same queue. A manual refresh may stay pending when a source is busy or has asked for a pause; the web reader tells you when this happens.
Run one application process per database. On hosts with little memory, start with POLL_CONCURRENCY=2 and POLL_HOST_CONCURRENCY=1. Allow 45 seconds for shutdown; the supplied Docker Compose file already does this. See Feed polling for the settings, logs and upgrade guidance.
Reader cleanup
Reader HTML is cleaned when served, without rewriting stored publisher content. Exact adjacent image copies (for example separate desktop/mobile elements) collapse to one; different sources, links, responsive sources, captions and repetitions separated by text remain distinct. Empty product-card headers and ad slots are removed using their container structure and German, English and Japanese labels. Existing advertising content, affiliate disclosures and sponsored-article labels remain readable. These rules also apply to previously stored articles when requested again; downloaded client copies need to refresh before they reflect a server update.
Article images
The image proxy shares downloads and cached images between subscribers of the same feed. This covers native clients requesting proxy images and the web app's offline copies; images loaded directly from a publisher bypass this cache. Every request still checks access to the article and its image. Different feeds and different source URLs, including query parameters, have separate cache entries.
The disposable cache defaults to 256 MiB, 2,000 images and six hours, with four active jobs and at most 32 waiting jobs. Full queues return 503 image_busy with Retry-After: 1. Downloads retain the existing HTTP limits, size limit, SSRF checks and redirect rules; POLL_REQUEST_TIMEOUT_MS also bounds time spent waiting in the image queue. Missing images (HTTP 404/410) and unsupported formats are remembered for 60 seconds; other failures are not cached. Source cache directives can shorten or prevent disk caching.
The web reader binds offline article snapshots and queued changes to the authenticated account. Account switches invalidate private service-worker responses, including when the previous session expired without an explicit logout; in-flight responses cannot refill a later session's cache. Legacy snapshots without account ownership are discarded and downloaded again. A change in another tab revokes that tab's offline account binding until authentication is refreshed.
Normal proxied article images use private cache lifetimes of at most six hours and a content ETag. Browsers and the web offline cache revalidate them; archived images keep their fixed version. A new proxy URL version lets existing clients move away from the previous year-long immutable policy.
See IMAGE_CACHE_* in .env.example to change these limits. IMAGE_CACHE_PATH defaults to image-cache next to the database. Use one process per cache directory and keep it separate from ARCHIVE_PATH. Expired and least recently used entries are removed automatically. The cache stores hashed keys rather than source URLs, uses asynchronous file operations, and does not write to SQLite on cache hits. Once used, it logs aggregate image_cache counters every minute: hits, misses, shared work, negative hits, errors, overloads, evictions, bytes, entries, active and waiting jobs.
Saved articles retain their permanent archives. Cache and archive files share disk space through hard links when they are on the same filesystem; otherwise saving an article copies its image. Evicting the cache never deletes a saved copy. Existing archives can refill the cache without contacting the source; these snapshots stay tied to their article so an old saved image cannot replace a newer one at the same source URL. Back up the database and archive as before; the disposable cache needs no backup.
No database migration is needed. To roll back, stop the application and return to the previous version. Alternatively, set IMAGE_CACHE_MAX_BYTES=0 and restart to disable disk caching; IMAGE_CACHE_NEGATIVE_TTL_SECONDS=0 also disables remembered failures. Existing disposable files can be removed while the application is stopped. Keep the archive.
Extending
Operators and products built on FeedKeeper can add settings sections, footer links, a page title and a custom sign-in to the web app through window.feedkeeperExtensions, without patching the code. FeedKeeper Cloud, the hosted edition, uses it for its membership settings. See Extending the web app.
Tech stack
Server: Node.js, TypeScript, Express, better-sqlite3,
@modelcontextprotocol/sdkWeb: React, Vite, Tailwind CSS, react-i18next
Contributing
Issues and pull requests are welcome — see CONTRIBUTING.md for how to get started. Improving or adding a language is a good first contribution, see docs/translating.md. So is a better starter feed for the lists new users see, see docs/feed-lists.md. Notable changes are listed in the changelog. This is a young project, so expect some rough edges.
License
Available Tools
34 toolsadd_muted_keywordAdd a muted keyword filterAInspect
Adds a new keyword filter rule. Articles whose title or summary contains this keyword (case-insensitive) will be suppressed from feeds and editions. Requires write scope. Returns the created keyword rule { id, keyword, created_at }.
Inputs: keyword (required).
bookmark_itemBookmark articles for laterAIdempotentInspect
Bookmarks (stars) one or more articles for permanent retention. Bookmarked articles retain full text and images and survive automatic retention cleanup and feed unsubscription. Idempotent. Returns { ok: true, updated: number }.
Inputs: itemId, itemIds.
create_folderCreate a feed folderAInspect
Creates a new category folder to organize feed subscriptions. Requires write scope. Returns the created folder object with its assigned id, name, and position. Folders can be assigned to feeds using move_feed_to_folder.
Inputs: name (required).
delete_folderDelete a feed folderADestructiveIdempotentInspect
Deletes a feed category folder. Subscribed feeds inside the folder remain intact and are moved to the root level (unfiled). Destructive action for the folder organization. Returns { ok: true } on success.
Inputs: folderId (required).
discover_feedsDiscover feeds on a websiteARead-onlyIdempotentInspect
Inspects a website URL and discovers available RSS, Atom, and JSON feed links from HTML link tags. Safe read-only operation: does NOT subscribe to any feed. Returns a list of discovered candidate feed URLs and titles. Use subscribe_feed to subscribe to one of the discovered URLs. For API documentation, see https://github.com/visualfusion/feedkeeper.
Inputs: url (required).
dismiss_editionDismiss the current newspaper editionADestructiveIdempotentInspect
Explicitly dismisses the current curated edition so it is no longer shown as active. Requires a UUID requestId and the current revision as expectedRevision for conflict detection. Requires write scope. Returns { ok: true } on success.
Inputs: requestId (required), expectedRevision (required).
export_opmlExport feeds as OPML XMLARead-onlyIdempotentInspect
Exports all subscribed feeds and folder structures of the current user as an OPML 2.0 XML document. Safe read-only operation.
Inputs: no named parameters.
fetch_full_textExtract full web article textAIdempotentInspect
Downloads and extracts the clean, full-length article text from the original publisher website via Readability, permanently caching it on the server and returning it. Use this tool ONLY when get_item indicates that the feed provided only an excerpt or teaser. If full text is already cached, it returns cached content unless force=true is passed.
Inputs: itemId (required), force.
get_digestDigest of recent articles grouped by feedARead-onlyIdempotentInspect
Returns recent articles grouped by subscribed feed with short summaries (newest first). This is the fastest and most token-efficient way to scan what is new. Defaults to unread articles. Do NOT use this tool for pagination, full text, or deep filtering—use list_items for cursor pagination or get_new_items for unread filtering, and follow up with get_item for full article bodies.
Inputs: hours, since, feedId, folderId, +3 more.
get_editionGet current curated newspaper editionARead-onlyIdempotentInspect
Returns the authoritative edition state, publication metadata, article list, and revision number for the user's curated newspaper edition ('Deine Zeitung'). Returns the current revision (even if empty, expired, or dismissed), which must be passed as expectedRevision when calling publish_edition. Safe read-only.
Inputs: no named parameters.
get_edition_candidatesGet candidate articles for newspaper curationARead-onlyIdempotentInspect
Use this tool ONLY when preparing to curate a newspaper edition with publish_edition. Returns a bounded shortlist of unread articles from the last 7 days scored for editorial curation, user reading preferences, and current revision. Do NOT use for general reading or browsing (use get_digest or get_new_items instead).
Inputs: limit.
get_feedGet subscribed feed detailsARead-onlyIdempotentInspect
Returns metadata, subscription settings, polling health status, and unread count for a single subscribed feed by its numeric feed ID. Safe read-only operation. Use list_feeds to view all subscribed feeds.
Inputs: feedId (required).
get_itemGet single article content and metadataARead-onlyIdempotentInspect
Returns full metadata and stored content (HTML or plain text) for a single subscribed article by its numeric itemId. Content is chunked at 40,000 characters; use offset and content.revision to paginate large articles. If an article only has an RSS teaser/summary and full web text is desired, call fetch_full_text.
Inputs: itemId (required), format, offset, maxChars, +1 more.
get_new_itemsList unread articles with optional filtersARead-onlyIdempotentInspect
Returns a flat list of unread articles matching specified filters (feed, folder, search query, bookmarked status, date range). Use this tool when you specifically need unread articles as a flat list or need article HTML content. Unlike get_digest, articles are flat rather than grouped. Unlike list_items, this tool returns only unread articles and does not use cursors. Follow up with get_item for individual full articles.
Inputs: limit, since, until, feedId, +5 more.
get_overviewAccount overview and reading statisticsARead-onlyIdempotentInspect
Returns account-wide statistics: total subscribed feeds, total unread articles, saved/bookmarked count, top feeds with the most unread items, folder unread counts, and feeds currently experiencing poll failures. Safe read-only overview.
Inputs: no named parameters.
import_opmlImport feeds from OPML XMLAInspect
Imports feed subscriptions and folders from an OPML 2.0 XML string for the current user. Existing subscriptions are preserved. Requires write scope. Returns { imported: number, failed: number, foldersCreated: number }.
Inputs: opml (required).
list_feedsList subscribed feedsARead-onlyIdempotentInspect
Lists all RSS/Atom feeds the current user is subscribed to, including subscription settings, unread counts, and polling health status. Safe read-only operation. To inspect a single feed in detail, use get_feed. To discover new feeds, use discover_feeds.
Inputs: onlyWithErrors.
list_foldersList folders / categoriesARead-onlyIdempotentInspect
Lists all feed categories/folders created by the current user, including feed counts and unread article counts per folder. Safe read-only operation.
Inputs: no named parameters.
list_itemsPaginate items chronologically with cursorsARead-onlyIdempotentInspect
Lists articles chronologically with bidirectional cursor-based pagination. Use this tool for comprehensive browsing or historical paging through both read and unread articles. Pass nextCursor as 'before' to page backwards into older history, or newestCursor as 'after' to stream newly added items. Do NOT use for quick digests (use get_digest) or unread-only triage (use get_new_items).
Inputs: after, limit, since, until, +5 more.
list_muted_keywordsList muted keywordsARead-onlyIdempotentInspect
Lists all keyword filters configured for the current user. Articles matching any active muted keyword are automatically filtered out from new item views and newspaper editions. Safe read-only.
Inputs: no named parameters.
mark_all_readMark all articles as readADestructiveIdempotentInspect
Marks all unread articles as read in a single operation. Can be scoped to a single feed or an entire folder. Idempotent. Returns { marked: number } with the count of newly read items.
Inputs: feedId, folderId.
mark_readMark articles as readAIdempotentInspect
Marks one or more subscribed articles as read. Accepts a single itemId or an array of itemIds for batch processing. Idempotent: already-read articles remain read. Returns { ok: true, updated: number } where updated is the count of items that actually transitioned from unread to read.
Inputs: itemId, itemIds.
mark_unreadMark articles as unreadAIdempotentInspect
Marks one or more subscribed articles as unread. Accepts a single itemId or an array of itemIds for batch processing. Idempotent. Returns { ok: true, updated: number } where updated is the count of items that actually transitioned to unread.
Inputs: itemId, itemIds.
move_feed_to_folderMove feed to folderAIdempotentInspect
Assigns a subscribed feed to a folder, or removes it from all folders (unfiled) if folderId is null. Requires write scope. Returns { ok: true } on success.
Inputs: feedId (required), folderId (required).
publish_editionPublish curated newspaper editionAIdempotentInspect
Publishes an ordered selection of 1 to 24 article IDs as the user's official curated edition ('Deine Zeitung'). The published edition remains available until the next edition is published or expires. Pass the revision from get_edition as expectedRevision for optimistic concurrency, and a UUID requestId for idempotent retries. Does NOT alter underlying articles. Requires write scope.
Inputs: itemIds (required), title, layout, summary, +5 more.
refresh_feedRefresh feed pollAInspect
Requests an immediate poll of a subscribed feed from its origin URL and returns its updated health status, number of new items found, and error state. Respects origin HTTP cache headers and backoff pauses. Returns { success: boolean, newItems: number, error: string | null, deferred: boolean, retryAt: string | null, feed: object }.
Inputs: feedId (required).
rename_folderRename a feed folderAIdempotentInspect
Renames an existing feed category folder for the current user. Requires write scope. Returns the updated folder record { id, name, position }. Returns error if folderId is not found or name is already taken.
Inputs: name (required), folderId (required).
save_to_inboxSave article or clipping to Universal InboxAInspect
Saves a web article URL, raw HTML, plain text/markdown clipping, or personal note directly into the user's Universal Inbox. At least one of url, contentHtml, or textContent must be provided. Returns { success: true, itemId: number, title: string, url: string, hasNote: boolean }. For API documentation, see https://github.com/visualfusion/feedkeeper.
Inputs: url, note, title, contentHtml, +1 more.
search_itemsSearch articles by keyword or phraseBRead-onlyIdempotentInspect
Searches article titles and summaries using SQLite FTS5 full-text search across all accessible items. Returns matching articles matching the query phrase, with optional feed, folder, bookmark, and date filters. Safe read-only search.
Inputs: query (required), limit, since, until, +3 more.
subscribe_feedSubscribe to a feedAIdempotentInspect
Subscribes the current user to an RSS/Atom feed URL or website URL (auto-discovering the feed link if a website URL is provided). Requires write scope. Idempotent: subscribing to an already subscribed feed returns the existing subscription. Returns the subscription record. For API documentation, see https://github.com/visualfusion/feedkeeper.
Inputs: url (required), label, folderId.
unbookmark_itemRemove article bookmarksADestructiveIdempotentInspect
Removes bookmark status from one or more articles. Safely triggers archive pruning for unreferenced cached assets. Idempotent. Returns { ok: true, updated: number }.
Inputs: itemId, itemIds.
unmute_keywordRemove a muted keyword filterADestructiveIdempotentInspect
Removes an existing muted keyword filter by its numeric keywordId. Future and existing articles matching this keyword will once again be visible. Returns { ok: true } on success.
Inputs: keywordId (required).
unsubscribe_feedUnsubscribe from a feedADestructiveIdempotentInspect
Unsubscribes the current user from a feed by its feed ID. Destructive action. Feeds and other users' subscriptions are unaffected. Returns { ok: true } on success.
Inputs: feedId (required).
update_feedUpdate feed settingsBIdempotentInspect
Updates subscription settings for a feed: custom display name, poll interval, full-text extraction policy, push notification preference, badge counter inclusion, or updates the feed URL if the publisher relocated. Returns the updated subscription record. For API documentation, see https://github.com/visualfusion/feedkeeper.
Inputs: feedId (required), url, badge, label, +3 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 34 tools
Most tools map to a distinct resource+action (feeds, folders, editions, bookmarks, keywords, OPML), and the item-reading cluster (get_digest, get_new_items, list_items, get_item, search_items) is explicitly differentiated with 'do NOT use for...' cross-references. Still, five overlapping item-retrieval tools plus get_edition_candidates vs get_digest create real misselection risk for an agent skimming names.
Almost all names follow a consistent snake_case verb_noun pattern (list_feeds, create_folder, publish_edition, mark_all_read). Minor deviations: unmute_keyword breaks the add_muted_keyword/list_muted_keywords family symmetry and fetch_full_text/save_to_inbox drop the object noun convention, but the overall pattern is predictable.
34 tools is heavy for an RSS reader; the edition-curation workflow (get_edition, get_edition_candidates, publish_edition, dismiss_edition) and keyword-filter trio each add surface area. Every tool is individually justified, but the set is at the upper bound of what an agent can hold coherently in one server.
Broad lifecycle coverage: feeds (subscribe/discover/update/refresh/unsubscribe), folders (create/rename/delete/move/list), items (read/unread/mark-all/search/full-text), bookmarks, keyword filters, OPML import/export, inbox capture, and a full edition lifecycle. Gaps: no dedicated bookmark-listing tool (only filters on other tools) and no tag/label or item-delete operations, though these are workable around.
Maintenance
Related MCP Connectors
Reddit MCP — public Reddit data via the Atom/RSS feeds.
RSS, Atom and JSON feeds for agents: find a site's feed, read items as JSON, keyless news search.
Related MCP Servers
- AlicenseAqualityBmaintenanceModel Context Protocol Server for aggregating RSS feeds in Claude Desktop327Mozilla Public 2.0
- FlicenseNot gradedqualityCmaintenanceEnables Claude to fetch, parse, and manage RSS/Atom feeds through the Model Context Protocol. It supports feed registration and retrieval, allowing users to access article summaries and full content from multiple sources via natural language.1-
- FlicenseAqualityDmaintenanceAn MCP server that enables users to interact with their Feedbin RSS account directly through Claude. It provides tools for reading articles, managing read and starred states, and browsing subscribed feeds and tags.151-
- AlicenseAqualityDmaintenanceEnables digital marketers to fetch, search, and filter RSS blog feeds from multiple sources, with tools for managing feeds and searching across categories and date ranges.829 npmApache 2.0