Agentic RSS Parser
An enterprise-grade Node.js library for parsing RSS and Atom feeds — a drop-in rss-parser replacement with agentic analysis, deduplication, enrichment, and native MCP tooling.
Why it exists
rss-parser hasn't received a security update since 2022, yet it remains widely used across production agent pipelines. Agentic RSS Parser is a from-scratch rebuild that keeps the API you already know while closing the supply-chain gap — zero runtime dependencies, a custom XML engine, and native LLM adapters built directly on fetch().
Migrate in one line
All existing parseURL, parseString, parseFile, customFields, headers, timeout, and callback-style usage is preserved exactly. The agentic pipeline is an optional layer on top.
// Before
import Parser from 'rss-parser';
// After — zero other changes needed
import Parser from 'agentic-rss-parser';
Core features
- RSS 2.0, Atom & JSON Feed — namespaces, CDATA, HTML entities,
dc:creator,media:content,content:encoded, plus native JSON Feed v1/v1.1 detection and parsing - Drop-in compatibility —
parseURL,parseString,parseFile,customFields, callback and promise styles - Podcast & media enclosures —
<enclosure>audio/video metadata,media:thumbnail/media:content, and iTunes podcast tags normalised on every item - OPML import —
parseOpml()extracts feed URLs and categories from OPML subscription lists, including nested folders - Continuous feed watcher —
createFeedWatcher()is an event emitter for background polling with automatic conditional-GET support andresult/poll/feedErrorevents - Persistent HTTP caching — ETag / Last-Modified are stored per feed, so repeat polls send conditional GETs and skip re-analysing unchanged feeds on a 304
- Vector database export —
storage.exportForEmbedding()formats analysed items into ready-to-embed documents for Pinecone, Chroma, pgvector, or any other vector store - Search & analytics APIs —
storage.searchAnalyses()for keyword search across stored intelligence,storage.getStatistics()for database-wide metrics - Heuristic analysis — signal-based relevance scoring, no API key needed, fully configurable via
signals,extraSignals, andthreshold - LLM analysis — OpenAI, Anthropic, and local (Ollama) providers via native
fetch(), with customsystemPrompt/promptTemplatesupport for domain-specific evaluation - Article enrichment — fetches and strips full article body from feed item URLs
- MCP server — stdio JSON-RPC 2.0 server exposing five tools (feed fetch, article fetch, history search, statistics, database pruning) plus a live resource endpoint, compatible with Claude Desktop, Cursor, VS Code, and any MCP host
- SQLite deduplication — items are SHA-256 deduplicated across runs, with
pruneOlderThan()for long-running deployments - Retry & conditional GET — automatic exponential-backoff retries on 429/5xx, plus ETag / If-Modified-Since support to skip unchanged feeds
- SDK integrations — ready-to-use examples for Anthropic SDK, OpenAI Agents SDK, Vercel AI SDK, LangChain, and Google ADK
userAgentoverride — avoid 403s on feeds that block bot user-agents (Reddit, HN, Lobste.rs)
MCP tools & resources
Exposed over stdio for Claude Desktop, Cursor, and Cline:
fetch_rss_feed— fetch and agentically analyse an RSS, Atom, or JSON feed; supports heuristic and LLM providersfetch_full_article— fetch and HTML-strip an article body for contextsearch_feed_history— search stored intelligence and analyses by keywordget_feed_statistics— retrieve metrics on processed feeds and relevance ratiosprune_database— prune items older than a given TTL in daysrss://analyses/latest— MCP resource for reading recent relevant intelligence straight from the SQLite database
New in v1.7.0
Security hardening and feature expansion: credential isolation so environment API keys are never auto-forwarded to a custom MCP baseURL, prototype-pollution and XML entity/nesting DoS hardening in the parser, complete IANA CIDR range coverage for SSRF blocking (multicast, reserved, documentation, benchmarking, and 6to4 ranges), native JSON Feed support, podcast/media enclosure normalisation, persistent ETag-based HTTP caching, and three new MCP tools plus a live resource endpoint.
Quick start
npm install agentic-rss-parser
import Parser from 'agentic-rss-parser';
const parser = new Parser({ timeout: 10000 });
const feed = await parser.parseURL('https://news.ycombinator.com/rss');
for (const item of feed.items) {
console.log(`- ${item.title} — ${item.link}`);
}
Agentic pipeline
Run the full fetch → parse → deduplicate → analyse pipeline with zero API key required, using the built-in heuristic engine:
import { runAgenticParser } from 'agentic-rss-parser';
const { results, feedErrors } = await runAgenticParser({
feedUrls: ['https://news.ycombinator.com/rss'],
dbPath: './data/rss-agent.db'
});
for (const { item, analysis } of results) {
if (analysis.decision === 'relevant') {
console.log(`[${analysis.confidence}%] ${item.title}`);
}
}
Import an OPML list and watch it continuously
Import a subscription list and poll it in the background without wiring a timer yourself.
import { parseOpml, createFeedWatcher } from 'agentic-rss-parser';
import { readFileSync } from 'node:fs';
const { feeds } = parseOpml(readFileSync('./subscriptions.opml', 'utf8'));
const watcher = createFeedWatcher({
feedUrls: feeds.map((f) => f.xmlUrl),
intervalMs: 5 * 60_000,
dbPath: './data/rss-agent.db'
});
watcher.on('result', ({ item, analysis }) => {
if (analysis.decision === 'relevant') console.log(item.title);
});
watcher.start();
Security posture
Safe to deploy in security-sensitive environments. The production runtime is intentionally small and auditable:
XXE / Billion Laughs
DOCTYPE and ENTITY declarations are ignored; entity expansion is never performed.
XSS mitigation
<script>, <iframe>, <object>, <embed>, <form> stripped from content snippets.
Prompt injection
Feed content is sanitised — control characters stripped, newlines collapsed — before LLM interpolation.
Response size caps
Feed responses capped at 5 MB; LLM responses capped at 1 MB — enforced by counting bytes as the response streams in, not after buffering the full body.
SSRF & DNS-rebinding protection
Non-HTTP(S) schemes rejected. Private ranges, loopback, link-local, and carrier-grade-NAT addresses blocked on every request and redirect hop — including hostnames that only resolve to a blocked address rather than embedding one literally. Full IANA CIDR coverage: multicast, reserved, documentation, benchmarking, and 6to4 ranges are blocked alongside RFC-1918.
Stack safety
XML is parsed iteratively via a state machine, never recursively — immune to stack overflow attacks. A maximum nesting-depth cap additionally rejects deeply-nested XML bombs outright.
Prototype pollution
Parsed object keys are checked with Object.hasOwn() rather than the in operator, and __proto__ / constructor / prototype keys are sanitised before assembly.
Entity-decoding DoS
Numeric XML entities are bounds-checked before code-point conversion, preventing crashes from malformed or out-of-range entity references.
MCP credential isolation
Environment API keys are never auto-forwarded when a custom or untrusted MCP baseURL is supplied — a proxy endpoint must be handed an explicit apiKey, preventing unintended credential capture.
Requirements
- Node.js ≥ 22.5.0 (required for
node:sqlite) - ESM-only package
- Linux, macOS, Windows
Get involved
Agentic RSS Parser is MIT licensed and developed in the open. Star it, file an issue, or open a pull request.