MyNews MCP Server
Provides tools to fetch and read news from RSS feeds across 16 categories, including headlines, article text, and metadata.
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., "@MyNews MCP ServerShow me top AI and crypto news from the past 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.
MyNews — Vazghen's news feed
A multi-topic news aggregator that doubles as an API your AI agents can read. One small Express server pulls RSS for 30 topics, serves a designed browser feed, and exposes the same data as a REST + MCP API — including full readable article text, not just headlines. No API keys required.
Live: https://mynews-nine.vercel.app · Repo: https://github.com/iamvazghen/mynews
/ landing page
/dashboard.html the live feed — filter, sort by newest/category, timeframe, search
/api/* the agent API (REST), also exposed over MCP via mcp.jsWhy I built it (portfolio note)
A focused full-stack project that solves a real problem I have: I read across ~29 unrelated topics, and I want my own agents to read them too. It demonstrates:
Full-stack JS — Express API, RSS aggregation, in-memory caching, HTML→text article extraction.
Design — a hand-built Cobalt design system (OKLCH tokens, Space Grotesk / Inter / JetBrains Mono), responsive, reduced-motion-safe; no UI framework.
Agent integration — the same API is consumed by a browser and by LLM agents over MCP, so a scheduled agent can fetch headlines and then read full articles to summarize.
Shipping — deployed to Vercel (serverless) from GitHub with CI on push, and to a private VPS as a systemd service.
It's deliberately small: ~1 backend file, 1 feed-config file, a static frontend, and an MCP shim.
Run it locally
npm install
npm start # → http://localhost:3000
npm test # unit checks for reading-time + filter/sort + XML/date helpersThe feed is live immediately — every card shows when it dropped and how long it takes to read; sort by newest or category, pick a timeframe, search.
Related MCP server: OmniWire-MCP
The live feed — what's wired and how to change it
Everything goes through feeds.js — the only file you edit. Each category is
{ slug, label, feeds: [rss urls] }. A dead/blocked URL is skipped so the page
never breaks; it is also logged to stderr and visible at GET /api/health.
Add a source: drop another RSS URL into a category's
feedsarray, or a typed entry like{ type: "json", adapter: "hn", url: "..." }(see the source layer below).Add a category: append a new
{ slug, label, feeds }object. Frontend, API and chips pick it up automatically.Check what is alive:
GET /api/healthreturns every configured source with its status, item count and last error — and lists the ones that are skipped because a key isn't configured yet.
Two URL patterns worth knowing
Some topics have no first-party RSS. Two query-based feeds cover any subject without a publisher relationship:
hnrss.org/newest?q=<terms>&points=<n>&count=30 # Hacker News search
news.google.com/rss/search?q=<terms>+when:7d # Google News searchThe count=30 on hnrss.org is not optional — without it those endpoints
intermittently return HTTP 502. Google News items carry the real publisher in
<source>, and the server surfaces that as the card's source instead of
news.google.com.
The 30 categories
Group | Categories |
AI | AI · Industry & Business · AI · Research & Practice · AI Agents |
Tech | Coding & Tech · Open-Source / GitHub · Cybersecurity |
Money | Startups · Business · Investments · Stock Markets & Equities · Rates, Treasuries & Bonds · Economics & Inflation · FX Reference Rates (ECB) · Global Currencies & FX · Crypto & Blockchain |
Science | Space & Science · Climate & Energy · Health & Biotech |
Culture | Gaming · Film & TV · Marvel & DC · Manga & Anime · Reading Recs · Sneakerhead · Watches |
Sports | Basketball · Football (Soccer) · Sports · F1, Tennis, NFL |
World | Germany · Ukraine · Armenia · Local |
Bold = new.
Money & markets in detail
The financial categories are split so you can read one without the rest:
Stock Markets & Equities — indices, earnings, market moves (CNBC, FT, Nikkei Asia, SCMP, Google News).
Rates, Treasuries & Bonds — policy decisions and sovereign debt: Fed monetary policy, Fed press releases, ECB press + tender operations, ECB Market Information Dissemination, Bank of England, Bank of Japan, Google News on Treasury yields.
Economics & Inflation — CPI and payrolls (BLS), euro-area statistics (ECB), macro desks (CNBC Economy, The Economist Finance & Economics), Google News on inflation / rate decisions / GDP.
FX Reference Rates (ECB) — the numbers: one authoritative daily feed per currency for USD, JPY, CNY, NOK, SGD, CHF, GBP, SEK, DKK, AUD, CAD, NZD, INR, KRW, MXN, BRL, ZAR, TRY, THB and PLN (
1 EUR = N units, published ~16:00 CET on TARGET days), plus the RBA's daily rates for AUD. These sit in their own category on purpose — a feed publishing one rate per day gets buried under a hundred breaking-news items once everything is sorted by date. Because rates are published on TARGET days, this category is markedperiodic: thesincewindow always keeps its newest day, so?since=24on a Sunday still returns Friday's rates instead of an empty list.Global Currencies & FX — the why: FXStreet, ForexLive, and per-currency Google News for USD, JPY, CNY, NOK, SGD, CHF, EUR and GBP, so you see the policy or risk event behind a move.
The source layer — RSS plus JSON APIs
RSS alone left 8 of 30 categories under 10 items in a 24-hour window: thin for a daily digest, and with no depth material at all. Every category now draws on two kinds of source.
1. RSS / Atom — the base layer. Free, keyless, no signup. 233 endpoints.
2. JSON APIs — normalised to the same item shape by adapters.js. 45
endpoints, all keyless:
Adapter | Gives you |
| preprints — the actual paper, not a headline about it |
| scholarly works, abstracts reconstructed from the inverted index |
| working engineers writing about what they built |
| the questions themselves, with vote counts and answer counts |
| Hacker News via the public Algolia index (newest-first, any topic) |
| ECB FX reference rates for 30 currencies in one keyless call |
| crypto market snapshot — price, 24h move, volume |
| 80,000+ sources in 41 languages, with the real publisher (keyed) |
Google News queries | one search feed per category, so no niche is ever empty |
A feed entry is a plain URL string (RSS) or a typed object (JSON):
"https://example.com/rss.xml" // RSS
api("hn", "https://hn.algolia.com/api/v1/...") // JSON adapter
api("guardian", "https://...api-key={{auth}}",
{ auth: { env: "GUARDIAN_KEY" } }) // needs a keyOptional API keys (none required)
Nothing is needed to run or deploy — all 30 topics work from keyless
sources alone. 23 further sources are wired up but dormant until you supply
credentials; a source whose key is missing is skipped, never failed, so
you can commit the full source list and switch integrations on one env var at
a time. GET /api/health reports them under skippedSources with the reason.
Integration | Register at | Free tier | Used for |
Guardian Open Platform | 500/day, 60/min, non-commercial | deep sectioned coverage for 9 categories | |
NewsAPI | 100 req/day, attribution required | broad multi-publisher headlines | |
GNews | 100 req/day, 1 req/sec, 12h delay | 8 categories, 80k+ sources | |
TMDB | generous | film, TV and anime discovery | |
Twelve Data | 800 credits/day, 8/min | live FX quotes | |
Reddit OAuth2 | standard | subreddit depth (6 subreddits) |
Copy .env.example to .env and fill in what you want — it lists every URL
above with the exact steps for each. Reddit needs an app id + secret (choose a
"script" app; the redirect URI can be anything), the rest are single API keys.
Store them as env vars — never hardcode them. .env is gitignored.
Locally, npm start loads .env automatically (Node's --env-file). On Vercel,
set them under Project → Settings → Environment Variables — or with the
CLI, using --value so no trailing newline gets stored:
vercel env add GUARDIAN_KEY production --value "<key>" --sensitiveThat last detail matters: a key with a trailing newline makes GNews answer
400 "You did not provide an API key" rather than "invalid key", and the
server now trims credentials on the way in so it cannot happen again.
The Guardian key is the highest-value one: it is the only source here with
genuinely deep per-topic coverage. Its free tier is non-commercial — if
MyNews ever earns money, request a commercial key at
https://bonobo.capi.gutools.co.uk/register/commercial instead.
How caching works
Caching is per source, not per category, and each source refreshes on its own schedule. That is what makes the free-tier quotas survivable:
Source kind | Refresh | Why |
keyless RSS | 5 min | cheap, wants to be fresh |
Guardian | 120 min | 500 requests/day, 9 sources → ~108/day |
NewsAPI | 120 min | 100 requests/day, 3 sources → ~36/day |
GNews | 240 min | 100 requests/day, 8 sources → ~48/day |
TMDB, Twelve Data, Reddit | 60 min | no daily cap; Twelve Data is 8 credits/min |
A source can override this with ttlMinutes.
Hosts with hard request limits also get a minimum gap between requests, and the gaps are measured rather than guessed:
Host | Gap | Measured behaviour |
| 150 ms | 60 req/minute, no per-second cap — 9 at once left the budget untouched |
| 1100 ms | genuinely 1 req/second — 8 concurrent gave six 429s |
| 1200 ms | 8 API credits/minute; a 5-symbol batch costs 5 |
The per-feed timeout is 10 s and a timeout is not retried — a slow host is a dead host, and a second attempt would hold a concurrency slot for another full timeout. A cold start over ~285 sources takes about 30 s on Vercel and is instant on the VPS, where the process never goes cold.
When a provider runs out of daily quota
Some providers answer 403 with "you have reached your request limit for
today" once a daily allowance is spent — GNews does this. The server
recognises that response, pauses the whole host until 00:00 UTC, and reports
it separately from a broken feed:
{ "url": "https://gnews.io/...", "ok": false, "quota": true,
"error": "daily request limit reached" }So a spent budget never turns into a wall of red in the health report, and the feed is not hammered with requests that cannot succeed. Check the quota usage before adding another provider on the same key — GNews's 100 requests/day is easy to consume with eight sources refreshing four times a day.
The result: categories under 10 items in 24h went 8 → 0, daily items
962 → 1,822, and ai alone went from 2 items / 1 source to 70 items /
30 sources.
The API
CORS is open, so any agent or page can call it.
GET /api/categories
→ [{ slug, label }, ...]
GET /api/sources?category=ai&since=24
→ { count, sources: [{ source, items }] }
every publisher currently in the feed, with its story count for the
window — the values for the `source` filter below.
GET /api/news?category=ai,crypto&since=24&sort=newest&q=bitcoin&source=theguardian.com&limit=50&offset=0
category comma-separated slugs (omit = all)
since only items from the past N hours (0 = all time)
sort newest | category
q keyword filter on title + snippet
source filter by publisher, e.g. theguardian.com
limit max items in this page (default 200, cap 500)
offset skip this many items — page through a feed larger than the cap
→ { count, offset, limit, hasMore, totalReadingMinutes,
items: [{ title, link, source, category, publishedAt,
readingMinutes, snippet, image }] }
`count` is how many stories match in total; `items` is the requested page.
GET /api/article?url=<article-url>
→ { url, title, author, published, source, wordCount, readingMinutes, content }
full readable body text, boilerplate stripped — what an agent reads to summarize a story
GET /api/health
→ { categories, deadFeeds: [{ slug, url, error, quota }],
skippedSources: [{ slug, url, reason }],
report: [{ slug, label, totalItems,
feeds: [{ url, adapter, ok, items, error, skipped, quota, reason }] }] }
per-source status for every configured source — so a thin category is
explainable instead of mysterious. `skipped` marks a source whose
credentials are not configured yet; `quota` marks one that has spent
its daily allowance and will recover on its own.curl "https://mynews-nine.vercel.app/api/news?category=agents,ai&since=24&limit=10"
curl "https://mynews-nine.vercel.app/api/article?url=https://www.theverge.com/some-story"
curl "https://mynews-nine.vercel.app/api/health?category=currencies"Connect your AI agent — step by step
The API is public and keyless, so wiring any agent takes three steps.
Point at the API. Base URL
https://mynews-nine.vercel.app/api.Get headlines.
GET /api/news?category=agents,ai&since=24→ titles, sources, timestamps, read-time.Read the full story.
GET /api/article?url=<link from step 2>→ clean body text to summarize.
That's enough for any framework (LangChain, a custom tool, a cron + curl). For MCP-native agents, use the bundled server instead of raw HTTP:
npm i @modelcontextprotocol/sdk zod
NEWS_API=https://mynews-nine.vercel.app node mcp.js # speaks MCP over stdioIt exposes five tools: get_news, get_article, list_categories, list_sources
and check_feeds. The same server is also mounted over Streamable HTTP at
POST /api/mcp on the deployed app, so an agent can point at the URL instead
of spawning a process.
OpenClaw (the simplest path)
Add one block to ~/.openclaw/openclaw.json under mcp.servers, then restart the
gateway — every agent gains the tools:
"mynews": {
"command": "/usr/bin/node",
"args": ["/home/openclaw/newsfeed/mcp.js"],
"env": { "NEWS_API": "https://mynews-nine.vercel.app" }
}A morning-news cron then calls get_news for the day's headlines and get_article
for the full text of each story it wants to summarize — no scraping glue.
Deployments
Vercel (public, online): Express runs as a serverless function (
api/index.js+vercel.json);public/is the static site. Auto-deploys on push tomain.VPS (private): a systemd
--userunit (newsfeed.service,Restart=always) on port 3000. Manage withsystemctl --user restart|status newsfeedandjournalctl --user -u newsfeed -f.
Files
server.js— API + cache + reading-time + article extraction + feed health + MCP over HTTPfeeds.js— the 30 categories → sources (RSS URLs and JSON adapters; edit this)adapters.js— normalisers that turn JSON API responses into feed items.env.example— the optional API keys, documentedpublic/— Cobalt-themed landing + feed (index.html,dashboard.html,app.js,styles.css,landing.css,tokens.css)api/index.js+vercel.json— Vercel serverless wiringmcp.js— MCP server (get_news / get_article / list_categories / list_sources / check_feeds)test.js— unit checks
Notes on the feed layer
Four things server.js handles that a naive rss-parser setup gets wrong:
Gzip. Some hosts (deepmind.google) gzip their response; the client inflates it before parsing.
Malformed XML. Some publishers ship unescaped
&inside imagesrcsetattributes (restofworld.org). Bare ampersands are escaped before parsing; CDATA sections are left alone.Undated feeds. GitHub Trending and Nikkei Asia ship no timestamps, so the
sincewindow used to drop them entirely and the category rendered "no stories". Undated items now inherit a bounded fallback date — the feed's own newest entry, or the fetch time when the feed has none — so they survive the 24-hour window instead of vanishing.Spent quotas. A provider that has used up its daily allowance answers
403, which looks exactly like a broken feed. The response body is read, the host is paused until 00:00 UTC, and the source is reported withquota: trueinstead of as a failure.
The browser UI
public/dashboard.html is a thin client over the same API the agents use:
Filter by category (multi-select chips), publisher (dropdown of every source with its story count), timeframe, or keyword.
Sort by newest, or by category — grouped, with a heading per topic.
Page through the feed with Load more;
offsetwalks past the 500-item cap.Health pill in the masthead shows how many sources are alive, paused on a quota, unreachable, or waiting for an API key. Click it to refresh.
Shareable state — the URL carries the filters, so a link opens the same filtered feed. The landing page's topic tiles deep-link into a pre-selected category.
This server cannot be deployed
Maintenance
Related MCP Connectors
Real-time corroborated news events + 5-year archive, for agents. Free tier, no key.
News for agents: 100k+ articles/day deduplicated into situations with timelines. Free, no key.
Free cross-lingual news briefings for AI agents across 89 languages. Read-only, hosted.
Your curated sources (RSS, YouTube, podcasts, Google News) as context for any AI agent.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to fetch real-time news from Google News RSS feeds with support for headlines, categories, location-based queries, and advanced search operators. Features automatic URL decoding, concurrent processing, and intelligent caching for optimized access to global news content.72MIT
- AlicenseCqualityCmaintenanceEnables AI models to fetch and aggregate news from RSS, Atom, JSON, and HTML feeds with fault-tolerant circuit breaker protection.426 npm6MIT
- AlicenseAqualityDmaintenanceEnables AI agents to fetch and search news from multiple sources including RSS/Atom feeds, HackerNews, and GDELT global news intelligence without requiring an API key.1134 PyPI4MIT
- AlicenseAqualityCmaintenanceEnables AI to manage RSS subscriptions, fetch and summarize news, and organize results into tools like Notion.94 npm3MIT