- 教程
- 文档
- 人工智能
【免费下载链接】mcp-for-beginners
This open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.
本文以本仓库 TypeScript 官方解题方案 为主体,结合 课程讲义 与源码实现,系统讲解如何基于 MCP(Model Context Protocol)规范 2025-06-18 推荐的stdio 传输,用 TypeScript 构建一个可被 Claude Desktop、VS Code 等客户端消费的本地 MCP 服务器。读完本文,你将掌握 stdio 传输的通信原理、MCP SDK 的工具注册与调用机制、Inspector 调试方法,以及如何将该服务器接入真实客户端。
为什么从 SSE 迁移到 stdio 传输
MCP 规范 2025-06-18 起,独立的 SSE(Server-Sent Events)传输已被弃用(deprecated),取而代之的是两种主要传输机制:
- stdio:通过标准输入/输出流通信,推荐用于本地服务器;
- Streamable HTTP:用于远程服务器,内部可能仍使用 SSE。
本仓库的 TypeScript 解题方案正是基于这一规范更新而重写的。课程讲义 明确指出:stdio 是当前规范中最常用、最被推荐的传输方式,它为大多数 MCP 服务器实现提供了简单且高效的构建路径。
stdio 传输的工作原理
stdio 传输的核心机制非常简洁:
- 简单通信:服务器从标准输入(
stdin)读取 JSON-RPC 消息,并向标准输出(stdout)发送消息; - 基于进程:客户端将 MCP 服务器作为子进程启动;
- 消息格式:消息是独立的 JSON-RPC 请求、通知或响应,以换行符(newline)分隔;
- 日志输出:服务器可以通过标准错误流(
stderr)输出 UTF-8 字符串用于日志记录。
关键协议要求
按照规范,stdio 服务器必须遵守以下约束:
| 要求 | 说明 |
|---|---|
| 消息必须按换行符分隔 | 消息内容中不得包含内嵌换行符 |
服务器不得污染stdout | stdout上只能输出合法的 MCP 消息,日志必须走stderr |
客户端不得污染stdin | 客户端写入服务器stdin的内容只能是合法的 MCP 消息 |
这条规则直接决定了后续开发中"用console.error()而非console.log()"这一最佳实践,是 stdio 服务器开发中极易踩坑的关键点。
项目结构速览
TypeScript 解题方案位于 03-GettingStarted/05-stdio-server/solution/typescript/,目录结构如下:
typescript/ ├── src/ │ └── index.ts # 主服务器实现 ├── build/ # 编译后的 JavaScript(自动生成) ├── package.json # 项目配置 ├── tsconfig.json # TypeScript 配置 └── README.md # 本文对应的说明文档整个服务器只有一个源文件(src/index.ts),代码量约 190 行,充分体现了 stdio 传输"无需 HTTP 服务器、无需路由与会话管理"的简洁性。
前置条件
在开始之前,请确保环境满足:
- Node.js 18+或更高版本;
- npm 或 yarn包管理器。
第一步:安装依赖并构建
进入 solution/typescript 目录,执行:
npm install npm run build从 package.json 可以看到关键依赖与脚本:
- 运行时依赖:
@modelcontextprotocol/sdk(版本要求>=1.26.0)与zod(^3.24.2),前者提供 MCP 协议实现,后者用于工具参数的运行时校验; - 开发依赖:
typescript(^5.3.3)与@types/node(^20.11.24); type: "module":采用 ES Module 规范,这也是源码中使用.js后缀导入路径的原因;- 脚本:
build:tsc—— 编译 TypeScript;start:node build/index.js—— 启动服务器;inspector:npx @modelcontextprotocol/inspector node build/index.js—— 一键启动调试器;
bin字段:将mcp-stdio-server命令映射到./build/index.js,便于全局安装后直接以命令方式启动。
tsconfig.json 的编译目标为ES2022、模块系统为Node16,输出目录为./build,并启用了strict严格模式。
版本提示:源码头部注释与文档均声明本示例遵循 MCP 规范 2025-06-18;而
package.json的 description 字段写的是"aligned with MCP Specification 2025-11-25",可见 SDK 版本在持续演进,实际使用时以你安装的 SDK 所支持的规范版本为准。
第二步:深入源码——服务器如何构建
完整实现见 src/index.ts。我们按逻辑拆解它的四个核心环节。
1. 创建 Server 实例并声明能力
const server = new Server( { name: "example-stdio-server", version: "1.0.0", }, { capabilities: { tools: {}, }, } );第一参数是服务器身份信息(名称与版本),第二参数声明capabilities。本例声明了tools能力,表示该服务器向客户端暴露可调用的工具(Tool)。
2. 用 zod 定义工具参数模式
服务器为工具参数定义了三个 zod schema(src/index.ts):
const AddArgsSchema = z.object({ a: z.number().describe("First number"), b: z.number().describe("Second number"), }); const MultiplyArgsSchema = z.object({ a: z.number().describe("First number"), b: z.number().describe("Second number"), }); const GreetingArgsSchema = z.object({ name: z.string().describe("Name of the person to greet"), });zod 在这里承担双重职责:参数类型声明(供 schema 定义复用)与运行时校验(调用时用parse校验并解构参数)。
3. 注册 tools/list 处理器
server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ /* 四个工具的完整描述 */ ], }; });客户端通过tools/list请求获取工具清单。每个工具描述包含name、description与inputSchema(JSON Schema 格式),其中get_server_info的inputSchema为空对象properties: {},表示该工具无需任何参数。
4. 注册 tools/call 处理器
server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; switch (name) { case "add": { const { a, b } = AddArgsSchema.parse(args); const result = a + b; console.error(`Adding ${a} + ${b} = ${result}`); // Log to stderr return { content: [ { type: "text", text: `${a} + ${b} = ${result}`, }, ], }; } // ... multiply / get_greeting / get_server_info default: throw new Error(`Unknown tool: ${name}`); } });这里有几个值得注意的实现细节:
- 响应统一使用
content数组包裹,元素类型为text; - 每次调用都通过
console.error()向stderr输出日志——这正是 stdio 协议要求的正确做法; get_server_info用JSON.stringify(..., null, 2)返回结构化的服务器元数据(服务器名、版本、传输类型、能力列表);- 遇到未知工具名时抛出
Error,向客户端报告失败。
5. 连接 stdio 传输并启动
async function runServer() { console.error("Starting MCP stdio server..."); // Log to stderr const transport = new StdioServerTransport(); await server.connect(transport); console.error("Server connected via stdio transport"); // Log to stderr }StdioServerTransport封装了 stdin/stdout 上的 JSON-RPC 消息读写与换行分隔处理,server.connect(transport)完成协议握手。启动入口还处理了优雅退出:
process.on("SIGINT", () => { console.error("Received SIGINT, shutting down gracefully"); process.exit(0); }); process.on("SIGTERM", () => { console.error("Received SIGTERM, shutting down gracefully"); process.exit(0); }); runServer().catch((error) => { console.error("Server error:", error); process.exit(1); });服务器对SIGINT/SIGTERM信号进行捕获并优雅退出,同时捕获启动阶段的异常并输出错误日志。
第三步:运行服务器
npm start重要提示:stdio 服务器与旧的 SSE 服务器运行方式完全不同——它不会启动 Web 服务器,而是通过 stdin/stdout 通信。因此运行后终端会看起来像是卡住了,这是完全正常的!它正在等待来自 stdin 的 JSON-RPC 消息。
第四步:用 MCP Inspector 测试服务器
方法一:通过 npm 脚本(推荐)
npm run inspector该命令将:
- 把你的服务器作为子进程启动;
- 打开一个用于测试的 Web 界面;
- 让你交互式地测试服务器上的所有工具。
方法二:直接命令行启动 Inspector
也可以直接调用 Inspector,显式指定启动命令:
npx @modelcontextprotocol/inspector node build/index.js服务器提供的四个工具
| 工具 | 签名 | 说明 |
|---|---|---|
add | add(a, b) | 两个数字相加 |
multiply | multiply(a, b) | 两个数字相乘 |
get_greeting | get_greeting(name) | 生成个性化问候语 |
get_server_info | get_server_info() | 获取服务器信息 |
在 Inspector 界面中,你可以观察到客户端与服务器之间交换的 JSON-RPC 消息(如tools/list、tools/call),这为协议层面的调试提供了极佳的可视化手段。
第五步:接入 Claude Desktop
要将该服务器接入 Claude Desktop,把以下配置写入claude_desktop_config.json:
{ "mcpServers": { "example-stdio-server": { "command": "node", "args": ["path/to/build/index.js"] } } }配置要点:
command为启动进程的可执行文件(这里是node);args传入编译产物build/index.js的绝对路径;- 配置后重启 Claude Desktop,即可在对话中调用
add、multiply、get_greeting、get_server_info等工具。
stdio 与已弃用 SSE 的对比
stdio 传输(当前推荐):
- ✅ 更简单的设置——无需 HTTP 服务器;
- ✅ 更好的安全性——没有 HTTP 端点暴露;
- ✅ 基于子进程的通信;
- ✅ JSON-RPC over stdin/stdout;
- ✅ 更好的性能。
SSE 传输(已弃用):
- ❌ 需要搭建 Express 服务器;
- ❌ 需要复杂的路由与会话管理;
- ❌ 更多依赖(Express、HTTP 处理);
- ❌ 额外的安全考量;
- ❌ 已在 MCP 规范 2025-06-18 中弃用。
开发与调试技巧
- 日志一律使用
console.error():console.log()会写入stdout,而stdout被协议保留用于 MCP 消息,污染stdout会直接破坏通信; - 测试前先
npm run build:start与inspector脚本都指向build/目录下的编译产物,未编译会导致启动失败; - 优先用 Inspector 做可视化调试:可以直观查看工具列表、参数校验结果与 JSON-RPC 消息流;
- 确保所有 JSON 消息格式正确:协议要求消息按换行符分隔且不含内嵌换行;
- 优雅退出已内置:服务器会自动处理
SIGINT/SIGTERM信号。
跨语言对照:同一解决方案的另两种实现
本仓库的 解题方案总览 提供了 TypeScript、Python、.NET 三种运行时的完整实现,帮助你理解 stdio 服务器在不同生态中的落地方式:
- Python:server.py 使用
mcp官方 SDK,通过@server.list_tools()与@server.call_tool()装饰器注册工具,用stdio_server()上下文管理器建立传输,并通过logging模块将日志输出到stderr; - .NET:Program.cs 基于
Host.CreateApplicationBuilder与依赖注入,通过.AddMcpServer().WithStdioServerTransport().WithTools<Tools>()链式配置,Tools.cs 则用[McpServerTool]特性声明工具方法。
三者共享同一套工具集(add、multiply、get_greeting、get_server_info)和相同的 stdio 协议约束,对照阅读可以快速掌握跨语言实现 MCP 服务器的共性模式。
小结
通过本文,你已经完整走通了用 TypeScript 构建 MCP stdio 服务器的全部流程:理解协议原理、安装构建、深入源码、启动测试、接入 Claude Desktop。关键要点总结如下:
- stdio 是本地 MCP 服务器当前推荐的传输方式,相比 SSE 更简单、更安全、性能更好;
- 服务器本质是一个"等待 stdin 消息的子进程",
stderr是日志通道、stdout是协议通道; - MCP SDK 的
Server+StdioServerTransport组合把协议细节封装到极致,开发者只需关注工具的定义与实现; - MCP Inspector 是调试 stdio 服务器的首选工具,可视化地呈现 JSON-RPC 交互全过程。
在此基础上,可以继续探索本仓库的进阶主题:HTTP Streaming(Streamable HTTP 传输) 用于远程服务器场景,以及 MCP 安全最佳实践 为服务器加固。
- 教程
- 文档
- 人工智能
【免费下载链接】mcp-for-beginners
This open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.
相关推荐
基于 stdio 传输构建 MCP 服务器:从原理到调试集成的完整实战指南(mcp-for-beginners)
基于 stdio 传输构建 MCP 服务器:从原理到调试集成的完整实战指南(mcp for beginners) 本教程面向希望快速掌握 Model Conte
教程文档人工智能基于 MCP SDK 构建 TypeScript stdio 服务器:从零实现、调试到接入 Claude(mcp-for-beginners 实战解析)
基于 MCP SDK 构建 TypeScript stdio 服务器:从零实现、调试到接入 Claude(mcp for beginners 实战解析) 导读
教程文档人工智能MCP for Beginners:基于 stdio 传输构建多语言 MCP 服务器(TypeScript / Python / .NET 完整实现解析)
MCP for Beginners:基于 stdio 传输构建多语言 MCP 服务器(TypeScript / Python / .NET 完整实现解析) MC
教程文档人工智能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考