在 mcp-use 中使用 Zod、ArkType 与 TypeBox 定义 MCP 工具输入 Schema:同款 greet 工具的三种校验器实现
【免费下载链接】mcp-useThe fullstack MCP framework to develop MCP Apps for ChatGPT / Claude & MCP Servers for AI Agents.项目地址: https://gitcode.com/gh_mirrors/mc/mcp-use
本指南以 mcp-use 仓库中的 schema-validators 示例 为主体,完整展示同一个带输入校验的greetMCP 工具如何分别用 Zod、ArkType 与 TypeBox 三种 schema 校验器构建,并深入mcp-use服务端源码,说明inputSchema字段、StandardSchemaWithJSON标准以及校验在工具回调执行前发生的底层机制。读完本文,你将掌握在mcp-useTypeScript 服务中接入任意主流 schema 库、写出可被 LLM 正确理解的工具参数定义,并完成本地启动与联调验证的完整方法。
示例概览:三种校验器,一个greet工具
examples/typescript/schema-validators目录下并排存放着三个结构完全对称的独立 npm 工程:
arktype/— 使用 ArkType(arktype: ^2.2.3)typebox/— 使用 TypeBox(typebox: 1.3.6,并搭配@modelcontextprotocol/server: 2.0.0的 JSON Schema 转换工具)zod/— 使用 Zod(zod: ^4.4.3)
三个工程都声明了相同的mcp-use: ^2.0.4依赖、相同的"type": "module"与相同的脚本集合(dev/build/start/typecheck)。它们实现的是同一个服务器:一个名为greet、输入受校验的工具,返回一段问候文本。这样并排组织的用意在于,让读者可以零成本地对比同一功能在不同校验器下的写法差异,从而根据自己的团队技术栈做出选择。
逐版本解读:同一功能的三种 Schema 写法
Zod 版本:z.object+describe
zod/src/index.ts 的完整实现如下:
import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "zod-schema-example", version: "1.0.0", description: "Tool input validation with Zod.", }); server.tool( { name: "greet", inputSchema: z.object({ name: z.string().describe("Name to greet"), }), }, async ({ name }) => ({ content: [{ type: "text", text: `Hello from Zod, ${name}!` }], }) ); export default server;关键点在于z.string().describe("Name to greet"):字段描述通过.describe()挂载,最终会成为 LLM 理解工具参数意图的提示信息(详见下文源码分析)。工具回调的入参{ name }类型由inputSchema自动推导,全程享有 TypeScript 类型安全。
ArkType 版本:type(...)描述式语法
arktype/src/index.ts 采用 ArkType 的字符串描述式 DSL:
import { type } from "arktype"; import { MCPServer } from "mcp-use"; const server = new MCPServer({ name: "arktype-schema-example", version: "1.0.0", description: "Tool input validation with ArkType.", }); server.tool( { name: "greet", inputSchema: type({ name: type("string").describe("Name to greet"), }), }, async ({ name }) => ({ content: [{ type: "text", text: `Hello from ArkType, ${name}!` }], }) ); export default server;ArkType 的type({ name: type("string") })与 Zod 的z.object({ name: z.string() })结构几乎一一对应;字段描述同样是.describe(...)。两者写法的亲缘性很高,从 Zod 迁移到 ArkType 的成本很低。
TypeBox 版本:Type.Object+fromJsonSchema显式转换
typebox/src/index.ts 是三者中唯一需要显式 JSON Schema 转换的版本:
import { fromJsonSchema } from "@modelcontextprotocol/server"; import { MCPServer } from "mcp-use"; import Type from "typebox"; const server = new MCPServer({ name: "typebox-schema-example", version: "1.0.0", description: "Tool input validation with TypeBox.", }); const greetInput = Type.Object({ name: Type.String({ description: "Name to greet" }), }); server.tool( { name: "greet", inputSchema: fromJsonSchema<Type.Static<typeof greetInput>>(greetInput), }, async ({ name }) => ({ content: [{ type: "text", text: `Hello from TypeBox, ${name}!` }], }) ); export default server;TypeBox 把 schema 描述为Type.Object({ name: Type.String({ description: ... }) }),描述以选项对象形式传递(而非链式.describe())。fromJsonSchema来自@modelcontextprotocol/server(TypeBox 1.x 输出为 JSON Schema),将其转换为 mcp-use 所需的StandardSchemaWithJSON结构;Type.Static<typeof greetInput>则用于保证转换后的 schema 与回调入参类型一致。这一差异恰好说明:不同校验器在 mcp-use 中接线的标准是统一的,只是个别库需要一层显式的桥接转换。
运行与联调:从npm run dev到/mcp端点
schema-validators的 README 给出了通用运行方式(以 zod 为例,其余两个工程操作完全一致):
cd zod npm install npm run devdev脚本执行的是mcp-use dev命令。从 CLI 源码看,开发服务器默认监听$PORT环境变量指定的端口,未设置时回落到3000;并且dev模式在端口被占用时会自动向上探测新端口,同时打印提示(见 libraries/typescript/packages/cli/src/cli/dev.ts#L378-L385 中的[mcp-use] port ${requested} is taken, using ${port})。因此 README 中说连接http://localhost:3000/mcp是默认情形——若日志提示端口已被占用,请以实际打印的端口为准。
启动后,用任意 MCP 客户端(或 mcp-use Inspector)连接:
- 端点:
http://localhost:3000/mcp - 工具:
greet - 调用参数:
{ "name": "Ada" }
三个版本的服务器都会返回一段问候文本,例如Hello from Zod, Ada!(ArkType/TypeBox 版本返回相应前缀的文本)。若传入的参数不符合 schema(例如name缺失或类型为数字),输入校验会在工具回调执行之前被拦截并返回校验错误——这正是本示例所演示的核心价值:让 MCP 工具的参数契约由 schema 强制保证,而非在业务代码里手写判断。
除dev外,package.json还提供了mcp-use build(构建产物)与mcp-use start(以生产模式启动)、tsc --noEmit(类型检查)等脚本,便于从开发到部署的完整链路。
源码纵深:inputSchema与StandardSchemaWithJSON
为什么三个完全不同的库能无缝接入同一个server.tool()?答案在 mcp-use 服务端的工具定义类型中。查看 libraries/typescript/packages/server/src/tools.ts#L53-L80 的ToolDefinition接口:
export interface ToolDefinition { name: string; title?: string; description?: string; /** 支持任何实现了 Standard Schema 且可转换 JSON Schema 的库:zod v4、ArkType、Valibot …… */ inputSchema?: StandardSchemaWithJSON; /** inputSchema 的别名,新代码推荐使用 inputSchema(与 MCP 线上字段名一致) */ schema?: StandardSchemaWithJSON; outputSchema?: StandardSchemaWithJSON; annotations?: ToolAnnotations; ... }inputSchema的类型是StandardSchemaWithJSON,它来自@modelcontextprotocol/server,是“Standard Schema + JSON Schema 转换能力”的统一抽象。源码注释明确列举了该协议兼容的库:zod v4、ArkType、Valibot 等。因此本示例中的 Zod 4(zod: ^4.4.3)与 ArkType 2(arktype: ^2.2.3)都可以直接传入而无需桥接;TypeBox 由于不直接暴露 Standard Schema 接口,才需要通过fromJsonSchema做一次转换——这正是三种写法存在差异的根本原因。
工具定义同时支持inputSchema与历史别名schema,二者的优先级由 resolveToolInputSchema 决定:同时设置时inputSchema胜出。服务器在注册工具时会调用该函数解析最终 schema,并在回调执行前完成校验(见 libraries/typescript/packages/server/src/server.ts#L1953-L1997 中resolveToolInputSchema(definition)与校验逻辑),校验通过后才会进入你的回调函数。
类型层面的闭环同样值得注意:InferToolInput(见 tools.ts#L162-L175)会从inputSchema推导回调参数类型——所以你不需要手写{ name: string }的入参注解,TypeScript 会自动把回调里的{ name }推导为string类型,schema 即单一事实来源。
此外,字段描述(Zod/ArkType 的.describe(...)、TypeBox 的description选项)会随 schema 一起出现在工具描述信息中,成为 LLM 选择与填参的依据,因此为每个字段编写清晰、面向模型的描述,是提升 MCP 工具可用性的关键实践。
小结与选型建议
本示例的核心结论可以归纳为三点:
- Schema 无关:mcp-use 通过
StandardSchemaWithJSON统一接纳 zod v4、ArkType、Valibot 等 Standard Schema 库,TypeBox 等非 Standard Schema 库则可用fromJsonSchema显式桥接; - 校验前置:工具输入在回调执行前即完成校验,业务代码无需重复防御;
- 类型闭环:回调参数类型由
inputSchema自动推导,schema 与实现天然一致。
选型上:追求极简上手与生态成熟可选 Zod;偏好编译期极致性能与描述式语法可选 ArkType;团队已有 JSON Schema 基础设施或需要与 OpenAPI/配置体系打通时可选 TypeBox。三种方案都可在本仓库的 schema-validators 目录 中直接npm install && npm run dev对照体验,选择最契合团队习惯的那一种即可。
【免费下载链接】mcp-useThe fullstack MCP framework to develop MCP Apps for ChatGPT / Claude & MCP Servers for AI Agents.项目地址: https://gitcode.com/gh_mirrors/mc/mcp-use
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考