experimental_MCPAppRenderer

experimental_MCPAppRenderer is experimental and may change in a future release.

experimental_MCPAppRenderer renders an MCP App for an AI SDK tool UI part. It detects MCP App metadata on the tool part, loads the app resource, renders the app in a sandbox proxy iframe, and bridges MCP Apps JSON-RPC messages between the iframe and your host application.

For tool parts without MCP App metadata, the component renders the fallback.

Import

import { experimental_MCPAppRenderer as MCPAppRenderer } from "@ai-sdk/react"

Example

'use client';
import {
experimental_MCPAppRenderer as MCPAppRenderer,
type MCPAppBridgeHandlers,
type MCPAppMetadata,
type MCPAppResource,
type MCPAppSandboxConfig,
} from '@ai-sdk/react';
import { isToolUIPart } from 'ai';
const sandbox = {
url: '/mcp-app-sandbox',
className: 'h-80 w-full rounded-lg border',
style: { border: 0 },
} satisfies MCPAppSandboxConfig;
async function loadResource(app: MCPAppMetadata): Promise<MCPAppResource> {
const response = await fetch('/api/mcp-app-host/read-resource', {
method: 'POST',
body: JSON.stringify({ uri: app.resourceUri }),
});
if (!response.ok) {
throw new Error('Failed to load MCP App resource');
}
return response.json();
}
const handlers: MCPAppBridgeHandlers = {
callTool: params =>
fetch('/api/mcp-app-host/call-tool', {
method: 'POST',
body: JSON.stringify(params),
}).then(response => response.json()),
openLink: ({ url }) => {
window.open(url, '_blank', 'noopener,noreferrer');
return {};
},
};
export function MessagePart({ part }: { part: unknown }) {
if (!isToolUIPart(part)) {
return null;
}
return (
<MCPAppRenderer
part={part}
loadResource={loadResource}
handlers={handlers}
sandbox={sandbox}
fallback={null}
/>
);
}

Props

part:

ToolUIPart<UITools> | DynamicToolUIPart

sandbox:

MCPAppSandboxConfig

resource?:

MCPAppResource

loadResource?:

(app: MCPAppMetadata) => Promise<MCPAppResource>

handlers?:

MCPAppBridgeHandlers

hostInfo?:

{ name: string; version: string }

hostContext?:

MCPAppHostContext

fallback?:

ReactNode

Sandbox Config

url:

string | URL

title?:

string

className?:

string

style?:

CSSProperties

targetOrigin?:

string

outerSandbox?:

string

innerSandbox?:

string

Bridge Handlers

experimental_MCPAppRenderer uses these handlers to respond to iframe requests. In production, server-backed handlers should validate authorization and MCP Apps tool visibility before calling the MCP server.

allowedTools?:

string[]

callTool?:

(params: MCPAppToolCallParams) => Promise<unknown> | unknown

readResource?:

(params: { uri: string }) => Promise<unknown> | unknown

listResources?:

(params?: unknown) => Promise<unknown> | unknown

sendMessage?:

(params: unknown) => Promise<unknown> | unknown

updateModelContext?:

(params: unknown) => Promise<unknown> | unknown

requestDisplayMode?:

(params: { mode: 'inline' | 'fullscreen' | 'pip' }) => Promise<{ mode: MCPAppDisplayMode }> | { mode: MCPAppDisplayMode }

onSizeChange?:

(params: { width?: number; height?: number }) => void

onInitialized?:

() => void

onRequestTeardown?:

(params: unknown) => void

onLog?:

(params: unknown) => void

onError?:

(error: Error) => void

See Also

MCP Apps guide
MCP Apps helpers