io.modelcontextprotocol/ui extension. The current fleet ships MCP Apps: ui:// HTML resources that an MCP Apps host can render inline after a linked tool call.
This page is the source-of-truth guide for the interactive surface. Use it with the MCP Server overview for auth, quota, transport, and general JSON-RPC behavior.
MCP Apps render WorldMonitor UI inside an MCP host after a hosted tool call. WebMCP instead lets a browser agent operate the existing WorldMonitor website in its current tab. WebMCP is not an MCP App and does not replace the hosted MCP server behind these resources.
Contract
Three discovery signals must stay aligned:
Fleet
The compact Country Brief view accepts the original response and supported object projections. Retained news digest coverage shows a neutral notice without claiming that the assessment used retained grounding. Reported snapshot age and a valid UTC refresh-attempt time appear only when supplied. Missing or malformed coverage makes no freshness claim. Replacing a result clears prior paragraphs, evidence, source links, generation time and retained notice. Hosts advertise
country-brief-v3.html; country-brief-v2.html and the original country-brief.html remain private read aliases until older installed metadata is retired. Ordinary country asks still open the full country view.
Country Risk v2 preserves supplied original and projected objects, including nested CII components and upstream availability. Missing or malformed advisory values remain unknown; an explicit empty native string still means no advisory. Result replacement clears prior risk details. The original ui://worldmonitor/country-risk.html remains a private read alias for installed metadata and can be removed when that metadata is retired.
The original ui://worldmonitor/prediction-markets.html and previous ui://worldmonitor/prediction-markets-v2.html remain private read aliases. Refresh installed connection metadata and open a new card to load v3. An existing cached card keeps its old HTML. Projections that omit the contract data cannot restore omitted details. Empty returned categories do not prove complete coverage of upstream venues.
Runtime Flow
- The host calls
initializeonhttps://worldmonitor.app/mcp. - WorldMonitor returns the normal MCP capabilities plus
capabilities.extensions["io.modelcontextprotocol/ui"]. - The host calls
tools/list. UI-linked tools carry_meta.ui.resourceUriand the deprecated flat_meta["ui/resourceUri"]alias. - The host calls
resources/listand sees theui://app resources. Each UI entry includesmimeType: text/html;profile=mcp-appand_meta.ui.csp. - The host calls
resources/readfor the chosenui://URI. This read is public and quota-exempt because it returns only a static, data-free template. - The host performs the normal authenticated
tools/callfor the linked tool. This is the only step that fetches live data and consumes any applicable quota. - The host embeds the returned HTML in a sandboxed iframe and exchanges MCP Apps messages:
Forecast List And Original Cases
For paid OAuth users,get_forecast_predictions opens a compact list and returns one signed panelRequest. The opening consumes one daily panel allocation. The list retains original IDs, generation, source notices and unknown odds. Domain and region filters use the loaded list.
Opening a case analysis calls get_forecast_case through the originating host with forecast_id, the exact list generated_at, and the same panel_request token. The read returns one unchanged original case from that generation. It uses the existing bounded panel read allowance and consumes no additional daily allocation. Successful details are reused when filtering or reopening. The host must support server tool calls; unavailable capability or source, a changed generation, and an oversized individual case are shown explicitly. Retry is manual and source recovery is not cached as a successful case.
Ordinary API-key calls to get_forecast_predictions retain their full-result contract and accounting. The case reader requires a valid forecast admission; it is not an arbitrary cache reader. forecasts.html remains a read alias for saved connections. The saved forecasts-v3.html and forecasts-v2.html resources also remain public, quota-free read aliases. Refresh tool metadata to discover forecasts-v4.html after deployment.
Original Active Theaters
The Load active theaters action callsget_forecast_theaters through the host with the same signed forecast panel_request. It reads only the latest original simulation summary. The source run and time are independent of the forecast list generation; the time does not establish freshness. Local expansion preserves every published path, actor, optional actor role, reaction, stabilizer and invalidator.
The reader shares the opening allocation and its 64 uncached-read budget. Complete validated snapshots and explicit no-eligible empty outcomes are reused. Partial, failed, missing, processing and unknown outcomes remain distinct and can be retried manually under the same admission. Original evidence is retained during a failed retry. No run selector, simulation trigger or private artifact is exposed. Malformed or oversized summaries report unavailable instead of truncating evidence.
Resource Reads And Quota
resources/list exposes concrete public resources, including all ui:// templates. resources/templates/list exposes parameterised data resources.
All methods still count toward the 60/minute per-key, per-user, or anonymous-IP rate limiter.
Conflict Events Accounting
On Pro and Pro Business,get_conflict_events opens one paid Conflict Events allocation. Country, fatality and limit filters and repeated opens reuse it within five minutes. Use the returned panelRequest.token as panel_request for bounded reads. Set refresh: true with a UUID request_id and omit panel_request for one new allocation; the same UUID retries it. API and free-account calls keep ordinary per-tool billing and reject these paid controls.
Each admission permits up to 64 uncached tool executions, with separate 64-per-minute uncached and cached-replay limits. One uncached execution reads five fixed Redis keys, or six when Iran events are enabled; these reads do not each spend an allocation. Identical successful filtered originals replay before summary or JMESPath presentation. An authorized receipt read includes current usage when confirmed; unknown usage omits the numeric notice.
Optional conflict_source.ucdp copies only correctly typed fetchedAt, candidateVersion, candidateComplete and annualFailedPages from already-read UCDP metadata. Missing fields stay absent. Known partial, missing, malformed, stale or incompatible observations remain retryable under the receipt. Usable collections still honor their filters when another source is degraded. The observation does not establish atomic publication, complete unrest-provider coverage or independent CII/Iran freshness.
Natural Disasters Accounting
On Pro and Pro Business,get_natural_disasters opens one Natural Disasters allocation. Repeated opens and dataset, magnitude, activity and limit filters reuse that admission within five minutes. Use its returned panelRequest.token as panel_request for bounded reads. Explicit refresh needs refresh: true, a UUID request_id, and no reader token; the same UUID retries the refresh allocation. API and free-account callers keep ordinary per-tool charging and existing filter coercions, and reject the paid refresh controls.
Each uncached execution reads three fixed data keys and the existing seismology metadata key as one logical read within the 64-read admission. Exact successful filtered originals replay before summary or JMESPath only until the earliest observable source or EONET retention deadline. A new filter or unavailable, malformed, known degraded or unknown-clock observation can reread under the same allocation. Blocked regional source decisions remain readable but uncached, including zero-request preflight decisions. This does not establish complete provider coverage. The existing news token still permits only its exact hazard dataset list and limits 100, 20 or 1; it cannot use standalone magnitude or activity filters. Source data and internal deadlines do not add public metadata fields. Confirmed current usage accompanies authorized reads; an unknown counter omits the numeric notice.
View Security
The app shells are deliberately static and narrow:- Statically bundled widgets use self-contained HTML. The news, country and market bootstraps are also inline resources; they load current public interface assets from the origin allowed by their resource metadata. UI loading does not fetch market data.
- Payload labels use DOM construction and
textContent. Market charts use the website’s trusted SVG renderer with finite numeric series; payload markup is never inserted. - Links are admitted only through
http:orhttps:URL parsing and are rendered withrel="noopener noreferrer". - The shared shell reports size after initialization and after every render so hosts can resize the iframe.
- Soft-error envelopes (
_budget_exceeded,_jmespath_error, and top-level stringerror) render as visible error messages instead of blank success states. - Inline shells include a meta CSP with
default-src 'none', scoped inline script/style allowances, lockedform-actionandbase-uri, and a connect-src mirror of the_meta.ui.csp.connectDomainspolicy.
frame-ancestors inside a meta CSP is advisory only. Browsers enforce frame-ancestors only from an HTTP Content-Security-Policy response header. The meta directive remains in the shell for static scanners and intent documentation; do not treat it as browser-level clickjacking protection.
Adding A New MCP App
- Add the self-contained app shell under
api/mcp/ui/*-app.ts. - Reuse
buildAppHtml()fromapi/mcp/ui/shell.tsunless there is a protocol reason not to. - Add a canonical
*_UI_URIconstant and registry entry inapi/mcp/ui/registry.ts. - Set
_uiResourceUrion exactly one backing tool inapi/mcp/registry/rpc-tools.tsorapi/mcp/registry/cache-tools.ts. - Update
docs/mcp-apps.mdx, the short MCP overview, andpublic/.well-known/mcp/server-card.json. - Run
npm run inventory:facts:checkto validate the build-owned inventory snapshot. - Run
npm run docs:checkand the focused MCP resource/tool tests.
api/mcp/ui/registry.ts and the tool registries. It fails when:
docs/mcp-apps.mdx,docs/mcp-overview.mdx, orpublic/mcp-server.mdomits a linked tool orui://URI.public/.well-known/mcp/server-card.json.metadata.mcpAppsdrifts from the code-derived app list, spec version, or MIME type.docs/docs.jsondrops this page from navigation.
Source Files
News Intelligence panel admission
On Pro and Pro Business,get_news_intelligence opens one News Intelligence allocation. Repeated opens, filters, summary and JMESPath views reuse the same complete original within the admission window. The returned panelRequest.token is a closed panel_request for this tool only; news and country receipts cannot authorize it. Explicit refresh uses refresh: true, a UUID request_id, and no reader token. The same UUID retries that allocation. Authorized receipt reads query current usage without a new allocation; unknown usage omits the numeric notice. API and free-account calls retain ordinary per-tool charging and reject these paid controls.
Reuse uses the existing four dataset GETs and three metadata GETs. It expires at the earliest of the 30/45/60-minute metadata deadlines, the shared 60-minute Insights generation limit, the assessed GDELT content-age deadline, and admission expiry. Advisory publication time is validated, but this source graph has no independent advisory freshness assessment. Missing, degraded, malformed, old, future or unassessed sources remain retryable. Paid reads expose proven stale generation through stale and unassessed clocks through freshnessUnknown; source values remain intact. The cross-source producer permits an observed empty signal list; empty Insights and advisory bootstrap lists are not reusable. The 64-read limit counts uncached tool executions, not individual Redis GETs. This does not prove complete provider coverage.
Chokepoint panel admission
On Pro and Pro Business,get_chokepoint_status opens one signed chokepoints allocation. Repeated filters, summary and JMESPath views share that allocation. Complete effective requested source subsets reuse their uncapped originals; changing the normalized dataset subset or chokepoint selector can reacquire sources under the same allocation. Unknown-only dataset selectors use the full bundle. A keyed filter with no match retains the original map, so it cannot manufacture complete empty coverage. Sparse AIS, unavailable today counts and partial modeled flows remain visible and retryable.
Use the returned panelRequest.token as panel_request only for this tool. Explicit refresh: true requires a UUID request_id and no reader token; the same UUID retries that allocation. Authorized receipt reads report current usage without reserving another allocation; unknown usage omits the numeric notice. API and free-account calls retain per-tool accounting and reject these paid controls.
An uncached execution uses the existing six dataset GETs, six metadata GETs and one activation EXISTS command. The 64-read admission bound counts tool executions, not those 13 Redis commands. Reuse checks selected source shapes, availability, publication clocks and CN/HK critical content age, both after lookup and before cache storage. Partial, malformed, unassessed or expired originals are not cached as complete. Reference-year baselines and modeled flow publication dates do not prove current metered oil or fresh underlying history. The private wrapped cache remains 512 KiB; tool output remains 128 KiB. This admission change does not add website details, histories, warnings or provider reads.
World Brief panel admission
On Pro and Pro Business,get_world_brief opens one signed world-brief allocation. Repeated questions, compatibility geo_context changes and JMESPath views share that allocation. The RPC ignores summary; it does not summarize the brief. Reuse retains the accepted original prose, evidence and citation order before presentation. It ends at the earlier of admission expiry and generatedAt plus 60 minutes; replay recomputes the content age. This is a retained accepted generation, not an attestation that the latest producer attempt succeeded.
Use panelRequest.token as panel_request only for this tool. Explicit refresh: true requires a UUID request_id and no reader token; the same UUID retries that allocation. Authorized receipt reads query current usage without reserving another allocation. Unknown usage omits the numeric notice. API allowances retain per-tool billing, and free accounts retain the existing subscription denial.
Valid content aged 60 minutes to less than three hours remains available with stale: true but is not retained for fresh replay. Failed, missing, malformed and expired originals can retry under the same allocation. The 64-read bound counts uncached tool executions. Acquisition uses the existing authenticated bootstrap gateway path; it adds no provider call or producer-health transport. The private wrapped cache remains 512 KiB and tool output remains 64 KiB.
Direct country brief and risk reads
On Pro and Pro Business,get_country_brief and get_country_risk share the same country allocation as open_country_brief. Country aliases resolve to one ISO2 identity. Repeated reads and analytical framework variants share that allocation. Accepted originals replay separately for each tool and effective analysis before JMESPath presentation. A first bare risk read is not a replay of the full panel’s differently shaped risk section.
Use the returned panelRequest.token as panel_request for authorized reads of that country. Explicit refresh: true requires a UUID request_id and no reader token. It starts one new country allocation; the same UUID retries that allocation. Refresh rereads the sources but does not force AI generation or bypass the backend’s six-hour brief cache. API and free-account calls retain their ordinary behavior and reject these paid refresh controls.
The brief preserves the effective first 2,000 framework characters and exact allow_stale: true opt-in. Incomplete, retained or malformed grounding remains retryable under the same allocation. Risk reuse preserves genuine untracked and unknown values. The CII timestamp does not attest current advisory or sanctions freshness. The 64-read bound counts uncached tool executions, including each distinct analysis. Authorized receipt reads query the current daily counter without another allocation; unknown usage omits the numeric notice.
Observed country Signals
The country view’s Signals section combines independently loaded authorized military observations with boundedsignalsRaw samples. These samples can add earthquake, Internet outage, travel advisory and thermal values while preserving static country classification. Count labels do not establish full provider coverage. Source scope, original event/computation dates, unknown snapshot clocks, partial evidence and retained not-fresh observations appear in the view, structured model context and evidence export. Denied sources clear their counts, and changing country clears prior dynamic observations. Other dynamic Signals and aggregate severity/recent evidence remain unknown. This release does not claim deployed native acceptance or source-license clearance.