MCP 2025-06-18 规范更新:安全、结构化输出和信息获取
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
模型上下文协议(MCP)过去因其安全漏洞而饱受诟病。Anthropic 最近发布了新的规范更新(MCP v2025-06-18),我一直在审阅它,尤其关注其安全性。以下是您应该了解的重要变更。
太长不看
以下是 MCP 规范 v2025-06-18 版本新增内容的简要概述:
1) MCP 服务器被归类为 OAuth 2.0 资源服务器。
2) 客户端在请求令牌时必须包含一个resource参数(RFC 8707),这将每个访问令牌明确绑定到特定的 MCP 服务器。
3) 现在支持结构化 JSON 工具输出(structuredContent)。
4) 服务器现在可以在会话期间通过发送 elicitation/create带有消息和 JSON 模式的请求来请求用户输入。
5) 添加了“安全注意事项”,以防止令牌被盗、PKCE、重定向 URI、代理混淆等问题。
6) 新增的安全最佳实践页面针对令牌传递、混淆的代理、会话劫持、代理滥用等威胁,提供了具体的应对措施。
7) 所有 HTTP 请求都必须包含该MCP-Protocol-Version标头。如果缺少该标头且无法推断版本,服务器应默认使用2025-03-26旧版本以确保向后兼容性。
8) 新resource_link类型允许工具指向 URI 而不是内联所有内容。客户端可以根据需要订阅或获取此 URI。
9) 移除了对 JSON-RPC 批处理的支持(重大变更)。
什么是MCP?我为什么要关注它?
MCP(模型上下文协议)是 Anthropic 公司为规范应用程序如何向生命周期模型 (LLM) 提供上下文和工具而推出的一项尝试。您可以将其理解为人工智能模型的 HTTP 协议——一种用于人工智能模型“接入”数据源和工具的标准化协议。
MCP 无需编写自定义集成(GitHub、Slack、数据库、文件系统),即可让主机动态发现可用工具tools/list,调用这些工具tools/call并获取结构化结果。这类似于函数调用 API,但可跨平台和服务运行。
MCP 的核心是客户端-服务器架构,其中主机应用程序可以连接到多个服务器。以下是其核心组件:
-
MCP hosts- 像 Claude Desktop、Cursor、Windsurf 或 AI 工具这样的应用程序想要通过 MCP 访问数据。 -
MCP Clients- 与 MCP 服务器保持 1:1 连接的协议客户端,充当通信桥梁。 -
MCP Servers- 轻量级程序,每个程序都通过标准化的模型上下文协议公开特定的功能(如读取文件、查询数据库等)。 -
Local Data Sources- 您计算机上的文件、数据库和服务,MCP 服务器可以安全地访问这些文件、数据库和服务。例如,浏览器自动化 MCP 服务器需要访问您的浏览器才能正常工作。 -
Remote Services- MCP 服务器可以连接的外部 API 和基于云的系统。
之前的规范相当简略(使用基于标准输入输出或 HTTP 的 JSON-RPC)。身份验证没有明确定义,因此许多实现干脆跳过了身份验证。
随着 MCP 的普及,团队正在努力解决这些差距,因为生态系统还处于早期阶段,可以做出有意义的改变。
确实存在一些尚未解决的核心安全漏洞(工具描述注入、供应链风险),但您可以遵循一些可能有所帮助的实用缓解策略。
OAuth 2.0 资源服务器分类
MCP 服务器(用于保护您的数据或服务的系统)现在已被正式归类为 OAuth 2.0 资源服务器。从概念上讲,这并非新概念,因为许多开发人员早已将 MCP 服务器视为受保护的资源,但规范现在通过明确的 OAuth 2.0 分类将其正式化。
现在每个 MCP 服务器都必须使用受保护的资源元数据 ( RFC9728 )指示其授权服务器的位置。
通过将授权端点 URL 嵌入到 MCP 服务器的元数据中,消除了歧义,并将令牌请求安全地定向到预期的颁发者。
阅读更多关于授权服务器位置的信息。令牌绑定将在下一节中详细解释。
资源指示器(RFC 8707)用于防止令牌滥用
客户端在请求令牌(RFC 8707 中的参数)和进行授权时,必须包含资源指示符resource。这会将每个访问令牌显式绑定到特定的 MCP 服务器。
授权服务器随后可以颁发仅对特定服务器有效的、范围严格的令牌,从而防止恶意行为者将令牌重定向到未经授权的端点。
将令牌绑定到单个资源可以防止“令牌误兑换”攻击,在这种攻击中,为一个资源颁发的令牌可能会被重放攻击不同的服务器。
例如,我们考虑一个简单的场景,客户端请求一个专门用于访问analyticsMCP 服务器的令牌。
由于resource包含了该参数,授权服务器将颁发一个与受众绑定的令牌https://mcp.example.com/analytics。
即使它们是同一 MCP 部署的一部分,该令牌也不能用于访问任何其他端点或服务器,例如https://mcp.example.com/payments或。https://mcp.example.com/notifications
POST /oauth/token
{
"grant_type": "client_credentials",
"client_id": "analytics-client",
"client_secret": "...",
"resource": "https://mcp.example.com/analytics"
}
更新的安全文档
规范现在包含了更明确的“安全注意事项”。
1)资源指标与受众绑定
resource代币现在使用指示器绑定到特定的 MCP 服务器。- 服务器必须
validate the audience先验证每个令牌才能接受它。
2)防止代币盗窃
- 客户端和服务器必须安全地存储令牌(无日志、缓存泄漏……)。
- 授权服务器应颁发有效期较短的令牌,以降低令牌泄露的风险。
- 对于公共客户端,刷新令牌必须轮换(根据 OAuth 2.1 规范)。
3)通信安全
- 所有身份验证端点都必须通过 HTTPS 提供服务。
- 重定向 URI 必须是
localhost(用于开发)或安全https://URL。 - 符合 OAuth 2.1 标准,可实现端到端安全传输。
4)授权码保护 (PKCE)
攻击者如果获取了授权响应中包含的授权码,就可以尝试将该授权码兑换成访问令牌或以其他方式利用它。为了缓解这种情况:
- PKCE 对所有客户都是强制性的,以防止拦截或注射。
- 这样就创建了一个秘密的验证者-挑战者对,因此只有原始客户端才能用授权码交换令牌。
5)开放重定向
攻击者可能会精心构造恶意重定向 URI,将用户引导至钓鱼网站。
- 客户端必须预先向认证服务器注册确切的重定向 URI。
- 服务器必须严格验证传入的重定向 URI,以避免网络钓鱼。
state建议使用该参数以防止请求被篡改。
授权服务器只有在信任重定向 URI 的情况下才应自动重定向用户代理。如果 URI 不可信,授权服务器可以通知用户,并由用户自行做出正确的决定。
6)混乱的副预防
攻击者可以利用充当第三方 API 中介的 MCP 服务器,导致 confused deputy vulnerabilities.
- MCP代理服务器不应盲目地将令牌转发给上游API。
- 当作为 OAuth 客户端时,他们必须从上游获取单独的令牌。
- 对于动态注册的客户,客户必须获得用户的明确同意。
7)令牌受众验证
此漏洞有两个关键方面:受众验证失败和令牌传递。为防止这种情况发生:
- MCP 服务器必须使用受众声明来验证访问令牌是否属于它们。
- 必须拒绝为其他服务颁发的令牌。
- 明确禁止将令牌传递给下游 API。
新的安全最佳实践页面
他们新增了一个“安全最佳实践”页面。该页面汇总了针对 MCP 实施者的可操作建议(例如明确的同意流程、最小数据范围、人机交互提示等)。它概述了与 MCP 合作的开发人员和实施者的安全指南。以下是涵盖的所有内容:
-
包括混淆代理人、令牌传递和会话劫持等威胁,每种威胁都配有明确的应对措施。
-
描述了当静态客户端 ID 和同意 cookie 允许未经授权的令牌兑换时,代理的滥用情况。
-
详细说明了转发无效令牌的风险,并强制要求严格拒绝非专门为 MCP 服务器颁发的令牌。
-
还涵盖会话 ID 泄露场景,包括提示注入和冒充攻击。
根据官方文档,本节内容应与 MCP 授权规范和 OAuth 2.0 安全最佳实践一起阅读。
如果你读到这里,非常感谢你的阅读。我只是想和大家分享一下Forge,它是一款支持 Claude、GPT、O 系列、Grok、Deepseek、Gemini 等 300 多种编程模型的 AI 赋能型结对编程工具。你应该试试!
结构化工具输出
1)结构化输出与非结构化输出
现在,工具可以在一个新字段中返回结构化的 JSON 输出structuredContent。有了结构化的结果,客户端可以以编程方式解析响应(例如 JSON 对象)。此前,该content字段仅允许输入非结构化的纯文本。
例如,对于应用程序来说,这比解析纯字符串(例如“.”)更容易"22.5°C, partly cloudy, humidity 65%"。
"structuredContent": {
"temperature": 22.5,
"conditions": "Partly cloudy",
"humidity": 65
}
2)向后兼容性
为了确保老客户无需任何更改即可继续使用:
- 工具仍然应该包含一个人类可读的
text块,以非结构化的形式描述相同的输出。 - 这种双重输出策略使得结构化内容可以自主选择是否接收,而不会破坏现有的工作流程。
"content": [
{
"type": "text",
"text": "{\"temperature\": 22.5, \"conditions\": \"Partly cloudy\", \"humidity\": 65}"
}
]
3) 输出模式支持(可选)
工具可以选择性地定义一个outputSchemaJSON Schema,用于描述输出结构structuredContent。如果提供了输出 Schema:
- 服务器必须提供符合此模式的结构化结果。
- 客户应根据此模式验证结构化结果。
✅ 这样做的好处:
- 启用严格的模式验证
- 改进与类型化语言(例如 TypeScript、Go)的集成
- 使工具响应可预测且可自动记录
- 提升开发者体验 (DX)
示例工具及输出模式:
{
"name": "get_price",
"title": "Price Checker",
"description": "Get current price of a product",
"inputSchema": {
"type": "object",
"properties": {
"productId": { "type": "string" }
},
"required": ["productId"]
},
"outputSchema": {
"type": "object",
"properties": {
"price": { "type": "number" },
"currency": { "type": "string" }
},
"required": ["price", "currency"]
}
}
此工具的有效响应示例:
{
"jsonrpc": "2.0",
"id": 42,
"result": {
"content": [
{
"type": "text",
"text": "{\"price\": 199.99, \"currency\": \"USD\"}"
}
],
"structuredContent": {
"price": 199.99,
"currency": "USD"
}
}
}
支持信息获取(交互式用户输入)
此次更新新增了请求获取支持elicitation/create。服务器现在可以在会话期间通过发送包含消息和预期数据 JSON 模式的请求,向用户索取额外信息。
该协议本身并未规定任何特定的用户交互模型,服务器不得使用诱导手段来请求敏感信息。
支持信息获取的客户端必须 在初始化elicitation期间声明该 功能 。
{
"capabilities": {
"elicitation": {}
}
}
1)创建需求征询书
服务器可以发送elicitation/create包含以下内容的请求:
- 要显示的消息
- 描述预期用户输入的 JSON 模式
客户端显示提示并返回用户的响应(如果用户拒绝,则返回取消/拒绝操作)。
请求示例:
{
"method": "elicitation/create",
"params": {
"message": "Please enter your email",
"requestedSchema": {
"type": "object",
"properties": {
"email": { "type": "string", "format": "email" }
},
"required": ["email"]
}
}
}
回复示例:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"action": "accept",
"content": {
"email": "user@example.com"
}
}
}
2)基于模式的输入验证
- 输入遵循简单的 JSON Schema(字符串、数字、枚举、布尔值)。
- 不支持复杂的嵌套,模式有意设计得扁平化,以方便客户端实现。
- 这样一来,客户就可以自动生成输入表单,并在提交前验证回复。
3)响应类型
客户必须返回以下三个明确操作之一:
"accept"用户提交了有效数据(包含在内content)"reject"用户明确拒绝提供数据"cancel"用户未作回应便忽略了提示。
以下是消息流程。
如果您有兴趣了解更多关于响应操作、请求架构和更多安全注意事项的信息,请查看官方文档。
工具结果中的资源链接
现在,工具可以在结果中返回资源链接resource_link。资源链接包含一个 URI 以及指向其他上下文或数据的元数据(名称、描述、MIME 类型)。
例如:
{
"type": "resource_link",
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
客户端随后可以根据需要订阅或获取此 URI。就像一个工具告诉客户端:“这里有一个文件,您可能需要在需要时浏览、下载或打开它。”
资源链接允许服务器“指向”文件或资源,而不是直接内联它们。它们不一定会出现在请求结果中 resources/list ,更像是用于在提供链接时让客户端直接获取。
协议版本强制执行(HTTP)
MCP-Protocol-Version: <protocol-version>初始握手之后,所有向 MCP 服务器发出的 HTTP 请求都必须在后续所有请求的 HTTP 标头中包含约定的版本。
这告诉服务器客户端正在使用哪个版本的 MCP 规范。如果标头包含无效或不受支持的版本,服务器必须拒绝该请求并返回错误400 Bad Request。
为什么?
- 保持客户端和服务器在协议行为方面同步。
- 防止在支持多个协议版本时出现细微的错误或不匹配。
- 起到会话间版本锁定的作用。
请求示例:
GET /mcp-server/tools/list HTTP/1.1
Host: api.example.com
MCP-Protocol-Version: 2025-06-18
为了向后兼容,如果服务器没有收到MCP-Protocol-Version标头,并且无法通过任何其他方式(例如依赖初始化期间协商的协议版本)检测到版本,则应假定版本为2025-03-26。
已移除 JSON-RPC 批处理
该规范不再支持JSON-RPC 2.0 批处理。这意味着每个 JSON-RPC 调用都必须作为单独的消息发送(每个请求一个 JSON 对象),而不是以调用数组的形式发送。
如果您的 SDK 或应用程序在单个批处理请求(数组)中发送多个 JSON-RPC 调用,则从版本开始,它将无法正常工作,因为 MCP 服务器将拒绝它2025-06-18。
例如:
POST /mcp [{ "jsonrpc": "2.0", "method": "foo", "id": 1 }, { "jsonrpc": "2.0", "method": "bar", "id": 2 }]
更新客户端逻辑,使每次调用只发送一个请求。这可能需要禁用 JSON-RPC 库中的批处理功能或重构请求管道。
我查看了GitHub PR 讨论(#416),发现并没有“令人信服的用例”来真正将其移除。
官方的 JSON-RPC 文档明确指出,客户端“可以发送请求数组”,服务器“应该返回结果数组”。MCP 的新规则实际上禁止了这种做法。一些审阅者指出了这一与标准的冲突,但规范制定者选择明确地做出更改。
不支持批处理会偏离 JSON-RPC 的原则。任何底层使用 JSON-RPC 库的 SDK 在关闭批处理功能时都可能遇到问题。
我认为,当协议版本较低时,移除 JSON-RPC 批处理支持>= 2025-06-18会更有意义。
此更改也不向后兼容(会破坏旧客户端/服务器),因此任何支持 的 MCP 客户端 2025-03-26都可能无法与仅支持 的 MCP 服务器一起使用 2025-06-18。
其他显著变化
为了增加灵活性,新增了几个字段:
-
_meta已添加到各种接口对象中,用于实现元数据。 -
context添加了此功能,CompletionRequest允许将先前已解析的变量与完成请求一起发送。 -
title许多对象上都引入了字段,用于保存易于人类理解的显示名称(与机器无关name)。
他们还在生命周期操作 中 进行SHOULD 了 更改,规定双方必须遵守协商一致的协议版本。MUST
底线
这些更新是 MCP 生态系统向前迈出的一大步。它们直接影响着 MCP 集成的安全性、稳定性和向前兼容性。忽略这些更新可能会导致客户端与服务器交互中断、令牌滥用或请求被拒绝。
由于采用了 OAuth 2.0 约定和令牌绑定,MCP 集成变得更加安全,并且由于结构化数据和用户提示,功能也更加强大。
所有这些变更均已生效2025-06-18。任何不采用更新后做法的 MCP 服务器或客户端都可能面临不符合当前规范和未来兼容性问题的风险。
如果您有任何问题或反馈意见,请告诉我。
祝你今天过得愉快!下次再见 :)
| 您可以在anmolbaranwal.com 查看 我的作品。 感谢阅读!🥰 |
|---|





