跳到主要内容

通读笔记 — Learn Model Context Protocol with TypeScript

原书 12 个正文章(text/03–14),导航章(01 前言/02 序言/15–17 促销+索引)跳过不引。 作者 Christoffer Noring(Packt, 2025-11-21)。书内代码仓:PacktPublishing/Learn-Model-Context-Protocol-with-TypeScript。

Ch1 Introducing the MCP (text/03, ~9.9k)

  • 历史线 SOAP→REST→GraphQL(N+1 问题)→gRPC(HTTP/2+Protobuf),各自的问题(:55-125)。
  • 为什么需要标准:开发者「太会编程」,什么都能胶水起来,但代价高(:165-189);prompt 成为新交互方式,LLM 与应用能力要不要分开(:141-153)。
  • MCP 定义:官方说法「USB-C port for AI applications」(:317-329);mcp.json 列出服务器,client 即接(:203-217)。
  • 可能性:Blender MCP(GitHub ahujasid/blender-mcp)、GitHub/Playwright/Google Maps MCP;modelcontextprotocol/servers 列表(:237-291)。
  • 「If you know how to prompt, you're Neo」(:265)。
  • 本章很浅,纯动机章。可引:历史线一句话、USB-C 比喻、glue 代价。

Ch2 Explaining the MCP (text/04, ~53k) — 全书最重的协议章

  • 方法:不靠架构图,带你徒手实现协议(不用 SDK)。JSON-RPC 消息四字段 jsonrpc/id/method/params(:21-48)。
  • Transport 接口 TypeScript 定义 start/send/close/onclose/onerror/onmessage(:122-133);MCP transport agnostic(:98)。
  • STDIO 实现:readline 服务器 + spawn 子进程客户端(:179-341);运行输出样例(:406-409)。
  • 握手三步:initialize(带 protocolVersion 2024-11-05 + capabilities + clientInfo)→ 服务器回 capabilities(logging/prompts/resources/tools)+ serverInfo → client 发 notifications/initialized;之前发别的要报错(:486-690)。
  • 实现要点:once 监听 + Promise 包装流回调,connect() 伪码到真码(:698-990);服务器侧 initialized 状态机(:1036-1149)。
  • features:tools/list、tools/call 响应结构 content.items 文本块(:1446-1496);Promise+流整合 _handleMessageResponse/_makeRequest/_serializeMessage(:1354-1399, 1821-1876)。
  • 运行输出实例(initialize response 全文,Tools response ExampleTool)(:1416-1442)。
  • Notifications:双向,notifications/cancelled、notifications/progress;schema 引用 2025-03-26(:1659-1699);onnotification 变量模式(:1719-1772)。
  • Sampling:服务器反向请求客户端 LLM(:1913-1945);请求字段 messages/modelPreferences(hints/costPriority/speedPriority/intelligencePriority)/systemPrompt/includeContext/temperature/maxTokens(:1963-1993);响应 model/stopReason/role/content(:2011-2039);电商产品描述场景,sampling/createMessage 实例(:2041-2083);实现 ExternalService 事件→server 发 sampling→client onsampling→callLLM(mock)→回包(:2091-2346);human in the loop(:2350-2356)。
  • SSE transport:/messages + /sse 两个路由,GET 长连接,text/event-stream(:2368-2404)。
  • Streamable HTTP:单一 /mcp 路由 POST,服务器可选 JSON 或 SSE 应答,client 要 accept 两种(:2416-2476)。
  • 关键出处短语:USB-C 在 ch1;握手在 notifications/initialized(:688);sampling 定义 I don't know how to do this(:1923)。
  • 注意:书基于 protocolVersion 2024-11-05 示例 + 2025-03-26 schema;我们 mcp-spec 拆解是 2026-07-28(无状态化)。书里有状态握手 vs 新规范每请求自带身份——重要②类锚对照点。

Ch3 Building and Testing Servers (text/05, ~27.5k)

  • 三件套概念:Resources(静态数据/上下文,类简化 RAG,:130-223;固定名 vs ResourceTemplate 模板 settings://{type});Tools(函数,Zod schema,:225-269);Prompts(模板消息,:271-302)。
  • 运行时列表:TS/Python/.NET/Java/Kotlin/Rust/Go(:310)。
  • 测试三法:Inspector(npx @modelcontextprotocol/inspector,UI+CLI,--cli --method)、cURL(仅 HTTP 系)、单测(书中竟用 pytest/FastMCP Python 例子,:524-530——TS 书的瑕疵)。
  • First server 五步:package.json(@modelcontextprotocol/sdk ^1.8.0, zod, bin/scripts)、tsconfig(ES2022/Node16)、McpServer 实例、server.tool(multiply)/server.resource(get_greeting greeting://{name})/server.prompt(review-code)、main 里 STDIOServerTransport + server.connect(:558-943)。
  • Inspector CLI 输出实例:tools/list 返回 inputSchema/outputSchema(multiply);tools/call 2*4=8 带 structuredContent;resources/list 空 vs resources/templates/list(模板资源不在普通列表!,:1128-1146);resources/read greeting://chris→Hello, chris!;prompts/list/get(:997-1213)。
  • 作业:电商 STDIO server(get-orders/place-order/add-to-cart/products 等 11 个工具+product_catalog 资源,:1231-1359)。
  • 瑕疵:书名 TS 但测试例子用 Python;prompt 名 review-code vs review_code 不一致。

Ch4 Building SSE Servers (text/06, ~17.5k)

  • SSE 已废弃:「SSE transport has been deprecated in favor of Streamable HTTP transport per May 2025」(:23);但 2000+ 野生服务器还在用(:25)。
  • SSE 概念:text/event-stream、EventSource、单向 server→client、长连接(:53-83);MCP 里拆两个端点 /sse(握手长连)+ /messages(消息路由)(:85-105)。
  • Express 实现:SSEServerTransport('/messages', res),transports.sse[sessionId] 表,res.on("close") 清理,POST /messages 按 query sessionId 找 transport.handlePostMessage(:131-150, 405-445)。
  • 测试:Inspector 要选 Transport Type=SSE + URL;cURL 三步——GET /sse 拿 event: endpoint 带 session_id → POST /messages?session_id 发 notifications/initialized → POST tools/list,响应出现在第一个终端(:248-290, 638-710)。
  • add 工具 5+10=15 走查(:489-636)。

Ch5 Streamable HTTP (text/07, ~36k)

  • 为什么是新标准:单端点 /mcp(POST+GET)、resumability(Last-Event-ID + Mcp-Session-ID 头)、兼容 LB/代理/网关、双向、无状态或会话可选(:51-141);废弃时 20 参考服务器/50+ 官方集成/186 社区在用 SSE(:77-85)。
  • Accept: application/json, text/event-stream,服务器自选 JSON 或 SSE 应答(:143-167)。
  • Resumability 服务器侧:InMemoryEventStore + sessionIdGenerator: randomUUID + onsessioninitialized 存 transport(:217-251);断线重连用 GET /mcp + mcp-session-id + last-event-id 头重放(:1283-1310);event store 内存版不能上生产(:1312)。
  • 完整服务器代码:POST /mcp(有 sessionId 复用,无且 isInitializeRequest 则新建),GET/DELETE handleSessionRequest;capabilities:{logging:{}} 才能发通知(:500-696)。
  • 通知:server 端从 tool 回调第二参 context 解构 sendNotification,notifications/message;client 端 client.setNotificationHandler(LoggingMessageNotificationSchema)(:306-404, 1040-1066)。
  • cURL 全程走查:initialize(protocolVersion 2025-03-26)→ initialized(注意 mcp-session-id 是头不是 query,:907-915)→ tools/call echo chris → 3 条 notification + result(:877-966)。
  • resumability 走查:sales1/2/3.csv,记住 id ..._meh2n52f,GET /mcp 带 last-event-id 重放 sales3 + result(:1230-1294)。

Ch6 Clean Architecture / Low-level (text/08, ~37k)

  • 为什么低层:生命周期控制、架构自由、sampling/elicitation 只能低层(:37-87)。
  • Context manager:With(manager, fn) 模式,enter/exit,generator yield 资源,try/finally 清理;TS SDK 没内置(Python SDK 有),自己实现(:91-454)。
  • 高层 vs 低层:McpServer(注册式)vs Server + setRequestHandler(ListPromptsRequestSchema/GetPromptRequestSchema)(:466-599)。
  • 架构:tools/ 目录,Tool 接口(name/description/rawSchema/inputSchema/callback),zodToJsonSchema 转 JSON Schema(低层要 JSON 格式)(:759-796);工具文件是纯 TS 无框架依赖,易测试(:908)。
  • CallToolRequestSchema 处理:按 name 找工具(tool_not_found)、Schema.parse 校验参数(invalid_arguments)、调 callback(:1264-1381)。
  • 瑕疵:TS 章里两次说「Pydantic schemas」(:1278、:1413)——从 Python 版改编的残留;Server 构造少个括号(:706-714)。

Ch7 Bespoke Clients (text/09, ~20k)

  • client 五步:连接→列特性→选特性→问参数→展示(:57-71)。
  • StdioClientTransport({command:"node", args:["./build/index.js"]}) + Client + connect(:97-117);listTools/listResources/listResourceTemplates(:173-187);readline 问参 + callTool(:233-255)。
  • 无 LLM vs 有 LLM 流程对比:「knowing」vs「doing」(:371-431)。
  • GitHub Models(免费,GITHUB_TOKEN,bearer;Ollama 本地不用 token)(:437-473);OpenAI SDK baseURL models.github.ai/inference,model openai/gpt-4o-mini,tools 参数(:503-551)。
  • toLLMTool 转换:MCP tool.inputSchema → OpenAI function 格式(:620-661);response.choices[].message.tool_calls → callTools → client.callTool(name, JSON.parse(args))(:675-754)。
  • temperature/max_tokens/top_p 只说「控制随机性与上下文窗口大小」(:556-574)——讲得浅。

Ch8 IDE 消费 (text/10, ~28.5k)

  • Host 概念:内置 MCP client + LLM + 配置文件;三职责(连接/UI/配置)(:59-103);VS Code 功能清单(装服务器/管工具/sampling/elicitation/调试)(:105-153)。
  • mcp.json:servers + inputs 两属性(:183-223);inputs promptString+password:true,${input:my-key} 引用,secrets 不入文件(:257-306);三种 transport 的 entry 形态(http/sse/command+args)(:308-394)。
  • Playwright 走查:mcp.json 加 entry → 启动 → agent 模式 prompt「Navigate to tfl.gov.uk… important use playwright tool」→ 一连串 tool 调用 → 可生成 Playwright 测试(:396-623)。
  • 本地 .vscode/mcp.json vs 全局 (Settings)/User/mcp.json(:625-697)。
  • debug:dev.watch(GLOB)+dev.debug{type:"node"}(:713-778)。
  • Output 日志完整握手走查(:853-924):VS Code Insiders 1.103.0,protocolVersion 2025-06-18,capabilities roots/sampling/elicitation;「Failed to parse message: "Starting MCP server...\n"」——stdout 混入非 JSON-RPC 会破坏解析(:861)!
  • 工具管理:tools 图标勾选、#add 前缀、virtualTools 设置(工具太多时按 prompt 筛选)、approval(本次/本工作区/总是,Chat: Reset Tool Confirmations)(:926-1022)。
  • 消费侧安全:secrets 入 inputs、每次批准、限制文件服务器目录、用 vetted registry(@mcp / Browse MCP Servers;Stripe 例子)(:1050-1168)。推荐 GitHub/Playwright/Microsoft Learn MCP(:1184-1236)。

Ch9 Sampling (text/11, ~23.5k)

  • 定义:Merriam-Webster「taking samples for analysis」;MCP 里=服务器把「样本」发给客户端分析=委派(:7-37)。客户端才有 LLM。
  • 四方:User(发起+human in the loop)/Server(发请求)/Client(展示+决定)/LLM(完成)(:71-111);请求是建议不是命令(:101-103)。
  • 三场景:博客标签、电商产品描述、NPC 对话(:127-192)。
  • 消息:sampling/createMessage 全文(tomato 例子,modelPreferences hints claude-3-sonnet,intelligencePriority 0.8/speedPriority 0.5,systemPrompt,maxTokens)(:207-237);响应 model/stopReason endTurn(:281-295)。
  • 服务器实现:server.server.createMessage(注意双层 server)(:375-388);create_product 工具走查(:349-404)。
  • VS Code 测试:Configure Model Access 选模型;agent 模式 prompt;产出 Red Garden Medley 描述(:443-541)。
  • 客户端实现:capabilities:{sampling:{}} + client.setRequestHandler(CreateMessageRequestSchema)(:549-622);paprika 运行日志(:644-667)。
  • 瑕疵:mcp.json 示例又是 python 命令(:453-456);日志是 server.py(:646)。

Ch10 Elicitation (text/12, ~21k)

  • 定义:官方「servers to request additional information from users through the client」(:13-25);假期预订日期不可用→问备选日期(:33-37)。
  • 动机:任务复杂(电影票/火车票分步)、转化率(红毛衣缺货→换色/排队)、体验(不只说 no)(:63-105)。
  • 安全准则:不得索取敏感信息;UI 要标清哪台服务器在问;可先改再发;要有 decline/cancel(:111-135)。
  • 两步:服务器先问客户端可否发起 → 客户端问用户;两步都可拒(:137-149)。
  • 消息:elicitation/create,message + requestedSchema(:163-181);schema 例 name/email/age(minimum 18)(:211-230);响应 accept 带 content(:240-253);decline(:265-273);cancel=按 Esc/关对话框(:277-289)。
  • requestedSchema 四类型:string(minLength/maxLength/pattern/format)、number/integer(minimum/maximum)、boolean(default)、enum+enumNames(:291-386)。
  • 服务器:server.server.elicitInput({message, requestedSchema});book-trip 工具:checkAvailability 失败→elicit→result.action==="accept" && content.checkAlternatives→订新日期(:394-564)。
  • VS Code 走查六图:prompt「Book trip on 2025-02-01」→批准→true→填新日期→确认(:566-675)。
  • 客户端:client.setRequestHandler(ElicitRequestSchema) 返回 {action, content};迭代 params.params.requestedSchema.properties 动态生成输入(:677-798);callTool 触发(:848-877)。

Ch11 Security (text/13, ~36k)

  • 场景表:公开数据/半公开/敏感个人数据(HTTPS+OAuth2.0/2.1+加密+RBAC,GDPR/HIPAA)(:15-65)。
  • Basic Auth:Authorization: Basic base64(user:pass) 或 API key(:99-160);中间件 401/403;Express app.use 全局 vs 每路由(:283-376);MCP client 用 StreamableHTTPClientTransportOptions.requestInit.headers 带 Authorization(:404-465)。
  • JWT:claims(scopes ["User.Read"])、无状态/可扩展/签名(:471-536);三段 header.payload.signature,HS256(:538-636);jsonwebtoken 库 sign/verify,exp 1 小时(:638-731);还要查 iss/aud/nbf/scopes;scopes 比 roles 细(:733-791);中间件集成 Bearer(:926-977)。
  • OAuth2:三方 resource server/client/authorization server;委派=用户授权 client 拿 access token,可吊销(:979-1027);JWT 常作 access token 载体。
  • OAuth2.1(MCP SDK 支持):ProxyOAuthServerProvider(endpoints authorizationUrl/tokenUrl/revocationUrl, verifyAccessToken, getClient)+ mcpAuthRouter(provider, issuerUrl, baseUrl)(:1029-1152)。
  • code flow 四步:/authorize→拿 code→/token 换 access_token→Bearer 访问(:1154-1351)。瑕疵:code_challenge_method=plain(:1238)——PKCE 应用 S256,plain 等于没保护
  • 生产:授权服务器用现成的(Entra ID/Cognito/Auth0);鉴权放哪层:web 服务器/MCP 服务器/网关(API Management 还有 content safety/semantic caching);每工具 scope 检查(:1353-1391)。
  • 资源链接全是 microsoft/mcp-for-beginners(作者维护的课程)与 Azure 示例(:1481-1497)。

Ch12 Production (text/14, ~37.7k)

  • 集成模式:web API(REST)前挡 + 中间件 + MCP client 转发 JSON-RPC(:69-101)。
  • 文档:代码生成 OpenAPI(又是 FastAPI Python 例子 :129-142)、测试即文档、Mermaid 图(:103-173)。
  • 架构审查:模块化(单一职责)、validation(Zod parse,低层 Server 完整例子 :206-274;create_user payload 例子与代码对不上 :362-393)、AI 影响(解耦/延迟与 UI/token 预算/least privilege)(:174-443)。
  • 打包:standalone(本地 STDIO 要沙箱,filesystem server 限目录+容器;远程要 OAuth2/API key/RBAC)vs embedded(连着 client 一起发)(:445-543)。
  • 分发:Docker(多阶段 Dockerfile 来自 filesystem server :557-576)、包管理器(npm/PyPI/NuGet)、仓库直发(playwright mcpServers 配置;链接写成 RBC/... 是错的 :604-621)。
  • semver:major/minor/patch,1.3.0→1.3.1/1.4.0/2.0.0;钉 1.3.x 或 1.x.x(:637-665)。
  • 测试:单元(解析逻辑拆模块)、集成(端到端 UI→API→client→MCP)、AI 测试(对抗测试、黄金 prompt 集)(:667-723)。
  • 部署:2025 的 robust=一键一天多次+guardrails;pipeline .yml;AI 可能要独立 pipeline(:725-767)。
  • 可观测:logging(级别+上下文)/tracing(请求旅程)/metrics(CPU/内存/吞吐/响应时间/错误率);MCP 特有:token 用量 vs 缓存命中;MCP 内建日志级别(:807-881)。
  • 弹性:load balancing(AI 端点分开)/rate limiting/circuit breakers(网关实现,Azure API Management XML 策略)(:883-1003)。
  • 监控:APM、AI 使用抽样审计、反馈环、防提示注入(:1005-1059)。
  • 治理:GDPR/HIPAA、audit trail、bias/fairness、content safety(:1061-1085)。
  • future-proofing:协议在进化(SSE 已废)、SDK 会 break、Dependabot/GHAS(:1087-1123)。

作者与时代(写总纲用)

  • 作者 Christoffer Noring:微软工程师(01:137-151),同事 John Papa/Dan Wahlin;维护 microsoft/mcp-for-beginners 课程(ch11 资源);LinkedIn uk.linkedin.com/in/christoffer-noring-3257061(14:1147-1151)。
  • 序言由微软 Principal Content Engineer 写(01:131);reviewer Maxim 是微软 Senior Solution Engineer(01:201)。
  • 声明用 GitHub Copilot 润色语言(02 preface,:80 附近「The author acknowledges the use of cutting-edge AI」)。
  • 出版 2025-11-21 Packt;书里协议版本脚印:2024-11-05(ch2 示例)、2025-03-26(ch5 curl)、2025-06-18(ch8 VS Code 日志)。
  • 利益相关:全书工具链 VS Code Insiders/GitHub Copilot/GitHub Models/Azure API Management/Entra ID——作者在微软任职,这是「这是谁在什么时候写的」必须点明的。
  • 改编瑕疵:多处 Python 残留(pytest/FastMCP、FastAPI、Pydantic、python 命令、server.py 日志),书疑似从 Python 课程/书改编为 TS 版。

②类锚(我们书架已有)

  • mcp-spec 拆解(2026-07-28 版,docs/mcp-spec/01..06):01 JSON-RPC/无状态、02 版本与 server/discover、03 三件套、04 MRTR+sampling/elicitation、05 transports(2026 版砍 HTTP 会话/GET 流/Last-Event-ID 可恢复 SSE!)、06 OAuth 2.1 资源服务器。
  • mcp-typescript-sdk 拆解(v2 pre-alpha,双纪元 codec):01 高层 McpServer、02 Protocol+Transport、03 wire codec eras、04 client 协商。
  • ai-agents-with-mcp(姊妹书拆,Kyle Stratis):术语对齐——采样=sampling、征询=elicitation、人在回路。
  • 关键异同:书=2025 年代有会话 Streamable HTTP + 可恢复 SSE;新规范 2026-07-28 砍掉会话与恢复(subscriptions/listen 替代)。书 SDK ^1.8.0;现 SDK v2 双纪元。