mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
fix: complete the MCP Apps handshake the way hosts validate it
The panel sent clientInfo and capabilities in ui/initialize, where the MCP Apps schema requires appInfo, so hosts such as Claude rejected the handshake and never showed the panel. It now sends exactly appCapabilities, appInfo and protocolVersion, sends initialized without parameters, says so when a host rejects it, and offers the link when God's Eye View does not load within 20 seconds. Checked against the MCP Apps SDK's own host bridge.
This commit is contained in:
1 parent
ba751d9433
commit
d368df533d
2 files changed
+19
-4
No files matched your search
+16
-4
@@ -38,6 +38,7 @@ function panelHtml(appOrigin) {
|
||||
<script>
|
||||
(() => {
|
||||
const APP_ORIGIN = ${JSON.stringify(appOrigin)};
|
||||
const LOAD_TIMEOUT_MS = 20000;
|
||||
const status = document.getElementById('status');
|
||||
const open = document.getElementById('open');
|
||||
let nextId = 1;
|
||||
@@ -83,6 +84,12 @@ function panelHtml(appOrigin) {
|
||||
frame.src = embedUrl(url);
|
||||
document.body.appendChild(frame);
|
||||
status.textContent = "Loading God's Eye View…";
|
||||
// Say so, rather than wait forever, when the app cannot load here.
|
||||
setTimeout(() => {
|
||||
if (!frameReady)
|
||||
status.textContent =
|
||||
"God's Eye View did not load here. Use Open in God's Eye View above.";
|
||||
}, LOAD_TIMEOUT_MS);
|
||||
return;
|
||||
}
|
||||
if (frameReady) postView(view);
|
||||
@@ -119,17 +126,22 @@ function panelHtml(appOrigin) {
|
||||
);
|
||||
});
|
||||
|
||||
// The handshake the MCP Apps SDK's App.connect performs: hosts validate
|
||||
// these parameters, and keep a view hidden until it is initialized.
|
||||
request('ui/initialize', {
|
||||
protocolVersion: ${JSON.stringify(MCP_APPS_PROTOCOL_VERSION)},
|
||||
clientInfo: { name: 'gods-eye-view-globe', version: '1' },
|
||||
capabilities: {},
|
||||
appCapabilities: { availableDisplayModes: ['inline', 'fullscreen'] },
|
||||
appInfo: { name: 'gods-eye-view', title: "God's Eye View", version: '1.0.0' },
|
||||
protocolVersion: ${JSON.stringify(MCP_APPS_PROTOCOL_VERSION)},
|
||||
}).then(() => {
|
||||
notify('ui/notifications/initialized', {});
|
||||
send({ method: 'ui/notifications/initialized' });
|
||||
notify('ui/notifications/size-changed', {
|
||||
width: document.body.clientWidth,
|
||||
height: ${PANEL_HEIGHT_PX},
|
||||
});
|
||||
}, (error) => {
|
||||
status.textContent =
|
||||
"This client did not accept the God's Eye View panel" +
|
||||
(error && error.message ? ': ' + error.message : '.');
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -21,6 +21,9 @@ test('the globe panel is an MCP Apps resource that may frame only the app', () =
|
||||
assert.match(resource.text, /'ui\/initialize'/);
|
||||
assert.match(resource.text, /'ui\/notifications\/tool-result'/);
|
||||
assert.match(resource.text, /protocolVersion: "2026-01-26"/);
|
||||
// The MCP Apps SDK's initialize parameters; hosts reject anything else.
|
||||
assert.match(resource.text, /appInfo: \{ name: 'gods-eye-view'/);
|
||||
assert.doesNotMatch(resource.text, /clientInfo/);
|
||||
});
|
||||
|
||||
test('show_in_gods_eye_view names the panel and shows a view another answer returned', async () => {
|
||||
|
||||
Reference in new issue
Block a user