使用 mcp-use 五分钟构建你的第一个 MCP Server:CopilotKit 仓库 open-mcp-client 快速上手实战
2026/9/11 5:35:12 网站建设 项目流程

使用 mcp-use 五分钟构建你的第一个 MCP Server:CopilotKit 仓库 open-mcp-client 快速上手实战

【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit

本指南以 quickstart.md 为核心骨架,讲解如何用mcp-use框架在 5 分钟内完成脚手架搭建、模板选择、开发调试,并逐步实现工具(Tool)、模拟数据、结构化响应与资源(Resource)四大基础能力。读完你可以在本地跑通一个带 Inspector 调试面板的完整 MCP Server,并为后续接入 ChatGPT、Claude 等 MCP Apps 兼容客户端的 Widget 可视化界面打好基础。


一、先认识 mcp-use 与本文的实战环境

本文的实操对象是 CopilotKit 仓库中的 open-mcp-client 展示项目,其核心是一个基于mcp-use框架实现的 MCP Server 示例:

  • 服务器入口:index.ts —— 创建MCPServer实例并注册工具;
  • 工具实现:tools/product-search.ts —— 一个返回 Widget 可视化界面的完整工具示例;
  • 依赖清单:package.json —— 声明了mcp-usezodreact等运行时依赖。

从依赖与源码结构看,mcp-use是一个把 MCP 协议(模型上下文协议)与 HTTP 服务器能力融为一体的 TypeScript 框架:它基于 Hono Web 框架构建,开发者通过server.tool()server.resource()server.prompt()声明 MCP 原语,同时还能通过server.app直接添加自定义 HTTP 路由。想深入了解这一架构,可以参考同目录下的 architecture.md 与 concepts.md。

在动手之前,请确认本地环境已安装Node.js(建议 18+)与 npm(或 pnpm),MCP 生态相关的类型定义与依赖都会由脚手架自动安装。


二、Setup:脚手架搭建一个全新项目

创建一个全新的 mcp-use 项目只需三条命令:

npx create-mcp-use-app my-server cd my-server npm run dev

执行第一条命令时,脚手架会自动完成依赖安装;npm run dev会启动开发服务器,默认监听 3000 端口,并自动打开内置调试器(Inspector)——地址为http://localhost:3000/inspector

关于端口与启动细节,仓库中的 package.json 给出了脚手架生成项目的真实脚本参考:

"scripts": { "build": "mcp-use build --inline", "dev": "mcp-use build --inline && cross-env NODE_ENV=production npx tsx index.ts", "start": "mcp-use start", "deploy": "mcp-use deploy" }
  • dev:先构建 Widget(--inline表示内联打包),再用tsx直接运行 TypeScript 入口,支持热重载;
  • build/start:生产构建与启动;
  • deploy:一键部署到生产环境。

提示:示例仓库 index.ts 中通过process.env.MCP_URLprocess.env.PORT支持环境变量覆盖,默认端口为 3109(server.listen(parseInt(process.env.PORT ?? "3109", 10)))。这意味着脚手架默认 3000 端口并非硬编码,你可以随时用环境变量调整,方便与本机其他服务错开端口。


三、选择一个合适的模板

脚手架内置了四种模板,应根据你要构建的内容来选择:

模板命令适用场景
starter(默认)npx create-mcp-use-app my-server功能完整的服务器,自带 tools、resources、prompts 与 widget 示例
mcp-appsnpx create-mcp-use-app my-server --template mcp-apps面向 ChatGPT、Claude 等 MCP Apps 兼容客户端的 Widget 专注型模板
blanknpx create-mcp-use-app my-server --template blank空白模板——只含带注释示例的裸服务器
GitHub reponpx create-mcp-use-app my-server --template owner/repo从任意 GitHub 仓库拉取自定义或社区模板

不确定选哪个时,直接选mcp-apps它是官方推荐默认值,内置了对 ChatGPT、Claude 等 MCP Apps 兼容客户端的 Widget 支持,后续若要给工具添加可视化界面,可以省去大量配置工作。

常见命令行参数(Common Flags)

# 选择包管理器 npx create-mcp-use-app my-server --npm npx create-mcp-use-app my-server --pnpm # 跳过交互式提问 npx create-mcp-use-app my-server --install --skills # 列出所有可用模板 npx create-mcp-use-app --list-templates

参数说明:

  • --npm/--pnpm:指定依赖安装工具,不传时按默认策略选择;
  • --install:跳过安装确认,直接安装依赖;
  • --skills:同时写入脚手架自带的开发技能文件(例如本仓库.agent/skills/目录下这套 mcp-apps-builder 文档就是此类技能);
  • --list-templates:查看当前版本全部可用模板与 GitHub 仓库模板列表。

经验之谈:仓库中 SKILL.md 反复强调一个原则——不要手写MCPServer样板代码、package.json 或项目结构。脚手架一次性配置好了 TypeScript、dev 脚本、Inspector 集成、热重载与 Widget 编译,这些手动复制极易出错,务必优先使用脚手架。


四、每个模板会生成什么

脚手架产物的目录结构决定了你的开发组织方式,下面是三个内置模板的标准产物:

starter 模板:

my-server/ ├── index.ts # 服务器入口,含 tool、resource、prompt 示例 ├── resources/ # Widget 目录(含 display-weather.tsx 示例) ├── public/ # 静态资源(favicon、icon) ├── package.json # 预配置脚本:dev、build、start、deploy └── tsconfig.json

mcp-apps 模板:

my-server/ ├── index.ts # 服务器入口,含返回 Widget 的工具 ├── resources/ # Widget 目录(含 product-search-result/ 示例) │ └── product-search-result/ │ ├── widget.tsx # React Widget(轮播卡片 UI) │ └── components/ # 可复用 Widget 组件 ├── public/ ├── package.json └── tsconfig.json

blank 模板:

my-server/ ├── index.ts # 裸 MCPServer,示例均为注释 ├── public/ ├── package.json └── tsconfig.json

对照仓库源码可以印证这套结构的真实性:index.ts 顶部注释详细说明了添加一个新 MCP App Widget 的三步流程——在resources/<widget-name>/widget.tsx创建 React 组件、在tools/<tool-name>.ts导出注册函数、最后在入口文件 import 并调用register()。而 tools/product-search.ts 正是这一流程的完整落地范例,可作为你编写第一个自定义工具时的对照样板。


五、脚手架搭建后的开发工作流

完成脚手架之后,标准开发循环如下:

  1. npm run dev—— 启动带热重载 + Inspector 的服务器;
  2. 编辑index.ts添加 tools、resources、prompts;
  3. resources/目录下以.tsx文件添加 Widget;
  4. http://localhost:3000/inspector中测试一切功能;
  5. npm run build—— 生成生产构建;
  6. npm run deploy—— 部署到生产环境。

这套循环的核心价值在于热重载:保存.ts/.tsx文件后,服务端会自动重建 Widget 并重启服务器,无需手动中断进程,非常适合快速迭代。


六、你的第一个工具:greet

脚手架生成的index.ts已经包含一个基础服务器,现在给它加一个最简单的工具——greet,接收一个名字参数并返回问候语:

import { MCPServer, text } from "mcp-use/server"; import { z } from "zod"; const server = new MCPServer({ name: "my-server", title: "My Server", version: "1.0.0", baseUrl: process.env.MCP_URL || "http://localhost:3000", }); // 新增这个工具 server.tool( { name: "greet", description: "Greet a user by name", schema: z.object({ name: z.string().describe("User's name"), }), }, async ({ name }) => { return text(`Hello, ${name}! Welcome to MCP.`); }, ); server.listen();

代码要点拆解:

  • MCPServer构造参数中的name/title/version是服务器元信息;baseUrlprocess.env.MCP_URL提供默认值兜底,这正是仓库 index.ts 采用的环境变量模式;
  • schema使用zod声明入参结构,每个字段都要调用.describe()补充描述——模型依赖这些描述理解参数含义(这也是 SKILL.md 中列出的第一条 Tool 定义最佳实践);
  • 返回值必须用响应辅助函数text()包装,而不是直接return一个普通字符串。

保存文件——服务器会自动重载!

在 Inspector 中测试

  1. 打开 Inspector(http://localhost:3000/inspector);
  2. 点击List Tools
  3. 找到greet工具;
  4. 点击Call Tool
  5. 输入参数{"name": "Alice"}
  6. 看到响应:"Hello, Alice! Welcome to MCP."

Inspector 是 mcp-use 开发体验的核心:它能列出全部已注册工具、资源和提示词,也能直接发起工具调用,是验证每个新功能的第一站。


七、添加模拟数据:一个天气工具

开发阶段的惯例是"Mock 数据优先,之后再接真实 API"。下面用一段硬编码数据实现天气查询:

// 模拟天气数据 const mockWeather: Record<string, { temp: number; conditions: string }> = { "New York": { temp: 22, conditions: "Partly Cloudy" }, London: { temp: 15, conditions: "Rainy" }, Tokyo: { temp: 28, conditions: "Sunny" }, Paris: { temp: 18, conditions: "Overcast" }, }; server.tool( { name: "get-weather", description: "Get current weather for a city", schema: z.object({ city: z.string().describe("City name"), }), }, async ({ city }) => { const weather = mockWeather[city]; if (!weather) { return text(`No weather data for ${city}`); } return text(`Weather in ${city}: ${weather.temp}°C, ${weather.conditions}`); }, );

测试方法与上一节相同:

  • {"city": "Tokyo"}调用工具;
  • 期望响应:"Weather in Tokyo: 28°C, Sunny"

这段代码展示了工具处理的两个典型分支:数据命中返回正常结果数据未命中返回友好的兜底文本。真实的工具实现通常在此基础上补充异常捕获与参数校验,可参考 tools/product-search.ts 中get-fruit-details的写法(用outputSchema声明结构化输出,并对未找到的水果返回默认字段)。


八、添加结构化数据:object() 返回

文本返回适合对话场景,但 AI 或客户端需要解析结构化信息时,应使用object()辅助函数返回 JSON:

import { MCPServer, text, object } from "mcp-use/server"; server.tool( { name: "get-weather-detailed", description: "Get detailed weather information", schema: z.object({ city: z.string().describe("City name"), }), }, async ({ city }) => { const weather = mockWeather[city]; if (!weather) { return object({ error: `No data for ${city}` }); } return object({ city, temperature: weather.temp, conditions: weather.conditions, unit: "celsius", timestamp: new Date().toISOString(), }); }, );

注意这里的错误分支同样用object()返回结构化错误对象,而不是抛出异常——这是 mcp-use 的约定:错误应作为响应的一部分优雅返回,让模型能读懂失败原因。

从源码层面看,response-helpers.md 列出了完整的辅助函数族:text()object()markdown()image()error()widget()mix()resource()。它们统一负责正确设置 MIME 类型、保证序列化并支持多内容响应。永远用辅助函数包装返回值,不要直接 return 原始对象——这是该文档反复强调的第一原则。


九、添加一个资源(Resource)

Resource 用于向客户端暴露只读数据,适合配置信息、静态列表等场景:

server.resource( { name: "available_cities", uri: "weather://available-cities", title: "Available Cities", description: "List of cities with weather data", }, async () => object({ cities: Object.keys(mockWeather), }), );

在 Inspector 中测试:

  1. 打开 Inspector →List Resources
  2. 找到 "Available Cities";
  3. 点击Read Resource
  4. 看到:{"cities": ["New York", "London", "Tokyo", "Paris"]}

Resource 与 Tool 的定位差异很关键:Tool 是 AI 可调用的动作,Resource 是客户端可拉取的只读数据。如果数据需要参数化(例如按城市 ID 取详情),则应使用 Resource 模板(动态 URI),具体可参考 resources.md。


十、进阶路线:从工具到可视化 Widget

掌握了 Tool、结构化响应与 Resource 之后,你的下一个能力跃迁点是Widget——让工具返回可视化 React 界面。在 concepts.md 中,Widget 被定义为"返回视觉 UI 的工具":本质仍是server.tool(),但声明了widget: { name }配置,并在处理器中通过widget({ props, output })返回组件所需数据与模型可见的文本摘要。

仓库里 tools/product-search.ts 就是完整的 Widget 工具范例:search-tools工具返回widget({ props: { query, results }, output: text(...) }),并通过_meta["ui/previewData"]提供尚未调用时的预览数据;配套的get-fruit-details数据工具则供 Widget 内部通过useCallTool()调用,演示了"Widget 外壳 + 数据工具"的组合模式。

建议按以下顺序继续学习(均位于本仓库的 skills 文档体系内):

  1. 学习响应辅助函数→ response-helpers.md
  2. 构建你的第一个 Widget→ basics.md
  3. 查看完整示例→ common-patterns.md

如果只想在本地快速跑通一个带 Widget 的成品,可以直接运行仓库中的 mcp-use-server 示例(package.json 中的npm run dev),在 Inspector 中调用search-tools观察轮播式水果卡片如何渲染。


十一、开发建议与常见误区

综合 quickstart 与 SKILL.md 的实践总结,快速上手阶段最容易踩的坑如下:

场景❌ 错误做法✅ 正确做法
返回值直接return { data }原始对象object()/text()等辅助函数包装
参数描述Zod schema 字段不加说明所有字段调用.describe()
错误处理throw new Error(...)抛出异常返回error("...")优雅降级
工具粒度一个manage-users大而全拆成create-userlist-users等单一职责工具
数据获取list-products+get-product-details两次调用一次返回完整数据,避免懒加载
Widget 状态select-item工具管理 UI 状态Widget 内部用useState自行管理

Mock 数据优先是快速上手阶段最重要的方法论:先用硬编码数据把工具链路跑通、把界面效果调好,再在后续迭代中替换为真实 API——tools/product-search.ts 中的水果目录就是这么做的,切换数据源时只需改动fruits常量即可。

【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询