8.5 内存传输与传输安全 本节摘要:第 8 章收尾节,讲两种特殊场景——内存传输(测试与嵌入用)与传输安全(公网部署的安全底线)。内存传输是 的底层机制,用直接分发代替读写流,跳过 JSON-RPC 序列化,极快零配置,是开发期验证的首选。传输安全则解决一个公网部署必须面对的威胁——DNS 重绑定攻击(DNS Rebinding),SDK 默认用防护机制只允许 localhost 连接,要公网暴露必须正确配置。读完本节,你掌握测试传输与公网安全两件事。 一、内存传输:测试与嵌入 内存传输是第 1.3 节 的底层机制。
本节摘要:第 8 章收尾节,讲两种特殊场景——内存传输(测试与嵌入用)与传输安全(公网部署的安全底线)。内存传输是
Client(mcp)的底层机制,用直接分发代替读写流,跳过 JSON-RPC 序列化,极快零配置,是开发期验证的首选。传输安全则解决一个公网部署必须面对的威胁——DNS 重绑定攻击(DNS Rebinding),SDK 默认用防护机制只允许 localhost 连接,要公网暴露必须正确配置。读完本节,你掌握测试传输与公网安全两件事。
内存传输是第 1.3 节 Client(mcp) 的底层机制。当客户端拿到一个服务端对象(而非 URL 或传输)时,它用内存传输连接——直接函数调用,无 JSON-RPC 序列化:
普通传输(stdio/HTTP): 客户端 ──序列化 JSON-RPC──► 服务端 客户端 ◄──反序列化────────── 服务端 内存传输: 客户端 ──直接函数调用──► 服务端 客户端 ◄──直接返回──────── 服务端 (无序列化、无帧)
内存传输用一种叫直接分发(Direct Dispatcher) 的机制——客户端的「发」函数直接调用服务端的「收」函数,中间没有序列化、没有 JSON-RPC 帧、没有网络。
内存传输的主要价值是测试与嵌入:
| 价值 | 说明 |
|---|---|
| 测试极速 | 无序列化开销,毫秒级,适合写大量测试 |
| 零配置 | 不用起子进程、不开端口,直接 Client(mcp) |
| 进程内嵌入 | 把 MCP 服务端嵌入应用,客户端直连 |
| 确定性 | 无网络,不受网络抖动影响 |
# 测试场景(第 1.3 节的骨架) async with Client(mcp) as client: result = await client.call_tool("add", {"a": 1, "b": 2}) assert result.structured_content["result"] == 3
这就是全书所有示例的测试基础——内存连接让验证服务端行为极快、极简单。
内存传输不适合生产,因为它有几个固有局限:
| 局限 | 说明 |
|---|---|
| 必须同进程 | 客户端与服务端在同一 Python 进程 |
| 不跨机器 | 不能远程访问 |
| 无并发隔离 | 共享进程资源,无进程/网络隔离 |
| 非生产 | 设计目标就是测试/嵌入,不是生产 |
⚠️ 注意:内存传输只用于测试与进程内嵌入,不能用于生产。生产环境客户端与服务端通常分属不同进程(甚至不同机器),那时必须用 stdio 或流式 HTTP。但你的服务端业务代码不变——这是传输解耦的体现。
讲完内存传输,转向传输安全。当流式 HTTP 服务端暴露到网络,一个必须面对的威胁是 DNS 重绑定(DNS Rebinding)攻击:
DNS 重绑定攻击(概念): 1. 攻击者控制一个域名,如 evil.com 2. 让受害者浏览器访问 evil.com 3. evil.com 的 DNS 第一次解析到攻击者服务器(正常页面) 4. DNS 第二次解析到 127.0.0.1(受害者本地!) 5. 浏览器的脚本 now 可访问受害者本地的服务(绕过同源策略)
这种攻击让恶意网页能访问受害者本地的服务(如你的 MCP 服务端)。如果你本地跑的 MCP 服务端没防护,恶意网页可能通过浏览器调用你的工具——读文件、执行操作。
SDK 用传输安全(transport_security)机制防护 DNS 重绑定——默认只允许 localhost 连接:
默认行为: 服务端监听 localhost 只接受来自 localhost 的连接 → 外部网络(含恶意网页)连不上 要公网暴露: 必须显式配置允许的主机(allowed hosts) → 明确放开,知道自己暴露了
这个默认是「安全优先」——宁可本地能用、公网连不上,也不要默认暴露。开发者要公网暴露时,必须显式配置,这一步强制你意识到「我在公开服务」。
如果你的 MCP 服务端要公网访问,必须正确配置传输安全:
mcp.run( "streamable-http", host="0.0.0.0", # 监听所有网卡 port=8000, transport_security={ "allowed_hosts": ["mcp.example.com"], # 允许的主机名 # 其他安全配置 } )
配置时的要点:
| 要点 | 说明 |
|---|---|
| allowed_hosts 要精确 | 只列你实际使用的主机名,别用通配符 |
| 配合认证 | 公网暴露必须加认证(第 11 章 OAuth) |
| HTTPS | 生产用 HTTPS,传输安全 + TLS 双保险 |
| 反代场景 | 如果在 nginx 后面,配置要考虑反代的 Host 头 |
⚠️ 注意:别为了「能连上」就关闭传输安全或用通配符 allowed_hosts。这等于把你的 MCP 服务端无保护暴露到公网——任何人都能调用你的工具。公网暴露的正确做法是:精确的 allowed_hosts + OAuth 认证 + HTTPS,三者缺一不可。
最后用一张表对比三种传输的安全特性,帮你选型:
| 传输 | 默认安全 | 暴露范围 | 需要认证吗 |
|---|---|---|---|
| stdio | 高(本地子进程) | 仅本机宿主 | 通常不需要(宿主可信) |
| 流式 HTTP | 中(默认 localhost) | 配置后可公网 | 公网必须(第 11 章) |
| 内存 | 高(同进程) | 仅本进程 | 不需要(无网络) |
stdio 与内存因「不暴露到网络」,天然安全;流式 HTTP 一旦暴露到网络,就必须配传输安全 + 认证。
第 8 章结束。你已经掌握 MCP 的全部传输机制:抽象、stdio、流式 HTTP、SSE、内存、安全。第 9 章转向客户端主线——Client 如何连上这些传输。