MCPcopy
hub / github.com/MCP-UI-Org/mcp-ui

github.com/MCP-UI-Org/mcp-ui @v5.12.1 sqlite

repository ↗ · DeepWiki ↗ · release v5.12.1 ↗
711 symbols 1,071 edges 75 files 106 documented · 15%
README

📦 Model Context Protocol UI SDK

image

Server Version Client Version Ruby Server SDK Version Python Server SDK Version Discord MCP Documentation

What's mcp-ui?Core ConceptsInstallationGetting StartedWalkthroughExamplesSupported HostsSecurityRoadmapContributingLicense


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!

💡 What's mcp-ui?

mcp-ui is a collection of SDKs comprising:

  • @mcp-ui/server (TypeScript): Utilities to generate UI resources (UIResource) on your MCP server.
  • @mcp-ui/client (TypeScript): UI components (e.g., <UIResourceRenderer />) to render the UI resources and handle their events.
  • mcp_ui_server (Ruby): Utilities to generate UI resources on your MCP server in a Ruby environment.
  • mcp-ui-server (Python): Utilities to generate UI resources on your MCP server in a Python environment.

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).

UI Resource

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

interface UIResource {
  type: 'resource';
  resource: {
    uri: string;       // e.g., 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, external URL, or remote-dom script
    blob?: string;      // Base64-encoded HTML, URL, or remote-dom script
  };
}
  • 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 http/s URL and warns if additional URLs are found
  • text vs. blob: Choose text for simple strings; use blob for larger or encoded content.

Resource Renderer

The UI Resource is rendered in the <UIResourceRenderer /> component. It automatically detects the resource type and renders the appropriate component.

It is available as a React component and as a Web Component.

React Component

It accepts the following props: - resource: The resource object from an MCP Tool response. It must include uri, mimeType, and content (text, blob) - onUIAction: Optional callback for handling UI actions from the resource: typescript { type: 'tool', payload: { toolName: string, params: Record<string, unknown> }, messageId?: string } | { type: 'intent', payload: { intent: string, params: Record<string, unknown> }, messageId?: string } | { type: 'prompt', payload: { prompt: string }, messageId?: string } | { type: 'notify', payload: { message: string }, messageId?: string } | { type: 'link', payload: { url: string }, messageId?: string } When actions include a messageId, the iframe automatically receives response messages for asynchronous handling. - supportedContentTypes: Optional array to restrict which content types are allowed (['rawHtml', 'externalUrl', 'remoteDom']) - htmlProps: Optional props for the internal <HTMLResourceRenderer> - style: Optional custom styles for the iframe - iframeProps: Optional props passed to the iframe element - iframeRenderData: Optional Record<string, unknown> to pass data to the iframe upon rendering. This enables advanced use cases where the parent application needs to provide initial state or configuration to the sandboxed iframe content. - autoResizeIframe: Optional boolean | { width?: boolean; height?: boolean } to automatically resize the iframe to the size of the content. - remoteDomProps: Optional props for the internal <RemoteDOMResourceRenderer> - library: Optional component library for Remote DOM resources (defaults to basicComponentLibrary) - remoteElements: remote element definitions for Remote DOM resources.

Web Component

The Web Component is available as <ui-resource-renderer>. It accepts the same props as the React component, but they must be passed as strings.

Example:

<ui-resource-renderer
  resource='{ "mimeType": "text/html", "text": "<h2>Hello from the Web Component!</h2>" }'
></ui-resource-renderer>

The onUIAction prop can be handled by attaching an event listener to the component:

const renderer = document.querySelector('ui-resource-renderer');
renderer.addEventListener('onUIAction', (event) => {
  console.log('Action:', event.detail);
});

The Web Component is available in the @mcp-ui/client package at dist/ui-resource-renderer.wc.js.

Supported Resource Types

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

Rendered using the internal <HTMLResourceRenderer /> 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 http/s URL.

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

Rendered using the internal <RemoteDOMResourceRenderer /> component, which utilizes 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+javascript; framework={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 (see onUIAction prop). 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

TypeScript

# 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

Ruby

gem install mcp_ui_server

Python

# using pip
pip install mcp-ui-server

# or uv
uv add mcp-ui-server

🚀 Getting Started

You can use GitMCP to give your IDE access to mcp-ui's latest documentation!

TypeScript

  1. Server-side: Build your UI resources

```ts import { createUIResource } from '@mcp-ui/server'; import { createRemoteComponent, createRemoteDocument, createRemoteText, } from '@remote-dom/core';

// Inline HTML const htmlResource = createUIResource({ uri: 'ui://greeting/1', content: { type: 'rawHtml', htmlString: '

Hello, MCP UI!

' }, encoding: 'text', });

// External URL const externalUrlResource = createUIResource({ uri: 'ui://greeting/1', content: { type: 'externalUrl', iframeUrl: 'https://example.com' }, encoding: 'text', });

// remote-dom const remoteDomResource = createUIResource({ uri: 'ui://remote-component/action-button', content: { type: 'remoteDom', script: const button = document.createElement('ui-button'); button.setAttribute('label', 'Click me for a tool call!'); button.addEventListener('press', () => { window.parent.postMessage({ type: 'tool', payload: { toolName: 'uiInteraction', params: { action: 'button-click', from: 'remote-dom' } } }, '*'); }); root.appendChild(button);, framework: 'react', // or 'webcomponents' }, encoding: 'text', }); ```

  1. Client-side: Render in your MCP host

```tsx import React from 'react'; import { UIResourceRenderer } from '@mcp-ui/client';

function App({ mcpResource }) { if ( mcpResource.type === 'resource' && mcpResource.resource.uri?.startsWith('ui://') ) { return ( { console.log('Action:', result); }} /> ); } return

Unsupported resource

; } ```

Python

Server-side: Build your UI resources

```python from mcp_ui_server import create_ui_resource

# Inline HTML html_resource = create_ui_resource({ "uri": "ui://greeting/1", "content": { "type": "rawHtml", "htmlString": "

Hello, from Python!

" }, "encoding": "text", })

# External URL external_url_resource = create_ui_resource({ "uri": "ui://greeting/2", "content": { "type": "externalUrl", "iframeUrl": "https://example.com" }, "encoding": "text", }) ```

Ruby

Server-side: Build your UI resources

```ruby require 'mcp_ui_server'

# Inline HTML html_resource = McpUiServer.create_ui_resource( uri: 'ui://greeting/1', content: { type: :raw_html, htmlString: '

Hello, from Ruby!

' }, encoding: :text )

# External URL external_url_resource = McpUiServer.create_ui_resource( uri: 'ui://greeting/2', content: { type: :external_url, iframeUrl: 'https://example.com' }, encoding: :text )

# remote-dom remote_dom_resource = McpUiServer.create_ui_resource( uri: 'ui://remote-component/action-button', content: { type: :remote_dom, script: " const button = document.createElement('ui-button'); button.setAttribute('label', 'Click me from Ruby!'); button.addEventListener('press', () => { window.parent.postMessage({ type: 'tool', payload: { toolName: 'uiInteraction', params: { action: 'button-click', from: 'ruby-remote-dom' } } }, '*'); }); root.appendChild(button); ", framework: :react, }, encoding: :text ) ```

🚶 Walkthrough

For a detailed, simple, step-by-step guide on how to integrate mcp-ui into your own server, check out the full server walkthroughs on the mcp-ui documentation site:

These guides will show you how to add a mcp-ui endpoint to an existing server, create tools that return UI resources, and test your setup with the ui-inspector!

🌍 Examples

Client Examples * Goose - open source AI agent that supports mcp-ui. * LibreChat - enhanced ChatGPT clone that supports mcp-ui. * 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 * MCP-UI Web Component Demo (examples/wc-demo) - local demo app to test the Web Component integration in hosts

Server Examples * TypeScript: A full-featured server that is deployed to a hosted environment for easy testing. * **[typescript-server-demo](./exampl

Extension points exported contracts — how you extend this code

ServiceWorkerGlobalScope (Interface)
* This ServiceWorker API interface represents the global execution context of a service worker. * Available only in sec
examples/server/worker-configuration.d.ts
SandboxAPI (Interface)
(no doc)
sdks/typescript/client/src/types.ts
Performance (Interface)
* The Workers runtime supports a subset of the Performance API, used to measure timing and performance, * as well as ti
examples/server/worker-configuration.d.ts
RemoteElementConfiguration (Interface)
(no doc)
sdks/typescript/client/src/types.ts
Response (Interface)
* This Fetch API interface represents the response to a request. * * [MDN Reference](https://developer.mozilla.org/doc
examples/server/worker-configuration.d.ts
RenderOptions (Interface)
(no doc)
sdks/typescript/client/src/types.ts
Request (Interface)
* This Fetch API interface represents a resource request. * * [MDN Reference](https://developer.mozilla.org/docs/Web/A
examples/server/worker-configuration.d.ts
ComponentLibraryElement (Interface)
(no doc)
sdks/typescript/client/src/types.ts

Core symbols most depended-on inside this repo

render
called by 43
sdks/typescript/client/scripts/iframe-entry.js
processHTMLResource
called by 24
sdks/typescript/client/src/utils/processResource.ts
createUIResource
called by 23
sdks/typescript/server/src/index.ts
create_ui_resource
called by 14
sdks/python/server/src/mcp_ui_server/core.py
getAttribute
called by 14
examples/server/worker-configuration.d.ts
error
called by 13
examples/server/worker-configuration.d.ts
get
called by 11
examples/server/worker-configuration.d.ts
toString
called by 9
examples/server/worker-configuration.d.ts

Shape

Interface 278
Method 226
Class 120
Function 87

Languages

TypeScript90%
Python10%

Modules by API surface

examples/server/worker-configuration.d.ts535 symbols
sdks/python/server/tests/test_create_ui_resource.py22 symbols
examples/remote-dom-demo/src/libraries/webcomponents.ts22 symbols
sdks/python/server/src/mcp_ui_server/types.py15 symbols
examples/server/app/graph/graph.tsx12 symbols
sdks/python/server/tests/test_ui_action_results.py8 symbols
sdks/python/server/src/mcp_ui_server/utils.py8 symbols
sdks/python/server/src/mcp_ui_server/core.py8 symbols
sdks/typescript/server/src/index.ts7 symbols
sdks/typescript/client/src/types.ts5 symbols
sdks/typescript/client/scripts/iframe-entry.js5 symbols
examples/server/src/index.ts5 symbols

Dependencies from manifests, versioned

@cloudflare/vite-plugin1.0.12 · 1×
@cloudflare/workers-types4.20250515.0 · 1×
@eslint/js9.25.0 · 1×
@mcp-ui/clientworkspace:* · 1×
@mcp-ui/server5.2.0 · 1×
@modelcontextprotocol/sdk* · 1×
@quilted/threads3.1.3 · 1×
@r2wc/react-to-web-component2.0.4 · 1×
@radix-ui/react-checkbox1.3.2 · 1×
@radix-ui/react-dialog1.1.14 · 1×
@radix-ui/react-label2.1.7 · 1×

For agents

$ claude mcp add mcp-ui \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact