# UAN-023: Inspector web host and clean-context Astro adoption

Date: 2026-10-03 UTC. Isolated public source base: `8a502b5` on `research` (macOS 27.0, build 26A425; Node 25.9.0; npm 11.12.1). This is a delegated clean-context agent using only public package docs, public example source, and official host docs. It is not an unrelated human trial. No canonical checkout was edited for these observations.

## Named MCP Apps web host

The official `@modelcontextprotocol/inspector@2.8.0` web Apps tab connected through real loopback Streamable HTTP to the packed E09 server. The Inspector's sandbox iframe rendered in headless Google Chrome 154.0.8037.95, driven with Playwright 1.56.1. The E09 project used `@modelcontextprotocol/server@2.3.0`, `@modelcontextprotocol/client@2.3.0`, and `@modelcontextprotocol/ext-apps@2.0.3`.

Reproduce after a normal repository `npm ci`:

~~~sh
npm run example:e09
npm install --no-save --package-lock=false --ignore-scripts --no-audit --no-fund playwright@1.56.1
node test/uan023-inspector-web.mjs
~~~

The browser script launches the Inspector with its web, sandbox, and App-origin listeners bound to `127.0.0.1`, disables automatic foreground opening, generates a fresh token without printing it, and uses the Inspector's documented deep link. It waits for `connected` and `data-app-status="ready"`, then enters the actual iframe. The initial tool result displayed `First Light (first-light)`. Submitting `blue-hour` from the view displayed `Blue Hour (blue-hour)`; submitting `blocked-album` displayed `The host denied this request.` The app's binding ran exactly twice, so the denied call did not execute it. There were three frames (Inspector, sandbox proxy, App), no page errors, and no App CSP console errors. This is a real named local host result, beyond the earlier in-memory AppBridge fixture and Inspector CLI metadata probe.

The first host attempt connected and called the E09 tool but left the view in `loading`. Headless Chrome showed a CSP-blocked `http://127.0.0.1:6485/view.js` request. Investigation found `template.replace(marker, replacementString)` expanded `$&` tokens in esbuild's minified bundle: the generated resource had 24 opening/closing script tags and 23 copied `src="./view.js"` references. The builder now replaces through a callback, checks for exactly one marker, and escapes any closing-script token in bundled JavaScript. The focused E09 resource assertion checks one inline module script, one closing tag, and zero external view references. After this fix, standalone E09 passed 3/3 and the real Inspector iframe passed.

[Inspector MCP App review recipe](https://github.com/modelcontextprotocol/inspector/blob/main/docs/mcp-app-review.md) and [Inspector web client contract](https://github.com/modelcontextprotocol/inspector/blob/main/clients/web/README.md) describe the deep link, iframe, and sandbox host used here.

## Fresh existing-Astro adoption

The agent followed [getting started](../getting-started.md), [static sites](../static-sites.md), [frameworks](../frameworks.md), and linked public E01/E02 example sources. Each before-state site was copied to a fresh temporary directory; no private planning instructions, private packages, credentials, or deployment were used. The local `0.0.0` package was installed from a tarball generated by `npm run example:e09`, since npmjs publication has not happened.

**E01 static Astro (Astro 7.3.5).** `npm ci` and the before-state build passed. The documented `createInitPlan` and `applyInitPlan` calls with `{ hosting: 'cloudflare', routeMode: 'sidecar', sidecarOrigin: 'http://127.0.0.1:8787' }` returned an applied plan. The detection accurately reported `hosting-unknown`; the explicit choice resolved it. The after-state build retained three static pages and the original data, pages, SVG, and CSS byte-for-byte. The init-generated browser entry only announces readiness. This proves the narrow documented init flow, not a registered capability or live sidecar.

The separate fully integrated public E01 example was exported with `npm run example:e01`. Its targeted fixture checks and three-page static build passed. A headless Chrome run initially exposed a real-browser failure hidden by simulated tests: the album form briefly displayed a result, then Astro ClientRouter navigated to `/albums/?slug=first-light` and cleared it. Adding Astro's documented `data-astro-reload` attribute to that one form let the application submit handler prevent navigation. Reproduction:

~~~sh
npm run example:e01
node test/uan023-browser-fallback.mjs
~~~

On Chrome 154.0.8037.95, `document.modelContext` was `undefined`. The page displayed the unavailable-agent fallback; human lookup returned `first-light`, returned `kind: missing` for an absent slug, and returned `blue-hour` after navigating About to Albums through ClientRouter. The URL stayed `/albums/` after form submissions, and page errors were empty. [Astro's ClientRouter form guidance](https://docs.astro.build/en/guides/view-transitions/#preventing-client-side-navigation) supports this form opt-out.

**E02 on-demand Astro (Astro 7.3.5, `@astrojs/node@11.1.6`).** The fresh before-state `npm ci`, build, and its six baseline tests passed. The public [E02 source](https://github.com/uppercut-labs/agent-native/blob/main/examples/e02-astro-on-demand-catalog/project/README.md) supplied the config, one registry/binding, HTTP/MCP endpoint files, browser entry, and live verification script. These files were copied into the existing site; then the public installation guide's exact MCP and Zod peers and the local package tarball were installed. The after-state Astro build and the copied public live HTTP/MCP verifier passed. The pre-existing ordinary JSON route still returned HTTP 200 for `night-bus-radio` and HTTP 404 for a missing slug. Seven unrelated source/data/asset files remained byte-identical.

The E02 integration required a source-guided intervention: the public guide links to working source but does not yet give a complete copy/edit sequence for a stranger's own project. The verification script also uses a local fixture bearer token from that public example. This is reproducibility evidence for the public example patterns, not independent design of a new site or production identity integration.

## Limits and remaining gates

Inspector web is a genuine local MCP Apps iframe host; no commercial host, remote deployment, consent dialog, external identity provider, or arbitrary third-party MCP server was checked. Chrome's default session did not expose native WebMCP, so the browser result proves the human fallback and no native browser-agent registration. E01's sidecar origin was a local planning choice, not a running Worker. E02 relied on the linked public after-state source. UAN-023's full acceptance and npm release matrix remain open.
