Skip to main content

Giving My AI Agents Access to My RSS Reader

How I turned Cove, the Mac RSS reader I built, into an MCP server so my AI agents send me a daily digest in Discord while my library stays on my Mac.

RSS seems to be having a bit of a resurgence, which makes me happy because I’ve always been a fan. One place to track and read every blog I follow. What’s not to like?

Except that over the past decade I’ve tried a handful of RSS readers, and the same thing happens every time. I build up my subscriptions, use the reader faithfully for a few weeks or months, then quietly stop and go back to reading blogs on the web one at a time. Every reader I’ve tried eventually turns into an inbox. The unread count climbs. The guilt climbs with it. Reading starts to feel like a chore I’m behind on, like an email inbox I’ll never get to zero, so I abandon it.

So I built my own. Cove is a native Mac RSS reader that keeps an archive instead of an inbox. It fetches the full text of articles when it can, keeps them on my Mac, and doesn’t nag me about what I haven’t read. I also wanted to see what I could add on top with AI that other readers don’t have. That’s how Cove ended up with an MCP server.

What Cove Exposes

Cove ships an MCP server. It’s off by default. Turn it on and agents get these tools:

  • Read: list_feeds, list_folders, list_unread, list_starred, get_article, search_articles
  • Write: mark_read, add_feed, rename_feed, move_feed, remove_feed

I left a few things out on purpose. There’s no chat pane inside Cove. There’s no hosted endpoint. It’s a door into the library that’s already on my Mac, nothing more.

How It Works

Open Settings > Advanced and flip the Enabled switch. Cove shows a config block you can copy straight into your agent:

{
  "mcpServers": {
    "cove": {
      "type": "http",
      "url": "http://127.0.0.1:27272/mcp",
      "headers": {
        "Authorization": "Bearer <your-token>"
      }
    }
  }
}

A few details:

  • The server only listens on loopback, so nothing off your Mac can reach it.
  • Every request needs the bearer token.
  • It stops when Cove quits. Regenerating the token cuts off every client.
  • If your client can’t speak HTTP, Cove also bundles a stdio bridge. Settings shows a config block for that too.

That’s enough for Claude Code, or any other agent that speaks MCP, running on the same Mac. My Hermes agent doesn’t run on my Mac, though.

My Setup

Diagram of the setup: Hermes Agent and executor on an exe.dev VM, connected over Tailscale to tailscale serve and Cove on my Mac, with Hermes posting the daily digest to Discord
  • Hermes Agent runs on a VM from exe.dev. It uses GLM-5.3-flash on Cloudflare Workers AI and runs the digest on a schedule.
  • executor runs on the same VM. It’s an MCP gateway: every agent I use gets its MCP tools through it, so I maintain my MCP settings in one place instead of in every agent’s config.
  • Tailscale connects the VM to my Mac. On the Mac, tailscale serve forwards tailnet traffic to Cove’s loopback port.

Reaching Cove from the tailnet is my setup, not a Cove feature. Cove only listens on loopback, on purpose. tailscale serve is what makes it reachable from other machines on my tailnet, and I opted into that. At that point the bearer token and my Tailscale access rules are what protect it, so I keep the rules scoped to the one VM that needs it. One gotcha: a client connecting through tailscale serve also needs to send a Host: 127.0.0.1:27272 header.

It’s also worth knowing what leaves my Mac in this setup. The agent runs on a cloud VM, the model runs on Workers AI, and the digest lands in Discord. The digest only calls list_unread, so what goes out is titles, feed names, authors, dates, and URLs.

If your agent runs on the same machine as Cove, say a Mac mini that’s always on, you can skip all of this.

Use Cases

The Daily Digest

Hermes has a built-in cron tool, so I asked it to set up a daily job: pull the 15 newest unread articles from Cove and post the links in my personal Discord server.

Every morning the agent makes one call to list_unread, drops anything it already sent me on a previous run, formats what’s left, and posts it to Discord.

A Cove digest in Discord: a header reading 15 new articles, 96 unread total, followed by a bulleted list of article titles with feed name, date, and link

The digest never marks anything read. It only shows me what’s new and leaves the rest alone. Cove works the same way, so the digest fits right in.

The one catch is that my Mac has to be awake and Cove has to be running. If either isn’t true, there’s no digest that day.

Adding Feeds

One night I came across a post on Hacker News and realized the author was a co-worker at Cloudflare who writes really good stuff. I pasted the URL to my agent and asked it to check whether the blog had an RSS feed and, if so, subscribe to it in Cove.

It read the post, searched for a feed URL, curled the result to confirm it was valid RSS, and then called add_feed. Thirty-eight articles ingested, including the one I’d linked. First try.

Discord conversation: I paste a blog URL and ask the agent to add it to Cove. The agent reads the post, searches for the feed, curls it to validate, then replies that the blog is in Cove with 38 articles ingested

Finding Similar Blogs

Then I wanted to push it a bit. While writing this post, I asked the agent to look at the feeds I already subscribe to and recommend blogs I might be missing.

It read all 31 of my feeds and my starred articles, told me what I’m apparently into (solo-founder hustle, engineering craft, LLM evals, remote-work writing), and came back with 18 suggestions grouped by topic. Every one had a live feed URL and a sentence on why it fit. It also listed what it skipped and why.

The agent's recommendations in Discord: a summary of my 31 existing feeds, then 18 suggested blogs grouped by topic with feed URLs and reasons, a list of what it skipped, and a closing offer to add them

Then it stopped and asked whether I wanted any of them added, since I’d asked for recommendations and not action.

The digest saves me a few clicks. An agent that can look at what I read, work out why I read it, and go find more of it is something no RSS reader I’ve used could do.

The latent.space one was one I’d never come across before, so that was a nice add to my reading library.

Under the Hood

One writer. The MCP server runs inside the Cove process. It goes through the same code path as the app, so there’s never a second program writing to the library.

Deletes take two calls. remove_feed can either keep a feed’s articles in the archive or delete them. Deleting requires a preflight call first, which returns a token describing exactly what will be removed. The delete only goes through if that still matches. After running agents in devcontainers, I think a lot about blast radius. One bad tool call shouldn’t wipe out years of articles.

I got the stdio bridge wrong the first time. My first version had no token. Any process on my Mac could launch the bridge and use it as a trusted proxy into Cove. Not great. Now Cove checks the bridge’s code signature, the bridge checks Cove’s, and the bridge has to present a separate secret that Cove derives from the main token. Regenerate the token and both go dead.

Wrapping Up

The MCP server itself is the boring part. Cove already had the library, and the server is a thin door into it. The interesting part is what agents do once they can see what I read: a morning digest, a feed added from a pasted URL, new blogs found from the ones I already follow. I’m sure there are more I haven’t thought of yet.

Try It

Cove is at covereader.app. The MCP server is free during the beta. Cove’s 1.0 pricing hasn’t been decided.

If you try it, I’d love to hear how it goes. Hit me up on X, especially if you find a use case I haven’t.

Thanks for reading.