- Add /api/static endpoint for instant geospatial data on boot (158 items) - Add per-coroutine 45s timeout to prevent SSE first-frame blocking - Dismiss loading overlay after static fetch instead of waiting for SSE - Render 24 oil/gas/hydrogen pipelines as colored polylines on map - Fix theaters dict-vs-list bug in posture.py and fleet.py - Add exposure detail modal and color/label entries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What This Is
World Intelligence MCP Server — 68 tools across 27 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.
Commands
# Install
pip install -e ".[dev,dashboard]"
# Run MCP server (stdio mode)
world-intel-mcp
# Run tests (pytest-asyncio, auto mode)
pytest
pytest --cov=world_intel_mcp
pytest src/world_intel_mcp/tests/test_sources.py::test_fetch_market_quotes -v # single test
# 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)
intel-dashboard --port 8501
Architecture
Three consumers share the same source modules and infrastructure stack:
server.py (MCP stdio) ─┐
cli.py (Click CLI) ├─> sources/*.py ─> Fetcher ─> CircuitBreaker ─> Cache (SQLite)
dashboard/app.py (SSE) ─┘ │
~/.cache/world-intel-mcp/cache.db
Infrastructure layer (fetcher.py, cache.py, circuit_breaker.py):
Fetcher: Centralized async HTTP client (httpx). All external calls go throughget_json(),get_text(), orget_xml(). Handles retries (2 max), per-source rate limiting, and stale-data fallback (never returns blank if old data exists).CircuitBreaker: Per-source tracking. 3 consecutive failures trips the breaker for 5 minutes. Each RSS feed gets its own breaker (rss:bbc_world).Cache: SQLite WAL-mode TTL cache.get()returns live data,get_stale()returns expired data for fallback.
Source modules (sources/*.py): Each module exports async def fetch_*(fetcher: Fetcher, **kwargs) -> dict. Pure data fetching — no MCP awareness. 25 modules covering markets, seismology, military, cyber, health, etc.
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.
Static config (config/*.py): Curated datasets — 22 intel hotspots, 70+ military bases, 40 ports, 24 pipelines, 24 nuclear facilities, 105 major cities, 28 world leaders, 36 APT groups.
Adding a New Tool
- Create
sources/your_source.pywithasync def fetch_your_data(fetcher: Fetcher, **kwargs) -> dict - Use
fetcher.get_json(url, source="your-source", cache_key=..., cache_ttl=300)— this gives you caching, retries, circuit breaking, and rate limiting automatically - In
server.py: import the module, add aTool(...)to theTOOLSlist, add acaseto_dispatch() - Optionally add to
dashboard/app.py(SSE endpoint) andcli.py(Click command) - Add tests using
respxto mock HTTP (seetests/test_sources.pyfor pattern)
Key Patterns
- Source name string: The
sourceparameter infetcher.get_json()identifies the API for circuit breaking and rate limiting. Must match entries in_SOURCE_RATE_LIMITSif rate-limited (e.g.,"yahoo-finance","coingecko","adsblol"). - Tool dispatch:
server.pyuses Pythonmatch/caseto route tool names to source functions. Tool names followintel_*convention. - All source functions take
fetcheras first arg — never construct your own httpx client. - Dashboard SSE:
dashboard/app.pyfetches all domains in parallel viaasyncio.gather(), streams updates every 30 seconds. - Tests strip proxy env vars automatically via
conftest.pyfixture (prevents SOCKS proxy interference).
Environment Variables
Only these unlock additional data sources (everything else works unauthenticated):
ACLED_ACCESS_TOKEN— conflict eventsNASA_FIRMS_API_KEY— satellite wildfire dataEIA_API_KEY— energy pricesCLOUDFLARE_API_TOKEN— internet outage dataFRED_API_KEY— macro economic dataOPENSKY_CLIENT_ID/OPENSKY_CLIENT_SECRET— military flight fallback
Testing
Tests use respx to mock httpx responses. Fixtures in conftest.py provide cache (tmp_path SQLite) and fetcher (with clean breaker). Tests are async (pytest-asyncio in auto mode). Proxy env vars are stripped automatically.