Getting Started
This guide will help you get started with the MCP-UI SDK, which provides tools for building Model Context Protocol (MCP) enabled applications with interactive UI components.
Prerequisites
- Node.js (v22.x recommended for the Typescript SDK)
- pnpm (v9 or later recommended for the Typescript SDK)
- Ruby (v3.x recommended for the Ruby SDK)
Installation
This project is a monorepo that includes the server and client SDKs.
For Typescript SDKs (@mcp-ui/server
and @mcp-ui/client
)
Clone the Monorepo:
bashgit clone https://github.com/idosal/mcp-ui.git cd mcp-ui
1
2Install Dependencies: From the root of the
mcp-ui
monorepo, run:bashpnpm install
1This command installs dependencies for all packages (
shared
,client
,server
,docs
) and links them together using pnpm.
For Ruby SDK (mcp_ui_server
)
Add this line to your application's Gemfile:
gem 'mcp_ui_server'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install mcp_ui_server
Building Packages
To build all library packages (shared
, client
, server
):
pnpm --filter=!@mcp-ui/docs build
Each package uses Vite for building and will output distributable files to its respective dist
directory.
Running Tests
To run all tests across the monorepo using Vitest:
pnpm test
Or for coverage:
pnpm run coverage
Using the Packages
Once built, you can typically import from the packages as you would with any other npm module, assuming your project is set up to resolve them.
In a Server-Side Project
// main.ts (your server-side application)
import { createUIResource } from '@mcp-ui/server';
const myHtmlPayload = `<h1>Hello from Server!</h1><p>Timestamp: ${new Date().toISOString()}</p>`;
const resourceBlock = createUIResource({
uri: 'ui://server-generated/item1',
content: { type: 'rawHtml', htmlString: myHtmlPayload },
encoding: 'text',
});
// Send this resourceBlock as part of your MCP response...
2
3
4
5
6
7
8
9
10
11
12
# main.rb (your server-side application)
require 'mcp_ui_server'
my_html_payload = "<h1>Hello from Server!</h1><p>Timestamp: #{Time.now.iso8601}</p>"
resource_block = McpUiServer.create_ui_resource(
uri: 'ui://server-generated/item1',
content: { type: :raw_html, htmlString: my_html_payload },
encoding: :text
)
# Send this resource_block as part of your MCP response...
2
3
4
5
6
7
8
9
10
11
12
In a React Project (Client-Side Example)
// App.tsx (your React application)
import React, { useState, useEffect } from 'react';
import { UIResourceRenderer, UIActionResult } from '@mcp-ui/client';
// Dummy MCP response structure
interface McpToolResponse {
content: any[];
}
function App() {
const [mcpData, setMcpData] = useState<McpToolResponse | null>(null);
// Simulate fetching MCP data
useEffect(() => {
const fakeMcpResponse: McpToolResponse = {
content: [
{
type: 'resource',
resource: {
uri: 'ui://client-example/dynamic-section',
mimeType: 'text/html',
text: '<h2>Dynamic Content via MCP-UI</h2><button onclick="alert(\'Clicked!\')">Click me</button>',
},
},
],
};
setMcpData(fakeMcpResponse);
}, []);
const handleResourceAction = async (result: UIActionResult) => {
if (result.type === 'tool') {
console.log(`Action from resource (tool: ${result.payload.toolName}):`, result.payload.params);
} else if (result.type === 'prompt') {
console.log(`Prompt from resource:`, result.payload.prompt);
} else if (result.type === 'link') {
console.log(`Link from resource:`, result.payload.url);
} else if (result.type === 'intent') {
console.log(`Intent from resource:`, result.payload.intent);
} else if (result.type === 'notify') {
console.log(`Notification from resource:`, result.payload.message);
}
// Add your handling logic (e.g., initiate followup tool call)
return { status: 'Action received by client' };
};
return (
<div className="App">
<h1>MCP Client Application</h1>
{mcpData?.content.map((item, index) => {
if (
item.type === 'resource' &&
item.resource.uri?.startsWith('ui://')
) {
return (
<div
key={item.resource.uri || index}
style={{
border: '1px solid #eee',
margin: '10px',
padding: '10px',
}}
>
<h3>Resource: {item.resource.uri}</h3>
<UIResourceRenderer
resource={item.resource}
onUIAction={handleResourceAction}
/>
</div>
);
}
return <p key={index}>Unsupported content item</p>;
})}
</div>
);
}
export default App;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
Next, explore the specific guides for each SDK package to learn more about their APIs and capabilities.
To build specifically this package from the monorepo root:
pnpm build -w @mcp-ui/client
See the following pages for more details:
Basic Setup
For MCP servers, you can use one of the server-side SDKs:
@mcp-ui/server
for Node.js projectsmcp_ui_server
for Ruby projects
For MCP clients, ensure @mcp-ui/client
and its peer dependencies (react
and potentially @modelcontextprotocol/sdk
) are installed in your React project.
npm i @mcp-ui/client
Key Components
Server-Side SDKs
@mcp-ui/server
(TypeScript):createUIResource
: Creates UI resource objects for MCP tool responses
mcp_ui_server
(Ruby):McpUiServer.create_ui_resource
: Creates UI resource objects for MCP tool responses
- Handles HTML content, external URLs, Remote DOM JS, and encoding options
Client-Side (@mcp-ui/client
)
<UIResourceRenderer />
: Main component for rendering all types of MCP-UI resources<HTMLResourceRenderer />
: Internal component for HTML resources<RemoteDOMResourceRenderer />
: Internal component for Remote DOM resources
Resource Types
MCP-UI supports several resource types:
- HTML Resources (
text/html
): Direct HTML content - External URLs (
text/uri-list
): External applications and websites - Remote DOM Resources (
application/vnd.mcp-ui.remote-dom+javascript
): Javascript-defined UI that use host-native components
All resource types are handled automatically by <UIResourceRenderer />
.
Next Steps
- Server SDKs: Learn how to create resources with our server-side packages.
- Client SDK: Learn how to render resources.
- Web Component Usage & Examples
- Protocol & Components: