MCP 协议入门:基础概念
MCP 概念
MCP 是一个将人工智能应用连接到外部系统的开源标准。MCP 被比喻为 USB-C,就像 USB-C 为电子设备提供了一种标准的连接方式。
为什么需要 MCP
大语言模型虽然强大,但存在一些缺点:
- 知识时效性问题:大语言模型是基于历史数据训练的,模型训练完成后,其知识就停留在训练时的状态,无法自动获取训练之后的信息。也就是说大语言模型的知识和实时需求之间存在信息差。
为了解决大模型对训练后信息的获取问题,行业探索出两类解决方案:模型微调和上下文补充。
模型微调是在预训练好的大模型的基础上,使用新的数据集进行额外训练,从而使模型学习新的知识或适应特定任务。
上下文补充是为大模型提供外部知识库或信息源的技术方案。其目的是让大模型突破知识的时效性限制,能够访问专业领域信息,从而提高回答的准确性、时效性和可靠性。目前主要有以下三种方案:
- 记忆存储:大模型客户端会将用户与大模型的每轮对话内容记录下来,并设定一定的记忆容量。但设定容量限制会导致大模型的上下文长度超出限制,影响对话的连贯性。
- RAG(检索增强生成):当用户发出提问时,AI应用通过向量检索、关键词匹配等方式,从外部知识库或数据源检索相关信息,再把检索到的信息作为上下文提供给大模型,让大模型基于补充的信息进行回答。
-
函数调用(Function Calling):让大模型执行特定任务,允许大模型将自然语言请求转换为具体的函数调用,供 AI 应用调用外部工具,并将结果反馈给用户。
-
智能体开发适配难度大:例如在 ChatGPT 平台创建了一个 GPTs,想要把 GPTs 部署到其他平台时,发现无法复用 GPTs。而且 GPTs 默认只能在云端处理数据,如果有上传操作,会存在隐私泄漏的风险。
MCP 提供了一个标准化协议,能让大语言模型以一致的方式访问外部信息和工具,同时借助标准化协议,可以让智能体扩展平台更加容易。
MCP 的灵感
MCP 的设计受到了 LSP 的启发。 LSP 是语言服务器协议,其目的是标准化编辑器与语言服务器之间的交互。它将代码补全、错误检查、智能跳转等功能从编辑器中解耦,有独立的语言服务器提供。
LSP 基于 JSON-RPC,通过统一的请求和响应格式,实现了编辑器与语言服务器之间的高效通信。
MCP 借鉴了 LSP 的架构设计,在应用层定义了三类角色:主机、客户端、服务器。
MCP 除了借鉴 LSP 的架构设计,还借鉴了 LSP 中的几个优秀的设计理念: - 资源与应用解耦,通过外部服务器连接数据或服务 - 支持本地运行,服务器可作为本地进程运行,通过标准IO与客户端通信 - 将 JSON-RPC 作为数据的交换标准 - 一次实现,多端复用。主要是反向让大模型应用(主机)提供 MCP 客户端的实现,从而对接 MCP 服务器。这样 MCP 服务器就可以单独开发。
JSON-RPC
RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,它允许程序能够像调用本地函数一样调用另一台计算机上的子程序,而无需编写底层网络通信代码。
一个完整的 RPC 框架通常包含客户端存根、网络传输和服务器端存根三个关键部分,其工作流程概括如下:
- 客户端(调用方):调用一个本地的”存根”函数(可理解为占位符或代理函数)
- 客户端存根:它看起来和远程函数一模一样
- 序列化(编码或封送):将函数名、参数等信息打包成一个可以被网络传输的消息格式(JSON、XML等)
- 通过网络将消息发送给服务器
- 网络传输:使用某种网络协议(TCP、HTTP)将数据包从客户端传送到服务器
- 服务器端存根:接收网络请求
- 反序列化(解码或解封送):将接收到的消息包解析出来,还原成函数名和参数
- 根据函数名,调用服务器上真正的函数实现
- 服务器执行真正的业务逻辑,获得结果
- 返回结果:服务器将结果按照同样的路径(序列化 -> 网络传输 -> 反序列化)返回给客户端
- 客户端存根拿到结果,并将其作为本地调用的返回值。对于客户端程序来说,它感觉就像调用了一个本地函数一样
客户端存根 是 RPC 框架在调用方(客户端)的一个代理组件。它的主要目的是隐藏进行远程调用的所有底层复杂细节,让客户端觉得它只是在做一个普通的本地函数调用。
MCP 架构中的关键角色
- MCP Host:MCP 主机负责协调和管理一个或多个 MCP 客户端的智能体,例如:Cursor。
- MCP Client:MCP 客户端是一个保持与 MCP 服务器连接的组件,并从 MCP 服务器获取上下文供 MCP 主机使用。
- MCP Server:MCP 服务器是一个向 MCP 客户端提供上下文的程序,例如调用数据库查询、操作浏览器等。
MCP 客户端和 MCP 服务器采用一对一的点到点连接方式。以官方示例为例:Visual Studio Code 充当 MCP 主机。当 Visual Studio Code 与 MCP 服务器(如 Sentry MCP 服务器)建立连接时,Visual Studio Code 运行时会实例化一个 MCP 客户端对象,该对象保持与 Sentry MCP 服务器的连接。当 Visual Studio Code 随后连接到另一个 MCP 服务器(如本地文件系统服务器)时,Visual Studio Code 运行时会实例化另一个 MCP 客户端对象以保持此连接,从而维持 MCP 客户端与 MCP 服务器的一对一关系。

客户端和服务器之间的数据交换采用 JSON-RPC 协议。数据传输支持两种方式:
- stdio 传输:适合调用本地服务器,通过标准输入输出进行通信
- 流式 HTTP 传输:支持远程服务器通信,并支持标准 HTTP 认证方法,包括令牌、API 密钥和自定义头信息
MCP 推荐使用 OAuth 获取认证令牌。
授权机制
MCP 遵循 OAuth 2.1 的规范,建立 MCP 客户端和 MCP 服务器之间的信任。
OAuth 的一个使用示例是,最终用户(资源所有者)授权一个财务管理服务(客户端)访问其存储在银行服务(资源服务器)中的敏感交易历史记录,而无需将用户名和密码共享给财务管理服务。相反,他们直接通过其金融机构的服务器(授权服务器)进行身份验证,该服务器会为财务管理服务颁发特定于委托的凭证(访问令牌)。
OAuth 是一个授权协议,而非认证协议,因为 OAuth 并未定义实现用户认证所需的必要组件。如果目标是认证用户,则必须使用认证协议。例如 OpenID Connect(OpenID),它基于 OAuth 提供认证协议所需的必要安全特性和组件。