最近MCP的风吹得很疯狂。有的人喜欢它,认为它象征着AI Agent光明的前景。有的人则觉得这也不是什么高深的东西,被一群人炒得像什么重大科学突破一样,有点招人烦了。当然,还有一些人在问:到底什么是MCP,这东西有什么用?
这篇文章将通过详细的描述,让一只猴子🐒进来都能完全理解MCP是什么、为何存在、有何作用。
1. Background
咱们先从闲聊几句开始。记得ChatGPT最初火起来的时候,大家在惊艳之余,还是迅速找到了种种生成式对话机器人所不擅长的场景,最后松一口气:果然还是人工智障。
最经典的例子是这个:9.11和9.8谁更大?
当时绝大多数人遇到的回答都是:9.11更大。
这在我们这些互联网从业者眼里很好理解。肯定是模型根据语料库的经验,把这两个数字当成了类似"版本号"之类的对比。
但广大用户不会这么想。他们觉得你这机器人聊起天来头头是道,好像什么都懂,原来这么基础的逻辑都判断不清楚啊!这不是一件小事。对于普通用户来说,这么基础的问题你都犯错,我怎么可能在那些更加高级的应用,比如AI医疗、智能驾驶等等上信任你,又怎么吃得下去科技公司画的大饼呢?
这暴露出了大语言模型的重大限制:它并不是真懂数学,更不懂逻辑。它只是一个根据前置token预测下一个token的机械式的模型而已。它的进化依赖语料库的积累,而现实世界变化更快,总不按套路出牌。换句话说,它"语文很好",但"数学很差"。
而巧妙的是,传统的计算机工具或软件,正是逻辑严密,"数学很好"的典型,它们功能可能没那么强大,但保证结果绝对准确!这时若能有一个专门用来比较数字大小的工具告诉大模型:再有这种类型的问题,直接找我,兄弟保证给你正确的答案。它们显然就能双剑合璧,解决问题!
2. Tool Use
在上述场景中,存在着4方实体,它们包括:用户,大模型(LLM),聊天软件(Client),以及工具。它们的工作流程大致是这样的:
[compare_numbers, ...] Note over User, Tool: User interaction User ->> Client: (Typing) Compare 9.11 with 9.8 Client ->> LLM: Compare 9.11 with 9.8 Note over LLM: (Thinking) Hmmm, there is a tool named
'compare_numbers' just suits the case! LLM -->> User: Can I use the tool 'compare_numbers'? User -->> LLM: 111 LLM ->> Client: tool_use: compare_numbers.
args: [9.11, 9.8] Client ->> Tool: compare_numbers(9.11, 9.8) Tool ->> Client: returns "9.8" Client ->> LLM: Tool returned "9.8" LLM -->> User: 9.8 is larger!
事实上,这样的调用过程,被称为"tool use",也可能有其他叫法,比如"function calling",大致都是这么个意思。接下来,我们来更加仔细地分析这个过程。
2.1 Register Tools
当然,第一步要让大模型知道有哪些可用工具。对此,Client需要将自己知道的信息通知LLM。Client如何知道有哪些可用tool呢?当然是由用户配置。举个例子,在Client的配置文件中,用户加了这么一段:
Note: 以下配置文件并非标准格式,仅用于辅助理解
json
{
"name": "compare_numbers_tool",
"description": "Compare 2 given numbers and return the larger one.",
"parameters": {
"left_value": "number",
"right_value": "number",
"required": ["left_value", "right_value"]
},
"returns": "A number indicates the larger one.",
"command": "python /path/to/compare2.py"
}
在用户准备开始聊天时,Client会事先对LLM说这些话:
json
{
Role: "system",
Content: "
你的名字叫xxx,你是一个xxx方面的高手,你的任务是......
......
在聊天时,你的回答必须符合以下要求:
......
对了,我这里有些有用的工具,如果你遇到相关的问题,请优先考虑使用它们,而不是自己给出答案。这些工具包括:
- compare_numbers_tool
- 它的功能是......它需要的参数是......它的返回结果格式是......
......
如果要使用这些工具,就用XML标签回答我,并遵循以下格式:
<actual_tool_name>
<parameter1_name>value1</parameter1_name>
<parameter2_name>value2</parameter2_name>
...
</actual_tool_name>
......
"
}
这和你自己把这段话发给ChatGPT没什么两样!这就是让LLM可以调用计算机工具的秘密,是不是很朴实无华?
通过这样的事先告知,LLM就会充分发挥自己"语文很好"的优势,在后续聊天时会"自然"地想到,唔,对于判断数字大小的问题,刚才好像有个叫"system"的告诉我他有一个叫compare_numbers_tool的工具。从它的描述上看,这正适合用户正在询问的问题,我可以用这个工具轻松回答用户的提问!
2.2 Use Tools
正如上面所说,LLM决定调用对用工具,它返回了这样一段符合格式要求的回答:
xml
<compare_numbers_tool>
<left_value> 9.11 </left_value>
<right_value> 9.8 </right_value>
</compare_numbers_tool>
当聊天软件(比如VSCode)识别到这样的格式时,就根据大模型提供的参数和配置中的命令------还记得上面的配置文件示例最后的一行"command": "python /path/to/compare2.py"
吗?它就是给Client看的------来调用对应的工具。像这样:
sh
python /path/to/compare2.py left_value right_value
这可以是一个脚本,也可以是一个服务,总之这工具会产生一个结果,聊天软件会将这一结果通知大模型,最后大模型结合这一答案,辅以自己擅长的客套话,给出用户最终的回答。
这就是Tool Use的流程。最初是OpenAI在2023年推出了GPT-4的Function Calling功能,几个月后,Claude推出了Tool Use接口。而到了如今,所有大模型几乎都支持这一能力。
3. MCP
上面介绍了Tool Use,这一能力是如此重要。它把大模型的"自然语言世界"和传统软件的"计算机语言世界"连接了起来,让大模型知道的更多,能做的更多。让所谓的"Agent"成为了可能。有了这样的桥梁,LLM不再只能支持"对话聊天"这一只有点用但又用处不大的尴尬应用场景。Cursor, Zed等AI Coding IDE横空出世,Devin, Manus等AI Agent也应运而生。AI应用的海洋上热闹了起来。
也正是随着模型越来越多、应用越来越多,各家公司自己的Tool Use规则不尽一致,导致模型和Tool之间常常强绑定。比如,一个给Claude写的Tool很难复用在ChatGPT上。这很像硬件驱动出现之前硬件(Tool)和操作系统(LLM)之间的关系。人们意识到,是时候出现一个统一的标准了。MCP就是在这样的背景下产生的。
MCP(Model Context Protocol)是由开发了Claude系列模型的Anthropic公司在2024年底提出的一种通信协议,旨在统一化、规范化工具调用,提升工具开发的效率,加强用户的数据安全保护。它和LSP(Language Server Protocol)相当类似,可以说MCP是在相当程度上借鉴了LSP。如果你了解后者,那理解MCP将是相当简单的事情。
当然,正如所有类似的提议,MCP在一开始反响平平。毕竟Anthropic不是Google这样一呼百应的权威机构。然而到了2025年3月,随着Manus的能力让市场大开眼界,重新审视相关领域的潜力,以及OpenAI, Google等巨头纷纷宣布准备支持MCP,让它真正成为了一个被广泛接受的标准。
3.1 Protocol
想要查看完整的数据格式规范,请参考官方文档 modelcontextprotocol.io/specificati...
MCP虽然名字叫Protocol, 但和我们熟悉的HTTP、TCP/IP等的"P"不同,MCP就像一个团队的前后端开发商量过后,产生的一套接口文档。
首先,它要求server或client提供一些接口给对方,比如:
- Server
- tools/list | prompts/list | resources/list
- prompts/get | resources/get
- tools/call
- ...
- Client
- Eliciation
- Sampling
- ...
MCP要求双方的通信要么通过STDIO(对,就是你熟悉的那个stdin/stdout)进行------这种情况下你得把MCP server下载到你的电脑上来使用------要么通过HTTP with Server-Sent Events进行。数据格式遵守JSON-RPC 2.0.
说到通过STDIO通信需要把MCP server的下载到本地来运行,这听起来似乎有点不协调,不太像"server"的感觉。但实际上,这种操作在目前的MCP server应用中相当常见。毕竟如前面所说,这个"server"的意思不是"网络服务器",而是"功能提供方"。本地调用能很好地保护你的数据安全,也能在多轮会话中避免过差的性能。
3.2 Tools, Prompts, Resources
下面说说MCP中定义的服务端可以支持的几种实体:
- Tools
- 无需多言,这就是前面Tool Use部分提到的Tools. 这是MCP server提供功能的核心载体,也是包了"MCP"饺子所为的"醋"。
- Prompts
-
这实际上只是一个"可复用的Prompt模板"。举个例子,server可以定义一个"prompt",具体代码是这样的:
python@mcp.prompt() def prompt_of_comparing_2_numbers(number1: str, number2: str) -> str: """ The prompt template to compare 2 numbers. """ return f"Please compare {number1} with {number2} and return the larger one."
你可以在Client(比如VSCode)上找到这一模板,选择使用后,填上两个参数(number1和number2),它就会自动给你拼成一个prompt,帮你填到输入框里。
这听起来似乎用处不大。不过对于一些不太会写prompt的非专业用户,且在prompt内容比较复杂的时候,由server预定义一些模板还是有意义的。
-
- Resources
- 与Prompts在某种程度上类似,都是"Client从Server上读取一些资源,可以包含参数"。不同的是,Resources的内容更宽泛,可以是字符串,也可以是图片、视频、音频等多媒体资源。后者需要通过base64编码返回。
比起"Tools", "Prompts"和"Resources"可能显得平平无奇。在目前主流的Client实现中,Client并不会将Server支持哪些Prompts和Resources的信息告诉LLM。只是在用户想查一下有哪些预定义的Prompts和Resources的时候临时读一下,就像打开一个普通的文件。
这显然有提升空间。如果Client能设计出更好的流程,让LLM知道这些信息,从而适当选用更好的预定义prompt代替用户的发言、结合Server提供的多媒体资源生成更多样化的内容,这将更好地提升Client作为Agent的能力。
3.3 Eliciation
这是一个Client需要提供给Server的能力。当Server遇到了一些问题需要与用户交互,比如需要用户提供账号和密码时,它会向Client发送一个Eliciation请求。这时,Client(比如你的VSCode)会将这一信息展示给用户,用户提供相应信息后,Server才可以继续执行。这为Server提供了一次tool call中实现多轮会话的能力。
如果上面的文字解释还不太好理解,那看看官方的示例请求你就懂了:
modelcontextprotocol.io/specificati...
目前的主流Client(例如VSCode, Claude Desktop等)应该都还不支持这一功能。如果你在这些工具内尝试这个功能发现并不work,别惊讶。
3.4 Sampling
这也是Client需要向Server提供的能力。
想象这样的场景:你准备编写一个MCP Server,它的功能是收集某个明星最近一个月发的所有微博,并分析他这个月都做了哪些事情。
收集微博这一部分很容易实现,你可以写一个网络爬虫拿到数据。但"通过微博分析他做了哪些事"则不是普通的代码就能实现的事情了。这是LLM所擅长的事情。所以这时候你可能需要找一个LLM服务,将收集到的数据发送给它,并问它:这些微博的主人这段时间做了什么?最终将结果返回给Client。
但是,等等,作为一个Server,与其花自己的钱找LLM服务问问题,何不直接去问Client的LLM呢?Sampling就是Server向Client正在使用的LLM问问题,然后收获回答的一种机制。
它类似于这个样子:
json
{
...
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please summarize what xxx did in the previous month. Here's his weibo posts in this period:
...
"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-4-sonnet"
}
]
}
}
如上所示,它就像用户一样对LLM提出问题。与此同时,它可以提出对选用模型的倡议,在VSCode中,用户也可以设置Sampling相关的权限,让server可以更好地选用适合自己的Model.
在Mac上的Client中,愚蠢的Claude Desktop作为亲儿子居然还不支持Sampling。反观VSCode可以较好地支持。
4. Conclusion
事到如今,不论喜欢还是讨厌,大家都不可避免地感受到了MCP的热度。如果要做类比,MCP俨然已经成为了应用开发领域的"原神"。
比起其简单易懂,甚至有点简陋的内容,真正令其广受各家厂商欢迎的是对AI Agent全新的预期。通过理解MCP,我们发现现在市场上风行的各种应用还远没有达到LLM+Tool所能实现的上限。现在大多数应用还只局限于用户提出要求,Client根据自身支持的Tool做一些力所能及的事情,比如编写代码,操作文件等等。
或许将来,网络上会出现更多开放的、通用的、垂直领域的MCP tools,像VSCode Extension Hub一样形成全面的生态环境,让LLM自己去发现和使用适宜的MCP Tool,将一切连接起来。从而使一个App能在LLM的驱动下完成更多任务。