MCP Apps SDK
repository·main·Indexed 25 days ago
https://github.com/modelcontextprotocol/ext-appsAn extension to the Model Context Protocol that enables MCP servers to deliver interactive user interfaces, such as charts, forms, and dashboards, that render inline within compliant chat clients. The SDK provides an App class and React hooks for communication between the UI and the host, including methods like callServerTool, sendMessage, sendLog, and openLink. The repository includes reference implementations for hosts and servers using Preact, React, Solid, and Svelte.
What's inside @modelcontextprotocol/ext-apps
- The Debug Server is a comprehensive testing and debugging tool designed to exercise every capability, callback, and result format combination within the MCP Apps SDK. It provides both server-side tools for testing data variations and a client-side App UI for monitoring SDK state and triggering actions.
Overview of MCP Apps: Interactive User Interfaces
mainMCP Apps is an extension to the Model Context Protocol (MCP) that allows servers to deliver interactive user interfaces (UIs) to hosts. It provides a standardized pattern for declaring UI resources using the
ui://URI scheme and associating them with tools via metadata. This enables rich, visual, and interactive experiences that go beyond plain text or structured data, while maintaining MCP's core principles of security and auditability.Key features include:
- Standardized UI Declaration: Uses the
ui://URI scheme. - Tool Association: UI resources can be linked to specific tools through metadata.
- Bidirectional Communication: Facilitates interaction between the UI and the host using the existing MCP JSON-RPC base protocol.
- HTML Support: The initial specification focuses on HTML resources with the MIME type
text/html;profile=mcp-app.
- Standardized UI Declaration: Uses the
Overview of Basic Vue MCP App architecture
mainThe Basic Vue MCP App demonstrates how to link an MCP server tool to a rich Vue 3 user interface.
Workflow
- Tool Registration: The server (defined in
server.ts) registers a tool (e.g.,get-time) and includes metadata that links the tool to a specific UI HTML resource (e.g.,ui://get-time/mcp-app.html). - UI Rendering: When a client invokes the tool, the Host renders the associated UI resource.
- Communication: The UI (built with Vue 3 in
src/App.vue) uses the MCP App SDK'sAppclass to communicate back to the host and call server tools.
App Communication APIs
The
Appclass provides the following methods for the UI to interact with the environment:callServerTool: Invokes a tool on the MCP server.sendMessage: Sends a message to the host.sendLog: Sends a log message.openLink: Opens a URL.
Build Strategy
This example uses Vite with
vite-plugin-singlefileto bundle the entire Vue application into a single HTML file. This ensures the entire UI can be served as a single MCP resource. For apps requiring external resources, you must define_meta.ui.csp.resourceDomainsin the UI resource metadata.- Tool Registration: The server (defined in
Overview of MCP Apps extension
mainMCP Apps (extension ID:
io.modelcontextprotocol/ui) allows MCP servers to deliver interactive user interfaces to hosts. It enables servers to provide HTML-based UIs that communicate with the host via standard MCP JSON-RPC.Key components include:
- UI Resources: Predeclared resources using the
ui://URI scheme. - Tool-UI Linkage: Tools that reference specific UI resources via metadata for rendering results.
- Bidirectional Communication: UI iframes that interact with hosts using MCP.
- Security Model: Mandatory iframe sandboxing and Content Security Policy (CSP) enforcement.
Note: MCP Apps is an optional extension and must be negotiated between client and server via capability negotiation.
- UI Resources: Predeclared resources using the
Security model for MCP Apps
mainMCP Apps enforces security through two primary mechanisms:
- Sandboxing: All Views run in sandboxed iframes with no access to the Host's DOM, cookies, or local storage. Communication is strictly limited to
postMessage. - Network Control (CSP): Servers must declare which network domains their UI requires via Content Security Policy (CSP) metadata. Hosts enforce these declarations; if no domains are declared, the View is prevented from making any external connections, mitigating data exfiltration risks.
- Sandboxing: All Views run in sandboxed iframes with no access to the Host's DOM, cookies, or local storage. Communication is strictly limited to
Use MCP Transport for host communication
mainMCP Apps communicate with hosts using the standard MCP JSON-RPC base protocol over
postMessage. This decision ensures compatibility with existing MCP infrastructure, including:- Standard type definitions and error handling
- Timeouts and Tasks for long-running calls
- Sampling and other core MCP features
Developers can use the standard
@modelcontextprotocol/sdkto implement these communications, avoiding the need for a custom message format.How MCP Apps work
mainMCP Apps extend the Model Context Protocol by allowing tools to declare interactive UI resources. The lifecycle follows these steps:
- Tool definition: An MCP tool declares a
ui://resource containing its HTML interface. - Tool call: The LLM invokes the tool on the MCP server.
- Host renders: The chat client (host) fetches the
ui://resource and renders it within a sandboxed iframe. - Bidirectional communication: The host sends tool data to the UI via notifications, and the UI can trigger other tools by communicating back through the host.
- Tool definition: An MCP tool declares a
Implement Host Theming using CSS Variables
mainTo ensure visual cohesion across different host environments, MCP Apps use a standardized set of CSS custom properties (variables). UI views should apply styles using
var(--name)with appropriate fallbacks.Theming Guidelines:
- Supported Variables: Hosts provide values for colors, typography, and borders.
- Exclusions: Hosts do not provide spacing variables, as varying spacing can break UI layouts.
- Implementation: Views should be framework-agnostic and rely on these variables rather than hardcoded values or host-specific CSS-in-JS injection.
Manage View Display Modes
mainMCP Views can be displayed in three modes:
inline(default),fullscreen, orpip(picture-in-picture).For View Developers:
- Declare Support: You MUST declare all supported modes in the
ui/initializerequest usingappCapabilities.availableDisplayModes. - Check Compatibility: Before requesting a mode change, check the
HostContext.availableDisplayModesto ensure the host supports it. - Handle Responses: You MUST handle cases where the host returns a different mode than the one you requested.
For Host Developers:
- Enforce Capabilities: Do NOT switch a view to a mode it hasn't declared support for.
- Respond to Requests: When a view calls
ui/request-display-mode, return the actual resulting mode in the response. - Notify Changes: Use
ui/notifications/host-context-changedto inform the view when thedisplayModechanges.
// Example: View declares support for inline and fullscreen during initialization { method: "ui/initialize", params: { appCapabilities: { availableDisplayModes: ["inline", "fullscreen"] } } }- Declare Support: You MUST declare all supported modes in the
How MCP Apps work: The Tool + Resource model
mainAn MCP App is a combination of two linked components that allow an LLM to trigger an interactive UI:
- Tool: Called by the LLM/host. It processes input and returns data.
- Resource: Serves the bundled HTML UI that displays the data.
The Linkage: The tool's metadata must include a reference to the resource's URI using the
_meta.ui.resourceUrikey.Lifecycle Flow: Host calls tool $\rightarrow$ Host renders resource UI $\rightarrow$ Server returns result $\rightarrow$ UI receives result.
Handle Host Context and Theming in a View
mainThe Host provides environment and styling information in the
hostContextfield of theMcpUiInitializeResult. Views should use this to adapt their appearance and behavior.Key context fields:
theme: Current preference ("light"or"dark").styles: Containsvariables(CSS custom properties) andcss(e.g.,@font-facerules) for the View to inject.displayMode: How the View is currently rendered ("inline","fullscreen", or"pip").containerDimensions: Sizing constraints for the iframe.locale&timeZone: User preferences for localization.platform: The host platform ("web","desktop", or"mobile").
// Host responds with McpUiInitializeResult { "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2026-01-26", "hostCapabilities": { /* ... */ }, "hostInfo": { "name": "claude-desktop", "version": "1.0.0" }, "hostContext": { "theme": "dark", "styles": { "variables": { "--color-background-primary": "light-dark(#ffffff, #171717)", "--color-text-primary": "light-dark(#171717, #fafafa)", "--font-sans": "Anthropic Sans, sans-serif" }, "css": { "fonts": "@font-face { font-family: \"Custom Font Name\"; src: url(\"https://...\"); }" } }, "displayMode": "inline", "containerDimensions": { "width": 400, "maxHeight": 600 } } } }How MCP Apps architecture works
mainMCP Apps uses a three-entity architecture to deliver interactive UIs securely:
- Server: A standard MCP server that declares tools and UI resources (HTML templates) using the
ui://URI scheme. - Host (Chat Client): The application (e.g., Claude Desktop) that connects to the server, embeds Views in sandboxed iframes, and acts as a proxy for communication.
- View (iframe): The UI running inside the sandboxed iframe. It acts as an MCP client, receiving tool data from the Host and communicating back via
postMessageto call tools or interact with the chat.
This model allows for Progressive Enhancement: if a Host does not support MCP Apps, tools still function as standard text/structured data tools. The UI is an optional enhancement.
- Server: A standard MCP server that declares tools and UI resources (HTML templates) using the