Inspector Version
Describe the bug
A Safari/WebKit-specific MCP Apps rendering failure occurs because the Inspector sandbox relay in server/static/sandbox_proxy.html assumes inner iframe messages will always arrive with:
event.source === inner.contentWindow
In Safari/WebKit, we observed the inner iframe's postMessage(...) arriving at the outer sandbox with:
event.origin === OWN_ORIGIN
event.source === window
instead of event.source === inner.contentWindow.
Because of that, the sandbox drops the app's ui/initialize request instead of forwarding it to the host. The MCP App then never receives a JSON-RPC init response and remains blank or partially initialized.
The failing implementation appears to be in server/static/sandbox_proxy.html, not in app-side render logic.
To Reproduce
Steps to reproduce the behavior:
- Start
@modelcontextprotocol/inspector.
- Connect it to an MCP server that returns an MCP App / generated UI.
- Open the same generated UI in a Chromium browser such as Brave or Chrome and confirm it renders.
- Open the same generated UI in Safari desktop or another WebKit-based host/surface.
- Observe that the app sends
ui/initialize, but Safari/WebKit never completes the handshake and the UI remains blank.
Expected behavior
The same MCP App should initialize and render in Safari/WebKit just as it does in Chromium. The sandbox relay should forward valid same-origin inner iframe messages even when Safari reports them with event.source === window.
Screenshots
I do not have screenshots included in this report.
Environment (please complete the following information):
- OS: macOS and iOS
- Browser: Safari desktop, iOS WebKit surfaces, and Brave/Chrome for working comparison
Additional context
We debugged this with runtime instrumentation in Safari and Chromium side-by-side.
What we observed before the patch:
- Chromium / Brave works:
- app sends
ui/initialize
- sandbox relays it
- host returns JSON-RPC response
- app renders normally
- Safari / WebKit fails:
- app sends
ui/initialize
- outer sandbox receives the message
- message is classified as unexpected because
event.source !== inner.contentWindow
- host never receives
ui/initialize
- app times out initialization and remains blank
What we observed after a local patch:
- allowing the same-origin Safari case where
event.source === window made the sandbox relay ui/initialize
- the host returned the JSON-RPC response
- the app initialized and rendered correctly
Current relay logic:
} else if (event.source === inner.contentWindow) {
if (event.origin !== OWN_ORIGIN) {
console.error(
"[Sandbox] Rejecting message from inner iframe with unexpected origin:",
event.origin,
"expected:",
OWN_ORIGIN,
);
return;
}
window.parent.postMessage(event.data, EXPECTED_HOST_ORIGIN);
}
Suggested fix:
} else if (
event.source === inner.contentWindow ||
(event.origin === OWN_ORIGIN && event.source === window)
) {
if (event.origin !== OWN_ORIGIN) {
console.error(
"[Sandbox] Rejecting message from inner iframe with unexpected origin:",
event.origin,
"expected:",
OWN_ORIGIN,
);
return;
}
window.parent.postMessage(event.data, EXPECTED_HOST_ORIGIN);
}
The important part is preserving the origin check while relaxing the brittle source identity assumption for Safari/WebKit.
There is a separate ext-apps transport race issue in modelcontextprotocol/ext-apps#542, but this bug appears distinct. In this case, the blocking failure was the sandbox relay dropping a valid inner-frame message on Safari/WebKit due to a strict event.source check.
Inspector Version
0.21.2Describe the bug
A Safari/WebKit-specific MCP Apps rendering failure occurs because the Inspector sandbox relay in
server/static/sandbox_proxy.htmlassumes inner iframe messages will always arrive with:In Safari/WebKit, we observed the inner iframe's
postMessage(...)arriving at the outer sandbox with:event.origin === OWN_ORIGINevent.source === windowinstead of
event.source === inner.contentWindow.Because of that, the sandbox drops the app's
ui/initializerequest instead of forwarding it to the host. The MCP App then never receives a JSON-RPC init response and remains blank or partially initialized.The failing implementation appears to be in
server/static/sandbox_proxy.html, not in app-side render logic.To Reproduce
Steps to reproduce the behavior:
@modelcontextprotocol/inspector.ui/initialize, but Safari/WebKit never completes the handshake and the UI remains blank.Expected behavior
The same MCP App should initialize and render in Safari/WebKit just as it does in Chromium. The sandbox relay should forward valid same-origin inner iframe messages even when Safari reports them with
event.source === window.Screenshots
I do not have screenshots included in this report.
Environment (please complete the following information):
Additional context
We debugged this with runtime instrumentation in Safari and Chromium side-by-side.
What we observed before the patch:
ui/initializeui/initializeevent.source !== inner.contentWindowui/initializeWhat we observed after a local patch:
event.source === windowmade the sandbox relayui/initializeCurrent relay logic:
Suggested fix:
The important part is preserving the origin check while relaxing the brittle source identity assumption for Safari/WebKit.
There is a separate
ext-appstransport race issue inmodelcontextprotocol/ext-apps#542, but this bug appears distinct. In this case, the blocking failure was the sandbox relay dropping a valid inner-frame message on Safari/WebKit due to a strictevent.sourcecheck.