diff --git a/CLAUDE.md b/CLAUDE.md
index 9faef39..972f1cf 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## What This Is
-World Intelligence MCP Server — 81 tools across 30 domains providing real-time global intelligence from free public APIs. Serves three interfaces: MCP stdio (for Claude Code/Cursor), a live Starlette dashboard with SSE, and a Click CLI with Rich output. Python 3.11+, built with hatchling.
+World Intelligence MCP Server — 80 tools across 30 domains providing real-time global intelligence from free public APIs. Serves three interfaces: MCP stdio (for Claude Code/Cursor), a live Starlette dashboard with SSE, and a Click CLI with Rich output. Python 3.11+, built with hatchling.
## Commands
@@ -23,7 +23,6 @@ pytest src/world_intel_mcp/tests/test_sources.py::test_fetch_market_quotes -v #
# CLI
intel markets # stock indices
intel earthquakes --min-mag 5.0 # USGS quakes
-intel report daily # generate HTML report
intel status # cache + circuit breaker health
# Dashboard (requires [dashboard] extra)
@@ -52,8 +51,6 @@ dashboard/app.py (SSE) ─┘
**Analysis modules** (`analysis/*.py`): Cross-domain intelligence that consumes outputs from multiple sources. Includes signal aggregation, instability indexing, NLP (entity extraction, classification, clustering, spike detection via Welford's algorithm), and strategic synthesis.
-**Reports** (`reports/*.py`): Jinja2-templated HTML/Markdown reports (daily brief, country dossier, threat landscape). `generator.py` orchestrates parallel source fetches. Output dir defaults to `$STORAGE_BASE/reports/intel` or `INTEL_REPORT_DIR` env var.
-
**Static config** (`config/*.py`): Curated datasets — 22 intel hotspots, 70+ military bases, 40 ports, 24 pipelines, 24 nuclear facilities, 34 undersea cables, 48 AI datacenters, 27 spaceports, 27 mineral deposits, 82 stock exchanges, 105 major cities, 28 world leaders, 36 APT groups.
**Dashboard** (`dashboard/`): Self-contained Starlette app with a single `index.html` template (no frontend build step). SSE endpoint streams all domains in parallel via `asyncio.gather()`, refreshes every 30 seconds. Loads `.env` from project root on startup.
diff --git a/ROADMAP.md b/ROADMAP.md
index fcd8db9..34ae9dc 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,8 +1,8 @@
# World Intel MCP — Feature Parity Roadmap
**Benchmark**: [koala73/worldmonitor](https://github.com/koala73/worldmonitor)
-**Updated**: 2026-02-24
-**Current tools**: 68 (67 intel + 1 status)
+**Updated**: 2026-02-26
+**Current tools**: 80 (79 intel + 1 status)
---
@@ -16,9 +16,9 @@
---
-## 1. Data Sources — Complete Inventory (59 intel tools)
+## 1. Data Sources — Complete Inventory
-### Markets & Economics (10 tools)
+### Markets & Economics (11 tools)
| Tool | WM Equivalent | Status |
|------|---------------|--------|
| `intel_market_quotes` | `list-market-quotes` | :white_check_mark: |
@@ -31,13 +31,16 @@
| `intel_energy_prices` | `get-energy-prices` | :white_check_mark: |
| `intel_fred_series` | `get-fred-series` | :white_check_mark: |
| `intel_world_bank_indicators` | `list-world-bank-indicators` | :white_check_mark: |
+| `intel_country_stocks` | Country main index ticker | :white_check_mark: |
-### Natural Disasters & Climate (3 tools)
+### Natural Disasters & Climate (5 tools)
| Tool | WM Equivalent | Status |
|------|---------------|--------|
| `intel_earthquakes` | `list-earthquakes` | :white_check_mark: |
| `intel_wildfires` | `list-fire-detections` | :white_check_mark: |
| `intel_climate_anomalies` | `list-climate-anomalies` | :white_check_mark: |
+| `intel_environmental_events` | NASA EONET events | :white_check_mark: |
+| `intel_disaster_alerts` | GDACS global disaster alerts | :white_check_mark: |
### Conflict & Security (4 tools)
| Tool | WM Equivalent | Status |
@@ -47,15 +50,17 @@
| `intel_unrest_events` | ACLED protests + GDELT dedup | :white_check_mark: |
| `intel_cyber_threats` | `list-cyber-threats` | :white_check_mark: |
-### Military & Defense (6 tools)
+### Military & Defense (8 tools)
| Tool | WM Equivalent | Status |
|------|---------------|--------|
| `intel_military_flights` | `list-military-flights` | :white_check_mark: |
| `intel_theater_posture` | `get-theater-posture` | :white_check_mark: |
| `intel_aircraft_details` | `get-aircraft-details` | :white_check_mark: |
+| `intel_aircraft_batch` | Batch ICAO24 lookup | :white_check_mark: |
| `intel_vessel_snapshot` | `get-vessel-snapshot` | :white_check_mark: |
| `intel_military_surge` | `military-surge.ts` | :white_check_mark: |
| `intel_military_bases` | Static dataset (70 bases) | :white_check_mark: |
+| `intel_usni_fleet` | USNI Fleet Tracker weekly disposition | :white_check_mark: |
### Infrastructure & Maritime (6 tools)
| Tool | WM Equivalent | Status |
@@ -78,7 +83,7 @@
### News & Information (4 tools)
| Tool | WM Equivalent | Status |
|------|---------------|--------|
-| `intel_news_feed` | 80+ RSS feeds, 4-tier sources | :white_check_mark: |
+| `intel_news_feed` | 90+ RSS feeds, 4-tier sources | :white_check_mark: |
| `intel_trending_keywords` | trending-keywords service | :white_check_mark: |
| `intel_gdelt_search` | `search-gdelt-documents` | :white_check_mark: |
| `intel_ai_releases` | AI model/paper tracker | :white_check_mark: |
@@ -90,7 +95,7 @@
| `intel_airport_delays` | `list-airport-delays` | :white_check_mark: |
| `intel_shipping_index` | Yahoo Finance shipping ETFs | :white_check_mark: |
-### Analysis & Intelligence (11 tools)
+### Analysis & Intelligence (9 tools)
| Tool | WM Equivalent | Status |
|------|---------------|--------|
| `intel_risk_scores` | `get-risk-scores` | :white_check_mark: |
@@ -102,17 +107,13 @@
| `intel_hotspot_escalation` | `hotspot-escalation.ts` | :white_check_mark: |
| `intel_alert_digest` | Cross-domain alert synthesis | :white_check_mark: |
| `intel_weekly_trends` | Temporal trend analysis | :white_check_mark: |
-| `intel_daily_brief` | — | :white_check_mark: |
-| `intel_threat_landscape` | `StrategicPosturePanel` | :white_check_mark: |
-### Country & Geopolitical (5 tools)
+### Country & Geopolitical (3 tools)
| Tool | WM Equivalent | Status |
|------|---------------|--------|
| `intel_country_brief` | `get-country-intel-brief` | :white_check_mark: |
-| `intel_country_dossier` | CountryBriefPage | :white_check_mark: |
| `intel_election_calendar` | Election proximity risk | :white_check_mark: |
| `intel_sanctions_search` | OFAC SDN search | :white_check_mark: |
-| `intel_nuclear_facilities` | Static dataset (24 facilities) | :white_check_mark: |
### Strategic Synthesis (4 tools)
| Tool | WM Equivalent | Status |
@@ -122,6 +123,18 @@
| `intel_fleet_report` | Naval fleet activity report | :white_check_mark: |
| `intel_population_exposure` | Population near active events | :white_check_mark: |
+### Tech & Science (3 tools)
+| Tool | WM Equivalent | Status |
+|------|---------------|--------|
+| `intel_hacker_news` | Top HN stories (Firebase API) | :white_check_mark: |
+| `intel_trending_repos` | GitHub trending repos | :white_check_mark: |
+| `intel_arxiv_papers` | Recent AI/ML papers | :white_check_mark: |
+
+### Government (1 tool)
+| Tool | WM Equivalent | Status |
+|------|---------------|--------|
+| `intel_usa_spending` | USAspending.gov federal data | :white_check_mark: |
+
### Specialist (3 tools)
| Tool | WM Equivalent | Status |
|------|---------------|--------|
@@ -129,6 +142,14 @@
| `intel_nuclear_monitor` | USGS seismic near test sites | :white_check_mark: |
| `intel_service_status` | Cloudflare/AWS/Azure/GCP | :white_check_mark: |
+### NLP Intelligence (4 tools)
+| Tool | WM Equivalent | Status |
+|------|---------------|--------|
+| `intel_extract_entities` | Regex NER (28 leaders, 41 orgs, 36 APTs) | :white_check_mark: |
+| `intel_classify_event` | Keyword threat classification (14 categories) | :white_check_mark: |
+| `intel_news_clusters` | Jaccard similarity clustering | :white_check_mark: |
+| `intel_keyword_spikes` | Welford's algorithm spike detection | :white_check_mark: |
+
### System (1 tool)
| Tool | Purpose | Status |
|------|---------|--------|
@@ -150,17 +171,17 @@
| Nuclear test sites | 5 sites with monitoring | config/countries.py | :white_check_mark: |
| Countries config | 22 nations with risk baselines | config/countries.py | :white_check_mark: |
| Major cities | 105 cities (pop > 2M, 1B coverage) | config/population.py | :white_check_mark: |
-| Undersea cables | Cable routes with landing points | — | :red_circle: |
-| AI datacenters | Major clusters globally | — | :red_circle: |
-| Spaceports | Launch facilities worldwide | — | :red_circle: |
-| Critical minerals | Strategic mineral locations | — | :red_circle: |
-| Stock exchanges | 92 global exchanges | — | :red_circle: |
+| Undersea cables | 34 cables with landing points | `intel_undersea_cables` | :white_check_mark: |
+| AI datacenters | 48 global clusters | `intel_ai_datacenters` | :white_check_mark: |
+| Spaceports | 27 launch facilities | `intel_spaceports` | :white_check_mark: |
+| Critical minerals | 27 deposit types | `intel_critical_minerals` | :white_check_mark: |
+| Stock exchanges | 82 global exchanges | `intel_stock_exchanges` | :white_check_mark: |
---
## 3. RSS Feed Coverage
-Expanded from 20 to **80+ feeds** across **15+ categories** with 4-tier source ranking (wire/major/specialty/aggregator) and propaganda risk labels.
+Expanded to **90+ feeds** across **16 categories** with 4-tier source ranking (wire/major/specialty/aggregator) and propaganda risk labels.
| Category | Count | Status |
|----------|-------|--------|
@@ -178,65 +199,53 @@ Expanded from 20 to **80+ feeds** across **15+ categories** with 4-tier source r
| Health (WHO/ProMED) | 3+ | :white_check_mark: |
| Space weather | 2+ | :white_check_mark: |
| AI/ML releases | 3+ | :white_check_mark: |
-| Latin America | 0 | :red_circle: |
-| Multilingual feeds | 0 | :red_circle: |
+| Latin America | 8+ | :white_check_mark: |
+| Multilingual (ES/FR/DE) | 7+ | :white_check_mark: |
---
-## 4. What's Still Missing
+## 4. Dashboard
-### Data Sources (P2-P3)
-| # | Feature | Priority | Effort |
-|---|---------|----------|--------|
-| 1 | **Country stock index lookup** — ticker for any country's main index | P2 | S |
-| 2 | **Aircraft details batch** — batch lookup by multiple ICAO24 codes | P3 | S |
-| 3 | **USNI fleet tracker** — US Navy fleet disposition from USNI News | P2 | M |
-| 4 | **Wingbits ADS-B** — crowd-sourced ADS-B coverage | P3 | S |
-| 5 | ~~**Population exposure**~~ — :white_check_mark: `intel_population_exposure` | — | — |
-| 6 | **Hacker News items** — top HN stories | P3 | S |
-| 7 | **Trending repos** — GitHub trending repos | P3 | S |
-| 8 | **arXiv papers** — recent AI/ML papers | P3 | S |
-| 9 | **PizzInt indicator** — pizza delivery patterns as OSINT proxy | P3 | S |
+Live Starlette app with SSE streaming at `intel-dashboard --port 8501`.
-### Analysis Layers (P2-P3)
-| # | Feature | Priority | Effort |
-|---|---------|----------|--------|
-| 10 | ~~**Strategic Posture Assessment**~~ — :white_check_mark: `intel_strategic_posture` | — | — |
-| 11 | ~~**World Brief**~~ — :white_check_mark: `intel_world_brief` (structured, data-driven) | — | — |
-| 12 | **USA Spending Tracker** — Federal contract data from USAspending.gov | P3 | S |
+| Feature | Status |
+|---------|--------|
+| SSE streaming (30s refresh) | :white_check_mark: 37 data streams |
+| Leaflet map (14 layers + 6 static) | :white_check_mark: |
+| 12 expandable drawer sections | :white_check_mark: |
+| USNI Fleet Tracker drawer | :white_check_mark: |
+| Data freshness monitoring drawer | :white_check_mark: |
+| Per-source circuit breaker health | :white_check_mark: |
+| AI situation brief (Ollama-powered) | :white_check_mark: |
+| Static HTML reports | Removed (dashboard replaces) |
-### Static Datasets (P3)
-| # | Feature | Priority | Effort |
-|---|---------|----------|--------|
-| 17 | **Undersea cable routes** — landing points (we have health, not routes) | P2 | M |
-| 18 | **AI datacenters** — 111 major clusters globally | P3 | S |
-| 19 | **Spaceports** — launch facilities worldwide | P3 | S |
-| 20 | **Critical mineral deposits** — strategic mineral locations | P3 | S |
-| 21 | **Stock exchanges** — 92 global exchanges with coordinates | P3 | M |
+---
-### System Architecture (P2)
-| # | Feature | Priority | Effort |
-|---|---------|----------|--------|
-| 22 | **Redis caching backend** — persistent TTL cache (currently in-memory) | P1 | M |
-| 23 | **Circuit breaker per-source** — configurable thresholds per API | P2 | S |
-| 24 | **Data freshness monitoring** — per-source staleness tracking | P2 | S |
+## 5. System Architecture
+
+| Feature | Status | Notes |
+|---------|--------|-------|
+| SQLite WAL-mode cache | :white_check_mark: | Persistent TTL, stale fallback |
+| Per-source circuit breaker | :white_check_mark: | Configurable thresholds |
+| Data freshness monitoring | :white_check_mark: | Per-source staleness in dashboard |
+| Per-coro timeout (45s) | :white_check_mark: | No single source blocks dashboard |
---
## Completed Phases
-### Phase 1-4: Foundation (0 -> 39 tools)
-Core data sources: markets, crypto, macro, earthquakes, wildfires, ACLED, UCDP, humanitarian, military flights, theater posture, aircraft, internet outages, cable health, nav warnings, climate, prediction markets, displacement, airport delays, cyber threats, news feeds, GDELT, trending keywords, country briefs, risk scores, instability index, signal convergence, daily brief, country dossier, threat landscape.
+### Phase 1-4: Foundation (0 -> 36 tools)
+Core data sources: markets, crypto, macro, earthquakes, wildfires, ACLED, UCDP, humanitarian, military flights, theater posture, aircraft, internet outages, cable health, nav warnings, climate, prediction markets, displacement, airport delays, cyber threats, news feeds, GDELT, trending keywords, country briefs, risk scores, instability index, signal convergence.
-### Phase 5: Core Analysis Engine (+3 = 42 tools)
+### Phase 5: Core Analysis Engine (+3 = 39 tools)
`intel_focal_points`, `intel_signal_summary`, `intel_temporal_anomalies`
Countries config with 22 nations, intel hotspots, conflict zones, strategic waterways. CII v2 upgraded with multi-signal weighted blend. Welford's online algorithm for temporal baseline anomaly detection.
-### Phase 6: Military & Infrastructure Intelligence (+6 = 48 tools)
+### Phase 6: Military & Infrastructure Intelligence (+6 = 45 tools)
`intel_vessel_snapshot`, `intel_military_surge`, `intel_cascade_analysis`, `intel_hotspot_escalation`, `intel_commodity_quotes`, `intel_unrest_events`
AIS vessel tracking, military surge detection in 17 sensitive regions, infrastructure cascade analysis, hotspot escalation scoring for 22 locations.
-### Phase 7: Domain Expansion (+10 = 58 tools)
+### Phase 7: Domain Expansion (+10 = 55 tools)
`intel_space_weather`, `intel_ai_releases`, `intel_disease_outbreaks`, `intel_sanctions_search`, `intel_election_calendar`, `intel_shipping_index`, `intel_social_signals`, `intel_nuclear_monitor`, `intel_alert_digest`, `intel_weekly_trends`
80+ RSS feeds with 4-tier source ranking. WHO/ProMED/CIDRAP health monitoring. OFAC sanctions search. Election proximity risk scoring. Reddit social signals. Nuclear test site seismic monitoring. Cross-domain alert digest. Temporal weekly trend analysis.
@@ -252,19 +261,10 @@ Regex-based NER (28 leaders, 41 orgs, 25 companies, 36 APT groups, CVE extractio
`intel_strategic_posture`, `intel_world_brief`, `intel_fleet_report`, `intel_population_exposure`
Composite strategic posture assessment from 9 weighted domains (military, political, conflict, infrastructure, economic, cyber, health, climate, space). Structured world intelligence brief aggregating posture, focal points, news clusters, temporal anomalies, and keyword spikes. Naval fleet activity report combining theater posture, vessel snapshots, and surge detections. Population exposure analysis near active events using 105-city dataset (1B pop coverage).
----
+### Phase 11: Extended Data & Geospatial (+12 = 80 tools)
+`intel_country_stocks`, `intel_aircraft_batch`, `intel_hacker_news`, `intel_trending_repos`, `intel_arxiv_papers`, `intel_usa_spending`, `intel_environmental_events`, `intel_disaster_alerts`, `intel_undersea_cables`, `intel_ai_datacenters`, `intel_spaceports`, `intel_critical_minerals`, `intel_stock_exchanges`, `intel_usni_fleet`
-## Next Phase
-
-### Phase 11: Data Expansion
-**Goal**: Fill remaining data gaps and static datasets.
-
-1. **Country stock index lookup** — ticker for any country's main stock index
-2. **USNI fleet tracker** — US Navy fleet disposition scraping
-3. **Hacker News** — top HN stories via public API
-4. **Trending repos** — GitHub trending repositories
-
-New tools: `intel_country_stocks`, `intel_usni_fleet`, `intel_hacker_news`, `intel_trending_repos`
+Static datasets completed: 34 undersea cables, 48 AI datacenters, 27 spaceports, 27 critical mineral deposits, 82 stock exchanges. USNI Fleet Tracker for Navy disposition. RSS feeds expanded to 90+ across 16 categories (added Latin America 8+, multilingual ES/FR/DE 7+). Data freshness monitoring added to dashboard. Static HTML report generation removed (live dashboard replaces).
---
@@ -272,10 +272,10 @@ New tools: `intel_country_stocks`, `intel_usni_fleet`, `intel_hacker_news`, `int
| Category | Have | Benchmark | Coverage |
|----------|------|-----------|----------|
-| Data source tools | 68 | 42 | **162%** |
+| Data source tools | 80 | 42 | **190%** |
| Analysis engines | 19 | 15 | **127%** |
-| Static datasets | 10 | 12 | 83% |
-| RSS feeds | 80+ | 150+ | 53% |
-| Strategic synthesis | Strategic posture + world brief + fleet report + population exposure | Dashboard-only | **Exceeds** |
+| Static datasets | 15 | 12 | **125%** |
+| RSS feeds | 90+ | 150+ | 60% |
+| Strategic synthesis | Posture + brief + fleet + exposure + USNI | Dashboard-only | **Exceeds** |
-**Bottom line**: 68 tools across 27 domains, exceeding WorldMonitor benchmark by 62% in tool count and 27% in analysis engines. Strategic synthesis layer complete — composite risk assessment, structured intelligence briefs, fleet reporting, and population exposure analysis. Remaining gaps: RSS feed breadth (80+ vs 150+), static datasets (10 vs 12), a few niche data sources.
+**Bottom line**: 80 tools across 30 domains, exceeding WorldMonitor benchmark by 90% in tool count, 27% in analysis engines, and 25% in static datasets. All phases 1-11 complete. Live Starlette dashboard with 37 SSE streams, 14 map layers, and data freshness monitoring. No remaining critical gaps — only niche sources (Wingbits requires API key, PizzInt has no public API).
diff --git a/src/world_intel_mcp/cli.py b/src/world_intel_mcp/cli.py
index 66add0d..20bec9f 100644
--- a/src/world_intel_mcp/cli.py
+++ b/src/world_intel_mcp/cli.py
@@ -19,7 +19,6 @@ from .cache import Cache
from .circuit_breaker import CircuitBreaker
from .fetcher import Fetcher
from .sources import markets, economic, seismology, wildfire, conflict, military, infrastructure, maritime, climate, news, intelligence, prediction, displacement, aviation, cyber
-from .reports import generator as report_gen
console = Console()
@@ -859,60 +858,6 @@ def instability(ctx: click.Context, country_code: str | None) -> None:
console.print(table)
-# ---------------------------------------------------------------------------
-# Reports
-# ---------------------------------------------------------------------------
-
-@main.group()
-def report() -> None:
- """Generate intelligence reports (HTML)."""
-
-
-main.add_command(report)
-
-
-@report.command(name="daily")
-@click.option("--output-dir", "-o", default=None, help="Output directory")
-def report_daily(output_dir: str | None) -> None:
- """Generate daily intelligence brief (HTML)."""
- console.print("[bold]Generating daily brief...[/bold]")
- result = _run(report_gen.generate_daily_brief(output_dir=output_dir))
- console.print(f"[green]Report saved:[/green] {result.get('file_path', '?')}")
- summary = result.get("summary", {})
- console.print(f" Quotes: {summary.get('market_quotes', 0)} | "
- f"Conflicts: {summary.get('conflict_events', 0)} | "
- f"Threats: {summary.get('cyber_threats', 0)} | "
- f"Quakes: {summary.get('earthquakes', 0)}")
-
-
-@report.command(name="threat")
-@click.option("--output-dir", "-o", default=None, help="Output directory")
-def report_threat(output_dir: str | None) -> None:
- """Generate threat landscape report (HTML)."""
- console.print("[bold]Generating threat landscape...[/bold]")
- result = _run(report_gen.generate_threat_landscape(output_dir=output_dir))
- console.print(f"[green]Report saved:[/green] {result.get('file_path', '?')}")
-
-
-@report.command(name="market")
-@click.option("--output-dir", "-o", default=None, help="Output directory")
-def report_market(output_dir: str | None) -> None:
- """Generate market overview report (HTML)."""
- console.print("[bold]Generating market overview...[/bold]")
- result = _run(report_gen.generate_market_overview(output_dir=output_dir))
- console.print(f"[green]Report saved:[/green] {result.get('file_path', '?')}")
-
-
-@report.command(name="dossier")
-@click.argument("country_code")
-@click.option("--output-dir", "-o", default=None, help="Output directory")
-def report_dossier(country_code: str, output_dir: str | None) -> None:
- """Generate country dossier report (HTML)."""
- console.print(f"[bold]Generating dossier for {country_code}...[/bold]")
- result = _run(report_gen.generate_country_dossier(
- country_code=country_code, output_dir=output_dir,
- ))
- console.print(f"[green]Report saved:[/green] {result.get('file_path', '?')}")
# ---------------------------------------------------------------------------
diff --git a/src/world_intel_mcp/dashboard/app.py b/src/world_intel_mcp/dashboard/app.py
index 7e53822..03a6274 100644
--- a/src/world_intel_mcp/dashboard/app.py
+++ b/src/world_intel_mcp/dashboard/app.py
@@ -52,6 +52,7 @@ from world_intel_mcp.analysis.posture import fetch_strategic_posture
from world_intel_mcp.analysis.exposure import fetch_population_exposure
from world_intel_mcp.analysis.situation import fetch_situation_brief
from world_intel_mcp.sources.fleet import fetch_fleet_report
+from world_intel_mcp.sources.usni_fleet import fetch_usni_fleet
from world_intel_mcp.config.countries import INTEL_HOTSPOTS, STRATEGIC_WATERWAYS
from world_intel_mcp.config.geospatial import MILITARY_BASES, STRATEGIC_PORTS, PIPELINES, NUCLEAR_FACILITIES
from world_intel_mcp.sources.infrastructure import CABLE_CORRIDORS
@@ -120,6 +121,7 @@ async def _fetch_overview() -> dict:
"service_status": service_status.fetch_service_status(fetcher),
"strategic_posture": fetch_strategic_posture(fetcher),
"fleet_report": fetch_fleet_report(fetcher),
+ "usni_fleet": fetch_usni_fleet(fetcher),
"population_exposure": fetch_population_exposure(fetcher),
"domestic_flights": aviation.fetch_domestic_flights(fetcher),
"traffic_flow": traffic.fetch_traffic_flow(fetcher),
@@ -205,6 +207,7 @@ async def _fetch_overview() -> dict:
# Attach source health + timestamp
result["source_health"] = _breaker.status() if _breaker else {}
result["cache_stats"] = _cache.stats() if _cache else {}
+ result["cache_freshness"] = _cache.freshness() if _cache else {}
result["timestamp"] = datetime.now(timezone.utc).isoformat()
return result
@@ -281,51 +284,10 @@ async def api_health(request):
async def api_report_pdf(request):
- """Generate a PDF daily brief report.
-
- Renders the daily_brief.html template with live data, then converts
- to PDF via weasyprint. Requires ``pip install world-intel-mcp[pdf]``.
- """
- try:
- from weasyprint import HTML as WeasyHTML
- except ImportError:
- return JSONResponse(
- {"error": "weasyprint not installed — run: pip install world-intel-mcp[pdf]"},
- status_code=501,
- )
-
- from world_intel_mcp.reports.html_report import render_template
-
- data = await _fetch_overview()
-
- context = {
- "title": "Daily Intelligence Brief",
- "generated_at": data.get("timestamp", ""),
- "market_quotes": data.get("market_quotes", {}),
- "crypto_quotes": data.get("crypto_quotes", {}),
- "macro_signals": data.get("macro_signals", {}),
- "earthquakes": data.get("earthquakes", {}),
- "cyber_threats": data.get("cyber_threats", {}),
- "news_feed": data.get("news_feed", {}),
- "military_flights": data.get("military_flights", {}),
- "internet_outages": data.get("internet_outages", {}),
- "climate_anomalies": data.get("climate_anomalies", {}),
- "displacement": data.get("displacement", {}),
- "risk_scores": data.get("risk_scores", {}),
- "alert_digest": data.get("alert_digest", {}),
- }
-
- html_str = render_template("daily_brief.html", context)
- pdf_bytes = WeasyHTML(string=html_str).write_pdf()
-
- now_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
- return Response(
- content=pdf_bytes,
- media_type="application/pdf",
- headers={
- "Content-Disposition": f'attachment; filename="intel-brief-{now_str}.pdf"',
- "Access-Control-Allow-Origin": "*",
- },
+ """PDF report generation (removed — use the live dashboard instead)."""
+ return JSONResponse(
+ {"error": "PDF reports removed — use the live dashboard at /"},
+ status_code=410,
)
diff --git a/src/world_intel_mcp/dashboard/index.html b/src/world_intel_mcp/dashboard/index.html
index 2ec5ad3..32d44a9 100644
--- a/src/world_intel_mcp/dashboard/index.html
+++ b/src/world_intel_mcp/dashboard/index.html
@@ -2461,6 +2461,49 @@ function updateDrawer(data) {
});
}
+ // ── USNI FLEET TRACKER ──
+ if (data.usni_fleet && !data.usni_fleet.error && data.usni_fleet.ship_count > 0) {
+ var uf = data.usni_fleet;
+ h += '
USNI FLEET TRACKER
';
+ h += '
' + esc(uf.report_title || '') + '
';
+ if (uf.force_totals && uf.force_totals.battle_force) {
+ var bf = uf.force_totals.battle_force;
+ var dep = uf.force_totals.deployed || {};
+ var uw = uf.force_totals.underway || {};
+ h += '
';
+ h += '
' + bf.total + '
Battle Force
';
+ h += '
' + (dep.total || '?') + '
Deployed
';
+ h += '
' + (uw.total || '?') + '
Underway
';
+ h += '
';
+ }
+ if (uf.region_breakdown) {
+ var regions = Object.entries(uf.region_breakdown).sort(function(a,b){return b[1]-a[1];});
+ regions.forEach(function(r) {
+ h += '
- {% if val is number %}
- {% if val >= 1e9 %}{{ "%.2f"|format(val / 1e9) }}B
- {% elif val >= 1e6 %}{{ "%.2f"|format(val / 1e6) }}M
- {% else %}{{ "%.4f"|format(val) if val < 1 and val > -1 else "%.2f"|format(val) }}{% endif %}
- {% elif val is not none %}{{ val }}
- {% else %}N/A{% endif %}
-