npx skills add https://github.com/mcp-use/skills --skill mcp-builder使用 mcp-use 框架构建生产就绪的 MCP 服务器。本技能提供创建 MCP 服务器的快速入门指南和最佳实践。
始终使用 npx create-mcp-use-app 进行引导:
npx create-mcp-use-app my-mcp-server
cd my-mcp-server
根据需求选择模板:
--template starter - 功能齐全,包含所有 MCP 原语(工具、资源、提示) + 示例小组件
--template mcp-apps - 针对 ChatGPT 小组件优化,包含产品搜索示例
--template blank - 自定义实现的最小化起点
npx create-mcp-use-app my-server --template mcp-apps cd my-server yarn install
模板详情:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
mcp-apps 和 starter 模板会自动发现并注册 resources/ 文件夹中的 React 小组件:
单文件小组件模式:
resources/
└── weather-display.tsx # 小组件名称变为 "weather-display"
基于文件夹的小组件模式:
resources/
└── product-search/ # 小组件名称变为 "product-search"
├── widget.tsx # 入口点(必需名称!)
├── components/ # 子组件
├── hooks/ # 自定义钩子
├── types.ts
└── constants.ts
自动执行的操作:
resources/ 文件夹.tsx 文件或文件夹中的 widget.tsxwidgetMetadataweather-display)ui://widget/weather-display.html)无需手动注册! 只需导出 widgetMetadata 和一个默认组件。
工具是 AI 模型可以调用的可执行函数:
import { MCPServer, text, object } from "mcp-use/server";
import { z } from "zod";
const server = new MCPServer({
name: "my-server",
version: "1.0.0",
description: "My MCP server"
});
// 简单工具
server.tool(
{
name: "greet-user",
description: "按名称问候用户",
schema: z.object({
name: z.string().describe("用户姓名"),
formal: z.boolean().optional().describe("使用正式问候语")
})
},
async ({ name, formal }) => {
const greeting = formal ? `Good day, ${name}` : `Hey ${name}!`;
return text(greeting);
}
);
关键点:
.describe()资源暴露客户端可以读取的数据:
import { object, text, markdown } from "mcp-use/server";
// 静态资源
server.resource(
{
uri: "config://settings",
name: "应用设置",
description: "当前配置",
mimeType: "application/json"
},
async () => {
return object({
theme: "dark",
version: "1.0.0"
});
}
);
// 动态资源
server.resource(
{
uri: "stats://current",
name: "当前统计",
description: "实时统计信息",
mimeType: "application/json"
},
async () => {
const stats = await getStats();
return object(stats);
}
);
// Markdown 资源
server.resource(
{
uri: "docs://guide",
name: "用户指南",
description: "文档",
mimeType: "text/markdown"
},
async () => {
return markdown("# 指南\n\n欢迎!");
}
);
可用的响应助手:
text(string) - 纯文本object(data) - JSON 对象markdown(string) - Markdown 内容html(string) - HTML 内容image(buffer, mimeType) - 二进制图像audio(buffer, mimeType) - 音频文件binary(buffer, mimeType) - 二进制数据mix(...contents) - 组合多种内容类型高级响应示例:
// 音频响应
import { audio } from 'mcp-use/server';
// 从 base64 数据
return audio(base64Data, "audio/wav");
// 从文件路径(异步)
return await audio("/path/to/audio.mp3");
// 二进制数据(PDF 等)
import { binary } from 'mcp-use/server';
return binary(pdfBuffer, "application/pdf");
// 混合多种内容类型
import { mix, text, object, resource } from 'mcp-use/server';
return mix(
text("分析完成:"),
object({ score: 95, status: "pass" }),
resource("report://analysis-123", text("完整报告..."))
);
提示是用于 AI 交互的可重用模板:
server.prompt(
{
name: "code-review",
description: "生成代码审查模板",
schema: z.object({
language: z.string().describe("编程语言"),
focusArea: z.string().optional().describe("特定关注领域")
})
},
async ({ language, focusArea }) => {
const focus = focusArea ? ` with focus on ${focusArea}` : "";
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Please review this ${language} code${focus}.`
}
}
]
};
}
);
开发模式(热重载):
yarn dev
生产模式:
yarn build
yarn start
检查器 UI: 访问 http://localhost:3000/inspector 以测试工具、查看资源和尝试提示。
隧道(在部署前与 ChatGPT 测试):
选项 1 - 自动隧道:
mcp-use start --port 3000 --tunnel
选项 2 - 独立隧道:
yarn start # 终端 1
npx @mcp-use/tunnel 3000 # 终端 2
您将获得一个公共 URL,例如 https://happy-cat.local.mcp-use.run/mcp
隧道详情:
部署到 mcp-use Cloud(推荐):
# 首先登录(如果尚未登录)
npx mcp-use login
# 部署
yarn deploy
如果出现身份验证错误:
npx mcp-use login
yarn deploy
部署后:
https://your-server.mcp-use.com/mcp)工具设计:
.describe()资源设计:
提示设计:
测试:
部署:
npx mcp-use login使用 mcp-apps 或 starter 模板时,resources/ 文件夹中的小组件会自动注册:
// resources/weather-display.tsx
import { useWidget, McpUseProvider, type WidgetMetadata } from 'mcp-use/react';
import { z } from 'zod';
const propSchema = z.object({
city: z.string(),
temperature: z.number()
});
// 必需:导出小组件元数据
export const widgetMetadata: WidgetMetadata = {
description: "显示天气信息",
props: propSchema, // 使用 'props',而不是 'schema'!
};
// 必需:导出默认组件
export default function WeatherDisplay() {
const { props, isPending } = useWidget<z.infer<typeof propSchema>>();
// 始终处理加载状态
if (isPending) return <div>Loading...</div>;
return (
<McpUseProvider autoSize>
<div>
<h2>{props.city}</h2>
<p>{props.temperature}°C</p>
</div>
</McpUseProvider>
);
}
小组件自动变为可用:
weather-displayui://widget/weather-display.html控制小组件可以访问哪些外部资源:
export const widgetMetadata: WidgetMetadata = {
description: "天气小组件",
props: z.object({ city: z.string() }),
metadata: {
csp: {
// 要调用的 API
connectDomains: ["https://api.weather.com"],
// 要加载的静态资源
resourceDomains: ["https://cdn.weather.com"],
// 要嵌入的 iframe
frameDomains: ["https://embed.weather.com"],
// 脚本指令
scriptDirectives: ["'unsafe-inline'"],
},
},
};
或者,在服务器级别设置:
server.uiResource({
type: "mcpApps",
name: "my-widget",
htmlTemplate: `...`,
metadata: {
csp: {
connectDomains: ["https://api.example.com"],
resourceDomains: ["https://cdn.example.com"],
},
},
});
mcp-use 支持 MCP Apps 标准(SEP-1865),具有自动双协议支持:
import { MCPServer } from 'mcp-use/server';
const server = new MCPServer({
name: 'my-server',
version: '1.0.0',
baseUrl: process.env.MCP_URL || 'http://localhost:3000', // 小组件必需
});
// 注册一个双协议小组件
server.uiResource({
type: "mcpApps", // 同时适用于 MCP Apps 客户端和 ChatGPT
name: "weather-display",
htmlTemplate: `<!DOCTYPE html>...`,
metadata: {
csp: { connectDomains: ["https://api.weather.com"] },
prefersBorder: true,
autoResize: true,
},
});
自动执行的操作:
text/html;profile=mcp-app 和 _meta.ui.*text/html+skybridge 和 _meta.openai/*需要 ChatGPT 特定功能?组合两个元数据字段:
server.uiResource({
type: "mcpApps",
name: "my-widget",
htmlTemplate: `...`,
// 统一元数据(双协议)
metadata: {
csp: { connectDomains: ["https://api.example.com"] },
prefersBorder: true,
},
// ChatGPT 特定覆盖
appsSdkMetadata: {
"openai/widgetDescription": "ChatGPT 特定描述",
"openai/customFeature": "some-value", // 任何自定义 OpenAI 元数据
},
});
my-mcp-server/
├── resources/ # React 小组件(apps-sdk)
│ └── widget.tsx
├── public/ # 静态资源
├── index.ts # 服务器入口点
├── package.json
├── tsconfig.json
└── README.md
带有双协议小组件的工具:
import { MCPServer, widget, text } from 'mcp-use/server';
import { z } from 'zod';
const server = new MCPServer({
name: 'my-server',
version: '1.0.0',
baseUrl: process.env.MCP_URL || 'http://localhost:3000',
});
server.tool(
{
name: "show-data",
description: "使用可视化显示数据",
schema: z.object({
query: z.string()
}),
widget: {
name: "data-display", // 必须存在于 resources/ 中
invoking: "加载中...",
invoked: "数据已加载"
}
},
async ({ query }) => {
const data = await fetchData(query);
return widget({
props: { data },
output: text(`找到 ${data.length} 个结果`)
});
}
);
资源模板(参数化):
server.resourceTemplate(
{
uriTemplate: "user://{userId}/profile",
name: "用户资料",
description: "按 ID 获取用户",
mimeType: "application/json"
},
async ({ userId }) => {
const user = await fetchUser(userId);
return object(user);
}
);
错误处理:
server.tool(
{
name: "divide",
schema: z.object({
a: z.number(),
b: z.number()
})
},
async ({ a, b }) => {
if (b === 0) {
return text("错误:不能除以零");
}
return text(`结果:${a / b}`);
}
);
有关全面示例和高级模式,请连接到 mcp-use MCP 服务器,它提供:
命令:
npx create-mcp-use-app my-server - 引导yarn dev - 开发模式yarn build - 构建生产版本yarn start - 运行生产服务器mcp-use start --tunnel - 启动隧道npx mcp-use login - 身份验证yarn deploy - 部署到云端响应助手:
text(str), object(data), markdown(str), html(str)image(buf, mime), audio(buf, mime), binary(buf, mime)mix(...) - 组合多种内容类型widget({ props, output }) - 返回带有数据的小组件服务器方法:
server.tool() - 定义可执行工具server.resource() - 定义静态/动态资源server.resourceTemplate() - 定义参数化资源server.prompt() - 定义提示模板server.uiResource() - 定义小组件资源server.listen() - 启动服务器小组件元数据字段:
description - 小组件描述props - 小组件属性的 Zod 模式metadata - 统一配置(双协议)metadata.csp - 内容安全策略appsSdkMetadata - ChatGPT 特定覆盖可用模板:
starter - 功能齐全(工具、资源、提示、小组件)mcp-apps - ChatGPT 优化,带有产品示例blank - 最小化样板代码每周安装量
303
仓库
GitHub 星标
1
首次出现
2026年1月22日
安全审计
安装于
claude-code267
opencode101
gemini-cli97
codex97
github-copilot91
cursor88
Build production-ready MCP servers with the mcp-use framework. This Skill provides quick-start instructions and best practices for creating MCP servers.
Always bootstrap withnpx create-mcp-use-app:
npx create-mcp-use-app my-mcp-server
cd my-mcp-server
Choose template based on needs:
--template starter - Full-featured with all MCP primitives (tools, resources, prompts) + example widgets
--template mcp-apps - Optimized for ChatGPT widgets with product search example
--template blank - Minimal starting point for custom implementation
npx create-mcp-use-app my-server --template mcp-apps cd my-server yarn install
Template Details:
The mcp-apps and starter templates automatically discover and register React widgets from the resources/ folder:
Single-file widget pattern:
resources/
└── weather-display.tsx # Widget name becomes "weather-display"
Folder-based widget pattern:
resources/
└── product-search/ # Widget name becomes "product-search"
├── widget.tsx # Entry point (required name!)
├── components/ # Sub-components
├── hooks/ # Custom hooks
├── types.ts
└── constants.ts
What happens automatically:
resources/ folder at startup.tsx files or widget.tsx in folderswidgetMetadata from each componentweather-display)ui://widget/weather-display.html)No manual registration needed! Just export widgetMetadata and a default component.
Tools are executable functions that AI models can call:
import { MCPServer, text, object } from "mcp-use/server";
import { z } from "zod";
const server = new MCPServer({
name: "my-server",
version: "1.0.0",
description: "My MCP server"
});
// Simple tool
server.tool(
{
name: "greet-user",
description: "Greet a user by name",
schema: z.object({
name: z.string().describe("The user's name"),
formal: z.boolean().optional().describe("Use formal greeting")
})
},
async ({ name, formal }) => {
const greeting = formal ? `Good day, ${name}` : `Hey ${name}!`;
return text(greeting);
}
);
Key points:
.describe() to all parametersResources expose data that clients can read:
import { object, text, markdown } from "mcp-use/server";
// Static resource
server.resource(
{
uri: "config://settings",
name: "Application Settings",
description: "Current configuration",
mimeType: "application/json"
},
async () => {
return object({
theme: "dark",
version: "1.0.0"
});
}
);
// Dynamic resource
server.resource(
{
uri: "stats://current",
name: "Current Stats",
description: "Real-time statistics",
mimeType: "application/json"
},
async () => {
const stats = await getStats();
return object(stats);
}
);
// Markdown resource
server.resource(
{
uri: "docs://guide",
name: "User Guide",
description: "Documentation",
mimeType: "text/markdown"
},
async () => {
return markdown("# Guide\n\nWelcome!");
}
);
Response helpers available:
text(string) - Plain textobject(data) - JSON objectsmarkdown(string) - Markdown contenthtml(string) - HTML contentimage(buffer, mimeType) - Binary imagesaudio(buffer, mimeType) - Audio filesbinary(buffer, mimeType) - Binary datamix(...contents) - Combine multiple content typesAdvanced response examples:
// Audio response
import { audio } from 'mcp-use/server';
// From base64 data
return audio(base64Data, "audio/wav");
// From file path (async)
return await audio("/path/to/audio.mp3");
// Binary data (PDFs, etc.)
import { binary } from 'mcp-use/server';
return binary(pdfBuffer, "application/pdf");
// Mix multiple content types
import { mix, text, object, resource } from 'mcp-use/server';
return mix(
text("Analysis complete:"),
object({ score: 95, status: "pass" }),
resource("report://analysis-123", text("Full report..."))
);
Prompts are reusable templates for AI interactions:
server.prompt(
{
name: "code-review",
description: "Generate a code review template",
schema: z.object({
language: z.string().describe("Programming language"),
focusArea: z.string().optional().describe("Specific focus area")
})
},
async ({ language, focusArea }) => {
const focus = focusArea ? ` with focus on ${focusArea}` : "";
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Please review this ${language} code${focus}.`
}
}
]
};
}
);
Development mode (hot reload):
yarn dev
Production mode:
yarn build
yarn start
Inspector UI: Access at http://localhost:3000/inspector to test tools, view resources, and try prompts.
Tunneling (test with ChatGPT before deploying):
Option 1 - Auto-tunnel:
mcp-use start --port 3000 --tunnel
Option 2 - Separate tunnel:
yarn start # Terminal 1
npx @mcp-use/tunnel 3000 # Terminal 2
You'll get a public URL like https://happy-cat.local.mcp-use.run/mcp
Tunnel details:
Learn more: https://mcp-use.com/docs/tunneling
Deploy to mcp-use Cloud (recommended):
# Login first (if not already)
npx mcp-use login
# Deploy
yarn deploy
If authentication error:
npx mcp-use login
yarn deploy
After deployment:
https://your-server.mcp-use.com/mcp)Tool Design:
.describe() on all Zod fieldsResource Design:
Prompt Design:
Testing:
Deployment:
npx mcp-use login if deploy failsWhen using the mcp-apps or starter template, widgets in the resources/ folder are automatically registered:
// resources/weather-display.tsx
import { useWidget, McpUseProvider, type WidgetMetadata } from 'mcp-use/react';
import { z } from 'zod';
const propSchema = z.object({
city: z.string(),
temperature: z.number()
});
// Required: Export widget metadata
export const widgetMetadata: WidgetMetadata = {
description: "Display weather information",
props: propSchema, // Use 'props', not 'schema'!
};
// Required: Export default component
export default function WeatherDisplay() {
const { props, isPending } = useWidget<z.infer<typeof propSchema>>();
// Always handle loading state
if (isPending) return <div>Loading...</div>;
return (
<McpUseProvider autoSize>
<div>
<h2>{props.city}</h2>
<p>{props.temperature}°C</p>
</div>
</McpUseProvider>
);
}
Widget automatically becomes available as:
weather-displayui://widget/weather-display.htmlControl what external resources widgets can access:
export const widgetMetadata: WidgetMetadata = {
description: "Weather widget",
props: z.object({ city: z.string() }),
metadata: {
csp: {
// APIs to call
connectDomains: ["https://api.weather.com"],
// Static assets to load
resourceDomains: ["https://cdn.weather.com"],
// Iframes to embed
frameDomains: ["https://embed.weather.com"],
// Script directives
scriptDirectives: ["'unsafe-inline'"],
},
},
};
Alternatively, set at server level:
server.uiResource({
type: "mcpApps",
name: "my-widget",
htmlTemplate: `...`,
metadata: {
csp: {
connectDomains: ["https://api.example.com"],
resourceDomains: ["https://cdn.example.com"],
},
},
});
mcp-use supports the MCP Apps standard (SEP-1865) with automatic dual-protocol support:
import { MCPServer } from 'mcp-use/server';
const server = new MCPServer({
name: 'my-server',
version: '1.0.0',
baseUrl: process.env.MCP_URL || 'http://localhost:3000', // Required for widgets
});
// Register a dual-protocol widget
server.uiResource({
type: "mcpApps", // Works with BOTH MCP Apps clients AND ChatGPT
name: "weather-display",
htmlTemplate: `<!DOCTYPE html>...`,
metadata: {
csp: { connectDomains: ["https://api.weather.com"] },
prefersBorder: true,
autoResize: true,
},
});
What happens automatically:
text/html;profile=mcp-app with _meta.ui.*text/html+skybridge with _meta.openai/*Need ChatGPT-specific features? Combine both metadata fields:
server.uiResource({
type: "mcpApps",
name: "my-widget",
htmlTemplate: `...`,
// Unified metadata (dual-protocol)
metadata: {
csp: { connectDomains: ["https://api.example.com"] },
prefersBorder: true,
},
// ChatGPT-specific overrides
appsSdkMetadata: {
"openai/widgetDescription": "ChatGPT-specific description",
"openai/customFeature": "some-value", // Any custom OpenAI metadata
},
});
my-mcp-server/
├── resources/ # React widgets (apps-sdk)
│ └── widget.tsx
├── public/ # Static assets
├── index.ts # Server entry point
├── package.json
├── tsconfig.json
└── README.md
Tool with dual-protocol widget:
import { MCPServer, widget, text } from 'mcp-use/server';
import { z } from 'zod';
const server = new MCPServer({
name: 'my-server',
version: '1.0.0',
baseUrl: process.env.MCP_URL || 'http://localhost:3000',
});
server.tool(
{
name: "show-data",
description: "Display data with visualization",
schema: z.object({
query: z.string()
}),
widget: {
name: "data-display", // Must exist in resources/
invoking: "Loading...",
invoked: "Data loaded"
}
},
async ({ query }) => {
const data = await fetchData(query);
return widget({
props: { data },
output: text(`Found ${data.length} results`)
});
}
);
Resource template (parameterized):
server.resourceTemplate(
{
uriTemplate: "user://{userId}/profile",
name: "User Profile",
description: "Get user by ID",
mimeType: "application/json"
},
async ({ userId }) => {
const user = await fetchUser(userId);
return object(user);
}
);
Error handling:
server.tool(
{
name: "divide",
schema: z.object({
a: z.number(),
b: z.number()
})
},
async ({ a, b }) => {
if (b === 0) {
return text("Error: Cannot divide by zero");
}
return text(`Result: ${a / b}`);
}
);
For comprehensive examples and advanced patterns, connect to the mcp-use MCP server which provides:
Commands:
npx create-mcp-use-app my-server - Bootstrapyarn dev - Development modeyarn build - Build for productionyarn start - Run production servermcp-use start --tunnel - Start with tunnelnpx mcp-use login - Authenticateyarn deploy - Deploy to cloudResponse helpers:
text(str), object(data), markdown(str), html(str)image(buf, mime), audio(buf, mime), binary(buf, mime)mix(...) - Combine multiple content typeswidget({ props, output }) - Return widget with dataServer methods:
server.tool() - Define executable toolserver.resource() - Define static/dynamic resourceserver.resourceTemplate() - Define parameterized resourceserver.prompt() - Define prompt templateserver.uiResource() - Define widget resourceserver.listen() - Start serverWidget metadata fields:
description - Widget descriptionprops - Zod schema for widget propsmetadata - Unified config (dual-protocol)metadata.csp - Content Security PolicyappsSdkMetadata - ChatGPT-specific overridesAvailable templates:
starter - Full-featured (tools, resources, prompts, widgets)mcp-apps - ChatGPT-optimized with product exampleblank - Minimal boilerplateWeekly Installs
303
Repository
GitHub Stars
1
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code267
opencode101
gemini-cli97
codex97
github-copilot91
cursor88
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
140,500 周安装
阿里云AI视频万维视频测试技能 - 最小可行性测试与验证指南
245 周安装
阿里云Data Lake DLF Next API测试指南 - 最小可行测试与元数据验证
245 周安装
MCP Hub:连接1200+ MCP服务器,扩展Claude AI的文件、数据库和API集成能力
245 周安装
多智能体开发共享参考文档:CLI降级策略、后端检测与验证契约
245 周安装
Apify Actor 输出模式生成工具 - 自动化创建 dataset_schema.json 与 output_schema.json
245 周安装
rclone 文件传输技能:命令行工具配置与使用教程,支持 AWS S3、Google Drive 等云存储
245 周安装