AI-powered news agency that detects newsworthy facts from Data360's 12,000 indicators and delivers them verified with local perspective to LAC newsrooms.
A prototype by Abrimos.info for the Data360 Global Challenge (World Bank and Media Party), phase 2.
Ten-day sprint (21 to 31 May 2026). Submission deadline is 31 May 2026, via Media Party Hub.
- Frontend. Node.js, Pug templates, vanilla JavaScript — country front pages, articles, indicators hub, chat, newsletter preview
- Backend. Node.js HTTP server (
data360-monitor.js) - Data layer. Data360 API v3 (REST + MCP optional in chat)
- LLM. Claude Opus 4.7 via Agent SDK (pipeline); multi-provider chat (
claude-code,vllm,nvidia, OpenRouter vialib/ai-client.js) - Verification. Proof-Carrying Numbers (PCN) from the World Bank
- Hosting. Abrimos-owned infrastructure
- Production roadmap. Apache NiFi orchestrates continuous updates
The monitor serves a newspaper-style product for five LAC countries:
| Route | Purpose |
|---|---|
/ |
Country picker + recently updated indicators |
/{country} |
Country front page (hero reportaje, headlines, indicator ticker) |
/{country}/{noticia|reportaje}/{year}/{month}/{slug} |
Full article + scoped chat |
/indicadores |
Global indicators hub by tier |
/indicador/{IDNO} |
Indicator detail and alerts by country |
/chat |
Global analytical chat (presets, freshness, MCP tools) |
/newsletter/lac/{date} |
LAC newsletter edition preview |
/metodologia, /privacidad, /terminos, /uso |
Static pages (config/copy/) |
Subscribe modal → POST /api/subscribe → local TSV (data/newsletter/subscribers.tsv, gitignored). No real email in demo.
Legacy card feed with client filters: /dev/feed or ?legacy=1 on a country page.
Full operator guide: docs/user-guide.md (ES) · docs/user-guide.en.md (EN).
The demo runs two independent processes on the server: the Node monitor (dashboard + chat UI) and the Data360 MCP server (Python, chat tools only). Nginx terminates TLS and proxies only the monitor; MCP stays on localhost.
| Service | Default port | Repo / entrypoint |
|---|---|---|
| Monitor | 8090 (D360_PORT) |
this repo — node data360-monitor.js |
| Data360 MCP | 8021 |
worldbank/data360-mcp |
Nginx example. infra/nginx/data360.example.conf and infra/nginx/README.md.
The chat agent calls Data360 through MCP (mcp_search_indicators, mcp_get_data, mcp_compare_countries, etc.). If MCP is down, lib/chat/tools.js falls back to the REST client automatically — the UI keeps working, but responses may be less enriched.
1. Install MCP (once per host)
Requires Python 3.10+ and uv.
git clone https://github.com/worldbank/data360-mcp.git
cd data360-mcp
uv sync
uv pip install -e data360-mcp
uv pip install -e data360-mcp-serverCreate .env in the MCP repo (or export):
DATA360_API_BASE_URL=https://data360api.worldbank.org2. Run MCP
Development:
uv run fastmcp run data360-mcp-server/src/data360_mcp_server/main.py:mcp --transport http --port 8021Or use the upstream script: ./run_server.sh.
The HTTP endpoint must be reachable at http://127.0.0.1:8021/mcp (Streamable HTTP + SSE).
3. Point the monitor at MCP
In this repo's .env:
MCP_URL=http://127.0.0.1:8021/mcpDo not expose MCP through nginx — bind to localhost and let only the Node process call it.
4. Verify
With MCP running:
node bin/evaluate-mcp.jsSmoke-test from the deployed site: open an article chat and ask for a LAC comparison or a sparkline; tool traces should show source: data360_mcp.
5. Production (systemd sketch)
Run MCP as its own unit, restart independently of the monitor:
# /etc/systemd/system/data360-mcp.service
[Unit]
Description=World Bank Data360 MCP server
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/data360-mcp
Environment=DATA360_API_BASE_URL=https://data360api.worldbank.org
ExecStart=/usr/local/bin/uv run fastmcp run data360-mcp-server/src/data360_mcp_server/main.py:mcp --transport http --host 127.0.0.1 --port 8021
Restart=on-failure
[Install]
WantedBy=multi-user.targetAdjust paths, then systemctl enable --now data360-mcp. Restart the monitor after changing MCP_URL.
For persistent hosting of the Node monitor, use PM2 with the included ecosystem file:
npm install -g pm2
cp .env.example .env # configure D360_PORT, MCP_URL, AI_*, etc.
pm2 start ecosystem.config.js
pm2 save
pm2 startup # optional: survive rebootecosystem.config.js runs data360-monitor.js with NODE_ENV=production, D360_PORT=8090, and loads secrets from .env via env_file. Run the Data360 MCP server separately (systemd or another PM2 app on port 8021).
pm2 logs data360-monitor
pm2 restart data360-monitorEnvironment reference: docs/environment-variables.md.
With AI_PROVIDER=claude-code, the pipeline calls the Anthropic Messages API when ANTHROPIC_API_KEY is set. This is the expected path for local development and production (pm2).
In .env:
AI_PROVIDER=claude-code
ANTHROPIC_API_KEY=sk-ant-api03-...
CLAUDE_MODEL=opusCreate keys at console.anthropic.com. Full variable reference: docs/environment-variables.md.
| Document | Description |
|---|---|
| User guide (ES) | All product features for newsrooms — front pages, articles, chat, verification, pipeline |
| User guide (EN) | English translation of the user guide |
| Environment variables | Complete .env reference (AI, chat, news, server) |
| Features reference | Technical feature catalog (API, tools, files) |
| Architecture overview | Demo vs production |
| Frontend architecture | Pug, routes, article chat |
| Security and data handling | Subscriptions, LLM, PCN, hosting |
| Sustainability plan | Post-Challenge partners and operation |
Guatemala, Honduras, Argentina, Ecuador, Mexico.
The demo covers two of the five canonical detection patterns.
- Abrupt changes. Observations with elevated z-score against their historical trajectory.
- Cross-indicator anomalies. Countries that fall outside the regional pattern.
Roadmap. Narrative versus data divergences, invisible trends, untold milestones.
The pipeline uses bin/fetch-data.js to detect upstream updates before downloading.
npm run fetch:probe # fast check (~2 s): which indicators changed?
npm run fetch # probe + download changed + refresh LAC contextOutputs.
data/changed-since.json— indicators updated since the last probe (changed_indicatorsarray)data/index.json— freshness summary for all watchlist indicators
Full design. docs/data-fetcher-architecture.md
Detection and narrative generation run in two phases inside one step:
npm run fetch:news # optional: headline pool (≤5 countries, Gemini → GDELT)
npm run analyze # strategies 1 + 4 → Phase 1 Noticias → Phase 2 Reportajes → data/alerts.jsonThe pipeline emits two content types:
- Noticia — bilingual news story (one per indicator/country, 250–600 words) triggered by a detection candidate.
- Reportaje — bilingual long-form (one per dataset, 500–1200 words) generated only when two or more Noticias share the same
dataset_id. Synthesises a regional view and reuses the Noticias'claim_ids.
Each alert carries a single country field (ISO3), not a list — see docs/alert-schema.json.
Per-indicator only: node bin/generate-analysis.js --only FAO_CP_23012
Indicators can be picked from the static 35-item watchlist (lib/watchlist.js) or discovered dynamically from /data360/searchv2:
npm run pipeline # discover → fetch → news → analyze → newsletter
npm run pipeline:force # same, but bypass the ETag cache
npm run build # alias for pipeline
npm run analyze:changed # analyze changed indicators only
npm run analyze:noticias # Phase 1 only
npm run analyze:reportajes # Phase 2 only
npm run fetch:news # headline pool (≤5 countries)
npm run fetch:news:indicator # legacy: Gemini per watchlist indicator
npm run fetch:news:gdelt # GDELT only
npm run generate:newsletter # LAC newsletter edition for today (also run by pipeline)
npm run replay:daily # day-by-day replay (fetch + analyze + newsletter)Pipeline and replay logs append run elapsed time (+2m 14s) on milestones via D360_RUN_EPOCH.
Pipeline (AI_PROVIDER) and chat (CHAT_AI_PROVIDER): claude-code, vllm (LAIA), nvidia (NIM), OpenRouter. See .env.example and docs/environment-variables.md.
See docs/user-guide.md for the full operator reference.
- Working prototype and repo (this repository)
- Demo video (5 min)
- Architecture overview.
docs/architecture-overview.md - Data360 API integration methodology.
docs/data360-integration-methodology.md - Security and data handling.
docs/security-data-handling.md - User guide.
docs/user-guide.md(ES) ·docs/user-guide.en.md(EN) - Features reference.
docs/features-reference.md - Sustainability plan.
docs/sustainability-plan.md
- Eduard Martín-Borregón. Lead, narrative, UX, video, documentation.
- Martin Szyszlican. Frontend, LLM agents, RAG, dashboard.
- Fernando Matzdorf. Data360 connector, schema, ETL.
GPLv3. See LICENSE.