Skip to main content
Glama

news-digest

A small personal news digest: RSS aggregator with optional LLM summarization, exposed as an MCP server for Claude Code / Claude Desktop (plus a FastAPI HTTP layer). Built as a hobby project "delve into Python", focused on asyncio, raw SQL, the Anthropic API and the Model Context Protocol.

README CONTENTS:

What it does

Register the server in Claude Code and ask "fetch the latest articles and give me an overview of today's AI news". The model calls the fetch_latest and get_articles_for_digest tools on its own and writes the digest from the source material.

The app is domain-agnostic: it digests whatever your feeds cover. The bundled defaults are tech feeds, so the examples below are tech - but point feeds.txt at economics, sports or local-news sources and everything downstream (archive, search, digest, topic filter) follows. A sample run with the defaults:

Today's AI news (Aug 11, 2026)

Local and edge inference - today's strongest theme

  • H3-metal (391 pts) - antirez wrote native MiniMax-H3 inference for Apple Silicon in plain C. The biggest AI story of the day on HN.

  • Needle 2 (472 pts) - a 14 MB agentic LLM: tool calls and structured extraction on phones and Raspberry Pi 5 (~500 tok/s).

Business and society

  • As AI eats the web (693 pts, 744 comments) - how AI answers drain the web...

Related MCP server: junk-filter-mcp

Architecture

                    ┌─────────────────────────┐
  RSS/Atom feeds ──▶│  ingest.py              │
  (httpx async,     │  httpx.AsyncClient      │
   N sources        │  + feedparser (sync!)   │
   in parallel)     │  → list[Article]        │
                    └────────────┬────────────┘
                                 │
                                 ▼
                    ┌─────────────────────────┐
                    │  storage.py             │
                    │  SQLite, raw SQL        │
                    │  articles, sources      │
                    │  dedup via UNIQUE(url)  │
                    └────────────┬────────────┘
                                 │
                                 ▼
                    ┌─────────────────────────┐
                    │  llm.py                 │
                    │  Anthropic API:         │
                    │  classify (Haiku)       │
                    │  → rank → summarize     │
                    │  (Opus), structured out │
                    └────────────┬────────────┘
                                 │
                 ┌───────────────┴───────────────┐
                 ▼                                ▼
    ┌─────────────────────────┐     ┌─────────────────────────┐
    │  mcp_server.py          │     │  api.py                 │
    │  MCPServer, stdio       │     │  FastAPI, Pydantic      │
    │  tools: fetch_latest,   │     │  GET /digest/latest     │
    │  search, digest,        │     │  GET /articles          │
    │  source management      │     │                         │
    └─────────────────────────┘     └─────────────────────────┘
         ▲
         │ stdio transport
    Claude Code / Claude Desktop (MCP host)

Design decisions

  • Two phases of intelligence. Phase 1 MCP tools (fetch_latest, search_archive, get_articles_for_digest) return data only - the host model does the synthesis, so the server needs no API key. Phase 2 (make_digest) runs its own pipeline against the Anthropic API: a cheap model (Haiku) classifies every article, a stronger one (Opus) only summarizes the top N. With MCP you have to decide on which side the LLM call runs - both variants live here side by side on purpose.

  • SQLite + raw SQL, no ORM. A local single-user tool: the DB is one file, dedup is UNIQUE(url) + INSERT OR IGNORE, every query is parametrized. On a bigger schema I would reach for SQLAlchemy/SQLModel for the same reasons I use Drizzle in TypeScript.

  • feedparser runs via asyncio.to_thread. No blocking calls inside async code - either the library has an async variant (httpx), or it goes to a worker thread.

  • One dead feed never kills the run. fetch_feed returns None instead of raising; a failing source is skipped and the rest proceed.

Getting started

You will need these tools installed:

  • git - to clone this repo (on macOS, xcode-select --install gets you it)

  • uv - Python package manager (also installs Python itself if you have none)

  • Claude Code - the MCP host you will talk to

No git? Download the repo as a ZIP from the green Code button on GitHub, unpack it, and start from cd news-digest below.

You do not "run" this app directly - you clone it, register it as an MCP server and then talk to it through Claude. In your terminal:

git clone https://github.com/davpu/news-digest
cd news-digest
uv sync
claude mcp add news-digest -- uv run --directory "$(pwd)" python src/mcp_server.py

The registration is scoped to the directory you run claude mcp add from - start your Claude Code sessions there (cd news-digest && claude) to see the server.

Then just ask, in plain language (examples assume the default tech feeds - with your own sources, ask about your own domain):

  • "fetch the latest articles and give me an overview of today's AI news"

  • "did we have anything about Kubernetes lately?"

or use the built-in prompt template as a one-click action: /mcp__news-digest__daily_digest (arguments: topic, days).

Phase 2 (make_digest, module llm.py) needs ANTHROPIC_API_KEY in .env (see .env.example).

Development

Each module doubles as a smoke test when run directly:

uv run python src/ingest.py      # feed fetching
uv run python src/storage.py     # SQLite layer

Configuration

Everything model- or content-facing lives outside the code, which is also what makes the app domain-agnostic:

  • feeds.txt - what to digest from: one feed URL per line, any domain; while empty, the app runs on bundled defaults (DEFAULT_FEEDS in src/ingest.py). You can also just ask Claude - the list_sources, add_source and remove_source tools manage this file conversationally, and each new feed is downloaded and validated before it is added. The setup_sources prompt template bootstraps a whole new domain in one go ("find me quality economics feeds")

  • prompts/interests.md - default relevance profile for the LLM classification step (phase 2)

  • what to digest: the daily_digest prompt template and the get_articles_for_digest tool both take an optional topic, so the same archive can produce an AI digest, a security digest, or anything else

Repo structure

  • src/ - the code (5 modules, see diagram)

  • prompts/ - model-facing text kept out of code

The MCP server also exposes a daily_digest(topic, days) prompt template (MCP prompts primitive), so hosts can offer the whole flow as a one-click action.

Available Tools

7 tools
add_sourceA

Validate and add a new RSS/Atom feed to feeds.txt. Use when the user wants to follow a new source. The feed is downloaded and parsed first - invalid or dead URLs are rejected, nothing is written.

While feeds.txt is empty the app runs on bundled default feeds. When adding the user's FIRST own feed, ask them once whether to keep the defaults too (then call this with keep_defaults=True) or start fresh with only their own sources. Do not ask again once feeds.txt has entries.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
keep_defaultsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, but the description discloses the validation parse step, rejection of invalid/dead URLs, and that nothing is written on failure. It also explains the default feeds behavior and the keep_defaults exception.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose in the first sentence, and every additional sentence adds necessary behavioral or usage context. No fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With only 2 parameters and no annotations, the description covers all relevant behavior including edge cases, and the presence of an output schema handles return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has no descriptions (0% coverage), but the description explains the url as the new feed and keep_defaults with practical meaning ('keep the defaults too').

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Validate and add a new RSS/Atom feed to feeds.txt' with a specific verb and resource, and distinguishes it from sibling tools like remove_source.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Use when the user wants to follow a new source' and provides conditional logic for the first feed, including when to ask about keep_defaults.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fetch_latestA

Fetch the latest articles from all configured RSS feeds and store them (duplicates are skipped). Use when the user wants to refresh the archive or asks about the newest articles.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description carries the full burden. It discloses the key behavior of storing fetched articles and skipping duplicates, which is valuable. However, it does not detail potential side effects like whether existing articles are altered or if there are rate limits. The deduplication note provides meaningful transparency beyond a simple 'fetch' statement.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences that front-load the core action and then provide usage context. There is no filler or repetition, making every word count.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless tool with an output schema, the description sufficiently covers what the tool does, when to use it, and a key behavioral nuance (duplicates skipped). This is complete for its complexity and context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the input schema is empty and there is nothing for the description to explain. The baseline of 4 for parameterless tools is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('Fetch'), the resource ('latest articles from all configured RSS feeds'), and the outcome ('store them'), which distinguishes it from sibling tools like search_archive or add_source. The verb-resource combination is specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool: 'Use when the user wants to refresh the archive or asks about the newest articles.' This gives clear context, though it does not mention alternatives or when not to use it, which would elevate it to a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_articles_for_digestA

Return raw article data (title, URL, source, summary) from the last days days as a markdown list. Use when you (the host model) should write the digest yourself - this tool only provides the source material.

topic is an optional keyword pre-filter (whole-word match) - useful for large archives. Omit it to get everything and pick relevant articles yourself, which handles synonyms and related themes better.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo
topicNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description takes on the full burden of behavioral disclosure. It explains the output is raw article data in markdown list format, describes the `topic` pre-filter as whole-word match, and notes that omitting it returns everything. It does not cover error behavior or limits, but for a simple read tool it provides substantial behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized: the first sentence states the core purpose, and the second paragraph adds essential parameter guidance. Every sentence earns its place, with no filler or repetition of schema defaults.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has an output schema and the description already explains parameters and usage, the description is mostly complete. It could mention ordering or limits, but the existing text covers the key decisions for selecting and invoking the tool, especially in the context of sibling tools like `make_digest` and `search_archive`.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides no parameter descriptions (0% coverage), so the description must compensate. It fully explains both parameters: `days` defines the time window, and `topic` is an optional whole-word keyword pre-filter, with advice on when to include or omit it. This adds significant meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Return raw article data') and clearly states the resource (articles from the last `days` days) and output format (markdown list). It also distinguishes itself from sibling tools like `make_digest` by specifying it only provides source material for the host model to write the digest itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool: 'Use when you (the host model) should write the digest yourself.' It also provides usage guidance for the optional `topic` parameter, including when to omit it. It does not explicitly name sibling alternatives, but the context makes the intended use clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_sourcesA

List the feeds the digest currently aggregates, with the number of stored articles per source. Reports whether the app runs on bundled default feeds (feeds.txt is empty) or the user's own selection.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of behavioral disclosure. It reveals important behavior: it returns per-source article counts and indicates whether the app uses bundled defaults (feeds.txt empty) or user selection. This goes beyond a bare 'list' statement, though it does not explicitly confirm a read-only side-effect profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded with the primary purpose in the first sentence. The second sentence adds meaningful detail without redundancy. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read-only listing tool, the description fully covers what is returned (feeds, article counts, default-vs-user status). An output schema exists, so return details need not be fully re-explained. The context is complete for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and schema coverage is 100% (empty). With no parameters to describe, a baseline of 4 is appropriate; the description adds no parameter detail but none is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening verb 'List' plus the specific resource 'feeds the digest currently aggregates' clearly states the action and scope. It further specifies what is reported (number of stored articles per source and whether default or user feeds), distinguishing it from sibling tools like add_source/remove_source.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool (when you need to see current aggregated feeds) but does not explicitly mention alternatives or when not to use it. It lacks explicit comparison to siblings like search_archive or get_articles_for_digest, so usage guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

make_digestA

Build a ready-made markdown digest of the most relevant articles from the last days days using the server's own LLM pipeline. Not implemented yet - use get_articles_for_digest instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite having no annotations, the description fully discloses the critical behavioral trait: the tool is not implemented. It also adds context about the server's LLM pipeline. This is more transparent than typical annotation-based disclosures.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, with two short sentences. The first sentence front-loads the intended functionality, and the second immediately provides the non-implementation warning and alternative. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with an output schema, the description is complete: it explains the intended action, states that it is not implemented, and names the alternative. This provides all context needed for the agent to handle the tool safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description interprets the sole parameter 'days' as 'from the last days days', adding semantic meaning beyond the schema's plain integer type and default value. However, it does not specify any constraints like valid range, which slightly limits completeness.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's intended purpose: building a markdown digest of relevant articles using the server's LLM pipeline. It also distinguishes this tool from its siblings by explicitly naming the replacement tool (get_articles_for_digest), making the actual utility unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance by stating 'Not implemented yet - use get_articles_for_digest instead.' This tells the agent precisely when not to use the tool and which alternative to invoke, satisfying the highest level of usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_sourceA

Remove a feed from feeds.txt. Use when the user no longer wants a source. Already stored articles from that source stay in the archive.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses an important behavioral consequence: already stored articles from the removed source remain in the archive. This goes beyond the basic removal action and helps set expectations about non-destructive side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description consists of two concise sentences with no wasted words. The main action is stated first, followed by a relevant usage condition and side effect, making it easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter removal tool, the description covers the core purpose, when to use it, and the key side effect on archived articles. The presence of an output schema means return values need not be described. Minor gaps like error behavior or idempotency are not critical here.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description does not explain the 'url' parameter beyond calling the item a 'feed'. Schema coverage is 0%, so the description must compensate, but it merely says 'Remove a feed' without explicitly clarifying that the url parameter is the identifier of the feed to remove. This leaves some ambiguity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool removes a feed from feeds.txt, using a specific verb and resource. This distinguishes it from siblings like add_source, and the context of user intent ('no longer wants a source') reinforces its purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly gives a usage condition: 'Use when the user no longer wants a source.' It does not list exclusions or alternatives, but the condition is clear and sufficient for a single-purpose removal tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_archiveA

Search stored articles by keyword (matches title or summary). Use when the user asks about a specific topic from the archive.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of transparency. It discloses that the search matches on title or summary, which is a valuable behavioral detail. It implies a read-only operation (search) but does not explicitly state side effects or edge cases, yet it is sufficient for a simple search tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no redundant phrasing. The first sentence front-loads the action and matching behavior, while the second provides a usage guideline. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (one parameter, output schema present). The description covers purpose, usage, and parameter semantics. It does not need to explain return values because the output schema exists. It omits any mention of result limits or ordering, but this is not essential for a basic search tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has one parameter ('query') with zero schema description. The description clarifies that 'query' is a keyword and that it matches title or summary, directly adding meaning beyond the schema. This adequately compensates for the lack of schema description, though it does not provide example formats.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Search stored articles') and the scope ('by keyword (matches title or summary)'). This specific verb+resource combination clearly distinguishes it from sibling tools like add_source, fetch_latest, and make_digest.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides an explicit usage cue: 'Use when the user asks about a specific topic from the archive.' This gives a clear context, though it does not explicitly mention alternatives or when not to use it, which is slightly less informative than the calibration high example.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 7 tool updatesv0.1.0
    • First observedadd_source
    • First observedfetch_latest
    • First observedget_articles_for_digest
    • First observedlist_sources
    • First observedmake_digest
    • First observedremove_source
    • First observedsearch_archive

TDQS

A4.4/5.0

Scored across 7 tools

Disambiguation4/5

Most tools have clearly distinct purposes: add_source vs remove_source are opposites, fetch_latest vs search_archive vs get_articles_for_digest each target different actions. The only slight ambiguity is between get_articles_for_digest and make_digest, but the latter is explicitly marked as not implemented and directs to the former.

Naming Consistency5/5

All tool names follow the same verb_noun pattern in lowercase with underscores (add_source, remove_source, fetch_latest, search_archive, get_articles_for_digest, make_digest, list_sources). This is highly consistent and predictable.

Tool Count5/5

With 7 tools, the set is well-scoped for an RSS digest server: source management (add, remove, list), content fetching, archive search, and digest creation. Each tool serves a distinct purpose without unnecessary bloat or missing essentials.

Completeness4/5

The core workflows are covered: source CRUD (add/remove/list), fetching latest articles, searching the archive, and retrieving articles for a digest. Minor gaps include lack of an update_source tool and the unimplemented make_digest, but the alternatives provided make the surface functional.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers