You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add an mcp-ui-widget fresh-ui registry island that renders ui:// MCP-UI resources in a themed, sandboxed iframe and remounts cleanly on theme change.
Context
Part of epic #238 · cluster fresh-ui · wave v1 · depends-on FB0, FA3.
This slice sits at the top of the fresh-ui plane's DAG: it consumes FB0's ai collection registration and FA3's ui:// origin/server handler to ship the actual consumer-facing widget. It cannot land before either, since there is no collection to register into and no origin to point the iframe at.
Problem / motivation
eis-chat renders MCP-UI resources today via a hand-rolled iframe with no sandbox hardening, no theme propagation, and no defined remount contract, so a theme switch leaves a stale iframe showing the previous theme's injected styles (or, worse, a half-updated DOM). NetScript has no registry item at all for consuming ui:// resources; fresh-ui's generative-UI story is incomplete without a themed, sandboxed widget that the renderer can hand a resource URL to and trust it will behave consistently across theme changes.
Scope
Ships
packages/fresh-ui/registry/islands/McpUiWidget.tsx — Fresh island rendering an <iframe> against a caller-supplied ui://-resolved src (the FA3-owned origin), with a restrictive sandbox attribute (allow-scripts only; no allow-same-origin).
Keyed remount: the iframe is keyed on the active theme value so a theme change forces a full unmount/remount instead of reusing a stale iframe document.
registry.manifest.ts: new registry item mcp-ui-widget (kind: 'island', layer: 3, tags ['ai', 'mcp-ui', 'iframe'], registryDependencies: ['theme-seed']), appended to the ai collection's items list (the collection itself is created by FB0).
Out of scope
The ui:// server handler / origin that actually serves MCP-UI resources — owned by FA3.
Creating the ai collection and registering the 7 chat primitives — owned by FB0 (hard prerequisite for this slice).
Any postMessage/RPC bridge between host app and iframe content beyond the iframe boundary itself — not specified in this slice; flag as a follow-on if the widget needs bidirectional messaging.
Public surface
New file packages/fresh-ui/registry/islands/McpUiWidget.tsx exporting a default island component, approximate props { src: string; theme: string; title?: string; sandbox?: string }.
mcp-ui-widget added to the ai collection's items array (collection object owned/created by FB0; this slice only appends its own item id).
No new @netscript/fresh-ui subpath exports — registry items are copy-scaffolded files, not module exports.
Acceptance & fitness gates
F-5: McpUiWidget.tsx carries the same JSDoc/@module convention as existing registry islands (e.g. Toast.tsx); item stays within the manifest's per-item field conventions.
F-6: @netscript/fresh-ui still publishes via deno task publish:dry-run WITHOUT --allow-slow-types after the new file and manifest entry land.
Keyed remount verified: changing the theme prop produces a distinct iframe mount (not a reused DOM node retaining the prior theme's injected content).
Sandbox attribute is present and restrictive on every render path (allow-scripts without allow-same-origin), and src only ever resolves to the FA3-owned origin, never a same-origin app route.
deno task check / lint pass on packages/fresh-ui with the new file and manifest entry included.
Dependencies
Depends on FB0, FA3 (GitHub numbers tracked in the #238 DAG checklist). FB0 must land first to create the ai collection this slice appends into; FA3 must land first to provide the ui:// origin this widget's iframe points at.
Add an
mcp-ui-widgetfresh-ui registry island that rendersui://MCP-UI resources in a themed, sandboxed iframe and remounts cleanly on theme change.Context
Part of epic #238 · cluster fresh-ui · wave v1 · depends-on FB0, FA3.
This slice sits at the top of the fresh-ui plane's DAG: it consumes FB0's
aicollection registration and FA3'sui://origin/server handler to ship the actual consumer-facing widget. It cannot land before either, since there is no collection to register into and no origin to point the iframe at.Problem / motivation
eis-chat renders MCP-UI resources today via a hand-rolled iframe with no sandbox hardening, no theme propagation, and no defined remount contract, so a theme switch leaves a stale iframe showing the previous theme's injected styles (or, worse, a half-updated DOM). NetScript has no registry item at all for consuming
ui://resources; fresh-ui's generative-UI story is incomplete without a themed, sandboxed widget that the renderer can hand a resource URL to and trust it will behave consistently across theme changes.Scope
Ships
packages/fresh-ui/registry/islands/McpUiWidget.tsx— Fresh island rendering an<iframe>against a caller-suppliedui://-resolved src (the FA3-owned origin), with a restrictivesandboxattribute (allow-scriptsonly; noallow-same-origin).registry.manifest.ts: new registry itemmcp-ui-widget(kind: 'island',layer: 3, tags['ai', 'mcp-ui', 'iframe'],registryDependencies: ['theme-seed']), appended to theaicollection'sitemslist (the collection itself is created by FB0).Out of scope
ui://server handler / origin that actually serves MCP-UI resources — owned by FA3.aicollection and registering the 7 chat primitives — owned by FB0 (hard prerequisite for this slice).Public surface
packages/fresh-ui/registry/islands/McpUiWidget.tsxexporting a default island component, approximate props{ src: string; theme: string; title?: string; sandbox?: string }.registry.manifest.tsentry:{ name: 'mcp-ui-widget', kind: 'island', layer: 3, files: [...], registryDependencies: ['theme-seed'], tags: ['ai', 'mcp-ui', 'iframe'] }.mcp-ui-widgetadded to theaicollection'sitemsarray (collection object owned/created by FB0; this slice only appends its own item id).@netscript/fresh-uisubpath exports — registry items are copy-scaffolded files, not module exports.Acceptance & fitness gates
McpUiWidget.tsxcarries the same JSDoc/@moduleconvention as existing registry islands (e.g.Toast.tsx); item stays within the manifest's per-item field conventions.@netscript/fresh-uistill publishes viadeno task publish:dry-runWITHOUT--allow-slow-typesafter the new file and manifest entry land.themeprop produces a distinct iframe mount (not a reused DOM node retaining the prior theme's injected content).allow-scriptswithoutallow-same-origin), andsrconly ever resolves to the FA3-owned origin, never a same-origin app route.deno task check/ lint pass onpackages/fresh-uiwith the new file and manifest entry included.Dependencies
Depends on FB0, FA3 (GitHub numbers tracked in the #238 DAG checklist). FB0 must land first to create the
aicollection this slice appends into; FA3 must land first to provide theui://origin this widget's iframe points at.Size
M
Part of #238