# I built an hourly newspaper for e-ink (and turned the pipeline into an MCP server)

> Source: <https://dev.to/jshelley/i-built-an-hourly-newspaper-for-e-ink-and-turned-the-pipeline-into-an-mcp-server-1ebg>
> Published: 2026-09-12 22:54:03+00:00

Every hour, a Lambda pulls about 120 items from ~100 RSS feeds, asks a small model to act as an editor, and typesets the result as a 480x800 one-bit page for the Xteink X4 e-ink reader on my desk. The same pipeline now produces a multi-page "Morning Paper" PDF for reMarkable and Kindle, a TRMNL plugin, and an MCP server that agents can call. This is what it does, what broke, and what I learned about "news for agents". Everything below is live at [https://briefing-service.wholemind.workers.dev](https://briefing-service.wholemind.workers.dev).

## 
  
  
  The pipeline

1. 
**Collect.** feedparser over ~100 feeds per briefing (AI, world, US, finance, sports, soccer, frontier-lab blogs). Each item keeps id, source, title, link, canonical link (utm and friends stripped), published, a 320-char summary, and a per-feed weight.
2. 
**Dedupe.** Exact duplicates collapse by canonical URL. My first near-duplicate rule (title+summary word-shingle Jaccard >= 0.5) measured zero merges on 480 live candidates, and only five false pairs even at 0.2: outlets rewrite wire copy, and RSS summaries share boilerplate, not story text. What works is headline entity overlap: adjacent capitalised words form one entity ("Wall Street", "Joao Pedro"), punctuation and hyphens end a phrase, Title-Case outlets are filtered against their own summary, and two headlines from different outlets merge on three shared entities or two non-generic ones. On the same 429 news items that gives nine merges, all the same story on inspection. The survivor lists the other outlets in`also_in` ; the collapsed records are published too, with`duplicate_of` , the rule and a score, so anyone doing provenance work can audit the merges.
3. 
**Rank.** Claude Haiku 4.5 on Bedrock gets the candidate list (id, source, age, title, summary) and a persona, and must call a`publish_briefing` tool with a lead, N stories, a research section, one-sentence summaries, a three-to-five-sentence detail passage, a why-it-matters line and key points. Facts must come from candidate text; the tool schema is the guardrail. A non-LLM fallback ranker (weight, recency, two-per-outlet cap) runs if the model call fails, so the device never shows a blank page.
4. 
**Render.** Pillow draws a masthead, lead, numbered stories and a research strip into 480x800, dithers to 1-bit, writes BMPs the reader's firmware can page through, plus a wide 800x480 variant for TRMNL-class panels and a PDF for e-readers.
5. 
**Publish.** S3 + CloudFront, a tiny manifest with a stamp that changes only when the editor's picks change, so the device never re-downloads unchanged pages.

## 
  
  
  What surprised me

- 
**The editor is the product.** The rendering is fun, but the thing people react to is "lead + why it matters" over a hundred sources with duplicates merged. That is why I exposed it as an API and an MCP server rather than keeping it a device toy.
- 
**Agents are terrible customers so far.** Listing the MCP server in the official registry, Glama, Smithery and a few awesome-lists produced steady traffic in a day: scanners, auditors, and health checks. Thirteen MCP calls, zero humans. If you are building "for agents", expect the first wave to be bots evaluating you.
- 
**E-ink people want files, not APIs.** reMarkable and Kindle owners asked for a PDF in their library each morning, so that exists (rmapi push, Send-to-Kindle email), free for the first ten.

## 
  
  
  Try it

I would like to hear what a "news" tool should return to your agent: full JSON, a short digest, or the rendered page.
