Tool-result contract
A widget-bearing tool declares its widget as aui://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.
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).