MCP基础知识

what is MCP?

定义

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

架构

MCP架构中一般包含下面5个组件:

  • Host:用户操作的主机,搭载了MCP Client,并且具备访问LLM的能力,如Cursor、vscode cline等
  • LLM:即大语言模型,主要负责处理用户输入、选择MCP tools、处理返回结果等
  • MCP Client:MCP的客户端,功能包括:查询Server端可用的tools,调用Server端指定tool等
  • MCP Server:MCP的服务端,核心功能,将数据源的API封装成tools,供Client调用
  • Data Source:即数据源,MCP功能之一是建立数据源与大模型之间的桥梁,例如:数据库、本地文件系统、高德地图等

通信机制

MCP 协议支持两种主要的 通信机制 :基于stdio的本地通信、基于SSE的远程通信。

这两种机制都使用 JSON-RPC 2.0 格式进行消息传输,确保了通信的标准化和可扩展性。

  • 本地通信:通过 stdio 传输数据,适用于在同一台机器上运行的客户端和服务器之间的通信。
  • 远程通信:利用 SSE 与 HTTP 结合,实现跨网络的实时数据传输,适用于需要访问远程资源或分布式部署的场景。

Why MCP?

谈到MCP的优势,一般分为两个对比方向:与传统LLM对比、与Function Calling对比。

与传统LLM对比

传统LLM的数据基于预训练的预料,模型的知识具有滞后性,在MCP之前的解决方式一般为添加额外数据源,如:联网搜索、本地知识库等。这些方法存在部署成本高、开发难度大、维护成本高等问题,而MCP则很好地解决了上述痛点,MCP通过大量现成的MCP Server,将常见数据源的API封装到MCP Server中,LLM引入新的数据源只需调用Server即可,接入方式变为即插即用式,使得LLM的数据集成变得简单高效。

与Function Calling对比

然而在MCP之前,为了解决LLM的数据孤岛问题,openai首先引入了Function Calling来进行LLM的外部交互,Function Calling 是一个允许LLM在生成文本的过程中调用外部函数或服务的功能,看起来与MCP是很相似的。阿里云百炼里给出了Function Calling的流程图,通过下图可以比较清晰地理解Function Calling 的作用。

官方文档给出了Function Calling的定义/功能:您可以通过Function Calling让模型访问您自己的自定义代码。根据系统提示和消息,模型可能会决定调用这些函数,然后,您将执行函数代码,发回结果,模型会将它们合并到最终响应中。

openai的文档给出了demo,下面代码中的tools变量包含一段描述信息,即让LLM知晓存在一个名为get_weather的用户自定义函数,并且写明函数所需参数等信息。运行代码,当用户提问中涉及查询天气时,LLM会尝试根据文本信息去构造符合get_weather要求的json,里面自然包含了get_weather所需参数信息(即经纬度)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from openai import OpenAI
import json

client = OpenAI()

tools = [{
"type": "function",
"name": "get_weather",
"description": "Get current temperature for provided coordinates in celsius.",
"parameters": {
"type": "object",
"properties": {
"latitude": {"type": "number"},
"longitude": {"type": "number"}
},
"required": ["latitude", "longitude"],
"additionalProperties": False
},
"strict": True
}]

input_messages = [{"role": "user", "content": "What's the weather like in Paris today?"}]

response = client.responses.create(
model="gpt-4.1",
input=input_messages,
tools=tools,
)

这里假设用户的提问触发了 Function Calling,LLM返回的json如下:

1
2
3
4
5
6
7
[{
"type": "function_call",
"id": "fc_12345xyz",
"call_id": "call_12345xyz",
"name": "get_weather",
"arguments": "{\"latitude\":48.8566,\"longitude\":2.3522}"
}]

然后自定义函数get_weather去处理LLM返回的json,即查询天气信息,然后返回结果:

1
2
3
4
tool_call = response.output[0]
args = json.loads(tool_call.arguments)

result = get_weather(args["latitude"], args["longitude"])

最后将结果整合到大模型中:

1
2
3
4
5
6
7
8
9
10
11
12
13
input_messages.append(tool_call)  ## append model's function call message
input_messages.append({ ## append result message
"type": "function_call_output",
"call_id": tool_call.call_id,
"output": str(result)
})

response_2 = client.responses.create(
model="gpt-4.1",
input=input_messages,
tools=tools,
)
print(response_2.output_text)

总结上述案例,Function Calling就是让LLM对文本进行解析,并返回符合用户自定义函数要求的json,然后调用自定义函数得到返回结果,再交由LLM润色输出。

不难看出,**Function Calling与外界交互的核心在于自定义函数**,LLM只负责提供参数,而自定义函数需要开发人员手动编写,每个Data Source又都需要编写一个自定义函数。而MCP则是为每个数据源提供统一开源的MCP Server,Server包含了已经封装好的工具,省去了为每个数据源都编写自定义函数、处理json参数的流程,开发人员需要做的仅是接入对应的MCP Client。

MCP quick start

MCP的实现参考官方github的mcp servers,其实本质上就是Web服务。下面通过一个简单的mcp项目来快速上手mcp。

项目旨在构建一个本地智能舆情分析系统,输入为自然语言描述,实现自动化的新闻检索、情感分析、邮件推送功能。项目源码放到 Github上 ,项目结构如下图所示,主要文件为:server.pyclient.py.env

首先是server.py,即MCP server,主要实现三个实际功能的对应路由函数,分别是search_google_newsanalyze_sentimentsend_email_with_attachment,每个函数接收 Client 的传参,然后去调用外部api获取响应,并返回给client。

其次是client.py,实际上是简化版本的MCP Client,即使用代码实现的一个简易的Client工具,基于官方GitHub上的quickstart-resources/mcp-client-python实现,包括connect_to_serverprocess_queryplan_tool_usageprocess_querychat_loop等函数,其中plan_tool_usage是新添函数,主要功能是实现Server端工具的顺序调用。

最后是.env,即环境变量文件,存储访问LLM、外部数据源等资源所需的api-key。

输入命令uv run ./client.py,执行结果如下:


How MCP works

通过详细阅读上面代码实现的Client和Server,结合下图对MCP的执行流程进行分析,流程如下:

  1. 用户输入查询,经大模型处理分析,决定是否需要调用 MCP Server,需要则下一步
  2. LLM将需要调用的tool_name、params交给MCP Client,Client向Server发送对应的调用请求
  3. MCP Server的对应路由处理函数收到Client的请求,事先封装好的代码逻辑按照传参去获取外部数据源的数据,并返回给Client
  4. Client得到Server返回的数据,再交给LLM对返回结果进行润色
  5. 用户得到最终输出结果

总结

本篇文章主要介绍了MCP的入门基础知识,对MCP的定义、优缺点、使用场景进行梳理,然后通过一个具体案例来加深理解,将MCP这个抽象的概念具体化,清晰化。

MCP由于之前快速了解过,在其本身的理解上没有遇到太大问题,而是在MCP和Function Calling的比较上有些疑惑,因为之前并没有了解Function Calling具体实现是怎样,也就不理解为什么MCP相对Function Calling更加便捷,碰巧这一点在现成的文章都是被一笔带过的。于是,我通过阅读Openai的文档案例,明白了Function Calling是怎么回事儿,疑惑也就迎刃而解。所以,当网上没有现成的文章总结时,就应该去翻官方文档尝试自己总结,这是这次写文章总结到的经验。

时间有限,本文仅分析了MCP的基础概念,属于小白入门文,没有深入研究SDK代码、SSE协议等内容,这里就留到下一篇文章了,另外刚刚看到MCP+DNS重绑定攻击,同样写在下一篇文章。

Reference