十分钟完全理解MCP

最近MCP的风吹得很疯狂。有的人喜欢它,认为它象征着AI Agent光明的前景。有的人则觉得这也不是什么高深的东西,被一群人炒得像什么重大科学突破一样,有点招人烦了。当然,还有一些人在问:到底什么是MCP,这东西有什么用?

这篇文章将通过详细的描述,让一只猴子🐒进来都能完全理解MCP是什么、为何存在、有何作用。

1. Background

咱们先从闲聊几句开始。记得ChatGPT最初火起来的时候,大家在惊艳之余,还是迅速找到了种种生成式对话机器人所不擅长的场景,最后松一口气:果然还是人工智障。

最经典的例子是这个:9.11和9.8谁更大?

当时绝大多数人遇到的回答都是:9.11更大。

这在我们这些互联网从业者眼里很好理解。肯定是模型根据语料库的经验,把这两个数字当成了类似"版本号"之类的对比。

但广大用户不会这么想。他们觉得你这机器人聊起天来头头是道,好像什么都懂,原来这么基础的逻辑都判断不清楚啊!这不是一件小事。对于普通用户来说,这么基础的问题你都犯错,我怎么可能在那些更加高级的应用,比如AI医疗、智能驾驶等等上信任你,又怎么吃得下去科技公司画的大饼呢?

这暴露出了大语言模型的重大限制:它并不是真懂数学,更不懂逻辑。它只是一个根据前置token预测下一个token的机械式的模型而已。它的进化依赖语料库的积累,而现实世界变化更快,总不按套路出牌。换句话说,它"语文很好",但"数学很差"。

而巧妙的是,传统的计算机工具或软件,正是逻辑严密,"数学很好"的典型,它们功能可能没那么强大,但保证结果绝对准确!这时若能有一个专门用来比较数字大小的工具告诉大模型:再有这种类型的问题,直接找我,兄弟保证给你正确的答案。它们显然就能双剑合璧,解决问题!

2. Tool Use

在上述场景中,存在着4方实体,它们包括:用户,大模型(LLM),聊天软件(Client),以及工具。它们的工作流程大致是这样的:

sequenceDiagram participant User participant Client participant LLM participant Tool Note over User, Tool: Conversation starts Client ->> Tool: What tools do you support? Tool ->> Client: [{name: compare_numbers, description: xxx, ...}] Client ->> LLM: Hey, you can use these tools:
[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的驱动下完成更多任务。

相关推荐
王国强20093 小时前
Unla MCP 网关代理配置教程
mcp
kagg8865 小时前
mcp-gateway —— 隐藏mcp上下文以避免不必要的tokens开销
llm·mcp
AAA阿giao5 小时前
qoder-cli:下一代命令行 AI 编程代理——全面解析与深度实践指南
开发语言·前端·人工智能·ai编程·mcp·context7·qoder-cli
饭勺oO1 天前
AI 编程配置太头疼?ACP 帮你一键搞定,再也不用反复折腾!
ai·prompt·agent·acp·mcp·skills·agent skill
AlienZHOU1 天前
MCP 是最大骗局?Skills 才是救星?
agent·mcp·vibecoding
Linux内核拾遗1 天前
人人都在聊 MCP,它到底解决了什么?
aigc·ai编程·mcp
谷哥的小弟1 天前
SQLite MCP服务器安装以及客户端连接配置
服务器·数据库·人工智能·sqlite·大模型·源码·mcp
tyw151 天前
解决 Trae MySQL MCP 连接失败(Fail to start)
mcp·trae·fail to start·mysql mcp·mcp兼容
谷哥的小弟1 天前
File System MCP服务器安装以及客户端连接配置
服务器·人工智能·大模型·file system·mcp·ai项目
啊湘2 天前
vscode 使用 github (适用CURSOR等使用)
ide·vscode·github·cursor·mcp