2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

对 MCP 的批判性审视

作者:Raz

  • 2025-09-30
    北京
  • 本文字数:5110 字

    阅读完需:约 17 分钟

大小:2.55M时长:14:52
对 MCP 的批判性审视

MCP 是一个开放协议,它标准化了应用程序向 LLM 提供上下文的方式。可以把 MCP 想象成 AI 应用程序的 USB-C 端口。正如 USB-C 提供了一种将设备连接到各种外设和配件的标准化方式一样,MCP 也提供了一种将 AI 模型连接到不同数据源和工具的标准化方式。

 

—— Anthropic

概述

我希望这到头来会是我自己的技能问题,也希望我遗漏了一些东西。

 

在过去的一个月里,MCP(模型上下文协议)——它可以让 LLM 成为代理并与世界互动——真的火了起来。这个想法很简单:让我们为 LLM/代理标准化一个 API,让它们与世界互动,并定下将这些信息告知 LLM/代理的方式。

 

事情发展得非常快,IBM 最近发布了他们自己的 MCP“正交标准”,称为代理通信协议 (ACP),紧随其后,谷歌发布了 Agent2Agent (A2A)。

 

MCP 服务器和客户端每天都有新的构建和发布,可以在 mcp.so 和 pulsemcp.com 等网站上找到。

 

然而,让我惊讶的是成熟工程实践实在太少了。所有主要参与者都花费了数十亿美元来训练和微调他们的模型,但据我所知,他们最后却让实习生编写文档,提供的 SDK 质量低劣,而且几乎没有提供任何实现指导。

 

这种趋势似乎在 MCP 中延续了下来,导致了一些非常奇怪的设计决策、糟糕的文档,以及更糟糕的实际协议规范。

 

我的结论是,提案的整个 HTTP 传输设置(SSE+HTTP 和 Streamable HTTP)都应该被抛弃,取而代之的是模仿 stdio 的 Websockets。

背景

大约三周前,我决定投身 MCP 的潮流尝试一下,看看它在我们自己的环境中如何应用。我非常希望在使用抽象之前先了解底层工作原理。现在我们有了一个可以在不同传输协议上运行的新协议——真是令人兴奋!

 

Anthropic 是 MCP 标准化工作的幕后推手,而之所以 Anthropic 首席执行官认定大多数代码将在一年左右的时间内转由 LLM 编写,MCP 似乎就是主要原因之一。对编程工具的重视似乎是其标准化工作的指导原则,其核心在于使用体验。

协议

简而言之,它是一个 JSON-RPC 协议,带有预定义的方法/端点,旨在与 LLM 结合使用。这并非本文的重点,但该协议本身确实存在一些需要批评的地方。

传输

与 2005 年之后的许多应用程序号称是“本地优先”(很讽刺)一样,MCP 似乎也是如此。查看传输协议,你就能了解它们源自何方——大概他们的目的是构建在笔记本电脑上编程的 LLM 工具。他们可能正在研究本地 IDE(或者更现实地说,Cursor 或 Windsurf),以及如何让 LLM 与本地文件系统、数据库、编辑器、语言服务器等进行交互。

 

这里主要有两种(或三种)传输协议:

 

  1. stdio

  2. “得通过 HTTP 传输,Web 似乎是我们应该支持的东西。”

Stdio

使用 stdio 本质上意味着启动一个本地 MCP 服务器,连接从服务器到客户端的 stdout 和 stdin 管道,并开始发送 JSON 并使用 stderr 记录日志。这在某种程度上打破了使用这些流进行双向通信的 Unix/Linux 管道范式。当需要双向通信时,我们通常会使用 socket、Unix socket,甚至是网络 socket。

 

不过,socket 有简单易懂,在所有操作系统中开箱即用,不需要额外处理等优势。所以即使有人提出批评,我也理解。

HTTP+SSE / Steamable HTTP

HTTP 传输则是另一回事。同样的一个错误有两个版本:HTTP+SSE(服务器发送事件)传输,它正在被“Steamable HTTP”(一个杜撰的术语)取代,后者将 REST 语义与 SSE 结合使用。但这又带来了许多额外的困惑和极端情况。

 

总结下来就是:“由于我们喜欢用 SSE 进行 LLM 流式传输,所以我们不使用 WebSocket。相反,我们实际上是在 SSE 之上实现 WebSocket,并将其称为‘Steamable HTTP’,让人们认为这是一种被接受/已知的处理方式。”

 

他们在这个 PR:modelcontextprotocol/pull/206 中讨论了 WebSockets 的问题(以及 Steamable HTTP 的原因),并提出了一些非常奇怪的扭曲和不切实际的论点来反对使用 WebSockets。该帖子中至少还有一个人似乎同意我的观点:modelcontextprotocol/pull/206#issuecomment-2766559523。

陷入疯狂

我打算用 Golang 实现一个 MCP 服务器。目前没有官方的 Go SDK,而且我想了解这个协议。结果证明,这是个会影响心理健康的错误……

警告信号……

我查看了 https://modelcontextprotocol.io,发现其文档写得很糟糕(所有 LLM 供应商似乎都在内部竞争,争相编写令人困惑的文档)。该规范掩盖或忽略了协议的一些重要方面,并且没有提供任何对话流程的示例。事实上,整个网站似乎都不是用来阅读标准规范的;相反,它引导你去学习如何实现他们的 SDK 的教程。

 

所有示例服务器都是用 Python 或 JavaScript 实现的,目的是让你下载并使用 stdio 在本地运行它们。如果你想在别人的电脑上运行程序,Python 和 JavaScript 可能是最糟糕的语言选择之一。作者似乎意识到了这一点,因为所有示例都以 Docker 容器的形式提供。

说实话……你上次运行 pip install 而没有陷入依赖地狱是什么时候?

我是不是太自命不凡/武断了,认为人工智能领域的从业者只懂 Python,而且“嗯,它在我的电脑上能用就行”这种做法仍被认为是可接受的?对于任何尝试过运行 Hugging Face 某一功能的用户来说,这一点都应该是显而易见的。

 

如果你想在本地运行 MCP,难道你不想选择 Rust、Go 这样的可移植语言,或者像 Java 或 C# 这样基于虚拟机的语言吗?

问题

当我开始实现该协议时,我立刻就觉得必须对其进行逆向工程。文档中缺少 SSE 部分的重要内容,而且似乎还没有人实现“Steamable HTTP”;甚至连他们自己的工具,例如 npx @modelcontextprotocol/inspector@latest,都没有。(公平地说,这可能是我自己搞出来的技术问题,可能是拉错了版本,因为几周后我再次检查时它已经可用了。你也可以在 inspect.mcp.garden 上找到版本,这可能更方便。)

 

一旦你掌握了架构,很快就会意识到实现 MCP 服务器或客户端可能是一项繁重的工作。问题在于 SSE/Streamable HTTP 实现试图像 socket 一样工作,模拟标准输入输出 (stdio),但实际上并非如此,它们会试图同时在任何地方执行所有操作。

HTTP+SSE 模式

modelcontextprotocol.io/specification/2024-11-05/basic/transports

 

HTTP+SSE 模式下,为了实现全双工,客户端会建立一个 SSE 会话,例如通过 GET /sse 来读取。第一次读取会提供一个可以提交写入操作的 URL。然后,客户端会继续使用指定的端点进行写入操作,例如发送 POST /a-endpoint?session-id=1234 的请求。服务器会返回 202 Accepted 状态码,且不包含任何正文,此时应该从 /sse 上预先存在的打开的 SSE 连接读取该请求的响应。

“Streamable HTTP” 模式

modelcontextprotocol.io/specification/2025-03-26/basic/transports

 

“Streamable HTTP”模式下,他们意识到无需在第一个请求中提供新的端点,而是可以使用 HTTP 标头作为会话 ID,并使用 REST 语义作为端点。例如,GET 或 POST /mcp 可以打开一个 SSE 会话并返回 mcp-session-id=1234 的 HTTP 标头。要发送数据,客户端会向 POST /mcp 发出请求,并添加 mcp-session-id=1234 的 HTTP 标头。响应可能:

 

  • 打开一个新的 SSE 流并发布回复

  • 返回 200 状态码,并在正文中包含回复

  • 返回 202 状态码,表示回复将被写入任意一个现有的 SSE 流

 

要结束会话,客户端可以发送或不发送带有 mcp-session-id=1234 标头的 DELETE /mcp 消息。服务器必须维护状态,除非客户端正常结束会话,否则无法明确知道客户端何时放弃了会话。

SSE 模式会有什么影响?

这是一个问题百出的设计,我都不知道该从何说起。

 

虽然 SSE 模式的一些关键特性尚未编写文档,但只要对其进行逆向工程,就会发现它相当简单。但这仍然会给服务器实现带来巨大且不必要的负担,服务器实现需要在调用之间“join”连接。实际操作几乎都会迫使你使用消息队列来回复任何请求。例如,以任何冗余方式运行服务器都意味着 SSE 流可能从一个服务器发送到客户端,而请求却被发送到完全不同的服务器。

“Steamable HTTP”会有什么影响?

Steamable HTTP 方法将其提升到了另一个层次,带来了一系列安全问题和令人困惑的控制流。 Streamable HTTP 虽然保留了 SSE 模式的所有缺陷,但它似乎更像是 SSE 模式的复杂扩展集。

 

就实现而言,我只是略知皮毛,但根据我对文档的理解……

 

可以通过 3 种方式创建一个新会话

 

  • 一个空的 GET 请求

  • 一个空的 POST 请求

  • 一个包含 RPC 调用的 POST 请求

 

一个 SSE 可以通过 4 种不同方式打开

 

  • 一个用于初始化的 GET 请求

  • 一个用于加入先前会话的 GET 请求

  • 一个用于初始化会话的 POST 请求

  • 一个包含请求并使用 SSE 响应的 POST 请求

 

一个请求可以通过 3 种不同方式响应

 

  • 一个作为对包含 RPC 调用的 POST 请求的 HTTP 响应

  • 一个作为对 POST RPC 调用的响应而打开的 SSE 中的事件

  • 一个作为之前打开的任何 SSE 的事件

总体影响

由于它有多种方式来发起会话、打开 SSE 连接和响应请求,因此带来了显著的复杂性。这种复杂性有几个普遍的影响:

 

  • 复杂性提升:执行同一件事(会话创建、SSE 开启、响应传递)的多种方式增加了开发人员的认知负担。代码的理解、调试和维护变得更加困难。

  • 不一致的可能性:由于实现同一结果的方式多种多样,不同服务器和客户端之间实现不一致的风险更高。这可能导致互操作性问题和意外行为。客户端和服务器只会实现它们认为必要的部分。

  • 可扩展性问题:虽然 Streamable HTTP 旨在提高效率,但从另一方面来说,其复杂性将带来需要克服的可扩展性瓶颈。服务器可能难以管理大量机器上的各种连接状态和响应机制。

安全隐患

Streamable HTTP 的“灵活性”带来了一些安全隐患,以下仅列举其中几项:

 

  • 状态管理漏洞:跨不同连接类型(HTTP 和 SSE)管理会话状态非常复杂。这可能导致会话劫持、重放攻击或 DoS 攻击等漏洞,因为服务器会创建需要管理并保存的状态,直到会话恢复。

  • 扩大攻击面:会话创建和 SSE 连接的多个入口点扩大了攻击面。每个入口点都代表着一个攻击者可能利用的潜在漏洞。

  • 困惑和混淆:发起会话和传递响应的多种方式可用于混淆恶意活动。

授权

最新版本的协议包含一些关于如何进行授权的非常主观的要求。

 

modelcontextprotocol.io/specification/2025-03-26/basic/authorization

使用基于 HTTP 的传输方式的实现应该符合此规范。

使用 STDIO 传输的实现不应遵循此规范,而应从环境中获取凭据。

我理解的意思是,对于 stdio,随便你。对于 HTTP,你最好还是去实现 OAuth2 吧。如果我使用 HTTP 作为传输方式,为什么还需要实现 OAuth2,而 stdio 用 API 密钥就够了?

应该怎样改进

我不知道,只是有点难过……目前业界似乎无计可施——“现在还凑合,但以后处理起来会很困难。”

 

JSON RPC 协议只有一个,而 Stdio 显然是首选的传输协议。那么我们应该尽量让 HTTP 传输方式接近 Stdio,只有在真的非常需要的情况下才引入变化。

 

  • 在 Stdio 中我们有环境变量;在 HTTP 中我们有 HTTP 标头。

  • 在 Stdio 中我们有类似 socket 的行为,包含输入和输出流;在 HTTP 中我们有 WebSocket。

 

就是这样。我们应该能够在 WebSocket 上完成与在 Stdio 上相同的操作。WebSocket 是通过 HTTP 进行传输的理想选择。我们可以省去会话中复杂的跨服务器状态管理。我们可以消除大量的极端情况,等等。

 

当然,有些事情,比如授权,在某些情况下可能会更复杂一些(而在某些情况下则更容易);有些防火墙可能会阻止 WebSocket;小型会话可能会有额外的开销;恢复中断的会话可能会更困难。但正如人们所说:

客户端和服务器可以根据其特定需求实现额外的自定义传输机制。该协议与传输无关,可以在任何支持双向消息交换的通信通道上实现。

 

modelcontextprotocol.io/specification/2025-03-26/basic/transports#custom-transports

作为一个行业,我们应该针对最常见的用例进行优化,而不是只优化一些特殊情况。

附注:替代方案和补充

如上所述,似乎有更多协议正在涌现。MCP 实际上是“向 LLM(可以创建代理)公开 API 的协议”。IBM 和谷歌的较新协议(ACP 和 A2A)实际上是“向 LLM(可以创建代理的代理)公开代理的协议”。

 

纵观 A2A 规范,似乎对它们的需求非常有限。尽管它们声称是正交的,但 A2A 中的大多数功能都可以使用 MCP 原样或通过少量添加来实现。

 

归根结底,它们就是两个完整的协议,它们也可以作为 MCP 服务器中的工具。甚至 IBM 似乎也承认他们的协议并非真正必要:

“代理可以被视为 MCP 资源,并进一步作为 MCP 工具调用。这种 ACP 代理的视角允许 MCP 客户端发现并运行 ACP 代理……”

 

—— IBM / agentcommunicationprotocol.dev/ecosystem/mcp-adapter

我一开始的感觉是,ACP 协议更像是 IBM 推广其“代理构建工具”BeeAI 的一种尝试。

 

这两个 A** 协议都提供了一个合理的传输层和一种发现代理的方法。



原文链接:

https://raz.sh/blog/2025-05-02_a_critical_look_at_mcp

2025-09-30 16:0012206

评论

发布
暂无评论

OpsPilot 动态知识图谱上线:让企业知识具备“理解力”与“关联力”

嘉为蓝鲸

智能运维 #WeOps OpsPilot

企业IM:BeeWorks私有化即时通讯助力高效协作

BeeWorks

即时通讯 IM 私有化部署

京东零售重磅开源 | OxyGent:像搭乐高一样组装AI团队,实现群体智能

京东零售技术

传奇IP续作:融合创新技术 数字娱乐产业迎来新发展机遇

江湖老铁

嘉为蓝鲸CTeam敏捷协同平台:一站式实现Jira迁移与研发管理升级

嘉为蓝鲸

DevOps 智能运维 敏捷协同平台

CMeas效能洞察平台:10分钟,从数据到研发度量报表

嘉为蓝鲸

DevOps 智能运维 效能洞察

Voice AI Agent 知识库:打造你自己的语音智能体!

声网

哈尔滨三级等保建设:从规划到落地的关键步骤

等保测评

免费不限量,通义灵码已经全面支持 Qwen3-coder 模型,“效果很惊艳”

阿里云云效

再添荣誉!嘉为蓝鲸斩获可信云技术典型实践大奖,彰显智能运维实力

嘉为蓝鲸

AIOPS 智能运维 cmp 可信云大会

嘉为蓝鲸 WeOps+Microsoft Teams:提升跨国运维信息传递精准度

嘉为蓝鲸

智能运维 #WeOps 一体化运维

提示注入2.0:混合AI威胁下的新型网络安全挑战

qife122

网络安全 提示注入

「宇树科技」启动IPO,29家产业链公司齐飞!

机器人头条

特斯拉 人形机器人 具身智能 宇树科技 智元机器人

直播精彩回顾 | 拆解金融行业“隐形风险”,可观测性守护核心业务生命线

博睿数据

开源 Qwen3-Coder 是顶级 AI 阳谋,阿里的野心藏不住了

程序员晚枫

开源 大模型

如何通过自动化工具发现10+SQL注入和30+XSS漏洞

qife122

网络安全 自动化工具

BEVDet 算法详细解读-全网最全攻略

十三Tech

Mac mini玩游戏怎么样?怎么提高Mac mini玩游戏的流畅度?

阿拉灯神丁

CrossOver Mac下载 如何在Mac上运行win游戏 苹果电脑必备软件 Mac游戏推荐 虚拟机安装

倒计时2天!合合信息WAIC黑科技剧透来袭!

合合技术团队

人工智能 算法 #大数据

哈尔滨二级等保测评:关注重点与实施要点

等保测评

微服务的10大问题

不在线第一只蜗牛

JavaScript 微服务

C#解析JSON数据全攻略

量贩潮汐·WholesaleTide

C# json

内网IM:BeeWorks私有化部署的安全通讯解决方案

BeeWorks

即时通讯 IM 私有化部署

让复杂 AI 应用构建就像搭积木:Spring AI Alibaba Graph 使用指南与源码解读

阿里巴巴云原生

阿里云 微服务 云原生 Spring AI Alibaba

KWDB多副本集群保姆级部署

KaiwuDB

Seed 端到端同声传译大模型:3s 延迟,实时声音复刻;昆仑万维 Mureka TTS 更新,支持音色设计丨日报

声网

CrossOver玩《幻兽帕鲁》进不去游戏、黑屏怎么办?

阿拉灯神丁

游戏卡顿 CrossOver Mac下载 如何在Mac上运行win游戏 幻兽帕鲁 雷神加速器

免费不限量,通义灵码已经全面支持 Qwen3-coder 模型,“效果很惊艳”

阿里巴巴云原生

通义灵码

硬核来袭!「AI 进化论:智算时代 OS 的破局之路」首期直播上线

OpenAnolis小助手

centos AI 操作系统 龙蜥社区 智算时代

Bonree ONE 发布直通车 | Bonree ONE多地多中心版本首发!全行业部署与应用深度解析

博睿数据

利用CSRF暴力破解用户ID实现批量删除用户攻击

qife122

CSRF WEB安全

对 MCP 的批判性审视_AI&大模型_InfoQ精选文章