Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion samples/community/agent/adk/mcp_app_proxy/pong_app.html
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,27 @@
window.parent.postMessage({jsonrpc: '2.0', method, params}, '*');
}

function applyContainerDimensions(containerDimensions) {
if (!containerDimensions) return;
if (containerDimensions.width) {
document.documentElement.style.width = `${containerDimensions.width}px`;
document.body.style.width = `${containerDimensions.width}px`;
}
if (containerDimensions.height) {
document.documentElement.style.height = `${containerDimensions.height}px`;
document.body.style.height = `${containerDimensions.height}px`;
}
if (typeof resize === 'function') resize();
Comment thread
sugoi-yuzuru marked this conversation as resolved.
}
Comment thread
sugoi-yuzuru marked this conversation as resolved.

window.addEventListener('message', event => {
const data = event.data;
if (data?.method === 'ping') {
if (data.id) {
window.parent.postMessage({jsonrpc: '2.0', id: data.id, result: {}}, '*');
}
} else if (data?.method === 'ui/notifications/host-context-changed') {
applyContainerDimensions(data.params?.containerDimensions);
} else if (data?.method === 'ui/notifications/data-model-update') {
// TODO: Refactor message handlers to use `@modelcontextprotocol/ext-apps/app-bridge` App client.
const params = data.params;
Expand Down Expand Up @@ -307,7 +322,13 @@
.then(result => {
console.log('Initialized with host:', result);
sendNotification('ui/notifications/initialized', {});
sendNotification('ui/notifications/size-changed', {width: 728, height: 502});

// The app is fully reactive to the host dimensions.
// The host determines the container dimensions and passes them to the app.
applyContainerDimensions(result.hostContext?.containerDimensions);

// Alternatively, if the app is to control the dimensions, uncomment and use:
// sendNotification('ui/notifications/size-changed', {width: 728, height: 502});
Comment thread
sugoi-yuzuru marked this conversation as resolved.
Outdated
})
.catch(err => {
console.error('Initialization failed:', err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export class McpApp extends CatalogComponent<any> implements OnDestroy, OnInit {
private lastHeight?: number;
private lastBoundRootValue: string | null = null;
private isProcessingAppWrite = false;
private hostResizeObserver: ResizeObserver | null = null;

ngOnInit() {
this.setupSandbox();
Expand All @@ -135,6 +136,10 @@ export class McpApp extends CatalogComponent<any> implements OnDestroy, OnInit {
if (this.messageHandler) {
window.removeEventListener('message', this.messageHandler);
}
if (this.hostResizeObserver) {
this.hostResizeObserver.disconnect();
this.hostResizeObserver = null;
}
const bridge = this.appBridge();
if (bridge) {
bridge.close().catch(e => console.error('Error closing AppBridge on destroy:', e));
Expand Down Expand Up @@ -400,6 +405,23 @@ export class McpApp extends CatalogComponent<any> implements OnDestroy, OnInit {
return {content: []};
};

// Inform the app of its dimensions
if (this.hostResizeObserver) {
this.hostResizeObserver.disconnect();
}
this.hostResizeObserver = new ResizeObserver(entries => {
const entry = entries[0];
if (entry && bridge) {
bridge.setHostContext({
containerDimensions: {
width: entry.contentRect.width,
height: entry.contentRect.height,
}
});
}
});
this.hostResizeObserver.observe(iframe);
Comment thread
sugoi-yuzuru marked this conversation as resolved.
Outdated

// Connect the bridge
// We must pass the iframe's contentWindow as the target
const transport = new PostMessageTransport(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,30 @@ Sent as a response to a `ui/requests/function-call` request.
**Embedded app action**
The embedded app processes the result or error based on its own logic.

### C. Resource update (`ui/notifications/sandbox-resource-ready`)
### C. Host context update (`ui/notifications/host-context-changed`)

Sent when the host's context changes, such as when the container dimensions are resized or the theme is toggled. This aligns with the [Model Context Protocol Apps Specification: Host Context](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx).

**Message schema**

```json
{
"jsonrpc": "2.0",
"method": "ui/notifications/host-context-changed",
"params": {
"theme": "string",
"containerDimensions": {
"width": "number",
"height": "number"
}
}
}
```

**Embedded app action**
The embedded app SHOULD merge the received context fields with its current state. If `containerDimensions` are provided, the app SHOULD adapt its internal layout to fit within the newly specified fixed or flexible boundaries.

### D. Resource update (`ui/notifications/sandbox-resource-ready`)

Sent when the application HTML content is modified or updated by the A2UI agent.

Expand Down
Loading