跳到主要内容

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.md
    Prompt(提示词)预制的对话模板用户显式触发review-code(code)
  • 用起来什么样: 下面是仓库自带的天气服务器示例的精简版——注册一个工具,然后接上 stdio 传输即可。

    // 示意,改编自 examples/server-quickstart/src/index.ts
    import { 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) + 传输 + OAuthpackages/client/
core-internal(私有)协议核心:Protocol、类型、wire codecpackages/core-internal/
core(私有)core-internal 的公共子集再导出packages/core/
middleware/*Express / Hono / Fastify / Node 适配器(薄)packages/middleware/
server-legacyv1 风格的 SSE 传输与 OAuth 路由packages/server-legacy/
codemodv1→v2 自动迁移工具packages/codemod/

关键认知: core-internalprivate: true,绝不直接发布;serverclient 各自从它 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
ProtocolJSON-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

2.3 v2 最该记住的一件事:双纪元

MCP 协议正在从「2025 纪元」演进到「2026 纪元」,两者报文不兼容:

  • 2025 纪元(legacy):initialize 握手协商版本;服务器能反过来向客户端发请求(采样、elicitation)。
  • 2026 纪元(modern): 没有 initialize,改用 server/discover 探测;每个请求带一个 _meta 信封;服务器不能反向发请求,改用 input_required 结果做多轮交互。

SDK 的做法是:公共类型层完全中性(不含 resultType、不含信封),把所有纪元差异塞进 wire/ 下两个 codec。运行时根据协商出的版本选 codec——这就是第 3 章的主题,也是读懂 v2 的钥匙。

3. 阅读地图(建议顺序)

按「先用得上、再懂底层」排序:

  1. 01-high-level-server.mdMcpServer 高层 API。你 90% 的时间在跟它打交道:registerTool/Resource/Prompt 怎么变成 tools/listtools/call 处理器,输入输出怎么校验。从这里开始。

  2. 02-protocol-and-transport.md — 底层骨架:Protocol 抽象类如何做请求/响应配对、超时、取消、进度通知;Transport 接口长什么样;一条请求在 _onrequest 里怎么被分发。

  3. 03-wire-codec-eras.md — v2 的灵魂:双纪元 wire codec。「中性类型 vs 上线字节」的分离,「删除即物理删除(registry membership)」,纪元门(era gate)如何在分发前拦截不属于本纪元的方法。

  4. 04-client-and-negotiation.md — 客户端侧:Client 类,以及连接期的版本协商(server/discover 探测、超时回退到 initialize、pin 模式)。

4. 代码地图(导航索引)

主题文件关键符号
高层服务器packages/server/src/server/mcp.tsMcpServerregisterToolsetToolRequestHandlers
底层服务器packages/server/src/server/server.tsServerServerOptions
协议核心packages/core-internal/src/shared/protocol.tsProtocolrequest_onrequest_onresponse
传输接口packages/core-internal/src/shared/transport.tsTransportTransportSendOptions
wire codec 契约packages/core-internal/src/wire/codec.tsWireCodeccodecForVersionisSpecRequestMethod
2025 codecpackages/core-internal/src/wire/rev2025-11-25/codec.tsrev2025Codec
2026 codecpackages/core-internal/src/wire/rev2026-07-28/codec.tsrev2026Codec
纪元判定packages/core-internal/src/shared/protocolEras.tsisModernProtocolVersionFIRST_MODERN_PROTOCOL_VERSION
客户端packages/client/src/client/client.tsClient
版本协商packages/client/src/client/versionNegotiation.tsnegotiateEraresolveVersionNegotiation
stdio 传输packages/server/src/server/stdio.tsStdioServerTransport
HTTP 入口packages/server/src/server/createMcpHandler.tscreateMcpHandlerMcpServerFactory