背景
最近 MCP(Model Context Protocol,模型上下文协议) 概念非常火,很多 AI 专家张口闭口 MCP,仿佛不知道 MCP,出门都不好意思打招呼。
为了让读者深刻理解 MCP 到底是什么东东,我们以一个智能聊天应用为例,开始通过正则匹配的原始方式来调用工具,然后通过 Function Calling 的原生方式调用工具,接着通过 ChatGPT 插件的方式调用工具,最后通过 MCP 的方式调用工具。
一个智能聊天应用
一个智能聊天应用 Agent 的核心包括历史消息、循环控制和提示词,接下来我们分别阐述一下。
历史消息
我们看一下 Agent 类代码:
from openai import OpenAI
DEFAULT_MODEL = "gpt-4o-mini"
client = OpenAI()
class Agent:
def __init__(self, system=""):
self.system = system
self.messages = []
if self.system:
self.messages.append({"role": "system", "content": system})
def invoke(self, message):
self.messages.append({"role": "user", "content": message})
result = self.execute()
self.messages.append({"role": "assistant", "content": result})
return result
def execute(self):
completion = client.chat.completions.create(
model=DEFAULT_MODEL,
messages=self.messages,
temperature=0
)
return completion.choices[0].message.content
说明如下:
- 在初始化的时候,我们给 Agent 做一些初始的设定。 messages 是我们维护的历史消息列表,如果设定了系统提示词,就将它添加到历史消息里。
- invoke 是主要的对外接口,在调用大模型之前,先将消息存放到历史消息里,之后再将应答存放到历史消息里。
- execute 处理了请求大模型的过程。因为我们要求大模型推理过程的高确定性,所以将 temperature 的值设为 0。因为大模型是无状态的,所以将所有历史消息都注入给大模型。
循环控制
我们看一下代码:
action_re = re.compile(r'^Action: (\w+): (.*)$')
known_actions = {
"calculate": calculate,
"get_current_weather": get_current_weather
}
def query(question, max_turns=5):
i = 0
agent = Agent(prompt)
next_prompt = question
while i < max_times:
i += 1
result = agent.invoke(next_prompt)
print(result)
actions = [action_re.match(a) for a in result.split('\n') if action_re.match(a)]
if actions:
# There is an action to run
action, action_input = actions[0].groups()
if action not in known_actions:
raise Exception("Unknown action: {}: {}".format(action, action_input))
print(" -- running {} {}".format(action, action_input))
observation = known_actions[action](action_input)
print("Observation:", observation)
next_prompt = "Observation: {}".format(observation)
else:
return
说明如下:
- 在第一次循环时,将用户问题添加到历史消息里。
- 每次调用 invoke 时,都会先询问大模型,然后大模型结构化应答。
- 针对应答结果,我们会先从里面分析出要执行的行动(这里采用了正则表达式直接匹配文本),然后执行该行动,最后再把执行的结果作为观察结果,发送给大模型进行下一次的询问。
- 当问题比较复杂,可能循环次数会大幅增加,在极端情况下,甚至会出现无法收敛的情况,也就是一次一次地不断循环下去,这会造成极大的成本消耗。所以,在设计 Agent 的时候会限制最大循环次数, query 函数的 max_times 参数就是做这个限制的,默认值为 5。
提示词
我们先介绍一下 ReAct 框架。ReAct 实际上是两个单词的缩写:Reasoning + Acting,也就是推理 + 行动。Agent 为了完成一个目标,需要不断地做一些任务。每个任务都会经历思考(Thought)、行动(Action)、观察(Observation)三个阶段。思考负责任务拆分,行动决定了具体的操作,而观察是执行行动,并对行动结果进行评估,决定是否要结束这个循环。
对于 Agent,思考和决策能力(规划组件)是最核心的。ReAct 框架引导大模型进行复杂问题的结构化思考和决策,从而赋予 Agent 动态决策能力,即 Agent 在每一步执行后会观察结果,并利用新信息调整后续决策。而在这一过程中,提示词起到了非常关键的作用。
假设用户有一个问题——“东京和西安当前的温差是多少”,我们的提示词应该怎么写?
prompt = """
## **流程说明**
- **思考(Thought)**:描述你对所提出问题的思考过程,输出任务拆分。
- **行动(Action)**:根据思考结果,明确具体操作。
- **观察(Observation)**:执行行动,并对行动结果进行评估,决定是否结束循环。
你在“思考(Thought)→行动(Action)→观察(Observation)”的循环中运行,在循环结束时,需要输出一个答案(Answer)。
## **操作说明**
### **1. 查询城市当前的天气(get_current_weather)**
get_current_weather 有两个参数:
- city:城市名称,比如 东京
- unit: 温度单位,比如摄氏度,华氏度,默认为摄氏度
**调用举例:**
get_current_weather: 东京
结果:{"temperature": 10°C, "condition": "晴天"}
### **2. 计算温差(calculate)**
calculate 只有一个参数:
- 整数表达式,比如 10-1
**调用举例:**
calculate: 10-1
结果:9°C
## **会话示例**
Thought: 要计算三公斤苹果和两公斤香蕉的总价,我首先需要知道每种水果的单价,然后再计算水果的总价,于是需要拆分成三个任务:
- 询问苹果的单价;
- 询问香蕉的单价;
- 计算水果的总价。
Action: ask_fruit_unit_price: apple
== 执行工具调用 ==
Observation: 苹果的单价是10元/公斤
Thought: 现在我已经知道了苹果的单价,还剩下两个任务:
- 询问香蕉的单价;
- 计算水果的总价。
Action: ask_fruit_unit_price: banana
== 执行工具调用 ==
Observation: 香蕉的单价是6元/公斤
Thought: 现在我已经知道了苹果和香蕉的单价,只剩下一个任务了:
- 计算水果的总价。
Action: calculate: 3 * 10 + 2 * 6
== 执行工具调用 ==
Observation:总价是52元
Answer: 三公斤苹果和两公斤香蕉的总价是42元
""".strip()
说明如下:
- Agent 运行的流程,是一个遵循 ReAct 框架的“思考(Thought)→行动(Action)→观察(Observation)”循环。
- 该问题涉及的操作有两个,分别是查询城市当前的天气(get_current_weather)和计算温差(calculate)。
- 提示词在 Agent 初始化时就被添加到了历史消息里,而该问题在第一次调用大模型之前作为请求也被添加到历史消息里,之后再将应答(Thought 和 Action)添加到历史消息里。从第二次开始,每次调用大模型之前将请求(Observation)添加到历史消息里,之后再将应答(Thought 和 Action)添加到历史消息里,直到循环控制判断无需再执行了。就是说,每次访问大模型时,都会携带所有历史消息。为了避免历史消息膨胀(超过大模型的最大 token 数限制),所以在循环控制中增加了最大次数(max_times)限制。
最后,我们给出本问题的完整会话,供大家参考:
Thought: 要计算东京和西安当前的温差,我首先需要查询东京当前的天气,然后再查询西安当前的天气,最后计算温差。于是我需要拆分成三个任务:
- 查询东京当前的天气;
- 查询西安当前的天气;
- 计算东京和西安的温差。
Action: get_current_weather: 东京
== 执行工具调用 ==
Observation: 东京当前的温度是10°C
Thought: 现在我已经知道了东京当前的天气数据,还剩下两个任务:
- 查询西安当前的天气;
- 计算东京和西安的温差。
Action: get_current_weather: 西安
== 执行工具调用 ==
Observation: 西安当前的温度是5°C
Thought: 现在我已经知道了东京和西安当前的天气数据,只剩下一个任务了:
- 计算东京和西安的温差。
Action: calculate: 10 - 5
== 执行工具调用 ==
Observation:东京和西安当前的温差是5°C
Answer: 东京和西安当前的温差是5°C
Function Calling
起源
在过去,很多大模型的输出通常是非结构化的文本形式,例如直接生成诸如“Action: get_current_weather: Xi'an, 2025-02-03”这样的字符串。然而,随着模型能力的提升,大模型可以直接生成符合特定 json 格式的结构化数据。通过在 API 请求中使用 response_format 参数,开发者可以指定模型的输出格式为严格的 json,对应特定的 json schema。这意味着模型的响应将直接以 json 格式返回,包含诸如函数名称和参数等信息,方便解析和调用。例如,针对查询天气的请求,模型可能返回如下的 json:
{
"action": "get_current_weather",
"parameters": {
"city": "西安",
"unit": "摄氏度"
}
}
对于通过正则匹配方法获取即将调用的工具及参数的处理,看似简单直接,但也有不可靠的缺点,因为大模型并不一定总是严格的遵循你的提示词。
对于大模型的 API 请求,响应结果是不可控的,就像掷骰子一样:
- 大模型生成的 json 少了一个大括号;
- 大模型生成的 json 少了一个逗号;
- 大模型生成的 json 中某个字符串很复杂,带有转义字符,大模型没有处理好,导致这个字符串混乱。
既然原始的正则匹配方法不可控,那么有没有更可靠的方法呢?OpenAI 也意识到了这个问题,于是在 2023 年炸裂的发布了函数调用(Function Calling) 功能,彻底改变了游戏规则。
本质
大模型原生的支持了函数调用,允许开发者显式的向大模型描述可用的函数,包括函数名称、功能描述和参数结构。模型在生成响应时,可以根据用户的输入,智能地判断是否需要调用这些函数,并以结构化的 json 格式返回调用信息。需要注意的是,大模型本身并不执行这些函数,而是生成包含函数名称和所需参数的 json 对象,供开发者在应用程序中解析并调用相应的外部函数或服务。
函数调用的优势:
- 结构化输出:通过预定义函数的参数和返回值,确保模型输出符合预期的结构,减少解析错误;
- 增强模型能力:结合外部工具,模型可以获取实时数据或执行复杂计算,扩展了其应用范围;
- 提高交互效率:模型可以直接生成调用外部函数所需的参数,减少了与用户的多轮交互,提高了响应速度和用户体验。
实现函数调用的步骤:
- 定义函数:在应用程序中,明确需要调用的函数,包括名称、描述和参数结构;
- 传递函数信息:在与大模型的交互中,将定义好的函数信息传递给模型,通常通过 API 调用时的参数来实现;
- 解析模型响应:模型根据用户输入,判断是否需要调用函数,并返回相应的 json 对象,然后应用程序解析该对象,提取函数名称和参数;
- 执行函数并返回结果:应用程序调用对应的外部函数,获取结果后,将其返回给模型或直接呈现给用户。
示例
假设用户询问:“东京当前的天气如何?”,Agent 需要在 API 请求中定义可供大模型调用的函数:
{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "东京的天气如何?"}],
"functions": [
{
"name": "get_current_weather",
"description": "获取指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称,例如:'东京'"
},
"unit": {
"type": "string",
"enum": ["摄氏度", "华氏度"],
"description": "温度单位"
}
},
"required": ["location"]
}
}
],
"tool_choice": "auto"
}
说明:
-
functions
:定义了模型可调用的函数,包括函数名称、描述和参数结构; -
tool_choice
:设置为 "auto",允许模型根据需要决定是否调用函数。
当大模型确定需要调用函数时,它会在响应中包含 function_call
字段,指示要调用的函数及其参数:
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1677858242,
"model": "gpt-4o",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"function_call": {
"name": "get_current_weather",
"arguments": "{\n \"location\": \"东京\",\n \"unit\": \"摄氏度\"\n}"
}
},
"finish_reason": "function_call"
}
],
"usage": {
"prompt_tokens": 56,
"completion_tokens": 17,
"total_tokens": 73
}
}
说明:
-
function_cal
l:包含大模型决定调用的函数名称和参数; -
arguments
字段是一个字符串,需解析为 json 对象以提取具体参数。
Agent 解析该响应,调用实际的天气查询工具,获取东京的当前天气信息,并将结果返回给用户。
OpenAI 的函数调用功能为智能聊天应用的开发提供了更为可靠和高效的方式,将大模型与外部工具无缝集成,提升了大模型的实用性和交互体验。通过预定义函数并传递给模型,开发者可以确保大模型输出的结构化和可预测性,减少了解析错误,增强了 Agent 的稳定性,提高了用户满意度。
ChatGPT Plugins
起源
函数调用功能已经很好了,但 Agent 需要调用更多的工具,最好像 App Store 中那么丰富,以便满足所有的用户。如何编写如此丰富的函数呢?Agent 的开发人员肯定没有这么多的精力,于是打算开发一个扩展系统,让其他开发人员来帮忙编写。
巧了,OpenAI 也是这么想的。Sam Altman 想让全球开发者主动为他的 ChatGPT 网页开发函数调用工具,于是 OpenAI 的 ChatGPT 插件(Plugins)登场了。
本质
通过插件,ChatGPT 可以:
- 访问实时数据:获取最新的天气、新闻、股票行情等信息;
- 执行复杂计算:调用外部计算引擎,处理复杂的数学或逻辑运算;
- 与其他服务集成:与日历、邮件、任务管理等应用交互,执行创建事件、发送邮件等操作。
这些功能使 ChatGPT 能够突破自身训练数据的限制,提供更为丰富和实用的服务。
要开发一个 ChatGPT 插件,需要完成以下步骤:
- 构建 API 服务:开发一个 Web API,提供特定的功能或数据服务;
- 编写 OpenAPI 描述文件:使用 OpenAPI 规范,详细描述 API 的接口、参数和返回值;
-
创建插件清单文件:编写一个
ai-plugin.json
文件,包含插件的元数据,如名称、描述、授权信息等。
完成上述步骤后,开发者可以在 ChatGPT 的插件商店中提交并发布插件,供用户安装和使用。
示例
-
创建一个
ai-plugin.json
文件:该文件包含插件的元数据、认证方式和 API 描述等信息
{
"schema_version": "v1",
"name_for_human": "天气查询插件",
"name_for_model": "weather",
"description_for_human": "用于查询指定城市的实时天气信息。",
"description_for_model": "用于查询指定城市的实时天气信息。",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "https://yourdomain.com/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "https://yourdomain.com/logo.png",
"contact_email": "support@yourdomain.com",
"legal_info_url": "https://yourdomain.com/legal"
}
-
编写 OpenAI 文档(
openapi.yaml
):该文件定义插件提供的 API 接口,包括请求路径、方法、参数和响应格式等
openapi: 3.0.0
info:
title: 天气查询插件 API
version: 1.0.0
paths:
/weather:
get:
summary: 获取指定城市的天气信息
parameters:
- in: query
name: city
required: true
schema:
type: string
description: 城市名称
responses:
'200':
description: 返回天气信息
content:
application/json:
schema:
type: object
properties:
city:
type: string
description: 城市名称
temperature:
type: string
description: 当前温度
condition:
type: string
description: 天气状况
- 实现天气查询功能:开发一个函数,通过调用天气服务 API 获取实时天气信息。例如,使用高德天气 API
import requests
def get_current_weather(city: str, unit: str = "摄氏度"):
"""
获取指定城市的当前天气信息。
参数:
city (str): 城市名称,例如 '东京'。
unit (str): 温度单位,可选 '摄氏度' 或 '华氏度',默认 '摄氏度'。
返回:
dict: 包含城市、天气状况和温度的字典,或包含错误信息的字典。
"""
# 高德地图API的天气查询接口
url = "https://restapi.amap.com/v3/weather/weatherInfo"
# 替换为您的高德API密钥
api_key = "您的高德API密钥"
# 请求参数
params = {
"key": api_key,
"city": city,
"extensions": "base", # 实时天气
"output": "JSON"
}
try:
# 发起GET请求
response = requests.get(url, params=params)
response.raise_for_status()
data = response.json()
if data.get("status") == "1" and data.get("lives"):
weather_info = data["lives"][0]
temperature = float(weather_info.get("temperature"))
# 根据需要转换温度单位
if unit == "华氏度":
temperature = temperature * 9/5 + 32
return {
"city": weather_info.get("city"),
"weather": weather_info.get("weather"),
"temperature": f"{temperature}°{unit}"
}
else:
return {"error": "无法获取天气信息"}
except requests.RequestException as e:
return {"error": f"请求异常: {str(e)}"}
except ValueError as e:
return {"error": f"解析响应失败: {str(e)}"}
MCP
起源
ChatGPT 插件固然很好,但是也有一定的局限性:
- 平台捆绑:只能在官方 ChatGPT 平台使用
- 审核限制:需要 OpenAI 审核和批准
- 集成复杂:需要开发和维护 API 服务
- 功能裁剪:只能通过 HTTP API 提供功能
于是大家就有了一些困惑:
- “我为 ChatGPT 开发了一个插件,审核等了三个月...”
- “我的插件还想在 Claude、Gemini 等其他平台使用”
- “有用户想在私有部署中使用我的插件,但它只能在网页版 ChatGPT 中使用”
- “这个插件功能与我有什么关系,我的聊天应用又不能用”
那怎么办呢?有没有一种方法,使得我们开发的插件让所有 AI 聊天应用都能调用?当然有,它就叫 MCP(Model Context Protocol,模型上下文协议)!
普通人对 MCP 的理解:
- AI 世界的“ USB 接口”;
- 统一不同 AI 应用的交流方式;
- 工具一次开发,多处运行。
本质
MCP 是由 Anthropic 在 2024 年 11 月推出的社区共建的开放协议,目的是提供一个通用的开放标准,用来连接大模型和外部数据及行为。
MCP 的架构如下图所示:
可以看出,MCP 是 AI 应用的“万能转接头” ,为连接大模型到不同数据源和工具提供了标准化方式。
MCP 底层使用标准的 json-rpc 进行通信,主要方法如下表所示:
方法 | 说明 |
---|---|
tools/list |
获取所有可用工具的列表 |
tools/call |
调用指定工具,传递参数后执行工具任务 |
resources/list |
获取所有可用资源的列表(如工具、API、服务等) |
resources/read |
根据资源ID获取某个资源的详细信息 |
prompts/list |
列出所有预定义的提示词集合,供 Agent 调用或展示 |
prompts/get |
获取单个提示词的详细内容,通常需要提供提示词的唯一标识符 |
MCP 在内容控制方面的三大核心功能:
- 工具(Tools):允许服务器向客户端暴露可执行功能,使 LLM 能够与外部系统交互、执行计算或采取现实世界的行动。工具设计为模型控制(model-controlled),即服务器将工具暴露给客户端,大模型可以自动调用这些工具。
- 资源(Resources):允许服务器向客户端暴露数据和内容,供 LLM 交互时使用。资源设计为应用控制(application-controlled),即客户端应用决定何时以及如何使用这些资源。不同客户端对资源的使用方式可能不同,例如,Claude Desktop 要求用户明确选择资源,而其他客户端可能基于启发式自动选择资源,甚至允许AI模型自行决定使用哪些资源。服务器开发者应准备好处理这些不同的交互模式。
- 提示模板(Prompts):提示功能使服务器能够定义可重复使用的提示模板和流程,便于客户端向用户和 LLM 展示。提示设计为用户控制(user-controlled),即服务器将提示暴露给客户端,用户可以明确选择使用哪些提示,从而标准化和共享常见的 LLM 交互。
MCP 遵循客户端-服务器架构,其中一个宿主应用程序可以连接到多个服务器:
说明如下:
- MCP Host:大模型的宿主应用,比如 Cursor、Cline 等等,是处理一个或多个 MCP Server 的应用程序。
- MCP Client:MCP Host 内部专门用于与 MCP Server 建立和维持一对一连接的模块。它负责按照 MCP 协议的规范发送请求、接收响应和处理数据。简单来说,MCP Client 是 Host 内部处理 RPC 通信的“代理”,专注于与一个 MCP Server 进行标准化的数据、工具或 prompt 的交换。
- MCP Server:提供外部能力或数据的工具,比如访问本地文件、实时获取天气、浏览网页等等能力。
- 本地数据源:计算机上的文件、数据库和服务,MCP 服务器可以安全地访问这些内容。
- 远程服务:通过 API 可访问的外部系统,MCP 服务器可以连接到这些系统。
MCP 工具对接 LLM 的步骤:
- MCP 客户端向服务器请求工具列表
- MCP 客户端将工具定义转化成 Function Calling 格式
- MCP 客户端发送 Function Calling 定义给 LLM
- MCP 客户端接收 LLM 生成的 Function Calling
- MCP 客户端将 Function Calling 转化为工具调用
- MCP 客户端发送工具调用结果给 LLM
示例
- 假设用户询问“东京的天气如何?”,Agent 会构造如下请求,调用 MCP 接口
tools/call
来调用获取天气信息的工具:
{
"endpoint": "tools/call",
"payload": {
"tool_name": "get_current_weather",
"arguments": {
"location": "东京",
"unit": "摄氏度"
}
},
"metadata": {
"request_id": "req-12345",
"timestamp": "2023-12-01T12:34:56Z"
}
}
说明:
-
endpoint:指定要调用的 MCP 接口路径,这里是
tools/call
。 -
payload:包含具体要调用的工具名称和参数。
-
tool_name:工具名称,例如
"get_current_weather"
。 - arguments:工具调用参数,这里指定了查询地点和温度单位。
-
tool_name:工具名称,例如
- metadata:附带一些请求元信息,如请求 ID 和时间戳,方便追踪和调试。
- MCP 服务器接收到请求后,执行相应工具,并返回如下响应:
{
"status": "success",
"data": {
"tool_name": "get_current_weather",
"result": {
"location": "东京",
"temperature": "15°C",
"condition": "晴"
}
},
"metadata": {
"request_id": "req-12345",
"timestamp": "2023-12-01T12:34:57Z"
}
}
说明:
-
status:标识调用结果状态,通常为
"success"
或"error"
。 -
data:返回的数据部分,其中包含:
- tool_name:确认调用的工具名称。
- result:工具执行后的返回结果,如查询到的温度和天气状况。
- metadata:包含与请求对应的元数据,方便前后关联。
- MCP 工作流程
说明如下:
- 聊天客户端就是 MCP 客户端,可以想象成 Cursor,我们可以在 Cursor 中设置 MCP,添加 MCP Server(Name 和 URL)。当 Cursor 每次打开的时候,都会主动与 MCP 服务器建立连接,访问
tools/list
,让 MCP Server 提供都有哪些工具可以用。 - MCP 服务器告诉 Cursor,我有这么多工具可以用,每个工具的详情和入参都是什么样的,于是 Cursor 知道了。
- 当用户说“查询东京天气”,那么 Cursor 就会把用户的消息及刚刚从 MCP 服务器拿到的这些工具转成 Function Calling 发送给大模型;
- 大模型看到有这么多工具可以用,而用户要查询天气,那么我就执行一下查询天气工具 get_current_weather,location 是东京。
- Cursor 作为中介收到后,再告诉 MCP 服务器执行操作 get_current_weather(东京)。
- MCP 服务器执行完该操作后,告诉 Cursor 东京晴10°C。
- Cursor 知道后,它再告诉大模型说执行结果是这样子,你总结一下给用户吧。
- 大模型说“东京今天天气晴朗,温度10°C”,聊天客户端转发给用户,用户看到了。
就这么简单?对,就这么简单!
这个 MCP 示例展示了一个统一的接口调用方式,将工具调用、参数传递和结果返回都以标准化的 JSON 结构进行封装。相比传统的正则匹配或 Function Calling,MCP 提供了一种更统一、更易管理的工具调用规范,有助于在复杂系统中实现模块化、可扩展的工具集成。
小结
我们将大模型调用工具的关键技术、方式和说明,对比展示如下:
关键技术 | 方式 | 说明 |
---|---|---|
正则匹配 | 原始方式:野蛮生长 | 1. 起源:在 Function Calling 提出之前,开发者为了增强大模型的能力,自然而然的选择 2. 开发者定义:在提示词中限定大模型的输出格式,并对大模型输出的结果通过正则表达式来匹配关键字,从而知道工具名词及调用参数 3. 局限性:本身不可控,可能会在正则匹配解析时出现异常 4. 适用场景:简单 AI 应用、快速原型、直接与 LLM API交互 |
Function Calling | 原生方式:基础层 | 1. 起源:由 OpenAI 在 2023 年首先提出,现在几乎所有大模型都支持这个接口规范 2. 开发者定义:由 AI 应用的开发人员自己编写的函数 3. 本地集成:在 AI 应用中直接调用内部函数 4. API 结构:通过函数参数对象直接定义 5. 适用场景:简单 AI 应用、快速原型、直接与 LLM API交互 |
ChatGPT Plugins | 私有化扩展方式:OpenAI 专用 | 1. 起源:由 OpenAI 在 2023 年首先提出 2. 第三方提供:由外部开发者编写的服务 3. HTTP API:通过互联网调用外部服务 4. OpenAPI 规范:使用标准化的 API 描述格式 5. 适用场景:平台化生态系统,用户可选择安装 |
MCP | 标准化扩展方式:通用协议 | 1. 起源:由 Anthropic 在 2024 年 11 月推出 2. 更完整的功能:工具、资源和提示三位一体 3. 本质:json-rpc + Function Calling + 标准化协议(创新了资源和提示功能) 4. 通用性:不绑定特定的大模型 5. 双向通信:除过同步调用,支持事件和通知 6. 细粒度权限:明确的控制机制 7. 相对复杂:实现和理解成本较高 8. 适用场景:企业级应用、需要支持多种 AI 的产品、复杂交互 |
考虑到文章规模,MCP 的实战内容在后续文章中再专门阐述,希望本文对读者理解 MCP 概念有一定的帮助!
MCP资料
参考文献
- 视频号:白话讲解MCP,葬爱非主流小明
- 简书:《深入浅出 AI Agent》,_张晓龙_