TOOLS / 8 BOOKS / 05 · ENGINE v1
MCP 模型上下文协议
本册:MCP 统一插件协议
30 SECONDS / 30 秒看懂
这一册只解决一件事:MCP 用统一协议把 AI 和外部工具连接起来,本地走 stdio,远程走 Streamable HTTP。
- MCP 有 Host、Client、Server 三层,Server 暴露 Resources/Tools/Prompts
- stdio 用标准输入输出传 JSON-RPC;远程用 Streamable HTTP 单端点
- stdio Server 里 print 调试会污染协议通道,日志必须写 stderr
3 MINUTES / 3 分钟拆解
先看来源里的例子:PDF 本册核心例子(来源)
写 MCP Server 时在工具函数里加了一句 print("正在查询数据...")。发生了什么
stdio 模式下 stdout 是 JSON-RPC 专用通道;普通 print 把中文写进 stdout,客户端 JSON 解析器收到非 JSON 字符,报错并断开。
输出
来源修复:调试日志一律写入 sys.stderr,保持 stdout 只输出 JSON-RPC 报文。
术语拆开
- MCP
- Model Context Protocol,AI 工具插件标准。
- stdio
- 本地进程通过标准输入输出通信。
- Streamable HTTP
- 远程 MCP 的单端点流式 HTTP 传输。
为什么有效
来源指出:过去每个工具各写一套插件格式;MCP 统一 Host-Client-Server 和传输层,成为 AI 界的 USB-C。
结构长什么样
Host → Client → Server(Resources/Tools/Prompts)\n本地 stdio / 远程 Streamable HTTP
为什么 MCP stdio Server 里不能随便 print 调试信息?
SOURCE READING / 来源精读
本册讲 MCP 的 Host-Client-Server 架构、stdio 与 Streamable HTTP 传输,以及 FastMCP 开发。
逐点读懂
- Host 管连接,Server 暴露工具/资源
- 本地 stdio,远程 Streamable HTTP
- MCP 解决插件格式碎片化
怎么对应本关练习
先用 30 秒看懂抓四层结构,再读本册的‘顿悟时刻/原理/动手实验’,最后做课后自测;答案在下方。
例子在哪
本册的动手实验与课后自测都在原文;参考答案见本页下方。
MCP 统一插件协议
【第二辑:神兵利器篇 · 课题 05 / 08】AI 现代必修课 · 前沿工具深讲与动手实验讲义
利器05:MCP 模型上下文协议——Streamable HTTP 与 stdio 万物插件实战同步 2026 最新 MCP 官方规范:搞懂 Host-Client-Server 架构、Streamable HTTP 远程传输、stdio 本地管道禁忌与 FastMCP 开发核心知识参考:MCP 2026 Specification (Streamable HTTP)、MCP Official Servers 与 MCP Python SDK
一、顿悟时刻:哦,原来 MCP 协议是怎么统一 AI 界的插件标准的!
在《内功06》中我们学过,大模型要调用外部工具必须依靠 Function Calling(函数调用)。
但过去几年里, OpenAI、Anthropic、Cursor、各类开源框架各自搞了一套互不兼容的插件定义格式——你想让 AI 查个本地 SQLite 数据库或读个 GitHub 仓库,得给每个软件重写一遍㬵水代码!
为了终结这种碎片化乱象,Anthropic 联合开源社区推出了 Model Context Protocol (MCP,模型上下文协议),并迅速成为 Claude Desktop、Claude Code、OpenAI Codex CLI、Cursor、Gemini CLI 等几乎所有主流 AI 工具共同遵守的“AI 界 USB-C 万能扩展标准”。
我们先花 3 分钟弄懂它的两项底层核心机制。
真相一:MCP 的三大原语(Resources / Tools / Prompts)与最新两大传输层(stdio vs Streamable HTTP) 根据最新的 MCP 2025/2026 官方协议规范,任何 MCP Server 都可以向客戶端暴露三类标准能力:Resources (只读数据资源,由应用按需挂载)、Tools(可执行工具函数,由大模型自主决定调用)与 Prompts(预设指令模板,由用戶通过斜杠命令触发)。
而在底层物理通信上,最新规范确立了两大标准传输协议(注意:早期旧版规范中的独立 HTTP+SSE 双端点模式已被更现代的 Streamable HTTP 正式取代!): 标准传输方式底层物理通信机制(它是怎么发消息的?
) 最佳适用场景
1. stdio
(标准输入输出管道) AI 客戶端(如 Claude / Cursor / Codex)直接在本机后台拉起 MCP Server 子进程,通过操作系统的标准输入(stdin)与标准输出 (stdout) 传输换行分隔的 JSON-RPC 2.0 报文。
本地单机工具:读写本机文件系统、操作本地 Git 仓库、查询本机 SQLite 数据库、 执行本地脚本。
2. Streamable HTTP
(单端点流式 HTTP) 自 MCP 2025-03-26 / 2026-07-28 规范引入的现代远程协议:服务端仅暴露单一 HTTP 端点(如 https://example.com/mcp),支持无状态请求或升级为双向流,并在请求头携带 Mcp-Method 等元数据以便网关路由。
云端远程多租戶服务:部署在云服务器或 Cloudflare Workers 上供多人共享的 SaaS 插件、远程企业知识库接口。
真相二:为什么在本地 stdio MCP 插件里写一句普通的 print("hello") 就会让整个连接瞬间崩溃?这是 90% 的初学者自己动手写第一个 Python MCP 插件时必踩的头号大坑!
当你看懂上面的 stdio 机制,就会一拍大腿喊出“哦,原来是这样!
”: 因为你的 Python 脚本是作为子进程被 AI 客戶端拉起的,客戶端把你脚本的 sys.stdout(标准输出通道)直接当成了传输 JSON-RPC 2.0 协议报文的专用网线 !
客戶端每一秒钟都在监听 stdout 吐出来的大括号 `{ "jsonrpc": "2.0", ... }。
如果你在函数里随手写了一句 print("正在查询数据..."),Python 默认就会把这串中文直接塞进 stdout` 管道发给客戶端!
客戶端的 JSON 解析器收到非 JSON 字符,当场报出 Unexpected token / Parse error (-32700) 并强制断开连接!
铁律:在 stdio 模式的 MCP Server 中,任何调试日志必须写往旁边的标准错误流 sys.stderr(即 print(..., file=sys.stderr))!
二、核心操作深讲:零代码挂载现成插件与 30 行手写自定义 FastMCP Server
1. 零代码即插即用:在 Claude / Cursor / Codex 中挂载官方 MCP 插件
只要你的电脑安装了 Node.js(提供 npx)或 Python uv(提供 uvx),无需手动下载源码,直接在客戶端配置文件 ( 如 claude_desktop_config.json 或 Cursor MCP 设置 ) 中声明即可一键拉起官方插件 ( 源自 modelcontextprotocol/servers): { "mcpServers": { "filesystem-local": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/yourname/Desktop/ai_study"] }, "git-inspector": { "command": "uvx", "args": ["mcp-server-git", "--repository", "/Users/yourname/Desktop/ai_study"] } } }
【跨环境报错防坑提示】:如果在终端里敲 npx 或 uvx 正常,但图形界面客戶端启动时弹窗报 spawn uvx ENOENT,
是因为 macOS/Windows 图形应用默认不加载终端 ~/.zshrc 的环境变量路径。只需在终端运行 which uvx 查出绝对路径(如 /Users/yourname/.local/bin/uvx)填入 `"command"` 字段即可根治!
2. 使用官方 Python SDK(FastMCP)手写你的第一个自定义插件
通过官方 mcp Python SDK,大模型到底是怎么知道你的函数需要什么参数的?全靠自动解析你的 Python 类型注解(Type Hints)与文档字符串(Docstring)!
import sys from pathlib import Path from mcp.server.fastmcp import FastMCP # 初始化 MCP 服务实例 mcp = FastMCP("StudyNotesServer") @mcp.tool() def search_local_notes(keyword: str, max_results: int = 5) -> str: """在本地学习笔记目录(/tmp/study_notes)中搜索包含指定关键词(keyword)的Markdown段落。
""" # 调试日志必须输出到 sys.stderr,严禁使用普通 print() 污染 stdout!
print(f"[Debug] 正在搜索关键词: {keyword}", file=sys.stderr) base_dir = Path("/tmp/study_notes").resolve() base_dir.mkdir(parents=True, exist_ok=True) matches = [] for md_file in base_dir.glob("*.md"): content = md_file.read_text(encoding="utf-8") if keyword.lower() in content.lower(): matches.append(f"【{md_file.name}】: {content[:150]}...") return "\n".join(matches[:max_results]) if matches else "未找到包含该关键词的笔记。
" if __name__ == "__main__": mcp.run(transport="stdio") # 本地挂载使用 stdio;远程云服务可切换为 streamable-http
三、动手实验(Hands-on Lab):使用 MCP Inspector 可视化调试插件
实验 1:不用启动大模型客戶端,直接用网页调试台验证你的 MCP Server 很多初学者写完上面的 server.py 直接往客戶端里挂,一旦写错很难看清报错。
官方提供了一个极其好用的本地网页调试器 MCP Inspector: 在终端运行:npx @modelcontextprotocol/inspector python3 server.py,然后在浏览器打开提示的本地端口, 你就能在网页上直观看到你的函数被自动转换成了怎样的 JSON Schema,并能手动输入参数点击 Call Tool 测试返回值与 stderr 日志!
四、课后自测习题与详细解析(5 关 50 分 · 检验你的 MCP 协议内功)
【课后自测题(请先独立思考作答,再对照下方解析)】
1. 第 1 题(最新传输层规范演进 · 10 分):在 2025‒2026 年的 MCP 官方协议规范中,针对本地进程通信和
远程云端部署分别推荐使用哪两种标准传输机制(Transports)?为什么新版规范用 Streamable HTTP 取代了早期的 HTTP+SSE 双端点方案?
2. 第 2 题(JSON-RPC 管道污染排障 · 10 分):你在基于 stdio 的 FastMCP 工具函数里调用了一个第三方数
据处理函数,该函数内部包含一句 `print("Processing Done!"),导致挂载到 Claude 后一调用该工具就报错 MCP error -32700: Parse error。
请解释报错根因,并写出利用 Python 标准库 contextlib` 在不修改第三方函数源码的前提下拦截重定向输出的代码。
3. 第 3 题(三大核心原语区分 · 10 分):MCP 包含 Resources、Tools、Prompts 三大原语。如果你要暴露以下
两项能力:1 一份只读的《实验室仪器参数对照表.json》供客戶端作为背景资料读取;2 一个能够向数据库插入实验记录并触发计算的 record_experiment() 函数。它们分别属于哪种原语?由谁决定何时调用?
4. 第 4 题(Schema 自动生成机制 · 10 分):为什么在编写 @mcp.tool() 函数时,如果把函数签名写成 def
run(x, y): 且不写注释,大模型在调用时极易传错参数类型或乱填参数?FastMCP 是靠提取 Python 函数的哪三项代码要素来生成 JSON Schema 说明书的?
5. 第 5 题(文件操作路径穿越护栏 · 10 分):当你编写一个允许大模型根据传入的 filename 参数读取
/Users/me/notes/ 目录下文件的 MCP 工具时,如果模型被恶意网页诱导传入了 `filename="../../.ssh/id_rsa",就会发生越权泄密。请在 Python 中写出两行使用 pathlib.Path` 防御路径穿越攻击的核心校验代码。
PRACTICE / 本关练习 · 本地规则 + 覆盖检查
本册课后自测与实验
本地检查在你的浏览器里完成,不上传。覆盖检查需要先登录(免费注册),并把这段答案发送到服务器计算一次,算完即弃、不存档,需你点同意;只核对本关评分项覆盖的方向,不在评分项里的题目不会被检查。
评分项
结构分 — / 50 分
查看参考答案与得分点 先自己写,再打开+
参考答案与解析
1. 第 1 题解析:本地进程通信使用 stdio(标准输入输出),远程云端服务使用 Streamable HTTP(单端点流式
HTTP)。早期 HTTP+SSE 必须维护一条长连接通道加一个独立 POST 端点,难以穿过企业网关、负载均衡器与无状态 Serverless 平台;而 Streamable HTTP 统一为单一 /mcp 端点,既支持普通无状态请求,又支持按需升级为流式推送,并通过标准请求头(如 Mcp-Method)大幅提升了网关兼容性。(答出两种传输方式得 5 分,解释单端点无状态与网关兼容优势得 5 分)
2. 第 2 题解析:根因是 stdio 模式将 sys.stdout 作为 JSON-RPC 2.0 报文传输线,第三方函数的 print() 将普通
字符串写进了 stdout,破坏了 JSON 格式。可使用 contextlib.redirect_stdout(sys.stderr) 将其输出临时重定向到安全的标准错误流: import sys, contextlib with contextlib.redirect_stdout(sys.stderr): third_party_func() (解释 stdout 管道污染根因得 4 分,写出 redirect_stdout(sys.stderr) 代码得 6 分)
3. 第 3 题解析:1 只读的《参数对照表.json》属于 Resources(资源,Application-controlled,由宿主应用或用
戶显式选择挂载,类似 HTTP GET 无副作用);2 执行写入与计算的 record_experiment() 属于 Tools(工具, Model-controlled,由大模型在推理过程中自主决定发起调用)。(准确区分两类原语及其控制权归属得 10 分)
4. 第 4 题解析:因为大模型看不到函数体内部的实现代码,它完全依赖 MCP Server 暴露的 JSON Schema 来
理解工具功能。FastMCP 依靠提取 Python 函数的三项要素自动编译 Schema:1 语义化的函数名与参数名;2 Type Hints(类型注解,如 keyword: str, limit: int = 5);3 Docstring(函数文档字符串注释)。 (答出这三项核心要素得 10 分)
5. 第 5 题解析:使用 .resolve() 解析真实绝对路径并校验其前缀是否仍在沙盒目录内(或使用
Path(filename).name 剥离目录层级): base = Path("/Users/me/notes").resolve() target = (base / Path(filename).name).resolve() assert str(target).startswith(str(base)), "安全拦截:禁止访问沙盒外路径!" (写出 resolve() + 前缀校验或 .name 剥离得 10 分)
网页永久免费。完整 PDF 会按顺序发给留邮箱的读者,不转售、不群发广告。
留邮箱,获取完整 PDF ↗