Problem
Today, webmcp-proxy registers MCP tools on navigator.modelContext but the host website remains completely static — there is no visual feedback when a browsing agent invokes a tool. The page looks the same before and after a tool call.
Additionally, if the connected MCP server is an MCP App (i.e. it exposes a render-ui tool and a ui:// HTML resource), the proxy discards the UI part entirely and only forwards tool calls. The rich interactive interface the server provides goes unused.
Proposal
When the remote MCP server is an MCP App, replace the host page content with the app's UI so tool executions produce live visual updates in the browser.
Concrete ideas
-
Detect MCP App capabilities at connect time
After tools/list, check whether the server exposes a render-ui tool and/or a ui:// resource. If it does, treat the server as an MCP App rather than a plain tool server.
-
Fetch and inject the app HTML
Read the ui:// resource (a self-contained HTML bundle) and inject it into the current page — either by replacing document.body contents or by mounting a full-viewport <iframe srcdoc="...">. The iframe approach sandboxes the app while still living in the same tab.
-
Bridge postMessage between injected UI and MCP client
The injected app uses useJsonRenderApp() which communicates via postMessage. The proxy would act as the message relay: forward render-ui specs from the MCP server to the iframe, and route user-initiated actions back through callTool.
-
Graceful fallback
If the server is not an MCP App (no render-ui / ui://), keep the current behavior unchanged — register tools silently alongside the existing page.
High-level flow
Browser tab
┌──────────────────────────────────────────────┐
│ Injected MCP App UI (iframe / srcdoc) │
│ ← receives render-ui specs via postMessage │
│ → sends user actions back via postMessage │
└──────────────┬───────────────────────────────┘
│ postMessage bridge
┌──────────────▼───────────────────────────────┐
│ webmcp-proxy (in host page) │
│ MCP client ⟷ remote MCP App server │
│ Also registers tools on modelContext │
└──────────────────────────────────────────────┘
API surface (strawman)
const proxy = await createWebMcpProxy({
url: "https://mcp.example.com/mcp",
// New option: inject the MCP App UI into the page when available
injectAppUI: true, // default: false (backward-compatible)
appContainer: "#root", // CSS selector or element to mount into
});
Benefits
- Live feedback: tool results immediately reflect in the UI the user is looking at.
- Reuse existing MCP App UIs: server authors already build rich interfaces — this lets websites surface them to browsing agents without any extra work.
- Progressive enhancement: plain MCP servers still work as before; MCP Apps get the upgraded experience automatically.
Problem
Today,
webmcp-proxyregisters MCP tools onnavigator.modelContextbut the host website remains completely static — there is no visual feedback when a browsing agent invokes a tool. The page looks the same before and after a tool call.Additionally, if the connected MCP server is an MCP App (i.e. it exposes a
render-uitool and aui://HTML resource), the proxy discards the UI part entirely and only forwards tool calls. The rich interactive interface the server provides goes unused.Proposal
When the remote MCP server is an MCP App, replace the host page content with the app's UI so tool executions produce live visual updates in the browser.
Concrete ideas
Detect MCP App capabilities at connect time
After
tools/list, check whether the server exposes arender-uitool and/or aui://resource. If it does, treat the server as an MCP App rather than a plain tool server.Fetch and inject the app HTML
Read the
ui://resource (a self-contained HTML bundle) and inject it into the current page — either by replacingdocument.bodycontents or by mounting a full-viewport<iframe srcdoc="...">. The iframe approach sandboxes the app while still living in the same tab.Bridge
postMessagebetween injected UI and MCP clientThe injected app uses
useJsonRenderApp()which communicates viapostMessage. The proxy would act as the message relay: forwardrender-uispecs from the MCP server to the iframe, and route user-initiated actions back throughcallTool.Graceful fallback
If the server is not an MCP App (no
render-ui/ui://), keep the current behavior unchanged — register tools silently alongside the existing page.High-level flow
API surface (strawman)
Benefits