Skip to main content
Many Semicola tools open an interactive page (a widget) next to the chat: the campaign receipt, the creative composer, the storefront’s Listing. They follow the MCP Apps convention, so any host that supports MCP Apps renders them.

Tool-result contract

A widget-bearing tool declares its widget as a ui://semicola/<view>/mcp-app.html resource (the tool catalog lists it as Opens widget). Its result carries:
  • short, model-facing text in content;
  • the widget’s data in structuredContent;
  • host-only data in _meta, which the model doesn’t see.
The host reads the ui:// resource with resources/read, renders it in a sandboxed iframe, and hands the tool result to it over the MCP Apps bridge. resources/list returns the live set of widgets; don’t hard-code a list, because it changes with the product. Widgets call back through the host with the same tools, so every write still goes through the tool’s confirmation rules (see Semi confirmations).

Widget HTML over REST

For a host that renders widgets without a live MCP client: Both need authentication. Pass the HTML to a sandboxed iframe as srcdoc. The response carries the widget’s content security policy in the x-mcp-app-csp header, which the host should apply, and cache-control: no-store. An unknown view returns 404 (“Unknown widget view.”). Treat the view name as opaque: use the one from the tool’s resource URI. Semicola’s own app renders widgets in an iframe sandboxed to allow-scripts allow-forms allow-downloads, with form-action 'none' so a form never submits anywhere.

Not available yet

  • Session-bound page capabilities and host-only page aliases (the Teach and Library pages’ private material tools).