@mcp-ui/server Usage & Examples
This page provides practical examples for using the @mcp-ui/server
package.
For a complete example, see the typescript-server-demo
.
Basic Setup
First, ensure you have @mcp-ui/server
available in your project:
bash
npm i @mcp-ui/server
1
Basic Usage
The core function is createUIResource
.
typescript
import {
createUIResource,
} from '@mcp-ui/server';
// Using a shared enum value (just for demonstration)
console.log('Shared Enum from server usage:', PlaceholderEnum.FOO);
// Example 1: Direct HTML, delivered as text
const resource1 = createUIResource({
uri: 'ui://my-component/instance-1',
content: { type: 'rawHtml', htmlString: '<p>Hello World</p>' },
encoding: 'text',
});
console.log('Resource 1:', JSON.stringify(resource1, null, 2));
/* Output for Resource 1:
{
"type": "resource",
"resource": {
"uri": "ui://my-component/instance-1",
"mimeType": "text/html",
"text": "<p>Hello World</p>"
}
}
*/
// Example 2: Direct HTML, delivered as a Base64 blob
const resource2 = createUIResource({
uri: 'ui://my-component/instance-2',
content: { type: 'rawHtml', htmlString: '<h1>Complex HTML</h1>' },
encoding: 'blob',
});
console.log(
'Resource 2 (blob will be Base64):',
JSON.stringify(resource2, null, 2),
);
/* Output for Resource 2:
{
"type": "resource",
"resource": {
"uri": "ui://my-component/instance-2",
"mimeType": "text/html",
"blob": "PGRpdj48aDI+Q29tcGxleCBDb250ZW50PC9oMj48c2NyaXB0PmNvbnNvbGUubG9nKFwiTG9hZGVkIVwiKTwvc2NyaXB0PjwvZGl2Pg=="
}
}
*/
// Example 3: External URL, text encoding
const dashboardUrl = 'https://my.analytics.com/dashboard/123';
const resource3 = createUIResource({
uri: 'ui://analytics-dashboard/main',
content: { type: 'externalUrl', iframeUrl: dashboardUrl },
encoding: 'text',
});
console.log('Resource 3:', JSON.stringify(resource3, null, 2));
/* Output for Resource 3:
{
"type": "resource",
"resource": {
"uri": "ui://analytics-dashboard/main",
"mimeType": "text/uri-list",
"text": "https://my.analytics.com/dashboard/123"
}
}
*/
// Example 4: External URL, blob encoding (URL is Base64 encoded)
const chartApiUrl = 'https://charts.example.com/api?type=pie&data=1,2,3';
const resource4 = createUIResource({
uri: 'ui://live-chart/session-xyz',
content: { type: 'externalUrl', iframeUrl: chartApiUrl },
encoding: 'blob',
});
console.log(
'Resource 4 (blob will be Base64 of URL):',
JSON.stringify(resource4, null, 2),
);
/* Output for Resource 4:
{
"type": "resource",
"resource": {
"uri": "ui://live-chart/session-xyz",
"mimeType": "text/uri-list",
"blob": "aHR0cHM6Ly9jaGFydHMuZXhhbXBsZS5jb20vYXBpP3R5cGU9cGllJmRhdGE9MSwyLDM="
}
}
*/
// Example 5: Remote DOM script, text encoding
const remoteDomScript = `
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);
`;
const resource5 = createUIResource({
uri: 'ui://remote-component/action-button',
content: {
type: 'remoteDom',
script: remoteDomScript,
framework: 'react', // or 'webcomponents'
},
encoding: 'text',
});
console.log('Resource 5:', JSON.stringify(resource5, null, 2));
/* Output for Resource 5:
{
"type": "resource",
"resource": {
"uri": "ui://remote-component/action-button",
"mimeType": "application/vnd.mcp-ui.remote-dom+javascript; framework=react",
"text": "\\n const button = document.createElement('ui-button');\\n button.setAttribute('label', 'Click me for a tool call!');\\n button.addEventListener('press', () => {\\n window.parent.postMessage({ type: 'tool', payload: { toolName: 'uiInteraction', params: { action: 'button-click', from: 'remote-dom' } } }, '*');\\n });\\n root.appendChild(button);\\n"
}
}
*/
// These resource objects would then be included in the 'content' array
// of a toolResult in an MCP interaction.
1
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
Metadata Configuration Examples
The createUIResource
function supports three types of metadata configuration to enhance your UI resources:
typescript
import { createUIResource } from '@mcp-ui/server';
// Example 7: Using standard metadata
const resourceWithMetadata = createUIResource({
uri: 'ui://analytics/dashboard',
content: { type: 'rawHtml', htmlString: '<div id="dashboard">Loading...</div>' },
encoding: 'text',
metadata: {
title: 'Analytics Dashboard',
description: 'Real-time analytics and metrics',
created: '2024-01-15T10:00:00Z',
author: 'Analytics Team',
preferredRenderContext: 'sidebar'
}
});
console.log('Resource with metadata:', JSON.stringify(resourceWithMetadata, null, 2));
/* Output includes:
{
"type": "resource",
"resource": {
"uri": "ui://analytics/dashboard",
"mimeType": "text/html",
"text": "<div id=\"dashboard\">Loading...</div>",
"_meta": {
"title": "Analytics Dashboard",
"description": "Real-time analytics and metrics",
"created": "2024-01-15T10:00:00Z",
"author": "Analytics Team",
"preferredRenderContext": "sidebar"
}
}
}
*/
// Example 8: Using uiMetadata for client-side configuration
const resourceWithUIMetadata = createUIResource({
uri: 'ui://chart/interactive',
content: { type: 'externalUrl', iframeUrl: 'https://charts.example.com/widget' },
encoding: 'text',
uiMetadata: {
'preferred-frame-size': ['800px', '600px'],
'initial-render-data': {
theme: 'dark',
chartType: 'bar',
dataSet: 'quarterly-sales'
},
}
});
console.log('Resource with UI metadata:', JSON.stringify(resourceWithUIMetadata, null, 2));
/* Output includes:
{
"type": "resource",
"resource": {
"uri": "ui://chart/interactive",
"mimeType": "text/uri-list",
"text": "https://charts.example.com/widget",
"_meta": {
"mcpui.dev/ui-preferred-frame-size": ["800px", "600px"],
"mcpui.dev/ui-initial-render-data": {
"theme": "dark",
"chartType": "bar",
"dataSet": "quarterly-sales"
},
}
}
}
*/
// Example 9: Using resourceProps for additional MCP properties
const resourceWithProps = createUIResource({
uri: 'ui://form/user-profile',
content: { type: 'rawHtml', htmlString: '<form id="profile">...</form>' },
encoding: 'text',
resourceProps: {
annotations: {
audience: ['developers', 'admins'],
priority: 'high'
}
}
});
console.log('Resource with additional props:', JSON.stringify(resourceWithProps, null, 2));
/* Output includes:
{
"type": "resource",
"resource": {
"uri": "ui://form/user-profile",
"mimeType": "text/html",
"text": "<form id=\"profile\">...</form>",
"annotations": {
"audience": ["developers", "admins"],
"priority": "high"
}
}
}
*/
1
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Metadata Best Practices
- Use
metadata
for standard MCP resource information like titles, descriptions, timestamps, and authorship - Use
uiMetadata
for client rendering hints like preferred sizes, initial data, and context preferences - Use
resourceProps
for MCP specification properties like annotations, descriptions at the resource level, and other standard fields
Advanced URI List Example
You can provide multiple URLs in the text/uri-list
format for fallback purposes. However, MCP-UI requires a single URL and will only use the first valid URL found:
typescript
// Example 10: Multiple URLs with fallbacks (MCP-UI uses only the first)
const multiUrlContent = `# Primary dashboard
https://dashboard.example.com/main
# Backup dashboard (will be logged but not used)
https://backup.dashboard.example.com/main
# Emergency fallback (will be logged but not used)
https://emergency.dashboard.example.com/main`;
const resource = createUIResource({
uri: 'ui://dashboard-with-fallbacks/session-123',
content: { type: 'externalUrl', iframeUrl: multiUrlContent },
encoding: 'text',
});
/* The client will:
* 1. Use https://dashboard.example.com/main for rendering
* 2. Log a warning about the ignored backup URLs
* This allows you to specify fallback URLs in the standard format while MCP-UI focuses on the primary URL
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Error Handling
The createUIResource
function will throw errors if invalid combinations are provided, for example:
- URI not starting with
ui://
for any content type - Invalid content type specified
typescript
try {
createUIResource({
uri: 'invalid://should-be-ui',
content: { type: 'externalUrl', iframeUrl: 'https://example.com' },
encoding: 'text',
});
} catch (e: any) {
console.error('Caught expected error:', e.message);
// MCP-UI SDK: URI must start with 'ui://' when content.type is 'externalUrl'.
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10