| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import { rpcError, rpcOk } from '../rpc'; |
| import { CHOKEPOINT_MONITOR_APP_HTML } from './chokepoint-monitor-app'; |
| import { COUNTRY_BRIEF_APP_HTML } from './country-brief-app'; |
| import { COUNTRY_RISK_APP_HTML } from './country-risk-app'; |
| import { MARKET_RADAR_APP_HTML } from './market-radar-app'; |
| import { buildUiMeta, UI_RESOURCE_MIME_TYPE as SHELL_UI_MIME_TYPE, type UiResourceMeta } from './shell'; |
| import { WORLD_BRIEF_APP_HTML } from './world-brief-app'; |
| import { NEWS_INTELLIGENCE_APP_HTML } from './news-intelligence-app'; |
| import { CONFLICT_EVENTS_APP_HTML } from './conflict-events-app'; |
| import { NATURAL_DISASTERS_APP_HTML } from './natural-disasters-app'; |
| import { PREDICTION_MARKETS_APP_HTML } from './prediction-markets-app'; |
| import { FORECASTS_APP_HTML } from './forecasts-app'; |
|
|
| |
| |
| export const UI_RESOURCE_MIME_TYPE = SHELL_UI_MIME_TYPE; |
|
|
| |
| |
| |
| export const COUNTRY_RISK_UI_URI = 'ui://worldmonitor/country-risk.html'; |
| export const WORLD_BRIEF_UI_URI = 'ui://worldmonitor/world-brief.html'; |
| export const COUNTRY_BRIEF_UI_URI = 'ui://worldmonitor/country-brief.html'; |
| export const MARKET_RADAR_UI_URI = 'ui://worldmonitor/market-radar.html'; |
| export const CHOKEPOINT_MONITOR_UI_URI = 'ui://worldmonitor/chokepoint-monitor.html'; |
| export const NEWS_INTELLIGENCE_UI_URI = 'ui://worldmonitor/news-intelligence.html'; |
| export const CONFLICT_EVENTS_UI_URI = 'ui://worldmonitor/conflict-events.html'; |
| export const NATURAL_DISASTERS_UI_URI = 'ui://worldmonitor/natural-disasters.html'; |
| export const PREDICTION_MARKETS_UI_URI = 'ui://worldmonitor/prediction-markets.html'; |
| export const FORECASTS_UI_URI = 'ui://worldmonitor/forecasts.html'; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export type { UiResourceMeta }; |
|
|
| interface UiResourceDef { |
| uri: string; |
| name: string; |
| description: string; |
| mimeType: string; |
| _meta: UiResourceMeta; |
| |
| html: string; |
| } |
|
|
| export const UI_RESOURCE_REGISTRY: UiResourceDef[] = [ |
| { |
| uri: COUNTRY_RISK_UI_URI, |
| name: 'Country Risk (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_country_risk: renders the Composite Instability Index (CII 0-100), the unrest/conflict/security/news component breakdown, travel-advisory level, and sanctions exposure. Linked from the get_country_risk tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: COUNTRY_RISK_APP_HTML, |
| }, |
| { |
| uri: WORLD_BRIEF_UI_URI, |
| name: 'World Brief (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_world_brief: renders the AI-summarised global intelligence brief as readable paragraphs, the grounding headlines, and the source feed articles. Linked from the get_world_brief tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: WORLD_BRIEF_APP_HTML, |
| }, |
| { |
| uri: COUNTRY_BRIEF_UI_URI, |
| name: 'Country Brief (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_country_brief: renders the AI-synthesised per-country intelligence brief as paragraphs, the analytical framework lens, and the grounding sources. Linked from the get_country_brief tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: COUNTRY_BRIEF_APP_HTML, |
| }, |
| { |
| uri: MARKET_RADAR_UI_URI, |
| name: 'Market Radar (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_market_data: renders the Fear & Greed composite plus per-asset-class quote tables (equities, commodities, crypto, Gulf, sectors) with signed, colour-coded change. Linked from the get_market_data tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: MARKET_RADAR_APP_HTML, |
| }, |
| { |
| uri: CHOKEPOINT_MONITOR_UI_URI, |
| name: 'Chokepoint Monitor (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_chokepoint_status: renders per-chokepoint rolling transit summaries (today\'s transit count, week-over-week change, tanker split) with a risk-level badge. Linked from the get_chokepoint_status tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: CHOKEPOINT_MONITOR_APP_HTML, |
| }, |
| { |
| uri: NEWS_INTELLIGENCE_UI_URI, |
| name: 'News Intelligence (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_news_intelligence: renders AI-classified top stories (title, category, alert flag, country, source) from WorldMonitor\'s intelligence layer. Linked from the get_news_intelligence tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: NEWS_INTELLIGENCE_APP_HTML, |
| }, |
| { |
| uri: CONFLICT_EVENTS_UI_URI, |
| name: 'Conflict Events (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_conflict_events: renders active armed-conflict events (belligerents, violence type, country, fatalities, date) from the UCDP feed. Linked from the get_conflict_events tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: CONFLICT_EVENTS_APP_HTML, |
| }, |
| { |
| uri: NATURAL_DISASTERS_UI_URI, |
| name: 'Natural Disasters (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_natural_disasters: groups recent earthquakes (USGS magnitude, place, time) and active wildfires (NASA FIRMS). Linked from the get_natural_disasters tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: NATURAL_DISASTERS_APP_HTML, |
| }, |
| { |
| uri: PREDICTION_MARKETS_UI_URI, |
| name: 'Prediction Markets (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_prediction_markets: renders active event-contract odds grouped by category (geopolitical, tech, finance) with a probability bar per market. Linked from the get_prediction_markets tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: PREDICTION_MARKETS_APP_HTML, |
| }, |
| { |
| uri: FORECASTS_UI_URI, |
| name: 'Forecasts (interactive)', |
| description: |
| 'Interactive in-conversation app shell for get_forecast_predictions: renders WorldMonitor\'s AI-generated geopolitical and economic forecasts as probability cards (title, domain, region). Linked from the get_forecast_predictions tool via _meta.ui.resourceUri; an MCP-Apps host renders it inline and streams the tool result in via postMessage. Static, data-free template β public and quota-exempt.', |
| mimeType: UI_RESOURCE_MIME_TYPE, |
| _meta: buildUiMeta(), |
| html: FORECASTS_APP_HTML, |
| }, |
| ]; |
|
|
| |
| const UI_RESOURCE_BY_URI = new Map(UI_RESOURCE_REGISTRY.map((r) => [r.uri, r])); |
|
|
| export function isUiResourceUri(uri: string): boolean { |
| return UI_RESOURCE_BY_URI.has(uri); |
| } |
|
|
| |
| |
| |
| export interface PublicUiResourceShape { |
| uri: string; |
| name: string; |
| description: string; |
| mimeType: string; |
| _meta: UiResourceMeta; |
| } |
|
|
| export const UI_RESOURCE_LIST_RESPONSE: PublicUiResourceShape[] = UI_RESOURCE_REGISTRY.map((r) => ({ |
| uri: r.uri, |
| name: r.name, |
| description: r.description, |
| mimeType: r.mimeType, |
| _meta: r._meta, |
| })); |
|
|
| |
| |
| |
| |
| export function buildUiResourceRead( |
| id: unknown, |
| uri: string, |
| corsHeaders: Record<string, string>, |
| ): Response { |
| const def = UI_RESOURCE_BY_URI.get(uri); |
| if (!def) { |
| |
| |
| return rpcError(id, -32602, `Unknown ui:// resource "${uri}".`, corsHeaders); |
| } |
| return rpcOk( |
| id, |
| { contents: [{ uri: def.uri, mimeType: def.mimeType, text: def.html, _meta: def._meta }] }, |
| corsHeaders, |
| ); |
| } |
|
|