mcpField
M
mcp-builder

mcp-builder

github.com/mcp-use开发2699 次安装39 周前更新
代码仓库

关于 mcp-builder

mcp-builder 是面向使用 mcp-use 框架创建 MCP 服务的开发者技能,涵盖项目初始化、服务端原语、组件、测试与部署,并提供模板和实践模式。

主要功能

  1. 01使用模板初始化项目
  2. 02定义工具、资源和提示词
  3. 03自动注册 React 组件
  4. 04通过 Inspector 和隧道测试
  5. 05构建并部署服务

适用场景

  1. 01从模板启动 MCP 服务
  2. 02添加 MCP 工具和资源
  3. 03创建交互式组件应用
  4. 04通过 MCP 客户端测试服务

MCP 相关

该技能指导开发者创建向 MCP 客户端提供工具、资源、提示词和组件资源的 MCP 服务,也介绍通过隧道使用客户端进行测试。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mcp-use/skills --skill mcp-builder

安装后在 Claude Code 中输入/mcp-builder确认已加载。

附带文件LICENSE.txt

详细介绍

MCP 服务构建器

使用 mcp-use 框架构建可用于生产环境的 MCP 服务。本 Skill 提供创建 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 - 为自定义实现提供最简起点
# Example: MCP Apps template
npx create-mcp-use-app my-server --template mcp-apps
cd my-server
yarn install

模板详情:

  • starter:最适合学习——包含所有 MCP 功能和小组件
  • mcp-apps:最适合 ChatGPT 应用——包含商品轮播图/手风琴示例
  • blank:最适合专家——仅包含最少的样板代码

MCP Apps 结构

自动注册小组件

mcp-apps 和 starter 模板会自动发现并注册 resources/ 文件夹中的 React 小组件:

单文件小组件模式:

resources/
└── weather-display.tsx  # Widget name becomes "weather-display"

基于文件夹的小组件模式:

resources/
└── product-search/      # Widget name becomes "product-search"
    ├── widget.tsx       # Entry point (required name!)
    ├── components/      # Sub-components
    ├── hooks/           # Custom hooks
    ├── types.ts
    └── constants.ts

自动执行的操作:

  1. 服务启动时扫描 resources/ 文件夹
  2. 查找 .tsx 文件或文件夹中的 widget.tsx
  3. 从每个组件中提取 widgetMetadata
  4. 注册为 MCP Tool(例如 weather-display)
  5. 注册为 MCP Resource(例如 ui://widget/weather-display.html)
  6. 使用 Vite 构建小组件包

无需手动注册! 只需导出 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"
});

// 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);
  }
);

要点:

  • 使用 Zod 验证架构
  • 为所有参数添加 .describe()
  • 返回适当的响应类型(文本、对象、小组件)

定义资源

资源提供客户端可读取的数据:

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!");
  }
);

可用的响应辅助函数:

  • text(string) - 纯文本
  • object(data) - JSON 对象
  • markdown(string) - Markdown 内容
  • html(string) - HTML 内容
  • image(buffer, mimeType) - 二进制图像
  • audio(buffer, mimeType) - 音频文件
  • binary(buffer, mimeType) - 二进制数据
  • mix(...contents) - 组合多种内容类型

高级响应示例:

// 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..."))
);

定义提示词

提示词是可重复使用的 AI 交互模板:

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}.`
          }
        }
      ]
    };
  }
);

本地测试

开发模式(热重载):

yarn dev

生产模式:

yarn build
yarn start

检查器 UI: 访问 http://localhost:3000/inspector,即可测试工具、查看资源并试用提示词。

建立隧道(部署前使用 ChatGPT 测试):

选项 1 - 自动建立隧道:

mcp-use start --port 3000 --tunnel

选项 2 - 单独建立隧道:

yarn start  # Terminal 1
npx @mcp-use/tunnel 3000  # Terminal 2

你会获得一个公共 URL,例如 https://happy-cat.local.mcp-use.run/mcp

隧道详情:

  • 24 小时后过期
  • 闲置 1 小时后关闭
  • 速率限制:每小时创建 10 个,每个 IP 最多同时启用 5 个

了解更多:https://mcp-use.com/docs/tunneling

部署

部署到 mcp-use Cloud(推荐):

# Login first (if not already)
npx mcp-use login

# Deploy
yarn deploy

如果出现身份验证错误:

npx mcp-use login
yarn deploy

部署后:

  • 提供公共 URL(例如 https://your-server.mcp-use.com/mcp)
  • 自动扩缩容并进行监控
  • 已启用 HTTPS
  • 部署期间零停机

最佳实践

工具设计:

  • ✅ 一个工具 = 一项专注的能力
  • ✅ 使用描述清晰的名称和说明
  • ✅ 对所有 Zod 字段使用 .describe()
  • ✅ 妥善处理错误
  • ✅ 返回有帮助的错误消息

资源设计:

  • ✅ 使用清晰的 URI 方案(config://、docs://、stats://)
  • ✅ 选择合适的 MIME 类型
  • ✅ 使用响应辅助函数,让代码更简洁
  • ✅ 在需要时将资源设为动态资源

提示词设计:

  • ✅ 保持提示词可复用
  • ✅ 使用系统消息提供上下文
  • ✅ 使用 Zod 架构设置参数
  • ✅ 包含清晰的说明

测试:

  • ✅ 先使用 Inspector UI 进行测试
  • ✅ 部署前使用隧道与真实客户端进行测试
  • ✅ 确认所有工具、资源和提示词都能按预期工作

部署:

  • ✅ 先在本地和通过隧道进行测试
  • ✅ 如果部署失败,运行 npx mcp-use login
  • ✅ 按语义化版本规范管理服务版本
  • ✅ 记录不兼容变更

Widget 支持

自动注册 Widget

使用 mcp-apps 或 starter 模板时,resources/ 文件夹中的 Widget 会自动注册:

// 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 会自动成为:

  • MCP 工具:weather-display
  • MCP 资源:ui://widget/weather-display.html
内容安全策略(CSP)

控制 Widget 可以访问哪些外部资源:

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'"],
    },
  },
};

也可以在服务级别设置:

server.uiResource({
  type: "mcpApps",
  name: "my-widget",
  htmlTemplate: `...`,
  metadata: {
    csp: {
      connectDomains: ["https://api.example.com"],
      resourceDomains: ["https://cdn.example.com"],
    },
  },
});

双协议 Widget 支持

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', // 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,
  },
});

自动处理内容:

  • MCP Apps 客户端(Claude、Goose)接收:text/html;profile=mcp-app 和 _meta.ui.*
  • ChatGPT 接收:text/html+skybridge 和 _meta.openai/*
  • 同一份 Widget 代码可在所有平台上运行!
自定义 OpenAI 元数据

需要 ChatGPT 专属功能?组合使用这两种元数据字段:

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

常见模式

带双协议 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`)
    });
  }
);

资源模板(带参数):

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);
  }
);

错误处理:

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}`);
  }
);

详细示例

如需全面的示例和高级模式,请连接到 mcp-use MCP 服务,其中提供:

  • 涵盖所有原语的完整示例资源
  • 完整可运行的服务示例
  • 详细文档
  • 交互式 Widget 展示

了解更多

快速参考

命令:

  • 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 }) - 返回包含数据的 widget

服务方法:

  • server.tool() - 定义可执行工具
  • server.resource() - 定义静态/动态资源
  • server.resourceTemplate() - 定义参数化资源
  • server.prompt() - 定义提示词模板
  • server.uiResource() - 定义 widget 资源
  • server.listen() - 启动服务

Widget 元数据字段:

  • description - Widget 描述
  • props - Widget 属性的 Zod 架构
  • metadata - 统一配置(双协议)
  • metadata.csp - 内容安全策略
  • appsSdkMetadata - ChatGPT 专用覆盖项

可用模板:

  • starter - 功能齐全(工具、资源、提示词、widget)
  • mcp-apps - 针对 ChatGPT 优化,附带产品示例
  • blank - 最简基础模板

评论

支持 Markdown