Skip to content

idosal/mcp-ui

Repository files navigation

📦 Model Context Protocol UI SDK

image

Server Version Client Version

What's mcp-ui?Core ConceptsInstallationQuickstartExamplesSecurityRoadmapContributingLicense


mcp-ui brings interactive web components to the Model Context Protocol (MCP). Deliver rich, dynamic UI resources directly from your MCP server to be rendered by the client. Take AI interaction to the next level!

This project is an experimental community playground for MCP UI ideas. Expect rapid iteration and enhancements!

mcpui.mp4

💡 What's mcp-ui?

mcp-ui is a TypeScript SDK comprising two packages:

  • @mcp-ui/server: Utilities to generate UI snippets (HtmlResourceBlock) on your MCP server.
  • @mcp-ui/client: UI components (e.g., <ResourceRenderer />) to render those snippets and handle their events.

Together, they let you define reusable UI snippets on the server side, seamlessly and securely render them in the client, and react to their actions in the MCP host environment.

✨ Core Concepts

In essence, by using mcp-ui SDKs, servers and hosts can agree on contracts that enable them to create and render interactive UI snippets (as a path to a standardized UI approach in MCP).

HTML Resource Block

The primary payload returned from the server to the client is the HtmlResourceBlock:

interface HtmlResourceBlock {
  type: 'resource';
  resource: {
    uri: string;       // ui://component/id
    mimeType: 'text/html' | 'text/uri-list' | 'application/vnd.mcp-ui.remote-dom'; // text/html for HTML content, text/uri-list for URL content, application/vnd.mcp-ui.remote-dom for remote-dom content (Javascript)
    text?: string;      // Inline HTML or external URL
    blob?: string;      // Base64-encoded HTML or URL
  };
}
  • uri: Unique identifier for caching and routing
    • ui://… — UI resources (rendering method determined by mimeType)
  • mimeType: text/html for HTML content (iframe srcDoc), text/uri-list for URL content (iframe src), application/vnd.mcp-ui.remote-dom for remote-dom content (Javascript)
    • MCP-UI requires a single URL: While text/uri-list format supports multiple URLs, MCP-UI uses only the first valid URL and logs others
  • text vs. blob: Choose text for simple strings; use blob for larger or encoded content.

Resource Renderer

The HTML Resource Block is rendered in the <ResourceRenderer /> component. It automatically detects the resource type and renders the appropriate component.

It accepts the following props:

  • resource: The resource object from an MCP response. Should include uri, mimeType, and content (text, blob, or content)
  • onUiAction: Optional callback for handling UI actions from the resource:
    { type: 'tool', payload: { toolName: string, params: Record<string, unknown> } } |
    { type: 'intent', payload: { intent: string, params: Record<string, unknown> } } |
    { type: 'prompt', payload: { prompt: string } } |
    { type: 'notification', payload: { message: string } } |
    { type: 'link', payload: { url: string } }
  • supportedContentTypes: Optional array to restrict which content types are allowed (['rawHtml', 'externalUrl', 'remoteDom'])
  • style: Optional custom styles for iframe-based resources
  • iframeProps: Optional props passed to iframe elements (for HTML/URL resources)
  • library: Optional component library for Remote DOM resources (defaults to basicComponentLibrary)
  • remoteElements: Optional remote element definitions for Remote DOM resources. REQUIRED for Remote DOM snippets.

Supported Resource Types

HTML (text/html and text/uri-list)

Rendered using the <HtmlResource /> component, which displays content inside an <iframe>. This is suitable for self-contained HTML or embedding external apps.

  • mimeType:
    • text/html: Renders inline HTML content.
    • text/uri-list: Renders an external URL. MCP-UI uses the first valid URL.

Remote DOM (application/vnd.mcp-ui.remote-dom)

Rendered using the <RemoteDomResource /> component, which uses Shopify's remote-dom. The server responds with a script that describes the UI and events. On the host, the script is securely rendered in a sandboxed iframe, and the UI changes are communicated to the host in JSON, where they're rendered using the host's component library. This is more flexible than iframes and allows for UIs that match the host's look-and-feel.

  • mimeType: application/vnd.mcp-ui.remote-dom; flavor={react | webcomponents}

UI Action

UI snippets must be able to interact with the agent. In mcp-ui, this is done by hooking into events sent from the UI snippet and reacting to them in the host. For example, an HTML may trigger a tool call when a button is clicked by sending an event which will be caught handled by the client.

🏗️ Installation

# using npm
npm install @mcp-ui/server @mcp-ui/client

# or pnpm
pnpm add @mcp-ui/server @mcp-ui/client

# or yarn
yarn add @mcp-ui/server @mcp-ui/client

🎬 Quickstart

  1. Server-side: Build your resource blocks

    import { createHtmlResource } from '@mcp-ui/server';
    import {
     createRemoteComponent,
     createRemoteDocument,
     createRemoteText,
    } from '@remote-dom/core';
    
    // Inline HTML
    const htmlResource = createHtmlResource({
      uri: 'ui://greeting/1',
      content: { type: 'rawHtml', htmlString: '<p>Hello, MCP UI!</p>' },
      delivery: 'text',
    });
    
    // External URL
    const externalUrlResource = createHtmlResource({
      uri: 'ui://greeting/1',
      content: { type: 'externalUrl', iframeUrl: 'https://example.com' },
      delivery: 'text',
    });
  2. Client-side: Render in your MCP host

    import React from 'react';
    import { ResourceRenderer } from '@mcp-ui/client';
    
    function App({ mcpResource }) {
      if (
        mcpResource.type === 'resource' &&
        mcpResource.resource.uri?.startsWith('ui://')
      ) {
        return (
          <ResourceRenderer
            resource={mcpResource.resource}
            onUiAction={(result) => {
              console.log('Action:', result);
              return { status: 'ok' };
            }}
          />
        );
      }
      return <p>Unsupported resource</p>;
    }
  3. Enjoy interactive MCP UI snippets — no extra configuration required.

🌍 Examples

Client example

  • ui-inspector - inspect local mcp-ui-enabled servers.
  • MCP-UI Chat - interactive chat built with the mcp-ui client. Check out the hosted version!
  • MCP-UI RemoteDOM Playground (examples/remote-dom-demo) - local demo app to test RemoteDOM resources (intended for hosts)

Server example Try out the hosted app -

  • HTTP Streaming: https://remote-mcp-server-authless.idosalomon.workers.dev/mcp
  • SSE: https://remote-mcp-server-authless.idosalomon.workers.dev/sse

The app is deployed from examples/server.

Drop those URLs into any MCP-compatible host to see mcp-ui in action.

🔒 Security

Host and user security is one of mcp-ui's primary concerns. In all content types, the remote code is executed in a sandboxed iframe.

🛣️ Roadmap

  • Add online playground
  • Expand UI Action API (beyond tool calls)
  • Support Web Components
  • Support Remote-DOM
  • Add component libraries (in progress)
  • Add declarative UI content type
  • Support generative UI?

🤝 Contributing

Contributions, ideas, and bug reports are welcome! See the contribution guidelines to get started.

📄 License

Apache License 2.0 © The MCP-UI Authors

Disclaimer

This project is provided "as is", without warranty of any kind. The mcp-ui authors and contributors shall not be held liable for any damages, losses, or issues arising from the use of this software. Use at your own risk.

About

SDK for UI over MCP. Create next-gen UI experiences!

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published