← Back to Articles
MCPMCP AppsInteractive UIAI ToolsChatGPTClaude

MCP Apps: The Complete Guide to Interactive UI Components in AI Conversations (2026)

Learn how MCP Apps bring interactive UI components like dashboards, forms, and visualizations directly into AI conversations. Complete guide with code examples and implementation steps.

By Web MCP GuideMarch 8, 202621 min read


Key Takeaways


  • MCP Apps are a new extension to the Model Context Protocol that let MCP tools return interactive UI components — dashboards, forms, charts, and visualizations — directly inside AI conversations.

  • Announced on January 26, 2026, MCP Apps represent the biggest evolution of MCP since the protocol's initial release, bridging the gap between text-based tool responses and rich interactive experiences.

  • MCP Apps work through sandboxed iframes rendered inside the host client, with a secure message-passing interface between the app and the AI conversation.

  • Supported clients already include ChatGPT, Claude, Goose, and VS Code Copilot, with more adopting the standard rapidly.

  • Building an MCP App requires extending your existing MCP server with UI resource declarations and bundled frontend assets — no separate deployment needed.
  • ---

    What Are MCP Apps? The Next Evolution of AI Tool Integration

    If you've been building with the Model Context Protocol (MCP), you know the fundamental pattern: an AI model calls a tool, the tool returns text or structured data, and the model presents it to the user. It works, but it's limited. What if your tool could return an interactive dashboard instead of a wall of JSON?

    That's exactly what MCP Apps deliver.

    MCP Apps are an extension to the MCP specification that allows tools to return interactive UI components rendered directly within the AI conversation. Instead of the model interpreting raw data and formatting it as text, an MCP App can present a fully interactive chart, a configuration form, a document editor, or a real-time monitoring dashboard — all without leaving the chat interface.

    Why Text-Only Responses Hit a Wall

    Consider a database query tool. With traditional MCP, you ask the AI to query your database, and the tool returns rows of data. The AI then formats it as a markdown table. This works for 10 rows. What about 10,000? What about wanting to sort, filter, or drill down into the data?

    Or think about a deployment tool. The AI tells you "deployment started" and then you wait, asking "is it done yet?" repeatedly. An MCP App could show you a live progress bar with real-time logs streaming in.

    The limitations of text-only tool responses become obvious when you need:

  • Data exploration — sorting, filtering, paginating large datasets

  • Visual feedback — charts, graphs, progress indicators

  • User input — forms, configuration wizards, multi-step workflows

  • Real-time updates — live dashboards, streaming logs, monitoring panels
  • How MCP Apps Differ from Regular MCP Tools

    A regular MCP tool declaration looks like this:

    {
    name: "query_database",
    description: "Run a SQL query against the production database",
    inputSchema: {
    type: "object",
    properties: {
    query: { type: "string", description: "SQL query to execute" }
    }
    }
    }

    An MCP App extends this with a ui field:

    {
    name: "explore_database",
    description: "Interactive database explorer with filtering, sorting, and visualization",
    inputSchema: {
    type: "object",
    properties: {
    connection: { type: "string", description: "Database connection name" }
    }
    },
    ui: {
    type: "iframe",
    resource: "database-explorer",
    width: "100%",
    height: 600,
    permissions: ["clipboard-write"]
    }
    }

    The key difference: when the AI calls this tool, instead of returning text, it renders an interactive iframe inside the conversation. The user can interact with it directly — clicking, typing, sorting — without the AI needing to mediate every action.

    ---

    How MCP Apps Work Under the Hood

    Understanding the architecture helps you build better MCP Apps and debug issues when they arise. The system has three main layers: declaration, rendering, and communication.

    UI Resource Declarations

    Every MCP App starts with a UI resource declaration in your MCP server's capabilities. This tells the client what UI assets are available and how to load them:

    server.setRequestHandler(ListResourcesRequestSchema, async () => {
    return {
    resources: [
    {
    uri: "ui://database-explorer",
    name: "Database Explorer",
    description: "Interactive database query and visualization tool",
    mimeType: "text/html"
    }
    ]
    };
    });

    When the client requests this resource, your server returns an HTML bundle:

    server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
    if (request.params.uri === "ui://database-explorer") {
    return {
    contents: [{
    uri: request.params.uri,
    mimeType: "text/html",
    text: getDatabaseExplorerHTML() // Your bundled HTML/CSS/JS
    }]
    };
    }
    });

    Sandboxed Iframe Rendering

    The client renders MCP Apps inside sandboxed iframes with carefully controlled permissions. This is critical for security — you don't want a third-party MCP App accessing the parent page's DOM or cookies.

    The sandbox attributes typically include:

  • allow-scripts — JavaScript execution within the iframe

  • allow-forms — Form submission within the iframe

  • allow-same-origin — Required for some storage APIs (controlled by client policy)
  • What's explicitly not allowed:

  • Access to the parent window's DOM

  • Navigation of the top-level page

  • Popups or new windows

  • Access to the parent page's cookies or storage
  • Message Passing Between App and Conversation

    MCP Apps communicate with the AI conversation through a structured message-passing protocol using postMessage. This is how an app can send data back to the conversation or request additional tool calls:

    // Inside your MCP App's frontend code
    const mcpBridge = {
    // Send a result back to the conversation
    sendResult(data) {
    window.parent.postMessage({
    type: 'mcp-app-result',
    payload: data
    }, '*');
    },

    // Request the AI to call another tool
    requestToolCall(toolName, args) {
    window.parent.postMessage({
    type: 'mcp-app-tool-request',
    tool: toolName,
    arguments: args
    }, '*');
    },

    // Listen for data from the conversation
    onData(callback) {
    window.addEventListener('message', (event) => {
    if (event.data.type === 'mcp-app-data') {
    callback(event.data.payload);
    }
    });
    }
    };

    This bidirectional communication is what makes MCP Apps truly interactive rather than just static embeds.

    > People Also Ask: Can MCP Apps access my local files?
    > MCP Apps run in sandboxed iframes and cannot directly access local files. However, the MCP server behind the app can access files if it has the appropriate permissions, and pass data to the app through the message-passing protocol. The app itself is isolated from the host system.

    ---

    Use Cases: What Can You Build with MCP Apps?

    MCP Apps unlock an entirely new category of AI tool interactions. Here are the most compelling use cases developers are building right now.

    Data Exploration and Visualization

    This is the killer use case. Instead of asking your AI to "show me sales data for Q4" and getting a text table, an MCP App can render an interactive dashboard with:

  • Sortable, filterable data tables with pagination

  • Interactive charts (bar, line, pie, scatter) powered by D3.js or Chart.js

  • Drill-down capabilities — click a data point to see underlying records

  • Export buttons for CSV/PDF download
  • // Example: Data explorer MCP App tool
    {
    name: "sales_dashboard",
    description: "Interactive sales data dashboard with charts and filtering",
    inputSchema: {
    type: "object",
    properties: {
    dateRange: { type: "string", enum: ["7d", "30d", "90d", "1y"] },
    region: { type: "string", description: "Filter by region" }
    }
    },
    ui: {
    type: "iframe",
    resource: "sales-dashboard",
    width: "100%",
    height: 500
    }
    }

    Configuration Wizards and Forms

    Instead of the AI asking you 15 sequential questions to configure a deployment, an MCP App can present a complete configuration form:

  • Multi-step wizards with validation

  • Dropdown menus populated from live data (e.g., available regions, instance types)

  • Toggle switches, sliders, and other rich input controls

  • Real-time cost estimates as you adjust settings
  • Document Review and Editing

    MCP Apps can render document previews with annotation capabilities:

  • PDF viewing with highlight and comment tools

  • Diff viewers for code review

  • Markdown editors with live preview

  • Spreadsheet interfaces for data editing
  • Real-Time Monitoring

    For DevOps and infrastructure use cases:

  • Live log streaming with search and filtering

  • Server health dashboards with auto-refreshing metrics

  • Deployment progress tracking with rollback buttons

  • Alert management interfaces
  • Interactive Code Playgrounds

    For developer tools:

  • Embedded code editors (Monaco/CodeMirror) with syntax highlighting

  • Live preview panes for HTML/CSS/JS

  • API testing interfaces similar to Postman

  • Schema designers for databases or API definitions
  • > People Also Ask: Do MCP Apps work offline?
    > MCP Apps are served by your MCP server, so they require the server connection to be active. However, once loaded, the frontend assets run in the browser and can function with limited connectivity. Any data operations still require the server connection.

    ---

    How to Build Your First MCP App: Step-by-Step Guide

    Let's build a complete MCP App from scratch — an interactive JSON data explorer that lets users visualize, search, and filter JSON data returned by an API.

    Step 1: Set Up Your MCP Server

    Start with a standard MCP server. If you're new to this, check our guide to building your first MCP server.

    import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
    import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

    const server = new McpServer({
    name: "json-explorer",
    version: "1.0.0",
    capabilities: {
    tools: {},
    resources: {},
    ui: { supported: true } // Declare UI support
    }
    });

    Step 2: Create the UI Resource

    Bundle your frontend as a single HTML file with embedded CSS and JavaScript:

    function getExplorerHTML(): string {
    return















    ;
    }

    Step 3: Register the Tool and Resource

    import { z } from "zod";

    // Register the UI resource
    server.resource("json-explorer-ui", "ui://json-explorer", async (uri) => ({
    contents: [{
    uri: uri.href,
    mimeType: "text/html",
    text: getExplorerHTML()
    }]
    }));

    // Register the tool with UI attachment
    server.tool(
    "explore_json",
    "Fetch and explore JSON data interactively with search, filtering, and tree navigation",
    {
    url: z.string().describe("URL to fetch JSON from"),
    headers: z.record(z.string()).optional().describe("Optional HTTP headers")
    },
    async ({ url, headers }) => {
    const response = await fetch(url, { headers });
    const data = await response.json();

    return {
    content: [
    { type: "text", text: Loaded JSON data from ${url} }
    ],
    ui: {
    resource: "ui://json-explorer",
    data: data // This gets sent to the app via postMessage
    }
    };
    }
    );

    Step 4: Connect the Transport and Run

    const transport = new StdioServerTransport();
    await server.connect(transport);

    Step 5: Configure in Your Client

    Add the server to your client configuration. For Claude Desktop, update claude_desktop_config.json:

    {
    "mcpServers": {
    "json-explorer": {
    "command": "npx",
    "args": ["tsx", "path/to/your/server.ts"]
    }
    }
    }

    For more on Claude Desktop configuration, see our Claude Desktop MCP setup guide.

    > People Also Ask: Can I use React or Vue in my MCP App?
    > Yes! You can use any frontend framework, but you'll need to bundle it into a single HTML file (or host it externally and reference the URL). Tools like Vite with the vite-plugin-singlefile plugin make this straightforward. Many developers use React with a single-file build for complex MCP Apps.

    ---

    Supported Clients: Where MCP Apps Work Today

    MCP Apps require client-side support to render the iframe and manage the communication bridge. Here's the current state of support as of early 2026:

    ChatGPT (Full Support)

    OpenAI added MCP Apps support in their February 2026 update. ChatGPT renders MCP Apps inline in the conversation with full sandbox security. The implementation is polished, with smooth transitions and responsive iframe sizing.

    Claude (Full Support)

    Anthropic's Claude Desktop and Claude.ai both support MCP Apps. Claude was one of the first clients to implement the specification, which makes sense given Anthropic's role in creating MCP. The Claude Desktop setup documentation covers MCP Apps configuration in detail.

    Goose (Full Support)

    Block's open-source AI agent Goose has had MCP Apps support since launch, making it a favorite for developers building and testing MCP Apps locally.

    VS Code Copilot (Partial Support)

    GitHub Copilot in VS Code supports MCP Apps in the Copilot Chat panel. The rendering area is more constrained due to the sidebar layout, so apps need to be responsive. Full-width rendering is available when using Copilot in the editor panel.

    Other Clients

    The MCP ecosystem is growing fast. Check our MCP architecture deep dive for a broader view of the protocol's client landscape.

    ---

    MCP Apps vs OpenAI Apps SDK: How They Compare

    When OpenAI released their Apps SDK around the same time, many developers asked: how do MCP Apps compare?

    Philosophy


  • MCP Apps: Open standard, works across any MCP-compatible client. You build once and it works in ChatGPT, Claude, Goose, VS Code, and any future client that implements the spec.

  • OpenAI Apps SDK: Proprietary to OpenAI's ecosystem. Tighter integration with ChatGPT, but locked to one platform.
  • Technical Approach

    | Aspect | MCP Apps | OpenAI Apps SDK |
    |--------|----------|-----------------|
    | Standard | Open (MCP spec) | Proprietary (OpenAI) |
    | Client support | Multi-client | ChatGPT only |
    | Rendering | Sandboxed iframes | Custom components |
    | Communication | postMessage protocol | SDK callbacks |
    | Hosting | Self-hosted or bundled | OpenAI-hosted option |
    | Framework | Any (HTML/CSS/JS) | React recommended |

    When to Choose MCP Apps

    Choose MCP Apps when:

  • You want cross-client compatibility

  • You're already building MCP servers

  • You prefer open standards over vendor lock-in

  • You need full control over hosting and data
  • When to Choose OpenAI Apps SDK

    Choose the OpenAI Apps SDK when:

  • You're building exclusively for ChatGPT

  • You want managed hosting through OpenAI

  • You prefer the higher-level React component abstractions

  • You need deep integration with ChatGPT-specific features
  • For most developers building MCP tools and resources, MCP Apps is the natural choice since it extends what you already have.

    > People Also Ask: Will MCP Apps replace traditional MCP tools?
    > No. MCP Apps are an extension, not a replacement. Many tools work perfectly as text responses — looking up a definition, running a calculation, fetching a single record. MCP Apps are for use cases where interactivity adds genuine value. Think of them as the rich response option, not the default.

    ---

    Advanced Patterns: Building Production-Grade MCP Apps

    Once you've built your first MCP App, here are patterns for taking them to production.

    State Synchronization

    Keep the AI conversation and the app UI in sync:

    // In your MCP App frontend
    class StateSync {
    private state = {};

    update(patch) {
    this.state = { ...this.state, ...patch };
    this.render();
    // Notify the conversation about state changes
    window.parent.postMessage({
    type: 'mcp-app-state-update',
    state: this.state
    }, '*');
    }

    render() {
    // Re-render UI based on current state
    }
    }

    This pattern lets the AI understand what the user has done in the app (e.g., "I see you selected the 'us-east-1' region in the form — shall I proceed with that configuration?").

    Lazy Loading and Performance

    For large apps, load assets progressively:

    // Load heavy libraries only when needed
    async function loadChartLibrary() {
    if (!window.Chart) {
    const script = document.createElement('script');
    script.src = 'https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js';
    document.head.appendChild(script);
    await new Promise(resolve => script.onload = resolve);
    }
    }

    Responsive Design

    MCP Apps render in different contexts — full-width chat panels, narrow sidebars, mobile screens. Always build responsively:

    / MCP App responsive patterns /
    .app-container {
    max-width: 100%;
    padding: 12px;
    }

    @media (max-width: 500px) {
    .data-table { font-size: 12px; }
    .chart-container { height: 200px; }
    .toolbar { flex-direction: column; }
    }

    Error Handling and Fallbacks

    Always provide a text fallback for clients that don't support MCP Apps:

    async ({ url }) => {
    const data = await fetchData(url);

    return {
    content: [
    {
    type: "text",
    text: formatAsTable(data) // Text fallback
    }
    ],
    ui: {
    resource: "ui://data-explorer",
    data: data,
    fallbackText: "Interactive explorer requires a UI-capable client. Showing text table above."
    }
    };
    }

    > People Also Ask: How large can an MCP App be?
    > There's no hard specification limit, but practical considerations apply. The HTML bundle is transferred through the MCP protocol, so keeping it under 1-2 MB is recommended. Use CDN links for heavy libraries (Chart.js, D3, Monaco Editor) rather than inlining them. For very complex apps, consider hosting the frontend externally and referencing it via URL.

    ---

    Security Considerations for MCP Apps

    MCP Apps introduce a new attack surface since they execute JavaScript in the user's client. Security is paramount.

    Iframe Sandboxing

    Clients must enforce strict sandbox attributes. As a server developer, design your apps to work within these constraints:

  • No access to parent.document

  • No access to cookies or localStorage of the host page

  • Limited postMessage communication through the defined protocol
  • Content Security Policy

    Include CSP headers in your HTML to prevent XSS within your app:

          content="default-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net;
    connect-src 'none';
    frame-src 'none';">

    Data Handling

    Be careful about what data you pass to the app frontend:

  • Never send credentials or API keys to the frontend

  • Sanitize data before rendering (prevent stored XSS)

  • Validate all data received back from the app via postMessage
  • For a deeper dive into MCP security, read our comprehensive MCP security best practices guide.

    > People Also Ask: Can MCP Apps make network requests?
    > By default, MCP Apps should not be able to make outbound network requests due to sandbox restrictions. However, some clients may allow connect-src for specific domains. The recommended pattern is for the app to request data through the MCP server (via postMessage → tool call) rather than making direct network requests. This keeps the server as the security boundary.

    ---

    Building MCP Apps with Python

    Not a TypeScript developer? The Python MCP SDK supports MCP Apps too:

    from mcp.server import Server
    from mcp.types import Resource, Tool, TextContent, UIContent

    app = Server("data-explorer")

    @app.list_resources()
    async def list_resources():
    return [
    Resource(
    uri="ui://chart-builder",
    name="Chart Builder",
    description="Interactive chart creation tool",
    mimeType="text/html"
    )
    ]

    @app.read_resource()
    async def read_resource(uri: str):
    if uri == "ui://chart-builder":
    html = open("chart_builder.html").read()
    return html

    @app.call_tool()
    async def call_tool(name: str, arguments: dict):
    if name == "build_chart":
    data = fetch_data(arguments["query"])
    return {
    "content": [TextContent(type="text", text=f"Chart data loaded: {len(data)} points")],
    "ui": UIContent(resource="ui://chart-builder", data=data)
    }

    For more on Python MCP development, see our Getting started with MCP in Python guide.

    ---

    Real-World MCP Apps Examples

    Here are MCP Apps that teams are building and deploying in production:

    1. Database Admin Dashboard


    A complete database administration interface with table browsing, query editing (with syntax highlighting), result visualization, and schema exploration. Replaces the need to switch to a separate DB client.

    2. Kubernetes Cluster Manager


    View pod status, scale deployments, read logs, and manage configurations — all from within your AI conversation. Perfect for incident response when you don't want to context-switch.

    3. API Documentation Browser


    Interactive API docs with a built-in request tester. Browse endpoints, see schemas, and test calls without leaving the chat.

    4. Financial Data Explorer


    Interactive candlestick charts, portfolio allocation views, and scenario modeling tools for financial analysis conversations.

    5. CI/CD Pipeline Monitor


    Real-time build status, test results, and deployment progress with one-click rollback buttons.

    ---

    Frequently Asked Questions

    What is the minimum MCP version required for Apps?

    MCP Apps were introduced in the MCP specification version 2026-01-26. Your MCP SDK must be updated to at least this version. Both the TypeScript SDK (@modelcontextprotocol/sdk@2.1.0+) and Python SDK (mcp>=2.1.0) support MCP Apps.

    Can MCP Apps persist state between conversations?

    MCP Apps themselves don't persist state — they're created fresh each time the tool is called. However, your MCP server can persist state (in a database, file system, etc.) and pass saved state to the app when it initializes. The MCP memory server pattern works well for this.

    How do I debug MCP Apps during development?

    Use your browser's DevTools. Since MCP Apps render in iframes, you can inspect them in the Elements panel and use the Console panel to debug JavaScript. Most clients also expose MCP protocol logs — check our debugging MCP server issues guide for detailed steps.

    Are MCP Apps accessible (WCAG compliant)?

    Accessibility is your responsibility as the app developer. Use semantic HTML, ARIA labels, keyboard navigation, and sufficient color contrast. The iframe sandbox doesn't prevent you from building accessible interfaces.

    Can multiple MCP Apps be displayed simultaneously?

    This depends on the client implementation. Currently, most clients show one MCP App at a time per conversation turn. Some clients like VS Code support side-by-side rendering. The specification allows for multiple simultaneous apps.

    Do MCP Apps work on mobile clients?

    Yes, if the mobile client supports MCP Apps. The iframe rendering adapts to the available screen size. Build your apps with responsive design to ensure they work well on smaller screens.

    Can MCP Apps communicate with each other?

    Not directly. Each MCP App runs in its own sandbox. However, they can communicate indirectly through the MCP server — one app saves state, the next app reads it. The conversation context also serves as a communication bridge.

    How do I version my MCP Apps?

    Include a version in your resource URI (e.g., ui://data-explorer/v2) and maintain backward compatibility. Clients cache resources, so versioned URIs ensure users get the latest version.

    What's the performance impact of MCP Apps?

    MCP Apps add the overhead of iframe creation and HTML parsing, typically 50-200ms depending on app complexity. For most use cases, this is negligible compared to the LLM response time. Keep your initial bundle small and lazy-load heavy assets.

    Can I monetize MCP Apps?

    Yes. MCP Apps follow the same distribution model as MCP servers. You can distribute them as open-source, sell them as part of a SaaS product, or offer them through MCP server marketplaces. The app code runs on your server, so you maintain full control over licensing and access.

    ---

    What's Next for MCP Apps?

    MCP Apps are still in their early days, but the trajectory is clear. Expect to see:

  • App marketplaces curated by client providers

  • Richer inter-app communication protocols

  • Collaborative apps where multiple users interact with the same MCP App in shared conversations

  • Native component libraries that match each client's design system

  • Offline-capable apps with service worker support
  • The future of MCP is interactive, visual, and deeply integrated into how we work with AI. MCP Apps are the bridge between text-based tool calling and the rich, interactive experiences that users expect.

    Start building your first MCP App today — the tools are ready, the clients support it, and the possibilities are wide open.