给 Agent 造一个 MCP 服务器,最花时间的往往不是业务逻辑,而是它周围的那一圈:输入输出要手写校验、结构化结果和界面各写一份、想看一眼工具到底返回了什么还得自己搭个调试页。mcp-use v2 的思路是把这一圈补齐——它构建在官方 TypeScript SDK v2 之上,额外提供类型化的输入输出契约、可绑定到工具的 React 视图(Views)、开箱即用的 Inspector,以及能在终端里连接服务器、列工具、调工具、给界面截图的命令行。用 Zod 写好一份 schema,它会同时成为入参校验、工具返回的 structuredContent 和界面组件的 props 类型,改一处三处同步。本教程六步落地:起项目并跑通本地端点、用 Zod 定义工具契约、给工具挂一个界面、用命令行做无头验收、让 ChatGPT 与 Claude 连上本地服务、最后构建部署并说清版本迁移的坑。
Step 1:起项目:一条脚手架命令,端点与调试页同时就绪
项目用官方脚手架创建,它会把服务端框架、TypeScript 配置、开发脚本、Inspector 与 React 视图构建管线一并生成好。进入目录装依赖后运行开发脚本,本机同时起来两个东西:MCP 端点与挂在同一个端口下的 Inspector 页面。也就是说你不再需要另开一个调试站点,也不用在每次改动后手动重启去验证。
# 创建项目(交互式脚手架)
npx -y create-mcp-use-app@latest
# 进入项目并启动开发模式
cd my-mcp-project
npm install
npm run dev
# 开发模式默认提供
# MCP 端点 http://localhost:3000/mcp
# 内置 Inspector http://localhost:3000/mcp/inspector
# 线上 Inspector(不想本地起也能用)
https://inspector.mcp-use.com/inspector
生成的项目里已经有示例工具与示例视图,建议先原样跑一遍,确认 Inspector 里能看到工具列表,再开始改。这个顺序能帮你把「环境问题」和「代码问题」分开。
Step 2:写工具:用 Zod 把输入、输出和界面 props 绑成一份契约
服务端入口是 MCPServer 实例,工具通过 server.tool 注册:入参有两个,前一个是元信息对象(名称、标题、描述、输入 schema、输出 schema、视图绑定、注解),后一个是处理函数。处理函数收到的是已经过校验的输入,返回时必须同时给 content(给模型读的文本)与 structuredContent(给程序与界面用的结构化结果)。
import { MCPServer } from "mcp-use";
import { z } from "zod";
// 1) 服务端实例
const server = new MCPServer({
name: "weather-app",
title: "Weather App",
version: "1.0.0",
});
// 2) 输入 / 输出契约(Zod)
const weatherInput = z.object({
city: z.string().describe("City to look up"),
});
const weatherOutput = z.object({
city: z.string(),
temperature: z.number(),
conditions: z.string(),
});
// 3) 注册工具:文本输出 + 结构化结果 + 视图绑定 + 注解
export const getWeather = server.tool(
{
name: "get-weather",
title: "Get weather",
description: "Get the current weather for a city",
inputSchema: weatherInput,
outputSchema: weatherOutput,
view: { name: "weather-card" },
annotations: {
readOnlyHint: true, // 只读:客户端更愿意自动执行
destructiveHint: false, // 不是破坏性操作
openWorldHint: true, // 会访问外部世界(网络)
},
},
async ({ city }) => {
const weather = { city, temperature: 22, conditions: "Sunny" };
return {
content: [
// 文本用普通字符串拼接,避免模板字符串与示例混淆
{ type: "text", text: "Weather in " + city + ": " + weather.conditions + ", " + weather.temperature + "°C" },
],
structuredContent: weather,
};
},
);
export default server;
注解这一段别跳过:readOnlyHint、destructiveHint、openWorldHint 会被客户端拿来判断「要不要先问人」和「能不能自动跑」。把会写数据的工具标成只读,等于替 Agent 关掉了它本该有的确认环节。
v1 与 v2 的 API 不是一回事:网上能搜到的旧代码里常见 createMCPServer 加 parameters 的写法,那是 v1;v2 是 new MCPServer 配合 server.tool 与 inputSchema 加 outputSchema。照抄旧示例会直接报类型错误。项目里若已有 v1 代码,让编码 Agent 读官方迁移指南再改,不要手工逐行猜。
Step 3:加界面:视图目录名必须和 view.name 对上
视图让工具结果以交互卡片的形式出现在对话里。绑定方式是工具元信息里的 view: { name: "weather-card" },对应的组件必须落在 views/weather-card/view.tsx——目录名与 name 逐个字母一致,否则界面不会渲染。组件从 mcp-use/react 取钩子:useToolContext 读输入、状态与输出,useCallTool 在界面里再调一次工具(比如刷新按钮)。
// views/weather-card/view.tsx
import { useCallTool, useToolContext } from "mcp-use/react";
export default function WeatherCard() {
// 读当前工具调用的输入、状态与输出
const { status, toolOutput, toolInput } = useToolContext<"get-weather">();
// 在界面里再次调用工具(刷新)
const refresh = useCallTool("get-weather");
if (status === "pending") {
return <p>Checking the weather in {toolInput?.city ?? "your city"}…</p>;
}
if (status === "error") return <p>Could not load the weather.</p>;
const weather = refresh.data?.structuredContent ?? toolOutput;
return (
<main style={{ padding: 24 }}>
<h2>{weather.city}</h2>
<p>{weather.temperature}°C · {weather.conditions}</p>
<button disabled={refresh.isPending} onClick={() => void refresh.callTool({ city: weather.city })}>
{refresh.isPending ? "Refreshing…" : "Refresh"}
</button>
{refresh.error && <p>{refresh.error.message}</p>}
</main>
);
}
如果你的目标是 ChatGPT 插件形态,还有一个额外钩子 useModelContext,它可以把界面里选中的内容(比如一本书、一条分析结果)作为消息加回对话。这个能力属于 ChatGPT 插件扩展的用法,Claude 连接器侧不需要。
目录名对不上是静默失败:视图文件放错位置或目录名与 view.name 不一致时,工具照常返回文本,界面就是不出现,日志里也不一定有醒目报错。写完视图先在 Inspector 里看一眼,再去接客户端。
Step 4:无头验收:连接、列工具、调工具、给界面截图
装 @mcp-use/client 之后,同一个服务器可以完全脱离浏览器来验证:连接本地端点、列出工具、按参数调用、把视图渲染成图片。这几条命令最适合放进 CI——不用起界面,也能确认工具还在、返回值结构没变、卡片还能画出来。
npm install --save-dev @mcp-use/client
# 连接本地服务器(起个别名,后续命令复用)
npx mcp-use client connect local http://localhost:3000/mcp
# 列出工具
npx mcp-use client local tools list
# 调用工具
npx mcp-use client local tools call get-weather city=Tokyo
# 把视图渲染成图片(做视觉回归很顺手)
npx mcp-use screenshot --server local --tool get-weather city=Tokyo --output weather-card.png
截图这条命令值得单独说:它产出的是真实渲染结果,团队评审时能直接看到卡片长什么样,而不是靠想象。把生成的图片作为构建产物留档,界面悄悄坏掉时你能立刻发现。
Step 5:让 ChatGPT 与 Claude 连上:用隧道把本地服务临时暴露出去
本地 3000 端口对云端客户端不可见,官方给了两条出路:在 Inspector 界面里直接启动隧道,或在命令行用开发命令加隧道参数。两种方式都会给出一个公网 URL,把它填进 ChatGPT 或 Claude 的连接器配置即可联调。
# 命令行起隧道,拿到公网 URL
mcp-use dev --tunnel
# 或在 Inspector 界面里点开隧道开关
# 把得到的公网 URL 填进 ChatGPT / Claude 的连接器配置
联调通过后就要把它关掉。隧道的本质是把你本机的服务放到公网上,任何拿到地址的人都能调用你注册的工具——包括那些会写数据的工具。
隧道不是部署方式:它适合临时验证,不适合长期挂着跑业务,更不适合在生产数据上用。联调结束就停掉隧道;要给团队稳定使用,走 Step 6 的构建与部署,而不是长期依赖一个临时地址。
Step 6:构建与部署:一条命令上托管,或按官方指引自托管
生产产物由构建命令产出,之后有两条选择:一是部署到官方托管平台,一次命令即可,附带可观测、分析、评测与基于 Git 的分支预览环境;二是按官方自托管指引落到自己的运行时上,适合有合规或内网要求的团队。两条路共用同一个构建产物,所以本地跑通的东西换环境不会变形。
# 生产构建
npm run build
# 部署到官方托管平台
npm run deploy
# 自托管:按官方 runtime patterns 指引部署构建产物
https://docs.mcp-use.com/typescript/server/deployment/runtime-patterns
生态里还有几个可单独安装的包:@mcp-use/client 负责从 Node、浏览器、React 与沙箱连接服务器,@mcp-use/agent 负责在客户端之上搭模型驱动的 Agent,@mcp-use/inspector 与 @mcp-use/tunnel 分别对应调试与隧道。按需装,不必一次全上。
托管不等于免运维:部署后仍然要关心谁在调用、调用频率与成本、以及工具里涉及的密钥。托管平台提供的是可观测与预览便利,不会替你决定一个工具该不该自动执行——那件事由 Step 2 里的注解说了算。
常见问题速查
| 现象 | 原因与处理 |
|---|---|
| 开发模式起不来 | 确认能跑 npx 与 npm;脚手架生成的项目需先 npm install |
| Inspector 打不开 | 它在 /mcp/inspector,不是根路径;也可用线上 Inspector |
| 界面不显示 | 视图目录名必须与 view.name 一致,且文件叫 view.tsx |
| 照抄示例报类型错 | 示例可能是 v1 写法(createMCPServer),v2 用 new MCPServer 与 server.tool |
| 视图读不到新字段 | 字段要先加进 outputSchema,视图 props 由它推导 |
| 客户端总要先问我 | 检查 annotations:只读与破坏性标注会影响客户端的自动执行判断 |
| 想在终端里验收 | 装 @mcp-use/client,用 client connect / tools list / tools call |
| 想留界面快照 | 用 mcp-use screenshot 产出图片,可作为构建产物存档 |
| ChatGPT 里想加内容回对话 | 用 mcp-use/react 的 useModelContext(ChatGPT 插件扩展场景) |
| 本地服务怎么给云端客户端用 | 临时用 dev --tunnel,正式用构建加部署,别长期挂隧道 |
| 必须付费吗 | 框架本身 MIT;托管平台有免费档,调用大模型的成本来自你自己的 key |
| Python 能造服务器吗 | Python 侧有同名的客户端与 Agent 能力,服务器完整能力在 TypeScript 侧 |
| 部署后怎么回滚 | 托管平台按 Git 分支管理预览与发布,回滚走同一套流程 |
| 想让 Agent 直接调我的服务器 | 用 @mcp-use/agent 在客户端之上搭模型驱动的 Agent |