MCP TypeScript SDK — 架构与原理
30 秒导读: 这是 Model Context Protocol(MCP,模型上下文协议)的官方 TypeScript 实现。你用它写一个「MCP 服务器」,把工具(tools)、资源(resources)、提示词(prompts)暴露给任何 MCP 客户端(如 Claude Desktop、IDE 插件);SDK 负责把这些注册项翻译成标准的 JSON-RPC 报文、走 stdio 或 HTTP 传输、并处理两套协议版本(2025 与 2026)之间的差异。本仓库是 v2(pre-alpha),最大的工程亮点是「双协议纪元」架构。
1. 这是什么(零基础也能懂)
-
一句话定义: MCP 是「给 LLM 喂上下文」的标准协议,这个 SDK 是它的 TypeScript 实现——一边是写服务器的库
@modelcontextprotocol/server,一边是写客户端的库@modelcontextprotocol/client。 -
解决什么问题 / 给谁用: 假设你 想让 Claude 能查天气、读你的数据库、调用你公司的内部 API。没有 MCP,你得为每个 LLM 客户端写一套定制集成。MCP 把「提供上下文」和「调用 LLM」这两件事拆开:你写一个标准 MCP 服务器,任何支持 MCP 的客户端都能直接用。
-
核心概念(协议的三个原语):
原语 是什么 谁控制 例子 Tool(工具) 可被 LLM 调用、有副作用的函数 模型决定何时调 get-forecast(lat, lon)Resource(资源) 可读的数据,有 URI 应用/用户挑选 file:///readme.mdPrompt(提示词) 预制的对话模板 用户显式触发 review-code(code) -
用起来什么样: 下面是仓库自带的天气服务器示例的精简版——注册一个工具,然后接上 stdio 传输即可。
// 示意,改编自 examples/server-quickstart/src/index.tsimport { McpServer } from '@modelcontextprotocol/server';import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';import * as z from 'zod/v4';const server = new McpServer({ name: 'weather', version: '1.0.0' });server.registerTool('get-forecast',{title: 'Get Weather Forecast',description: 'Get weather forecast for a location',inputSchema: z.object({ // 入参用 Zod 描述(也支持 Valibot/ArkType)latitude: z.number(),longitude: z.number(),}),},async ({ latitude, longitude }) => ({ // 处理器:返回 content 数组content: [{ type: 'text', text: `Forecast for ${latitude},${longitude}: ...` }],}),);await server.connect(new StdioServerTransport()); // 接上传输,开始监听 stdin真实的两个工具注册见
examples/server-quickstart/src/index.ts:87(get-alerts)与:133(get-forecast)。 -
一句话直觉/类比: 把 MCP 服务器想成一个「USB 设备」,把 LLM 客户端想成「电脑」。USB 标准让任何设备插任何电脑都能用——MCP 就是 AI 工具的 USB 标准,而这个 SDK 是写「USB 设备固件」的工具包。
2. 顶层全 景(它大概怎么转)
这个 SDK 是 pnpm monorepo,拆成多个发布包。理解架构的关键是看清「分层」:从你写的业务代码,到最终发出去的字节,中间隔了三层。
2.1 包的布局
| 包 | 干什么 | 在哪 |
|---|---|---|
@modelcontextprotocol/server | 高层服务器 API(McpServer) + 底层 Server + 传输 | packages/server/ |
@modelcontextprotocol/client | 客户端 API(Client) + 传输 + OAuth | packages/client/ |
core-internal(私有) | 协议核心:Protocol、类型、wire codec | packages/core-internal/ |
core(私有) | 把 core-internal 的公共子集再导出 | packages/core/ |
middleware/* | Express / Hono / Fastify / Node 适配器(薄) | packages/middleware/ |
server-legacy | v1 风格的 SSE 传输与 OAuth 路由 | packages/server-legacy/ |
codemod | v1→v2 自动迁移工具 | packages/codemod/ |
关键认知:
core-internal是private: true,绝不直接发布;server和client各 自从它 re-export 公共类型。所有「协议怎么落到字节」的机密都藏在core-internal/src/wire/里。
2.2 一条 tools/call 请求的旅程(高层)
这张图从左到右是一个工具调用从「客户端发起」到「服务器处理器跑完」的控制流。重点看中间三层:传输 搬运字节、Protocol 做 JSON-RPC 配对、wire codec 按纪元翻译。
客户端 ┌─────────── 服务器进程 ───────────┐
┌──────┐ JSON-RPC over │ Transport Protocol │
│Client│──── stdio / HTTP ─────▶│ (搬字节) ──▶ (配对/分发) ──┐ │
└──────┘ │ ▲ │ │
▲ │ │ wire codec ▼ │
│ result(已按纪元编码) │ │ (按纪元解码请求) McpServer │
└────────────────────────────│─────┘ (按纪元编码结果) (跑你的 │
│ ▲ 处理器) │
│ └──────────────┘ │
└───────────────────────────────────┘
四个部件,各管一段:
| 部件 | 一句话职责 | 在哪个文件 |
|---|---|---|
Transport | 把 JSON-RPC 消息搬过线(stdio/HTTP/in-memory),不懂语义 | core-internal/src/shared/transport.ts:107 |
Protocol | JSON-RPC 帧、请求↔响应配对、超时、取消、进度 | core-internal/src/shared/protocol.ts:517 |
WireCodec | 按「协议纪元」决定哪些方法存在、字节长什么样 | core-internal/src/wire/codec.ts:159 |
McpServer | 高层 API:把 registerTool 等变成请求处理器 | packages/server/src/server/mcp.ts:66 |