io.modelcontextprotocol/ui extension. The current fleet ships 10 MCP Apps: self-contained 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.
Contract
Three discovery signals must stay aligned:
Fleet
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:
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.
View Security
The app shells are deliberately static and narrow:- They are self-contained HTML: no external scripts, styles, images, iframes, fonts, or network fetches.
- Rendering uses DOM construction and
textContent, neverinnerHTML. - 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. - The HTML includes 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 docs:statsto refreshdocs/generated/stats.json. - 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.- The documented MCP tool count drifts from the server-card tool inventory.
