Skip to main content
Glama
danmarce

news-mcp

by danmarce

news-mcp

Curated RSS/Atom/RDF news → SQLite (rolling ~14-day window) → structured MCP tools. Items are stored in their original language; the LLM translates, summarizes and compares framing at query time. Design rationale: CLAUDE.md.

Tools

tool

use

latest_news(source?, lang?, country?, category?, hours=24, n=15)

newest headlines, filterable

news_by_topic(query, days=7, lang?, n=20)

keyword search; spaces = AND, | = OR ("Noboa | ノボア") — case/accent-insensitive

compare_coverage(topic, days=7, per_source=3)

matches grouped by outlet + outlets with no match → framing comparison

sources()

curated feeds, item counts, freshness / last status

Related MCP server: News Aggregator MCP Server

Run

uv sync
uv run news-mcp refresh                      # pull all feeds once (conditional GET), upsert, prune
uv run news-mcp serve                        # stdio (Claude Desktop / dev)
NEWS_MCP_TOKEN=secret uv run news-mcp serve --transport http --host 0.0.0.0 --port 8000   # streamable-http at /mcp
uv run pytest

env

default

NEWS_DB

data/news.db

SQLite path (WAL; refresh and server can share it)

NEWS_FEEDS

packaged src/news_mcp/feeds.toml

curated feed list

NEWS_RETENTION_DAYS

14

rolling window

NEWS_REFRESH_MINUTES

0 (off)

>0: serve also refreshes in the background (no timer needed)

NEWS_MCP_TOKEN

unset

bearer token required on HTTP (/healthz stays open)

NEWS_USER_AGENT, NEWS_FETCH_TIMEOUT

polite UA, 20

Claude Desktop

%APPDATA%\Claude\claude_desktop_config.json:

{
  "mcpServers": {
    "news": {
      "command": "uv",
      "args": ["--directory", "C:\\Code\\news-mcp", "run", "news-mcp", "serve"],
      "env": { "NEWS_DB": "C:\\Code\\news-mcp\\data\\news.db", "NEWS_REFRESH_MINUTES": "45" }
    }
  }
}

Docker Compose (e.g. mcpo → Open WebUI)

Build the image with docker build -t news-mcp .. By default it serves HTTP on :8000 at /mcp, with an open /healthz endpoint for the built-in healthcheck.

services:
  news-mcp:
    image: news-mcp:latest
    restart: unless-stopped
    environment:
      NEWS_MCP_TOKEN: ${NEWS_MCP_TOKEN}      # put it in .env; clients send "Authorization: Bearer <token>"
      NEWS_REFRESH_MINUTES: "45"             # refresh at startup, then every 45 min (no timer needed)
      NEWS_USER_AGENT: "news-mcp/0.1 (+https://example.org/your-contact)"   # identify your deployment
      # NEWS_FEEDS: /config/feeds.toml       # use your own curated list
    volumes:
      - news-data:/data                      # SQLite; local disk, not NFS/SMB
      # - ./feeds.toml:/config/feeds.toml:ro
    # ports: ["8000:8000"]                   # only if clients live outside this compose network
volumes:
  news-data:

If you'd rather use a host timer, leave NEWS_REFRESH_MINUTES unset and have the timer run docker compose run --rm news-mcp refresh. It uses the same /data volume.

mcpo entry (from a container on the same network):

{ "mcpServers": { "news": { "type": "streamable-http", "url": "http://news-mcp:8000/mcp",
  "headers": { "Authorization": "Bearer ${NEWS_MCP_TOKEN}" } } } }

AI assistance

news-mcp is developed openly with the help of Claude (Anthropic). We state this plainly: commits Claude helped write carry a Co-Authored-By: Claude trailer. The code and design are open source so the work can be inspected, reused, and given back.

License

Code: MPL-2.0. The repo ships only feed URLs; the news content it fetches belongs to each publisher and stays in your local database. Respect each feed's terms, keep the refresh interval polite (≥30 min), and set NEWS_USER_AGENT to identify your own deployment.

Available Tools

4 tools
compare_coverageA
Read-only

How different outlets/countries covered one story - for framing comparison ("compare how the German, Qatari, US and Ecuadorian press covered X"). Returns matching items grouped by outlet, plus the active outlets with NO matching item (silence can be telling, but may also just mean the keywords were in another language).

    Same matching as `news_by_topic`: include the key term in every relevant language separated by
    "|", e.g. "Ecuador | Équateur | エクアドル | الإكوادور".
    When answering, compare emphasis, word choice and what each outlet includes or omits, citing each
    outlet by name; translate faithfully and do not inject your own view.

    Args:
        topic: keywords; spaces = AND, "|" = OR between alternatives.
        days: look-back window in days (default 7).
        per_source: max items per outlet (default 3, max 10).
    
ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo
topicYes
per_sourceNo

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the readOnlyHint/openWorldHint annotations, it discloses non-obvious behavior: results come back grouped by outlet, and active outlets with no matching item are returned too, with the caveat that 'silence' may simply reflect keyword/language mismatch. It also warns that key terms must be supplied in every relevant language, which directly shapes correct invocation.

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

Conciseness4/5

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

Front-loads the core purpose and return behavior, then the matching rules and Args, which is a sensible ordering. The 'When answering...' paragraph is useful but is answer-style guidance rather than tool-invocation guidance, so it is slightly off-target and lengthens the description.

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 no output schema, the description must explain what comes back, and it does: matching items grouped by outlet plus outlets with no matches. Combined with the parameter documentation and language caveat, an agent has everything needed to call it and interpret the result.

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 description coverage is 0%, so the description carries the full burden and does: topic is documented with AND ('spaces') and OR ('|') semantics plus a multi-language example, days is the look-back window with default 7, and per_source is capped at 10 with default 3. Every parameter gains meaning not present in the bare 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?

States a specific verb and resource ('compare how different outlets/countries covered one story') and immediately frames the use case as framing comparison with a concrete example query. It also distinguishes itself from the sibling news_by_topic by noting it uses the same matching but groups results per outlet, so an agent can tell the two apart without opening a schema.

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?

Provides a clear usage scenario and an example phrasing, plus points to news_by_topic as the related matcher, which implicitly routes single-topic searches elsewhere. It does not explicitly state when not to use this tool (e.g., when no cross-outlet comparison is wanted), so it falls short of a full when/when-not/alternatives statement.

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

latest_newsA
Read-only

Most recent headlines, newest first. Use for "what's the news", "latest from Ecuador", "what does DW say today", "tech news". All filters are optional and combine with AND.

    Args:
        source: feed id from `sources()` (e.g. "elcomercio", "bbc-mundo", "dw-de").
        lang: ISO 639-1 language of the original items (e.g. "es", "en", "de", "fr", "ar", "ja").
        country: ISO 3166 alpha-2 country of the outlet (e.g. "EC", "US", "DE"); "INT" = international.
        category: one of general, politics, economy, science, tech, sport.
        hours: look-back window in hours (default 24; up to ~336 = two weeks).
        n: max items (default 15, max 50).
    
ParametersJSON Schema
NameRequiredDescriptionDefault
nNo
langNo
hoursNo
sourceNo
countryNo
categoryNo

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already cover the read-only, non-open-world profile, and the description layers on genuinely useful behavior: filters combine with AND, defaults (24h/15 items), and caps (~336h, max 50). It does not describe result ordering beyond 'newest first' or pagination, but that is minor against the annotation coverage.

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

Conciseness4/5

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

Front-loaded purpose followed by a clean per-argument list; every line adds information. Slightly long, but nothing is padding, so it stays efficient for a six-parameter tool.

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 six-parameter, no-output-schema read tool, the description documents selection, filtering semantics, and limits thoroughly. Only the shape of returned items is unaddressed, which is acceptable given the read-only annotations.

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 coverage is 0%, so the description carries the full burden and does so: every one of the six parameters gets meaning, format (ISO 639-1, ISO 3166 alpha-2), examples, defaults, and range for hours/n. This is exactly what a low-coverage schema requires.

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

Purpose4/5

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

States a specific resource and ordering ('Most recent headlines, newest first') plus its scope. It reads clearly as a general latest-news feed, distinguishable from news_by_topic, but it never names a sibling or explains the split between them.

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?

Concrete natural-language triggers ('what's the news', 'latest from Ecuador', 'what does DW say today', 'tech news') give an agent a clear sense of when to reach for it, and it points at sources() for feed ids. It lacks any when-not or explicit alternative-selection rules.

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

news_by_topicA
Read-only

Search recent headlines + summaries by keyword, newest first. Use for "news about X", "what happened with X this week".

    Matching is case- and accent-insensitive substring search on the ORIGINAL-language text, so a
    Spanish word will not find German or Japanese items. Words separated by spaces must ALL appear;
    separate alternatives with "|". To search across languages give the key name/term in each
    language, e.g. "Noboa | ノボア" or "elecciones | Wahl | élection | election".
    Prefer short distinctive terms (names, places) over full sentences.

    Args:
        query: keywords; spaces = AND, "|" = OR between alternatives.
        days: look-back window in days (default 7, max ~14).
        lang: optional ISO 639-1 filter on the original language.
        n: max items (default 20, max 50).
    
ParametersJSON Schema
NameRequiredDescriptionDefault
nNo
daysNo
langNo
queryYes

TDQS

A4.2/5.0
Behavior4/5

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

Annotations only cover readOnly and openWorld, so the description carries the real behavioral load and does it well: substring matching semantics, case/accent insensitivity, per-language corpus limits, AND/OR operator behavior, and hard caps (days ~14, n 50). It stops short of describing result shape or what 'summary' fields contain.

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

Conciseness4/5

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

Front-loaded with purpose and ordering, then matching rules, then per-arg notes. The cross-language examples are the most expensive part but they earn their place by teaching non-obvious query construction; a touch of redundancy in restating operators.

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?

With no output schema and thin annotations, the description supplies the matching model, language limitation, and parameter caps an agent needs to call it correctly. The only missing piece is any indication of what a returned item looks like, which matters for chaining into downstream tools.

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 coverage is 0%, so the description must do all the work, and it does: query documents space=AND and '|'=OR with worked bilingual examples, days documents default 7 and max ~14, lang documents ISO 639-1 original-language filtering, and n documents default 20 and max 50 — including max bounds absent from the schema.

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

Purpose4/5

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

States a specific verb (search), resource (recent headlines + summaries), and ordering (newest first), plus a keyword scope. It is clearly distinguishable from sources and compare_coverage, though it does not explicitly contrast itself with the sibling latest_news, which plausibly overlaps in 'recent news' territory.

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?

Gives concrete when-to-use phrasing ('news about X', 'what happened with X this week') that maps directly onto query construction. It lacks any explicit when-not/alternative-tool clause, which is the only gap at this tier.

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

sourcesA
Read-only

List the curated feeds: id, outlet name, language, country, category, whether active, when it was last refreshed successfully, and how many items it currently holds. Use to know which ids/filters exist or to check how fresh the data is.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds that 'last refreshed successfully' and current item count are exposed, which is useful behavioral context about what the listing reports, but it says nothing about pagination or ordering.

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

Conciseness4/5

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

Two sentences, front-loaded with the resource and its fields, followed by usage. There is a little field-list density but no filler or repetition.

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?

With no output schema, the description carries the return-shape burden and discharges it by listing the fields. For a trivial no-param read tool with annotations covering safety, this is close to complete; only ordering/pagination details are absent.

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 takes zero parameters, so the baseline is 4. The description adds value by enumerating the returned attributes, which is the natural substitute for parameter documentation on a no-arg lookup tool.

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

Purpose4/5

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

States a specific verb and resource ('List the curated feeds') and enumerates the fields returned, so the agent knows this is a metadata/lookup tool rather than a content-fetching one. It does not explicitly contrast itself with siblings like latest_news or news_by_topic, but the field list makes the distinction inferable.

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?

Gives two concrete use cases: discovering which ids/filters exist, and checking data freshness. That is clear context for when to reach for this tool. It stops short of naming an alternative tool or stating when not to use it, so it does not reach a 5.

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. 4 tool updatesv0.1.0
    • First observedcompare_coverage
    • First observedlatest_news
    • First observednews_by_topic
    • First observedsources

TDQS

A4.1/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: listing feeds, browsing latest news with metadata filters, keyword search, and cross-outlet comparison. Although latest_news and news_by_topic both return news, their descriptions clearly separate browsing from searching, and compare_coverage is uniquely analytical.

Naming Consistency3/5

The names mix a bare noun (sources), a noun phrase (latest_news), a prepositional phrase (news_by_topic), and a verb_noun pattern (compare_coverage). While all are readable, there is no consistent convention across the set.

Tool Count5/5

With only 4 tools, the set is well-scoped and each tool earns its place. There is no redundancy, and the count fits the narrow domain of news retrieval and comparison.

Completeness4/5

The surface covers listing sources, browsing, searching, and comparing coverage, which are the core operations for a news server. Minor gaps exist, such as fetching full article content or paginating results beyond the n parameter, but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with RSS readers that support the FreshRSS API through natural language. Allows users to manage and query their RSS feeds and articles via LLM conversations.
    7
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides curated international news feeds with tools to list, read, and fetch RSS/Atom/RDF feeds. Enables AI agents to access and filter world news data through natural language.
    169 npm
    MIT