Skip to main content
Glama
nguyenminhduc9988

SITUROOM MCP Server

SITUROOM

The zero-backend global situation room — real-time earthquakes, conflicts, hazards and markets in one static page. No server. No API keys. No paywall.

License: MIT PRs Welcome Dependencies Build

SITUROOM dashboard — dark ops world map with live quakes, events, tension heat, headlines and markets

Live demo: https://nguyenminhduc9988.github.io/situroom/


Why

Most "world monitor" intel dashboards are hosted products: a big server fleet renders the picture, the scoring is a black box, and the useful parts (APIs, agent access) sit behind a paid key. SITUROOM is the opposite bet — everything a situation dashboard needs is available from free, keyless, CORS-friendly public APIs, so the entire product can be one static folder.

SITUROOM

Typical hosted intel dashboards

License

MIT, no commercial tier

AGPL + commercial-license upsell

Backend

none — static files

fleets of edge functions + Redis + relays

API / agent access

free local MCP server, included

paid API keys

Scoring

documented client-side formula (js/score.js) — recompute it in devtools

opaque, server-side

Offline

PWA + committed data snapshot fallback

online-only

Setup

open one URL, or python3 -m http.server

cloud deployment

Six free sources today, PRs for more welcome.

Related MCP server: publicfinance

Quick start

1. Just open ithttps://nguyenminhduc9988.github.io/situroom/

2. Run it locally (any static server works; no install, no build):

git clone https://github.com/nguyenminhduc9988/situroom
cd situroom
python3 -m http.server 8080
# open http://localhost:8080

3. Host your own — fork the repo, enable GitHub Pages (deploy from main, root). Done: it's static files.

Features

  • Canvas world map — vendored d3-geo projection, graticule, country hover, magnitude-scaled quake markers, category-colored natural events, tension heat blobs. Toggleable layers, pulse animations (disabled under prefers-reduced-motion).

  • Tension index — transparent per-country score over the current news window, top-10 bars colored green→amber→red. The formula is documented below and in the UI ("formula?" button).

    Tension index panel — ranked country bars

  • Headlines — conflict-flavored world news from GDELT (English sources by default, all-languages toggle in settings).

  • Quakes / Events / Tech panels — USGS earthquakes, NASA EONET natural events, Hacker News front page.

  • Markets ticker — BTC/ETH/SOL with 24h change, USD FX reference rates.

  • Status chips per source — LIVE / STALE (cached) / SNAPSHOT / ERROR, so you always know what you're looking at.

  • Watchlist — pin countries you care about to the top of the tension board.

  • Responsive — panels stack on narrow viewports; the six status chips collapse into one aggregate chip.

Data sources

All free, keyless, fetched directly from your browser (CORS-friendly). Attribution and thanks:

Source

Data

Refresh

USGS Earthquake Hazards Program

earthquakes, past 24h

5 min

NASA EONET

open natural events (wildfires, storms, volcanoes…)

10 min

GDELT Project DOC 2.0

conflict/military/sanctions/protest headlines, ~6h window

15 min

CoinGecko

BTC / ETH / SOL spot + 24h change

2 min

Frankfurter

USD→EUR/JPY/GBP/CNY reference rates

60 min

HN Algolia

Hacker News front page

10 min

Every source degrades independently: live fetch → last good response from localStorage (STALE) → committed capture in data/snapshot.json (SNAPSHOT) → ERROR chip. The dashboard never renders blank.

The tension index formula

No black box — the entire computation runs in your browser over the raw GDELT article list, in js/score.js:

  • volume(C) — articles published in country C or naming C (or a common alias) in the headline

  • severity(C) — mean headline keyword weight: 3 war/strike/attack/missile…, 2 sanctions/military/nuclear…, 1 protest/unrest/clashes…, floor 0.5

  • score(C) = 100 × norm(0.6·log1p(volume) + 0.4·severity) — the hottest country of the moment reads 100, everything else is relative

Honesty note: GDELT's article-list API doesn't expose its per-article tone field, so severity is a documented keyword proxy — cruder than GDELT tone, but fully auditable, which is the point. The full country/alias gazetteer and keyword table are plain data at the top of the file; the unit tests in test/score.test.js pin the behavior.

AI sitrep (optional, bring your own key)

Off by default and never required. If you point settings (gear icon) at any OpenAI-compatible endpoint — including a local Ollama at http://localhost:11434/v1 — an AI SITREP button appears that summarizes the current headlines + tension board into a 5-bullet brief. Your endpoint, key and model live only in your browser's localStorage and are sent nowhere except the endpoint you configured.

Settings dialog — BYOK endpoint, watchlist, language toggle

MCP server (agents get the feeds for free)

mcp/situroom_mcp.py is a zero-dependency Python 3.10+ stdio MCP server exposing the same feeds as tools: get_quakes, get_events, get_headlines, get_tension, get_markets — normalized to the web app's shapes, tension formula faithfully ported from js/score.js. Config snippets for Claude Desktop/Code and Cursor in mcp/README.md.

claude mcp add situroom -- python3 /path/to/situroom/mcp/situroom_mcp.py

Architecture

Vanilla ES modules. No framework, no build step, no npm install. The only third-party code is vendored and committed: d3 v7 + topojson-client (plus the world-atlas 110m topology) in vendor/, so the app runs with zero network access to any CDN.

index.html
├── css/app.css           dark ops theme (system fonts only)
├── js/app.js             boot, source registry, 60s scheduler, panels
│   ├── js/map.js         canvas map (offscreen-cached base + marker layer)
│   ├── js/score.js       tension index (pure, documented, tested)
│   ├── js/store.js       localStorage cache + settings
│   ├── js/brief.js       optional BYOK sitrep
│   └── js/sources/*.js   one module per feed: fetchX() + pure normalizeX()
├── sw.js                 PWA: precached shell, network-first API fallback
└── data/snapshot.json    committed real capture — the floor of the chain:

      live fetch ──fail──▶ localStorage last-good ──miss──▶ committed snapshot ──miss──▶ ERROR chip
        (LIVE)                    (STALE)                        (SNAPSHOT)

Run the tests (pure functions only, fully offline):

node --test test/*.test.js    # or: npm test — 44 tests, zero dependencies

Contributing

PRs welcome — especially new free, keyless, CORS-friendly data sources. The bar for a source module: one file in js/sources/, export a pure normalizeX() (unit-tested against a captured payload in data/snapshot.json) and a fetchX() that returns null on any failure. Open an issue first for anything bigger than a source or a fix.

License

MIT © 2026 Minh-Duc Nguyen


Built by BigWinner.work — AI Tools & Consulting

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables fetching top headlines and searching news archives from NewsAPI.org, allowing AI agents to access current and historical news data.
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI agents to access SEC EDGAR filings, US Treasury rates, BLS labor statistics, and economic indicators without API keys.
    6
    44 npm
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Exposes live earth-science data (e.g., earthquakes from USGS) as tools for MCP-compatible AI agents, enabling them to fetch and reason about real-time geophysical events.
    1
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides AI agents with read-only access to various public data sources (web, YouTube, RSS, GitHub, V2EX, Bilibili, and semantic search) without requiring any login credentials or API keys.
    13
    MIT