numenews
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., "@numenews What's the numerology forecast for today?"
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.
numenews
MCP server and one-shot CLI that reads the news numerologically.
numenews fetches news from several public APIs, extracts numbers, dates and names, computes numerology (digit reduction, master numbers 11/22/33, gematria), finds patterns with hybrid vector search in Qdrant, and builds a daily forecast — while keeping every number activation as long-term memory.
It is a pet project that takes its subject seriously and itself not very: the numerology layer is
pure, deterministic and property-tested, the retrieval is a real hybrid search over a real vector
store, and the default demo path needs no API keys at all. v0.1.0 is out and both interfaces work.
What it does
Nine MCP tools over stdio, so Claude Desktop, Cursor or any MCP host can fetch news, extract numbers, find patterns, build a forecast and query the memory.
Six one-shot commands —
today,forecast,history,search,patterns,mcp— each printing one JSON document on stdout and nothing else, so they pipe straight intojq.Five news sources (GDELT, NewsAPI, GNews, Mediastack, Currents) behind one
NewsSourceProtocol, with an aggregator that degrades gracefully when a feed is down or rate-limited, and an RFC 9111 cache so a repeated run does not re-hit the network.Local embeddings only — two
bgemodels throughfastembed. No embedding API, ever.Six Qdrant collections with semantic and hybrid (reciprocal-rank-fusion) search, and payload indexes that make filtered queries cheap.
Four
pydantic-aiagents — extract numbers, find patterns, build the forecast, summarise old news — every one returning a validated Pydantic model rather than free-form JSON.A pipeline that composes them:
ingest → analyze → forecast, with a sliding window over the last week and a digest for everything older.Long-term memory: every number activation is logged, folded into a per-day frequency, and fed back into the forecast over a thirty-day window.
A ragas evaluation of the retrieval path, isolated in its own environment so LangChain never reaches the runtime.
Related MCP server: Google News MCP Agent
Quick start
uv sync --all-extras # install the environment (Python 3.14+, uv)
make dev # start Qdrant (Docker Compose) and wait until healthy
cp .env.example .env # optional: the default demo path needs no API keys
make lint && make test # ruff + mypy --strict, pytest with coverageQdrant's dashboard is then at http://localhost:6333/dashboard.
Over the CLI
today needs Qdrant and an LLM endpoint; history, search and patterns need Qdrant only. The
full command surface is in docs/USER_FLOW.md.
uv run numenews today | jq .dominant_number # ingest the window and read the day
uv run numenews forecast --date tomorrow # a stored/derived reading, no fetch
uv run numenews history --number 11 --days 30 # when 11 was active
uv run numenews search -q "число 7 и деньги" # hybrid search over stored news
uv run numenews patterns --min-strength 0.7 # the strong patterns, strongest first
uv run numenews --helpOver MCP
The server starts without Qdrant or an API key and builds each dependency on the first tool call
that needs it, so it can be attached to a host right away. Cursor's project config ships in
.cursor/mcp.json; Claude Desktop takes the same command in its own
claude_desktop_config.json. The nine tools, their examples and the failure semantics are in
docs/MCP_TOOLS.md.
make mcp # serve stdio (Ctrl-D to stop)
uv run pytest tests/integration/test_mcp_stdio.py # the same handshake, as a testWhat the output looks like
The pipeline builds this, the CLI serializes it, and stdout is always JSON:
{
"date": "2026-09-21",
"dominant_number": 11,
"master_active": true,
"patterns": [
{
"id": "8bb3a3e4-53cd-5333-92ab-5309c63d3b78",
"type": "resonance",
"numbers": [11, 22],
"news_ids": ["b371bc46-7b4b-5b38-92db-cdf94a550f33"],
"strength": 0.87,
"interpretation": "Числа 11 и 22 резонируют в новостях о технологиях",
"discovered_at": "2026-09-21T12:00:00Z"
}
],
"forecast": "День благоприятен для начинаний, связанных с коммуникацией",
"advice": "Избегайте конфликтов — число 11 усиливает эмоции",
"warnings": ["Возможны повторяющиеся события из прошлого"]
}How OpenSpec is used here
Specs are the source of truth for behaviour, and they live in the repository next to the code.
openspec/specs/holds what the project ships today, one capability per directory. Two exist so far:mcp-surface(the nine tools — inputs, return shapes, error reporting) andcli-surface(the six commands — JSON-only stdout, the--dategrammar, exit codes, idempotency). The internals are not specified yet; they get a capability the first time a change really touches them.openspec/changes/holds work in flight: a proposal, the spec deltas it would make, a design when the approach needs deciding, and a task list.The loop is propose → review → implement → archive.
openspec listshows what is active,openspec validate "<name>" --strictchecks a change, and archiving merges its spec deltas intoopenspec/specs/.New work starts as a change, not as an edit. An idea that is not a change yet lives in a GitHub issue.
docs/MCP_TOOLS.md and docs/USER_FLOW.md remain the narrative companions to the two specs: the
specs say what the behaviour must be, those documents show how to use it.
Project layout
src/numenews/
├── config.py # pydantic-settings
├── logging.py # structlog + contextvars correlation
├── models/ # Pydantic v2 domain models
├── numerology/ # pure logic: reduction, master numbers, gematria (no I/O)
├── news/ # GDELT, NewsAPI, GNews, Mediastack, Currents behind one Protocol
├── embeddings/ # fastembed wrapper
├── vector/ # Qdrant client, collections, hybrid search
├── agents/ # pydantic-ai: extract, pattern, forecast, summarize
├── pipeline/ # the RAG chain, the sliding window, step timings
├── mcp/ # MCP server and 9 tools
└── cli/ # one-shot Typer commands
openspec/
├── specs/ # behaviour that ships, one capability per directory
└── changes/ # proposals in flightLayer | Choice |
Package manager |
|
Types |
|
Vector store | Qdrant (Docker Compose; |
Embeddings |
|
LLM orchestration |
|
MCP server | Python |
HTTP |
|
Config / logs |
|
CLI | Typer + Rich, JSON-only stdout |
Tests |
|
Commands
make help # list every target
make install # uv sync --all-extras
make lint # ruff check + format check + mypy
make test # unit + integration (with coverage)
make test-eval # ragas evaluation in .venv-eval (needs an LLM endpoint; see docs/EVAL.md)
make eval-env # build .venv-eval (ragas; ADR 0013)
make dev # docker compose up -d --wait
make dev-down # stop Qdrant, keep the volume
make clean # stop Qdrant, delete volumes and caches
make run # sample one-shot CLI run (needs Qdrant and an LLM endpoint)
make mcp # start the MCP server (stdio)make test runs the unit and integration suites with coverage and then checks the per-layer floors
(numerology ≥ 95 %, pipeline/agents ≥ 80 %, vector/news ≥ 70 %); the levels, the doubles and the
dated coverage snapshot are in docs/TESTING.md.
Documentation
docs/ARCHITECTURE.md— the layers, the data flow and the runtime topologydocs/STACK.md— every tool, why it was chosen and what it costsdocs/TESTING.md— the test levels, the doubles and the coverage floorsdocs/coverage_report.md— the dated coverage snapshot and the floorsdocs/TOOL_USE.md— which MCP tool answers which questiondocs/GLOSSARY.md— MCP, RAG, gematria, master number and the restdocs/FAQ.md— "why numerology?", "do I need API keys?", "how do I connect Cursor?"docs/NUMEROLOGY.md— terminology and rulesdocs/NEWS_SOURCES.md— the five news APIs, their limits and the cachedocs/QDRANT_COLLECTIONS.md— the six collections, payloads and indexesdocs/EMBEDDINGS.md— the local models, the cache and why two of themdocs/PROMPTS.md— every agent prompt, verbatim, with its rationaledocs/RAG_PIPELINE.md— the chain, its degradation rules and its testsdocs/CONTEXT_MANAGEMENT.md— the window, the history and the digestdocs/MCP_TOOLS.md— the nine MCP tools, their examples and the client configsdocs/USER_FLOW.md— the one-shot CLI, its commands and their JSONdocs/EVAL.md— the ragas evaluation: how to run it and how to read the reportdocs/eval_report.md— the latest committed eval rundocs/adr/— architecture decision recordsdocs/agentic/— how AI coding agents work here, and their guardrailsAGENTS.md— the rules for AI coding agents in this repository
Contributing
It is a solo pet project, so there is no ceremony — but there is a workflow, and
CONTRIBUTING.md spells it out. The short version: work starts as an OpenSpec
change rather than a direct edit, one tasks.md item is one atomic task, and make lint && make test has to be green. Issues and ideas are welcome; there is no CI, on purpose, which is why the
commands are the gate.
License
Available Tools
9 toolsbuild_forecastA
Return the numerological reading for a calendar day, saving it for later calls.
A day that was already read answers from Qdrant without running a model. Otherwise the reading is assembled from the last seven days of stored news (their dominant number, whether a master number is active, and the patterns among them) plus the activations of exactly those numbers over the pipeline's thirty-day memory window, and then written back. Needs Qdrant and an LLM endpoint.
Inputs: day (required). Returns: One day's reading. ``dominant_number`` is the reduced value the day is read und…
check_master_numbersA
Report the master numbers (11, 22, 33) among a list of numbers.
master_numbers lists the distinct master numbers found, ascending, and count how many
occurrences there were: [11, 11] gives has_master=True, master_numbers=(11,) and
count=2. An empty list is a valid input and reports no master number. Pure logic: no
configuration, no service.
Inputs: numbers (required). Returns: Outcome of :func:`numenews.numerology.check_master_numbers`. ``master_numbers``…
compute_numerologyA
Reduce a text to its numerological value.
Returns the raw gematria sum, the digit-reduced value (11, 22 and 33 are master
numbers and are not reduced further), whether the value is master, and the rendered calculation
steps. Pure logic: no Qdrant, no model, no configuration.
Inputs: text (required). Returns: The reading of one text. ``gematria`` is the raw letter sum, ``value`` the redu…
extract_numbersA
Read the numbers, dates and symbols out of a text with the extraction agent.
The model's reading is combined with the deterministic regex pass, so a mention the model
formats differently ("eleven" beside "11") is still found, and a model that cannot answer at all
degrades to the regex reading instead of failing. sources says which strategies contributed.
Needs an LLM endpoint (OPENAI_API_KEY or OPENAI_BASE_URL).
Inputs: text (required). Returns: Numbers, symbols and provenance produced from one text. ``sources`` names the e…
fetch_newsA
Fetch the news of a topic in an inclusive date range from every configured source.
The five feeds run in parallel and the result is merged, de-duplicated and filtered to the range. A source that fails is skipped with a warning, so a broken feed thins the result instead of failing the call; if no source is configured at all (no GDELT, which needs no key) the call is a tool error.
Inputs: topic (required), date_range (required). Returns: result
find_patternsA
Find the connections among the stored news items with these ids, save them and return them.
The ids come from an earlier fetch_news/ingest run or from query_qdrant. An id that is
not in the store is skipped rather than refused, and an empty list answers [] without asking
the model — "nothing connects" and "nothing to look at" stay tellable apart. Each returned
pattern carries the discovered_at timestamp save_pattern stamped. Needs Qdrant and an
LLM endpoint.
Inputs: news_ids (required). Returns: result
get_historyA
Return when a number was activated in the news, newest first, inside the last days days.
One entry per (news item, number) pair the ingest stored: the day the article was published,
the item's id and the snippet the number was read in. The window ends today and includes it
(days=1 is today). The original design sketch wrote the signature as
get_history(number); the read is a window, so days is a parameter whose default of 30
matches the memory window. Needs Qdrant only.
Inputs: number (required), days. Returns: result
query_qdrantA
Search the stored news or patterns by meaning and return the matching entities.
collection="news" runs the hybrid (multi-stage) search over stored articles and honours the
optional payload filters — publication window, source, reduced value or master number.
collection="patterns" finds saved pattern interpretations and takes no filters: passing any
is an error rather than a silently ignored argument. Needs Qdrant only; nothing is embedded
remotely and no model is called.
The returned items are the typed entities themselves (NewsItem or Pattern), best
match first; the scores stay in Qdrant because the callers work with the entities.
Inputs: query (required), collection (required), limit, filters. Returns: What ``query_qdrant`` found: the collection it searched and the entities it ret…
save_patternA
Store one pattern and return it as written, with discovered_at filled in.
The original design sketch called the return type SavedPattern; the saved model is a
Pattern (the one numenews.vector.save_pattern returns), so the tool returns that rather
than a second type saying the same thing. Re-saving the same pattern id overwrites the point
instead of adding a copy, and a timestamp already present is never rewritten. Needs Qdrant only.
Inputs: pattern (required). Returns: A connection between news items with a confidence. ``strength`` is bounded to `…
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 9 tools
Each tool has a clearly distinct purpose: build_forecast, save_pattern, get_history, fetch_news, extract_numbers, compute_numerology, find_patterns, check_master_numbers, and query_qdrant target different domain actions. The descriptions distinguish overlapping-sounding tools (e.g., compute_numerology vs extract_numbers vs check_master_numbers) by scope and input/output.
Names consistently follow a verb_noun pattern (build_forecast, save_pattern, get_history, fetch_news, extract_numbers, compute_numerology, find_patterns, check_master_numbers, query_qdrant). The only noun-only name is query_qdrant, which still fits the pattern loosely as a verb-mechanism combination.
Nine tools is well-scoped for a numerological news analysis pipeline. Each tool covers a distinct stage (ingest, extract, compute, find, save, query, forecast) with no obvious redundancy or missing pieces at the count level.
The surface covers fetch/extract/analyze/save/query/forecast, which is a complete lifecycle for the domain. Minor gaps include no direct delete or update for stored patterns/news, and no batch operations, but agents can work around these via query and re-save.
Maintenance
Related MCP Connectors
News radars with AI anchors, market and network sensors, a daily violin piece composed from them
Worldwide news search by keyword and date, Hacker News, and any RSS or Atom feed as JSON
Read Google News across 80 editions and any public Telegram channel, without an API key
Monitor news sources, read clustered articles and generated texts, manage goals and workflows.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables fact-checking of news headlines using Google Gemini AI and web search verification, and retrieves trending news topics from RSS feeds with comprehensive multi-source analysis.1-
- FlicenseBqualityDmaintenanceFetches news articles from Google News, vectorizes them locally using ChromaDB, and enables semantic search through natural language queries.2-

newspaper-mcpofficial
AlicenseNot gradedqualityCmaintenanceEnables LLM agents to discover news sources, list articles, parse and extract article text, search news, and perform NLP analysis such as keyword extraction and summarization.MIT- FlicenseNot gradedqualityBmaintenanceEnables searching and fetching news articles with configurable date ranges, returning structured, sourced evidence for daily mineral-rights briefings.-