UI资源 MCP 服务器
一个集成了新UIResource的MCP服务器,用于简化小部件管理并确保MCP与UI的兼容性。
特点/特性
- 🚀 UIResource 方法一种同时注册工具和资源的单一方法
- 🎨 React 小部件使用React构建的交互式用户界面组件
- 🔄 自动注册自动创建的工具和资源
- 📦 感谢参数(或“参数的功劳”)小部件属性自动成为工具参数
- 🌐 兼容MCP-UI与MCP-UI客户端完全兼容
- 🛠️ TypeScript 支持完全的类型安全和IntelliSense(智能感知)功能
新特性:UIResource
这个(或:该) uiResource 该方法是一个强大的新功能,简化了小部件的注册过程:
// Old way: Manual registration of tool and resource
server.tool({
/* tool config */
})
server.resource({
/* resource config */
})
// New way: Single method does both!
server.uiResource({
name: 'kanban-board',
widget: 'kanban-board',
title: 'Kanban Board',
props: {
initialTasks: { type: 'array', required: false },
theme: { type: 'string', default: 'light' },
},
})这会自动创建:
- 工具:
kanban-board- 接受参数并返回UIResource - 资源:
ui://widget/kanban-board- 使用默认值的静态访问
入门指南
发展
# Install dependencies
npm install
# Start development server with hot reloading
npm run dev这将开始:
- 端口3000上的MCP服务器
- 小部件服务在
/mcp-use/widgets/* - 检查器用户界面(Inspector UI)在
/inspector
生产
# Build the server and widgets
npm run build
# Run the built server
npm start基本用法
简单的小部件注册
import { createMCPServer } from 'mcp-use/server'
const server = createMCPServer('my-server', {
version: '1.0.0',
description: 'Server with UIResource widgets',
})
// Register a widget - creates both tool and resource
server.uiResource({
name: 'my-widget',
widget: 'my-widget',
title: 'My Widget',
description: 'An interactive widget',
})
server.listen(3000)带有属性的小部件
server.uiResource({
name: 'data-chart',
widget: 'chart',
title: 'Data Chart',
description: 'Interactive data visualization',
props: {
data: {
type: 'array',
description: 'Data points to display',
required: true,
},
chartType: {
type: 'string',
description: 'Type of chart (line/bar/pie)',
default: 'line',
},
theme: {
type: 'string',
description: 'Visual theme',
default: 'light',
},
},
size: ['800px', '400px'], // Preferred iframe size
annotations: {
audience: ['user', 'assistant'],
priority: 0.8,
},
})小部件开发
1. 创建您的小部件组件
// resources/my-widget.tsx
import React, { useState, useEffect } from 'react'
import { createRoot } from 'react-dom/client'
interface MyWidgetProps {
initialData?: any
theme?: 'light' | 'dark'
}
const MyWidget: React.FC = ({
initialData = [],
theme = 'light',
}) => {
const [data, setData] = useState(initialData)
// Load props from URL query parameters
useEffect(() => {
const params = new URLSearchParams(window.location.search)
const dataParam = params.get('initialData')
if (dataParam) {
try {
setData(JSON.parse(dataParam))
} catch (e) {
console.error('Error parsing data:', e)
}
}
const themeParam = params.get('theme')
if (themeParam) {
// Apply theme
}
}, [])
return
{/* Your widget UI */}
}
// Mount the widget
const container = document.getElementById('widget-root')
if (container) {
createRoot(container).render()
}2. 向UIResource注册
// src/server.ts
server.uiResource({
name: 'my-widget',
widget: 'my-widget',
title: 'My Custom Widget',
description: 'A custom interactive widget',
props: {
initialData: {
type: 'array',
description: 'Initial data for the widget',
required: false,
},
theme: {
type: 'string',
description: 'Widget theme',
default: 'light',
},
},
size: ['600px', '400px'],
})其工作原理
工具注册
当你打电话时 uiResource,它会自动创建一个工具:
- 名字:
[widget-name] - 接受所有属性作为参数
- 返回文本描述和UIResource对象
资源注册
同时创建一个资源:
- URI(统一资源标识符):
ui://widget/[widget-name] - 返回具有默认属性值的 UIResource
- 可被MCP客户端发现
参数传递
工具参数自动:
- 转换为URL查询参数
- 复杂对象被转换为JSON字符串
- 通过iframe URL传递给小部件
高级示例
多个小部件
const widgets = [
{
name: 'todo-list',
widget: 'todo-list',
title: 'Todo List',
props: {
items: { type: 'array', default: [] },
},
},
{
name: 'calendar',
widget: 'calendar',
title: 'Calendar',
props: {
date: { type: 'string', required: false },
},
},
]
// Register all widgets
widgets.forEach((widget) => server.uiResource(widget))混合注册
// UIResource for widgets
server.uiResource({
name: 'dashboard',
widget: 'dashboard',
title: 'Analytics Dashboard',
})
// Traditional tool for actions
server.tool({
name: 'calculate',
description: 'Perform calculations',
cb: async (params) => {
/* ... */
},
})
// Traditional resource for data
server.resource({
name: 'config',
uri: 'config://app',
mimeType: 'application/json',
readCallback: async () => {
/* ... */
},
})API 参考文档
server.uiResource(definition)
参数
definition: UIResourceDefinition
- name: string - 资源标识符 - widget: string - 小部件目录名称 - title?: string - 人类可读的标题 - description?: string - 小部件描述 - props?: WidgetProps - 小部件属性配置 - size?: [string, string] - 推荐的iframe尺寸 - annotations?: ResourceAnnotations - 发现提示
WidgetProps(可译为“小部件属性”)
每个道具可以具有:
type: 'string' | 'number' | 'boolean' | 'object' | 'array'required?: boolean- 是否需要道具default?: any- 未提供时的默认值description?: string- 属性描述
测试您的小工具
通过检查器用户界面
- 启动服务器:
npm run dev - 开放:
http://localhost:3000/inspector - 测试工具和资源
直接浏览器访问
访问: http://localhost:3000/mcp-use/widgets/[widget-name]
通过MCP客户端
// Call as tool
const result = await client.callTool('kanban-board', {
initialTasks: [...],
theme: 'dark'
})
// Access as resource
const resource = await client.readResource('ui://widget/kanban-board')UIResource的优势
✅ 简化版API - 用一种方法代替两种 ✅ 自动布线 - 道具自动成为工具输入 ✅ 类型安全 - 完全支持TypeScript ✅ MCP-UI 兼容 - 与所有MCP-UI客户端兼容 ✅(勾选标记,通常表示正确、确认或已完成) DRY原则 - 不要重复创建UIResource ✅ 可发现的 - 工具和资源均已列出
故障排除
小部件未加载
- 确保小部件存在
dist/resources/mcp-use/widgets/ - 检查服务器控制台中的错误
- 验证小部件是否已注册
uiResource()
未传递属性
- 在浏览器开发者工具中检查URL参数
- 确保属性名完全匹配
- 复杂对象必须被转换为JSON字符串
类型错误
- 导入类型:
import type { UIResourceDefinition } from 'mcp-use/server' - 确保mcp-use已更新至最新版本
从旧模式向新模式的转变
如果你已有使用单独工具/资源的现有代码:
// Old pattern
server.tool({ name: 'show-widget' /* ... */ })
server.resource({ uri: 'ui://widget' /* ... */ })
// New pattern - replace both with:
server.uiResource({
name: 'widget',
widget: 'widget',
// ... consolidated configuration
})未来的改进/增强
即将推出:
- 从文件系统中自动发现小部件
- 小部件清单(widget.json)
- 从TypeScript接口中提取属性
- 构建时优化
了解更多
祝你小部件构建愉快! 🚀
