MCP Apps

Interactive HTML UI resources and tool visual interfaces for MCP clients supporting the MCP Apps extension.

The MCP Apps extension (io.modelcontextprotocol/ui) allows MCP servers to serve interactive web applications (HTML/CSS/JS) directly as resources and bind them to tools. When supported by an MCP client, the client can render an interactive user interface alongside or in place of standard tool outputs. For the official protocol specification, schemas, and client SDKs, refer to the modelcontextprotocol/ext-apps repository.

Note

Protocol Version Differences:

  • Modern Protocol (2026-07-28): Supports the official MCP extensions capability negotiation. The server advertises io.modelcontextprotocol/ui under capabilities.extensions during server/discover, and dynamically enables _meta.ui on tools when the client also advertises io.modelcontextprotocol/ui in its request capabilities.
  • Legacy Protocols (2024-11-05, 2025-03-26, 2025-06-18, and 2025-11-25): Toolbox backports io.modelcontextprotocol/ui extension capability negotiation to initialize and tools/list across earlier protocol versions, and provides a --disable-extension-check startup flag for legacy clients that do not advertise extension capabilities.

Defining a UI Resource

In Toolbox, UI capabilities are configured directly on standard resources (kind: resource or kind: resourceTemplate) by setting ui: true.

Any type of resource can function as an interactive MCP App simply by setting ui: true. When ui: true is set:

  • mimeType must be text/html;profile=mcp-app (defaults automatically if omitted; explicit non-conforming types are rejected).
  • uri defaults to ui://{name} if omitted.
  • Security policies (CSP), device permissions, application domain, and container display settings can be configured.
kind: resource
name: customer_dashboard
type: file
path: "./ui/dashboard.html"
description: "Interactive customer metrics dashboard."
ui: true
domain: "https://example.com"
prefersBorder: true
csp:
  connectDomains:
    - "https://api.example.com"
  resourceDomains:
    - "https://cdn.example.com"
permissions:
  - clipboardWrite

UI Resource Configuration

When ui: true is enabled on kind: resource or kind: resourceTemplate, the following fields can be configured:

fieldtyperequireddescription
uiboolYesSet to true to designate this resource as an interactive MCP UI application.
mimeTypestringNoMIME type of the UI resource. Must be text/html;profile=mcp-app (defaults automatically if omitted).
domainstringNoApplication domain. Must be a valid absolute URI with an http or https scheme (e.g., https://example.com).
cspCSPConfigNoContent Security Policy restricting the domains that the UI app can communicate with or load assets from.
permissions[]stringNoList of browser device permissions requested by the app (e.g., camera, microphone, geolocation, clipboardWrite).
prefersBorderboolNoSuggests whether the host client should render a visible border around the app container.

Content Security Policy (CSP)

To safeguard client environments from untrusted origins, Toolbox allows you to define a strict Content Security Policy for your UI resources. All origins must include a valid protocol scheme (http or https) and host:

fieldtypedescription
connectDomains[]stringAllowed origins for fetch and XMLHttpRequest connections (connect-src).
resourceDomains[]stringAllowed origins for scripts, styles, images, and fonts (script-src, img-src, etc.).
frameDomains[]stringAllowed origins for nested iframes (frame-src).
baseUriDomains[]stringAllowed origins for document base URIs (base-uri).

Permissions

The permissions field specifies browser capabilities requested by the UI app. The following permissions are supported:

  • camera: Access to video capture devices.
  • microphone: Access to audio capture devices.
  • geolocation: Access to geographic location data.
  • clipboardWrite: Permission to write text and data to the system clipboard.

Linking Tools to UI Resources

Tools can link directly to a UI resource so clients know which visual interface to render when executing the tool.

To associate a tool with a UI resource, add the ui block to the tool’s configuration:

kind: tool
name: view_customer_dashboard
type: postgres-sql
source: my-db
statement: "SELECT * FROM customers WHERE id = $1"
description: "Retrieves customer records and displays an interactive dashboard."
parameters:
  - name: customer_id
    type: integer
    description: "The unique ID of the customer."
ui:
  resource: customer_dashboard
  visibility:
    - model
    - app

Tool UI Schema

fieldtyperequireddescription
resourcestringYesThe name of a configured resource or resourceTemplate providing the UI for this tool (must have ui: true).
visibility[]stringNoControls who can see the tool. Allowed values are model and app. Defaults to ["model", "app"] if omitted.

Visibility Options

  • model: The tool is advertised to LLMs for automated tool calling.
  • app: The tool is exposed to the interactive UI application for direct invocation.
  • Both (["model", "app"]): The default setting, allowing both the model and the UI app to call the tool.

Global Availability & Group Scoping

Unlike standard tools, prompts, or resources that are scoped to specific Groups, UI resources are strictly global and cannot be scoped to groups:

  1. Server-Wide Tool References: Tools in any group can link to UI resources without needing to declare the UI resource in that group.
  2. UI Resource Requirement: Toolbox validates that every ui.resource referenced by a tool exists and is explicitly configured as a UI resource (ui: true). Referencing a standard (non-UI) resource or template will fail startup validation with an error:
    resource "<name>" referenced by tool "<tool>" is not a UI resource (ui: true is required)
    
  3. Forbidden in Groups: UI resources and UI resource templates (ui: true) cannot be included in groups[].resources or groups[].resourceTemplates. Attempting to add a UI resource to a group will fail startup validation with an error:
    UI resource "<name>" cannot be included in group "<group>": UI resources are globally accessible and cannot be scoped to groups
    
  4. Omitted from Resource Listing: UI resources (ui: true) are intentionally excluded from resources/list and resources/templates/list across all endpoints (including the default /mcp group endpoint) so they do not clutter standard LLM context. Clients obtain the UI resource URI directly from the tool’s manifest metadata and retrieve it via resources/read.

Capability Negotiation & Graceful Degradation

  • Modern Protocol (2026-07-28): Employs dynamic client capability negotiation to ensure backwards compatibility with standard text-only MCP clients:

    1. Client Advertising: Clients that support interactive apps advertise the extension in their request metadata (_meta):
      {
        "_meta": {
          "io.modelcontextprotocol/clientCapabilities": {
            "extensions": {
              "io.modelcontextprotocol/ui": {
                "mimeTypes": ["text/html;profile=mcp-app"]
              }
            }
          }
        }
      }
      
    2. Graceful Degradation:
      • When a client supports the UI extension, Toolbox includes UI metadata on tools in tools/list under _meta.ui:
        {
          "name": "view_customer_dashboard",
          "description": "Retrieves customer records and displays an interactive dashboard.",
          "_meta": {
            "ui": {
              "resourceUri": "ui://customer_dashboard",
              "visibility": ["model", "app"]
            }
          }
        }
        
      • When a client does not support the UI extension (or omits io.modelcontextprotocol/ui), Toolbox automatically strips _meta.ui from tool definitions, serving the tool as a standard text-based tool.
      • All tools continue to return standard structured text output in their content array regardless of UI mode.
  • Legacy Protocols (2024-11-05, 2025-03-26, 2025-06-18, and 2025-11-25):

    • Toolbox backports client capability advertisement and negotiation to all legacy protocols to support modern clients running on older endpoints:
      1. Initialization: Clients advertise UI capabilities during initialize via capabilities.extensions["io.modelcontextprotocol/ui"] (with mimeTypes: ["text/html;profile=mcp-app"]). When present, Toolbox advertises server UI capability in InitializeResult.capabilities.extensions["io.modelcontextprotocol/ui"]: {}. If omitted by the client, server extensions is omitted.
      2. Per-Request Negotiation: Clients should also advertise UI support in request metadata (_meta or params.capabilities) on tools/list:
        {
          "_meta": {
            "io.modelcontextprotocol/clientCapabilities": {
              "extensions": {
                "io.modelcontextprotocol/ui": {
                  "mimeTypes": ["text/html;profile=mcp-app"]
                }
              }
            }
          }
        }
        
      3. Graceful Degradation: When UI capabilities are advertised, Toolbox includes _meta.ui on tools in tools/list. If the client does not advertise UI support, Toolbox gracefully degrades by omitting _meta.ui from tool definitions, ensuring full backward compatibility with standard text-only clients.
      4. Bypassing Capability Checks (--disable-extension-check): For clients on older protocol versions that render MCP Apps without advertising io.modelcontextprotocol/ui capabilities during initialize or tools/list, start Toolbox with --disable-extension-check:
        ./toolbox --config tools.yaml --disable-extension-check
        
        When enabled, Toolbox bypasses the client extension capability check in older protocol versions (2024-11-05 through 2025-11-25) and always includes io.modelcontextprotocol/ui in InitializeResult.capabilities.extensions and _meta.ui on tools in tools/list.
      5. Resource Retrieval: UI documents and security policies remain available via resources/read for clients that support rendering MCP Apps.

Reading UI Resources

When a client or host application requests a UI resource via resources/read, Toolbox delivers the HTML document along with the declared security policies in the content item’s _meta.ui:

{
  "contents": [
    {
      "uri": "ui://customer_dashboard",
      "mimeType": "text/html;profile=mcp-app",
      "text": "<!DOCTYPE html><html>...</html>",
      "_meta": {
        "ui": {
          "csp": {
            "connectDomains": ["https://api.example.com"],
            "resourceDomains": ["https://cdn.example.com"]
          },
          "permissions": {
            "clipboardWrite": {}
          },
          "domain": "https://example.com",
          "prefersBorder": true
        }
      }
    }
  ]
}

The host application uses this _meta.ui payload to configure iframe sandbox policies, enforce Content Security Policy headers, and apply frame boundary styling.




Last modified October 22, 2026: chore(main): release 1.15.0 (#4255) (8e8e569)