You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Simple SDK for an MCP-UI update that would use MCP messages for its iframe / host interface.
This makes it easy to expose more than tools to the UI (which gets fuller access to its server!), and relies mostly on the TypeScript SDK for the request / response mechanics.
Examples
Vanilla JavaScript Host
git clone https://gist.github.com/ochafik/a9603ba2d6757d6038ce066eded4c354 mcp-ui-sdk
cd mcp-ui-sdk
npm i
npm start
open http://localhost:8000/dist/example-host.html
npm start
open http://localhost:8000/dist/example-host-react.html
Development mode
# No minification, and no inlining of html - no dist/
NODE_ENV=development && npm start && open http://localhost:8000/example-host.html
NODE_ENV=development && npm start && open http://localhost:8000/example-host-react.html
TODO:
add webpack build example config (w/ builtin html inline)
(Later) Stick to low-level interface
sandbox.html
on load:
parent.postMessage({
method: sandbox-proxy-ready
})
on sandbox-proxy-resource-ready from parent:
inner iframe.srcdoc = resource
pipes messages from parent <-> inner iframe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SEP-...: MCP-UI: Interactive User Interfaces for MCP
Track: Extensions
Authors: Ido Salomon, Liad Yosef, Olivier Chafik, Jonathan Hefner, Anton Pidkuiko
Status: Draft
Created: 2025-11-11
Abstract
This SEP proposes an extension (per SEP-1724) to MCP that enables servers to deliver interactive user interfaces to hosts. MCP-UI introduces a standardized pattern for declaring UI resources via the ui:// URI scheme, associating them with tools through metadata, and facilitating bidirectional communication between the UI and the host using MCP's JSON-RPC base protocol. This extension addresses the growing community need for rich, interactive experiences in MCP-enabled applications, maintaining security, auditability, and alignment with MCP's core architecture. The initial specification focuses on HTML resources (text/html) with a clear path for future extensions.
Motivation
MCP lacks a standardized way for servers to deliver rich, interactive user interfaces to hosts. This gap blocks many use cases that require visual presentation and interactivity that goes beyond plain text or structured data. As more hosts adopt this capability, there's a growing risk of fragmentation and interoperability challenges.
The MCP-UI project has demonstrated the viability and value of UI resources, and served as a community playground for the UI spec and SDK. MCP-UI currently supports multiple rendering modes (HTML, external URLs, Remote DOM), has SDKs for TypeScript, Python, and Ruby, and has been adopted by multiple hosts, including Postman, Goose, LibreChat, and more.
However, without formal standardization:
Servers cannot reliably expect UI support
Each host may implement slightly different behaviors
Security and auditability patterns are inconsistent
This SEP addresses the current limitations through an optional, backwards-compatible extension.
Specification
Extension Identifier
This extension is identified as: modelcontextprotocol.io/ui
Overview
MCP-UI extends the Model Context Protocol to enable servers to deliver interactive user interfaces to hosts. This extension introduces:
UI Resources: Predeclared resources using the ui:// URI scheme
Tool-UI Linkage: Tools reference UI resources via metadata
Bidirectional Communication: UI iframes communicate with hosts using standard MCP JSON-RPC protocol
Security Model: Mandatory iframe sandboxing with auditable communication
This specification focuses on HTML content (text/html) as the initial content type, with extensibility for future formats.
As an extension, MCP-UI is optional and must be explicitly negotiated between clients and servers through the extension capabilities mechanism (see Capability Negotiation section).
UI Resource Format
UI resources are declared using the standard MCP resource pattern with specific conventions:
interfaceUIResource{uri: string;// MUST start with 'ui://'name: string;// Human-readable identifierdescription?: string;// Description of the UI resourcemimeType: string;// SHOULD be 'text/html' in MVP}
The resource content is returned via resources/read:
// resources/read response for UI resource{
contents: [{uri: string;// Matching UI resource URI
mimeType: "text/html";// MUST be "text/html"
text?: string;// HTML content as string
blob?: string;// OR base64-encoded HTML
_meta?: {"mcp-ui/widgetCSP"?: {connect_domains?: string[];// Origins for fetch/XHR/WebSocketresource_domains?: string[];// Origins for images, scripts, styles};"mcp-ui/widgetDomain"?: string;"mcp-ui/widgetPrefersBorder"?: boolean;};}];}
Content Requirements:
URI MUST start with ui:// scheme
mimeType MUST be text/html (other types reserved for future extensions)
Content MUST be provided via either text (string) or blob (base64-encoded)
UI resources MUST be registered and discoverable via the standard MCP resource discovery pattern:
Server declares UI resources in resources/list response
Host can enumerate available UI resources before tool execution
Host can prefetch UI resource content via resources/read
Host can cache UI resources for performance optimization
Benefits:
Performance: Host can preload templates before tool execution
Security: Host can review UI templates during connection setup
Caching: Separate template (static) from data (dynamic)
Auditability: All UI resources are enumerable and inspectable
Tool Metadata
Tools associate with UI resources through the _meta field:
interfaceTool{name: string;description: string;inputSchema: object;_meta?: {// Required: URI of the UI resource to use for rendering"mcp-ui/resourceUri"?: string;};}
Example:
{name: "get_weather",description: "Get current weather for a location",inputSchema: {type: "object",properties: {location: {type: "string"}}},_meta: {"mcp-ui/resourceUri": "ui://weather-server/dashboard-template",}}
Behavior:
If mcp-ui/resourceUri is present and host supports MCP-UI, host renders tool results using the specified UI resource
If host does not support MCP-UI, tool behaves as standard tool (text-only fallback)
Host MUST validate that referenced URI exists in resources/list
Communication Protocol
MCP-UI reuses the standard MCP JSON-RPC 2.0 protocol over postMessage for iframe-host communication.
Transport Layer
UI iframes act as MCP clients, connecting to the host via a postMessage transport:
Hosts act as MCP servers (proxies to the actual MCP server), receiving and handling requests from UI iframes.
Sandbox proxy
If the Host is a web page, it MUST wrap the Guest UI and communicate with it through an intermediate Sandbox proxy.
The Host and the Sandbox MUST have different origins.
The Sandbox MUST have the following permissions: allow-scripts, allow-same-origin.
The Sandbox MUST send a mcp-ui/sandbox-ready notification to the host when it’s ready to process an mcp-ui/sandbox-resource-ready notification.
Once the Sandbox is ready, the Host MUST send the raw HTML resource to load in a mcp-ui/sandbox-resource-ready notification.
The Sandbox MUST load the raw HTML of the Guest UI with CSP settings that:
Enforce the domains declared in mcp-ui/widgetCSP metadata
Prevent nested iframes (frame-src 'none')
Block dangerous features (object-src 'none', base-uri 'self')
Apply restrictive defaults if no CSP metadata is provided
The Sandbox MUST forward messages sent by the Host to the Guest UI, and vice versa, with any method that doesn’t start with mcp-ui/sandbox-. This includes lifecycle messages, e.g. initialize request & initialized notification both sent by the Guest UI. The Host MUST NOT send any request or notification to the Guest UI before it receives an initialized notification.
The Sandbox SHOULD NOT create/send any requests to the Host or to the Guest UI (this would require synthesizing new request ids).
The Host MAY forward any message from the Guest UI (coming via the Sandbox) to the MCP-UI server, for any method that doesn’t start with mcp-ui/. While the Host SHOULD ensure the Guest UI’s MCP connection is spec-compliant, it MAY decide to block some messages or subject them to further user approval.
Standard MCP Messages (Reused)
UI iframes can use standard MCP protocol messages:
Tools:
tools/list - Enumerate available tools
tools/call - Execute a tool
notifications/tools/list_changed - Tool list updated
Resources:
resources/list - Enumerate resources
resources/read - Read resource content
resources/subscribe - Subscribe to resource updates
resources/unsubscribe - Unsubscribe from resource updates
notifications/resources/list_changed - Resource list updated
notifications/prompts/list_changed - Prompt list updated
Notifications:
notifications/message - Log messages to host
Lifecycle:
initialize - Standard MCP handshake (replaces custom iframe-ready pattern)
ping - Connection health check
Host Context in InitializeResult
When the Guest UI sends an initialize request to the Host, the Host SHOULD include
UI-specific context in
the InitializeResult response via the _meta field:
Host sends this notification after the Guest UI's initialize request completes, when tool arguments become available. This notification is sent at most once and is required before sending mcp-ui/tool-result.
mcp-ui/notifications/tool-input-partial - Host MAY send this notification zero or more times while the agent is streaming tool arguments, before mcp-ui/notifications/tool-input is sent.
The arguments object represents best-effort recovery of incomplete JSON, with unclosed structures automatically closed to produce valid JSON.
Host behavior (optional):
MAY parse the agent's partial JSON output by closing unclosed brackets/braces
MAY send recovered arguments as they become available during streaming
MUST stop sending once mcp-ui/notifications/tool-input is sent with complete arguments
Guest UI behavior (optional):
MAY ignore these notifications entirely
MAY render progressive loading/streaming states based on available fields
MUST NOT rely on partial arguments for critical operations
SHOULD gracefully handle missing or changing fields between notifications
mcp-ui/tool-result - Tool execution result
{jsonrpc: "2.0",method: "mcp-ui/tool-result",params: CallToolResult// Standard MCP type}
Host MUST send this notification when tool execution completes (if UI is displayed during tool execution).
mcp-ui/tool-cancelled - Tool execution was cancelled
Host MUST send this notification if the tool execution was cancelled, for any reason (which can optionally be specified), including user action, sampling error, classifier intervention, etc
mcp-ui/size-change - Fired by client when its body size changes
{jsonrpc: "2.0",method: "mcp-ui/size-change",params: {width?: number,// Viewport width in pixelsheight?: number// Viewport height in pixels}}
Guest UI SHOULD send this notification when rendered content body size changes (e.g. using ResizeObserver API to report up to date size)
mcp-ui/host-context-change - Host context has changed
{jsonrpc: "2.0",method: "mcp-ui/host-context-change",params: Partial<HostContext>// See HostContext type above}
Host MAY send this notification when any context field changes (e.g., theme toggle, display mode change, device orientation change, window/panel resize). This notification contains partial updates - Guest UI SHOULD merge received fields with its current context state.
Reserved Messages (Sandbox Proxy)
These messages are reserved for web-based hosts that implement the recommended double-iframe sandbox architecture:
// Tool was called with:tools/call("get_weather",{location: "San Francisco"})// UI receives:
notification: mcp-ui/notifications/tool-input
params: {arguments: {location: "San Francisco"}}
2. Tool Result (via mcp-ui/tool-result notification)
The tool's execution result:
// Server returns from tool execution:{content: [{type: "text",text: "Current weather: Sunny, 72°F"}],structuredContent: {temperature: 72,conditions: "sunny",humidity: 45},_meta: {timestamp: "2025-11-10T15:30:00Z",source: "weather-api"}}// UI receives:
notification: mcp-ui/tool-result
params: {content: [...],// Same as abovestructuredContent: {temperature: 72, ... },_meta: {timestamp: "...", ... }}
Best Practices:
content: Text representation for model context and text-only hosts
structuredContent: Structured data optimized for UI rendering (not added to model context)
_meta: Additional metadata (timestamps, version info, etc.) not intended for model context
3. Interactive Updates
UI can request fresh data by calling tools:
// UI requests updated dataawaitclient.callTool("get_weather",{location: "New York"});// Result returned via standard tools/call response
This pattern enables interactive, self-updating widgets.
Note: The called tool may not appear in tools/list responses. MCP servers MAY expose private tools specifically designed for UI interaction that are not visible to the agent. UI implementations SHOULD attempt to call tools by name regardless of discoverability.
Capability Negotiation
Hosts and servers negotiate MCP-UI support through the standard MCP extensions capability mechanism defined in SEP-1724.
Client (Host) Capabilities
Hosts advertise MCP-UI support in the initialize request using the extension identifier modelcontextprotocol.io/ui:
Servers SHOULD check client (host would-be) capabilities before registering UI-enabled tools:
consthasUISupport=clientCapabilities?.extensions?.["modelcontextprotocol.io/ui"]?.mimeTypes?.includes("text/html");if(hasUISupport){// Register tools with UI templatesserver.registerTool("get_weather",{description: "Get weather with interactive dashboard",inputSchema: {/* ... */},_meta: {"mcp-ui/resourceUri": "ui://weather-server/dashboard"}});}else{// Register text-only versionserver.registerTool("get_weather",{description: "Get weather as text",inputSchema: {/* ... */}// No UI metadata});}
Graceful Degradation:
Servers SHOULD provide text-only fallback behavior for all UI-enabled tools
Tools MUST return meaningful content array even when UI is available
Servers MAY register different tool variants based on host capabilities
Extensibility
This specification defines the Minimum Viable Product (MVP) for MCP-UI. Future extensions may include:
Content Types (deferred from MVP):
externalUrl: Embed external web applications
remoteDom: Shopify Remote DOM for native-like components
Advanced Features (see Future Considerations):
Support multiple UI resources in a tool response
State persistence and restoration
Partial tool input streaming
Private tools (not visible to agent)
Custom sandbox policies per resource
Widget-to-widget communication
Screenshot/preview generation APIs
Rationale
This proposal synthesizes feedback from the UI CWG and MCP-UI community, host implementors, and lessons from similar solutions. The guiding principle of this proposal is to start lean and expand in the future. There are breaking changes from existing solutions, which will be addressed via the MCP-UI SDK during the migration period.
Design Decisions
1. Predeclared Resources vs. Inline Embedding
Decision: Require UI resources to be registered and referenced in tool metadata.
Rationale:
Enables hosts to prefetch templates before tool execution, improving performance
Separates presentation (template) from data (tool results), improving caching
Allows hosts to review UI templates
Aligns with MCP's resource discovery pattern
Alternatives considered:
Embedded resources: Current MCP-UI approach, where resources are returned in tool results. Although it's more convenient for server development, it was deferred due to the gaps in performance optimization and the challenges in the UI review process.
Resource links: Predeclare the resources but return links in tool results. Deferred due to the gaps in performance optimization.
2. Host communication via MCP Transport
Decision: Use MCP's JSON-RPC base protocol over postMessage instead of custom message format.
UI developers can use standard MCP SDK (@modelcontextprotocol/sdk) or alternatives
Automatic compatibility with future MCP features (long-running tools, sampling, etc.)
Better auditability through structured JSON-RPC messages
Reduces maintenance burden (no parallel protocol to evolve)
Alternatives considered:
Custom message protocol: Current MCP-UI approach with message types like tool, intent, prompt, etc. These message types can be translated to a subset of the proposed JSON-RPC messages.
Global API object: Rejected because it requires host-specific injection and doesn't work with external iframe sources. Syntactic sugar may still be added on the server/UI side.
3. Support Raw HTML Content Type
Decision: MVP supports only text/html (rawHtml), with other types explicitly deferred.
Rationale:
HTML is universally supported and well-understood
Simplest security model (standard iframe sandbox)
Allows screenshot/preview generation (e.g., via html2canvas)
Sufficient for most observed use cases
Provides clear baseline for future extensions
Alternatives considered:
Include external URLs in MVP: This is one of the easiest content types for servers to adopt, as it's possible to embed regular apps. However, it was deferred due to concerns around model visibility, inability to screenshot content, and review process.
Support multiple content types: Deferred to maintain a lean MVP.
Backward Compatibility
The proposal builds on the existing core protocol. There are no incompatibilities.
Reference Implementation
The MCP-UI project (github.com/mcp-ui-org/mcp-ui) serves as a reference implementation demonstrating the core concept, though it uses pre-SEP patterns.
Olivier Chafik has developed a prototype demonstrating the pattern described in this SEP.
Attackers may use the embedded UI in different scenarios. For example:
Malicious server delivers harmful HTML content
Compromised UI attempts to escape sandbox
UI attempts unauthorized tool execution
UI exfiltrates sensitive host data
UI performs phishing or social engineering
Mitigations
1. Iframe Sandboxing
All UI content MUST be rendered in sandboxed iframes with restricted permissions.
The sandbox limits the UI from accessing the host or manipulating it. All communication with the host is done via postMessage, where the host is in control.
2. Auditable Communication
All UI-to-host communication goes through auditable MCP JSON-RPC messages.
Host behavior:
Validate all incoming messages from UI iframes
Reject malformed message types
Log UI-initiated RPC calls for security review
3. Predeclared Resource Review
Hosts receive UI templates during connection setup, before tool execution.
Host behavior:
Review HTML content for obvious malicious patterns
Generate hash/signature for resources
Warn users about suspicious content
Implement allowlists/blocklists based on resource hashes
4. User Consent for Tool Calls
Hosts MUST implement user consent for tool calls originating from UI.
Host behavior:
Require explicit user confirmation for “non-safe” tools
Implement automatic approval for "safe" tools
Show clear UI indication when UI is calling tools
Maintain separate permission model for UI vs. model-initiated calls
5. Content Security Policy Enforcement
Hosts MUST enforce Content Security Policies based on resource metadata.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters