mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
feat(intelligence): GetCountryRisk RPC + MCP tool for per-country risk scores (#2502)
* feat(intelligence): GetCountryRisk RPC for per-country risk intelligence Adds a new fast Redis-read RPC that consolidates CII score, travel advisory level, and OFAC sanctions exposure into a single per-country response. Replaces the need to call GetRiskScores (all-countries) and filter client-side. Wired to MCP as get_country_risk tool (no LLM, ~200ms, good for agent screening). - proto/intelligence/v1/get_country_risk.proto (new) - server/intelligence/v1/get-country-risk.ts (reads 3 pre-seeded Redis keys) - gateway.ts: slow cache tier - api/mcp.ts: RpcToolDef with 8s timeout - tests/mcp.test.mjs: update tool count 27→28 * fix(intelligence): upstream-unavailable signal, fetchedAt from CII, drop redundant catch P1: return upstreamUnavailable:true when all Redis reads are null — prevents CDN from caching false-negative sanctions/risk responses during Redis outages. P2: fetchedAt now uses cii.computedAt (actual data age) instead of request time. P2: removed redundant .catch(() => null) — getCachedJson already swallows errors. * fix(intelligence): accurate OFAC counts and country names for GetCountryRisk P1: sanctions:pressure:v1.countries is a top-12 slice — switch to a new sanctions:country-counts:v1 key (ISO2→count across ALL 40K+ OFAC entries). Written by seed-sanctions-pressure.mjs in afterPublish alongside entity index. P1: trigger upstreamUnavailable:true when sanctions key alone is missing, preventing false-negative sanctionsActive:false from being cached by CDN. P2: advisory seeder now writes byCountryName (ISO2→display name) derived from country-names.json reverse map. Handler uses it as fallback so countries outside TIER1_COUNTRIES (TH, CO, BD, IT...) get proper names.
This commit is contained in:
23
api/mcp.ts
23
api/mcp.ts
@@ -348,6 +348,29 @@ const TOOL_REGISTRY: ToolDef[] = [
|
||||
return res.json();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'get_country_risk',
|
||||
description: 'Structured risk intelligence for a specific country: Composite Instability Index (CII) score 0-100, component breakdown (unrest/conflict/security/news), travel advisory level, and OFAC sanctions exposure. Fast Redis read — no LLM. Use for quantitative risk screening or to answer "how risky is X right now?"',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
country_code: { type: 'string', description: 'ISO 3166-1 alpha-2 country code, e.g. "RU", "IR", "CN", "UA"' },
|
||||
},
|
||||
required: ['country_code'],
|
||||
},
|
||||
_execute: async (params, base, apiKey) => {
|
||||
const code = String(params.country_code ?? '').toUpperCase().slice(0, 2);
|
||||
const res = await fetch(
|
||||
`${base}/api/intelligence/v1/get-country-risk?country_code=${encodeURIComponent(code)}`,
|
||||
{
|
||||
headers: { 'X-WorldMonitor-Key': apiKey, 'User-Agent': 'worldmonitor-mcp-edge/1.0' },
|
||||
signal: AbortSignal.timeout(8_000),
|
||||
},
|
||||
);
|
||||
if (!res.ok) throw new Error(`get-country-risk HTTP ${res.status}`);
|
||||
return res.json();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'get_airspace',
|
||||
description: 'Live ADS-B aircraft over a country. Returns civilian flights (OpenSky) and identified military aircraft with callsigns, positions, altitudes, and headings. Answers questions like "how many planes are over the UAE right now?" or "are there military aircraft over Taiwan?"',
|
||||
|
||||
Reference in New Issue
Block a user