Skip to main content
The MCP App HTML endpoint serves the same built widgets that are exposed through MCP resources/read, but over authenticated REST for hosts that do not have a live MCP client. Most widgets are single self-contained HTML files; see Shared-runtime shells for widgets that load their code from separate files.

Endpoint

Use this endpoint when an Apostra-hosted UI needs to render a ui://agentic-api/.../mcp-app.html widget in a sandboxed iframe. The response body is HTML text and should be passed to the iframe as srcdoc; hosts provide widget data over the MCP Apps bridge after the iframe initializes.

Path parameters

view must match a registered MCP App resource. MCP clients discover the live set through resources/list; use the slug between ui://agentic-api/ and /mcp-app.html. A REST-only host should use the resource URI supplied by Apostra tool or rendering contract and treat the slug as opaque. Do not hard-code a short “supported views” list: the registered set evolves with the product and includes compatibility aliases for persisted messages.

Tool-result contract

A conformant MCP host normally does not call this endpoint directly. A widget-bearing tool declares or returns _meta.ui.resourceUri, and its standard tool result carries:
  • compact model-facing text in content;
  • the app payload in structuredContent;
  • optional host/app-only data in _meta.
The host reads the referenced ui:// resource, renders it in a sandboxed iframe, and delivers the tool result over the MCP Apps bridge. The REST HTML endpoint exists for authenticated Apostra-hosted surfaces that need the same built resource without a live MCP resource client.

Page capability and tool bridge

An interactive Page may receive a session-bound capability from open_page. The capability is returned in app-only metadata and delivered to the Page over the app bridge; it is not model-visible. The host routes Page calls through its scoped proxy and must not expose Page aliases as general-purpose tools. The Teach Page uses the host-only teach_search_materials, teach_get_material, teach_save_material, and teach_renew_capability aliases for Material listing and exact reads, seller-private URL and file additions, upload finalization, Material-owned candidate decisions, and capability renewal. MCP clients continue to use the public search, get, and save_material tools. The bridge does not permit generic Material writes or return source-access or visual-preview URLs. Private-file uploads receive an expiring write URL only for the browser PUT; the Page keeps that URL out of rendered state and model context, then finalizes the reservation through the canonical Material lifecycle. Teach accepts PDF, PowerPoint (.pptx), Excel (.xlsx), CSV, PNG, JPEG, GIF, and WebP files up to 100 MB. The Library Page uses the host-only library_search_materials, library_get_material, library_search_requests, library_search_rfps, library_get_rfp_turn, library_open_proposal_pass, library_save_material, library_save_request, library_save_rfp, and library_renew_capability aliases for document and unit browsing, exact reads pinned to a source revision, request and response listing, opening the authorised Proposal Pass for a response, uploads, request closure, and capability renewal. MCP clients continue to use the public search, get, save_material, save_library_request, save_rfp, and open_proposal_pass tools. A missing, expired, wrong-session, or wrong-resource Page capability returns ACCESS_DENIED, as does any call shape outside the Page allowlist. Teach also returns ACCESS_DENIED rather than rejecting a destination-owned candidate. Teach presents it as a handoff; direct MCP clients record rejection with public save_material, while acceptance stays with the candidate’s canonical typed owner.

Response

Successful responses return the built HTML as text:
The response is intentionally cacheable only by the authenticated caller. Hosts should still apply their own iframe sandbox and bridge-level allowlists before sending data or actions into the widget.

Shared-runtime shells

Some widgets can be served as a shared-runtime shell: a short HTML document whose scripts, styles and fonts load from content-hashed files on the Apostra API origin instead of being inlined. The libraries every widget uses are split into a separate file, so a browser downloads them once and reuses them across widgets and visits. This is currently a limited trial on selected accounts; other accounts receive single-file widgets. When a shell is served this way, the API origin it loads from is added to the resourceDomains the widget declares (the _meta.ui.csp returned by resources/read, and the x-mcp-app-csp header on this endpoint). Hosts that follow the MCP Apps specification map resourceDomains to the frame’s allowed script, style and font sources, so no other host configuration is needed. The files are served without authentication:
They contain only static widget code, styles and fonts, never customer data. File names change whenever their content changes, so they can be cached indefinitely. A file that does not exist, or a widget that is not served as a shared-runtime shell, returns 404 NOT_FOUND. Hosts should not construct these URLs themselves; use the ones in the shell.

Errors

Example