Aident AI

MCP App Not Rendering? Fix a Blank UI Step by Step
If an MCP tool succeeds but its app is blank, debug the path in this order: confirm the host supports MCP Apps, inspect the tool's ui:// resource link, read the HTML resource directly, render it in the official basic-host, verify the app bridge receives the tool result, and only then investigate the production host. This sequence separates a server problem from a UI bundle, bridge, security-policy, cache, or host-compatibility problem.
MCP Apps add interactive HTML to MCP tools. The server still owns the tool and its data; the host fetches the declared UI resource and renders it in a sandboxed iframe. A successful tool call proves only the first part of that chain.
Prerequisites
You need:
Node.js 18 or newer for the official MCP Apps build guide;
an MCP server with one app-backed tool;
the exact local or remote Streamable HTTP endpoint;
a browser with developer tools; and
permission to inspect the server and test host locally.
Keep credentials out of command history and screenshots. If the server requires authentication, use a disposable development credential and redact it from saved diagnostics.
1. Record Which Layer Actually Failed
Start with one tool call and record four observations:
Does the host list the tool?
Does the tool return a successful result?
Does the host request the declared
ui://resource?Does the iframe show content or a browser-console error?
These observations produce a useful first split:
Observation | Likely boundary |
|---|---|
Tool is missing | MCP connection, protocol negotiation, or tool registration |
Tool returns an error | Tool implementation or input validation |
Tool succeeds but no resource is requested | Tool-to-UI metadata or host support |
Resource is requested but the iframe is blank | HTML bundle, app bridge, CSP, or host behavior |
App works locally but not in one host | Host compatibility, authentication, caching, or remote delivery |
Do not change several layers at once. A tunnel, bundler, UI framework, authentication flow, and host upgrade can each produce the same blank rectangle.
2. Verify the Tool and Resource Contract
Build and start the app using the project's documented commands. The official minimal guide uses:
Its example endpoint is http://localhost:3001/mcp. Use MCP Inspector to query the server without the conversational host:
Expected result: the app-backed tool appears, and its metadata names a ui:// resource through _meta.ui.resourceUri.
Then inspect the registered resources:
Open the same server in the Inspector UI when you need to read the resource body. Confirm all three facts:
the resource URI exactly matches the tool metadata;
the response uses the MCP Apps HTML media type,
text/html;profile=mcp-app; andthe returned HTML contains the built JavaScript and CSS that the page expects.
A successful tools/call cannot compensate for a misspelled URI, a missing resource handler, the wrong media type, or HTML that still points to development-only assets.
3. Remove the Production Host From the Test
The official ext-apps repository includes basic-host, a local reference host that renders the app in a sandboxed iframe.
Open http://localhost:8080, select the tool, and call it.
Expected result: basic-host fetches the ui:// resource, creates the iframe, pushes the tool result to the app, and displays an interactive UI. Click one control that calls a server tool and verify the result changes.
This gives you a decisive comparison:
Blank in
basic-host: stay local and fix the tool, resource, bundle, bridge, or CSP.Works in
basic-hostbut blank in Claude, ChatGPT, VS Code, or another client: preserve the working local evidence and investigate that host's support and delivery path.
Do not use the core MCP protocol date as proof that a host supports MCP Apps. Apps are an extension, and host support varies independently.
4. Check the App Bridge
The UI must connect to the host before it can receive tool results or call server tools. A minimal client using the official SDK follows this shape:
Verify that:
app.connect()runs once after the document loads;the result handler is registered before the first result is needed;
the handler reads the shape your tool actually returns;
UI-initiated calls use the exact registered tool name; and
errors are rendered visibly instead of leaving a permanent loading state.
An app can receive structuredContent, text content, or both, depending on the tool and host. Do not assume that a field seen in one client will be present everywhere. Validate the exact result contract you depend on and provide an explicit empty or error state.
5. Make the Bundle Self-Contained First
For the first working version, bundle JavaScript and CSS into the HTML. The official tutorial uses vite-plugin-singlefile for this reason. A single-file build removes external asset paths and most CSP variables from the initial diagnosis.
Inspect the generated HTML, not the source template:
Expected result: the intended app HTML exists. Any remaining script, stylesheet, font, image, or API origin is deliberate and allowed by the resource's CSP metadata.
Do not add wildcard origins or disable the sandbox to make a blank app render. MCP Apps run in a sandboxed iframe specifically so they cannot read the host's cookies, local storage, or parent DOM. Fix the required origin or bundle the asset instead.
6. Test the Real Host Last
After the app passes basic-host, expose the server only if the target host requires a public HTTPS endpoint. The official guide demonstrates a temporary Cloudflare tunnel:
Add the generated HTTPS URL as a development connector, start a new conversation, and call the same tool. Verify the public endpoint, authentication, tool metadata, resource request, iframe console, and one UI-initiated tool call.
Treat the tunnel as temporary. Do not publish it, attach production credentials, or mistake a successful tunnel for a production deployment.
Common Blank-UI Failures
Symptom | Check | Safe next step |
|---|---|---|
Tool works, but no app frame appears |
| Fix the exact URI or test in a supported host |
Host requests the resource and gets not found | Resource registration and URI equality | Make the tool and resource share one URI constant |
HTML appears as text or is rejected | Resource media type | Return |
Frame stays on |
| Connect once and render an explicit missing-result state |
Buttons do nothing | Tool name, input shape, and host-granted capability | Inspect the call and show the returned error in the UI |
Local host works, remote host is blank | Tunnel URL, auth, cache, or host implementation | Compare network requests and iframe console output |
Browser console reports blocked assets | Bundle output and CSP metadata | Bundle locally or allow only the required origins |
Inspector hangs on Streamable HTTP | Inspector version or current regression | Save the command and version, then use |
On July 29, 2026, an open Inspector report described v2 hanging silently on a Streamable HTTP connection. An independent MCP Apps issue described a view becoming blank when a host omitted expected structured content. These reports are reasons to preserve layer-by-layer evidence, not reasons to assume every blank UI has the same cause.
Why This Order Works
The sequence moves from stable contracts toward environment-specific behavior. tools/list proves the app link is advertised. Reading the resource proves the HTML exists with the correct media type. basic-host proves the sandbox and bridge can render it. Only then does a production-host difference become meaningful.
This applies the useful structure behind Aident's Ollama networking guide: name the exact failure, give a direct diagnostic order, use reproducible commands, state expected results, separate look-alike causes, and explain why the checks work. The Ollama post's traffic does not prove this topic will perform the same way.
Give Your Coding Agent One Verifiable MCP App Task
Connect GitHub through Aident Loadout, then ask your coding agent to compare your failure with current MCP Apps and Inspector issues. Require one evidence note containing the tools/list app URI, resource media type, basic-host result, target-host result, and the closest current issue URL. Success means the blank UI is assigned to one layer before any fix is attempted.
Sources
MCP Apps overview, Model Context Protocol, accessed July 30, 2026
Build an MCP App, Model Context Protocol, accessed July 30, 2026
The 2026-07-28 MCP specification release candidate, Model Context Protocol, published May 21, 2026 and accessed July 30, 2026
MCP Apps official repository, Model Context Protocol, accessed July 30, 2026
MCP Inspector, Model Context Protocol, accessed July 30, 2026
Claude MCP App renders blank, Model Context Protocol, closed April 21, 2026
Host strips structured content and the view renders blank, Model Context Protocol, updated July 29, 2026
Inspector v2 hangs on Streamable HTTP, Model Context Protocol, updated July 30, 2026
Refresh this guide when the MCP Apps tool metadata, resource media type, bridge API, supported-client matrix, basic-host, or Inspector command surface changes.


