基本理解
MCP 是一个开放协议,它规范了应用程序向 LLM 提供上下文的方式。当LLM想从应用程序获取信息,或者是使用应用程序,就需要应用程序提供一个规范,便于大模型进行使用和调用。
工具
LLM是大模型,大模型只有推理的能力,然而我们所见到的许多大模型应用有很多丰富的功能。例如,问大模型天气如何?
作为大模型而言,其自身是不携带例如查询天气等功能的,需要一定的第三方来协助大模型,例如当询问今天天气如何时,大模型应借助第三方查询天气的数据,再得到数据进行回复。那这些第三方我们可以称作工具。
MCP协议
由于需求不断变大,大模型需要各种各样的工具,然而工具提供的查询方法是不同的,为了让工具更好的统一和大模型进行对接,我们需要使用一个协议来统一这种对接方式,这就是MCP协议。
从发展角度理解
还是以LLM获取天气为例:
初始调用
借助提示词工程,让大模型生成请求所需参数,
例如生成请求json,给大模型一定的提示词要求,要求大模型根据某些个规定格式进行请求json生成,便于大模型获取天气数据。或者再通过正则匹配获取请求需要的参数,进行手工的构建。
缺点:依旧存在不稳定性,难以统一格式,提示词定制化
Function Calling
作为大模型早期带头人,为了让自家 ChatGPT 拥有更灵活的功能,Openai 提出了 Function Calling
概念:
- 将工具信息全部告知大模型,让大模型自行判断选择工具使用。
- 提供了自己函数的名称,描述,参数规范。
- 自动生成符合格式的参数json。
以下就是一个Function Calling 例子
{
"name": "get_weather", // 函数名
"description": "获取某个城市当前的天气", // 函数功能
"parameters": { // 参数格式要求
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市的名称"
}
},
"required": ["city"]
}
}
当用户问到涉及天气的问题时,大模型就会给出以下格式统一的内容
{
"function_call": {
"name": "get_weather",
"arguments": "{ \\"city\\": \\"杭州\\" }"
}
}
当获得结果后,大模型收到以下,便会以以下作为参考进行回复。
{
"city": "杭州",
"temperature": "21℃",
"condition": "多云"
}
代码解析示例:
# 1. 定义函数 schema
functions = [ ... ]
# 2. 用户对话输入
messages = [ ... ]
# 3. 模型生成函数调用请求
response = openai.ChatCompletion.create(...)
function_call = response["choices"][0]["message"].get("function_call")
# 4. 你自己的函数处理逻辑 —— 写在这里
if function_call:
name = function_call["name"]
args = json.loads(function_call["arguments"])
if name == "get_weather":
city = args.get("city")
# 你的逻辑:
result = get_weather(city) # 你自己定义的函数
这样的设计不容易出现参数错误,但随着更多更多功能的需求,就需要更多灵活的可移植的Function Calling
功能,因此产生ChatGPT插件功能。
ChatGPT插件
ChatGPT 插件 = Function Calling + 你提供的 HTTP API + OpenAPI 描述文档
也就是说:
- 模型通过 Function Calling 机制调用一个你暴露的 HTTP 接口(你的服务)
- 你写一个 API 接口 + 对应的 OpenAPI 文档(JSON)
- ChatGPT 根据 OpenAPI 文档 知道你能提供哪些函数、参数长什么样
- 它就能自动生成调用请求,发给你的 API
例:
{
"openapi": "3.0.0",
"info": {
"title": "Weather Plugin",
"version": "1.0.0"
},
"paths": {
"/weather": {
"get": {
"operationId": "getWeather",
"parameters": [
{
"name": "city",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "返回天气信息",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"temperature": { "type": "string" },
"condition": { "type": "string" }
}
}
}
}
}
}
}
}
}
}
确实可以共享给更多人,但是其限制在了ChatGPT Web上,没有办法使用到自己的应用上,还需要维护自己提供的api接口,难以维护。
MCP协议
为了解决以上问题,提供出通用协议,提出一个大模型与应用程序的交互。
架构组成
MCP 采用 客户端-服务器(Client-Server)模型,包含三个主要组件:
- MCP Hosts:运行大模型的应用程序(如 Claude Desktop、Cursor IDE)。
- MCP Clients:维护与服务器的 1:1 连接,负责协议代理。
- MCP Servers:提供标准化的数据访问和工具调用能力,支持本地(如数据库、文件)和远程(如 API、云存储)资源。
- 本地数据源: MCP 服务器可以安全访问的计算机文件、数据库和服务
- 远程服务: 通过互联网(例如,通过 APIs)可用的外部系统,MCP 服务器可以连接到这些系统
功能接口
并为了结合大模型的使用,MCP 有三个基本的服务器端功能:提示、资源、工具
- 提示:指导与 LLM 交互的预定义模板或说明。
- 资源:为模型提供额外背景的结构化数据或内容。
- 工具:允许模型采取行动或检索信息的可执行函数。
控制实体 | 解释 | 例子 | |
---|---|---|---|
提示 | 用户控制 | 通过用户选择调用的交互式模板 | 斜线命令、菜单选项 |
资源 | 应用程序控制 | 客户端提供和管理的上下文数据 | 文件内容,Git 历史记录 |
工具 | 模型控制 | LLM(大规模语言模型)中公开的执行函数 | API POST请求,写入文件 |
MCP接口示例
tools/list
: 获取可用工具列表tools/call
: 调用工具resource/list
: 获取可用资源resource/read
: 读取资源内容prompts/list
: 获取可用提示prompts/get
: 获取提示内容
MCP流程
我们定义有以下几个对象:
- 用户:进行操作的对象,操作客户端
- 客户端:负责协调和展示给用户,被用户操作
- MCP服务器:提供MCP服务
- LLM大模型:负责逻辑推理和决策
以获得天气为例:
- 客户端 → MCP服务器:获取工具列表,预先要载入的资源,
- 用户 → 客户端:向客户端发送查询天气的请求(“今天的天气如何?”)
- 客户端 → LLM大模型 → 客户端:让LLM大模型推理处理用户问题产生工具使用申请
- 客户端 → MCP服务器 → 客户端:客户端从MCP服务器调用工具函数获取结果值
- 客户端 → LLM大模型 → 客户端:将结果值给予大模型,大模型再次结合推理给出结果
- 客户端 → 用户:将结果显示给用户。
1. 客户端 → MCP服务器:获取工具列表
客户端 首先查询 MCP 服务器可用的工具和资源:
{
"jsonrpc": "2.0",
"method": "tools/list",
"id": 1
}
服务器响应:
{
"jsonrpc": "2.0",
"result": {
"tools": [
{
"id": "get_weather",
"description": "查询指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "城市名称"}
},
"required": ["location"]
}
}
]
},
"id": 1
}
2. 用户 → 客户端:发送查询请求
用户输入自然语言请求:
"今天的天气如何?"
3. 客户端 → LLM 推理,生成工具调用请求
客户端 将用户输入传给 LLM,LLM 分析后返回结构化调用请求:
{
"tool_use": {
"tool_name": "get_weather",
"parameters": {
"location": "北京" // LLM 推断用户可能想查询北京天气
}
}
}
4. 客户端 → MCP服务器:调用工具
客户端 按照 LLM 的指示,调用 get_weather
工具:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"tool_id": "get_weather",
"args": {"location": "北京"}
},
"id": 2
}
服务器返回天气数据:
{
"jsonrpc": "2.0",
"result": {
"location": "北京",
"temperature": "25°C",
"condition": "晴",
"humidity": "60%"
},
"id": 2
}
5. 客户端 → LLM:用工具结果生成最终回复
客户端 将天气数据传给 LLM,LLM 生成自然语言回复:
{
"response": "北京今天的天气是晴天,气温 25°C,湿度 60%。"
}
6. 客户端 → 用户:返回最终结果
客户端 将 LLM 生成的回复展示给用户:
"北京今天的天气是晴天,气温 25°C,湿度 60%。"
这个流程体现了 MCP 的核心思想:
- 标准化工具交互(JSON-RPC 格式)。
- LLM 作为决策中枢(决定何时调用工具)。
- 客户端作为协调者(连接用户、LLM 和 MCP 服务器)。