外观
第 21 章 工具使用与函数调用(Tool Use)
让模型从“说”到“做”
21.1 语言模型只会说,不会做
语言模型的知识面和语言能力已经相当强。问它李白和杜甫的诗风有何不同,它能旁征博引地聊上半小时;让它写一封措辞得体的道歉邮件,它也能拿捏得恰到好处。
一位工程师刚搭好自己的聊天机器人,随口问了它一个再简单不过的问题:“嘿,帮我看看苹果公司现在的股价是多少?”
然后,屏幕上出现了那句很多人见过无数次、礼貌却又让人火大的回答:“对不起,我是一个语言模型,无法访问实时信息,所以我不能告诉你当前的股价。”
这个回答把问题暴露得很清楚。模型关于“股票”的知识很全,从 K 线形态到估值模型都能讲清楚,但它拿不到此刻的一条实时行情。它能写一篇关于价值投资的长文,却没法告诉用户苹果现在值多少钱。
这就是长久以来面对的困境,语言模型只有训练时学到的知识。它的知识都来自训练截止日期之前的、静态的互联网数据,知道“过去”,但不认识“现在”;能处理送进来的文本,却无法与外面的真实世界进行任何交互。它只能生成文本,没有任何执行动作的部件。
这个问题的本质,是模型缺少与外部世界连接的输入通道和执行手段。它无法调用一个行情 API,无法查询一个数据库,无法操作日程表,甚至无法帮忙打开电脑上的计算器。
这一章要讲的“工具使用”,或者说“函数调用”(Function Calling),正是为解决这个核心问题而生的。它的出现,让模型第一次有了读取实时信息和改动外部数据的通道。这不只是一个新功能,更是模型从“信息处理器”走向“智能体”(Agent)的关键一步。
所以,忘掉那些复杂的术语,这一章就干一件事,给模型接上执行能力,让它真正能办事。
21.2 函数调用,让模型只管决策
难道要教模型写代码,让它自己去请求 API 吗?
一开始,很多人的确是这么想的。他们尝试在提示词里塞进一大段关于如何调用 API 的说明,甚至给出 Python 代码示例,希望模型照着示例生成一段可以执行的代码。有时候这确实能行,但更多时候,结果会错得离谱。模型可能会搞错参数名,可能会生成语法错误的代码,甚至可能会“幻觉”出一个根本不存在的 API。这种方式太不稳定,偶尔能成功一次,但没人敢把它用到生产环境里。
真正的突破,来自一个思路的转变,不该期望模型自己写代码,而应该让它只负责决策。
具体来说,执行代码、请求网络、操作数据库这些实际操作,还是交给工程师自己写的、稳定可靠的程序来完成。模型要做的,只是理解用户意图之后,判断出“应该使用哪个工具”以及“使用这个工具需要哪些信息”,然后把这个决策“告诉”外部程序。
放在实际流程里看。假设需求方提了一句:“小王,帮我拉一下上个季度的销售数据,按区域分组。” 模型理解这句话之后,自己不去操作数据库,而是判断这件事该交给哪个工具函数、需要哪些信息,然后输出一张标准的工作单:“任务:查询销售数据;负责人:数据分析师;参数:时间范围=上季度,分组依据=区域。” 这张工作单交给真正的执行者(外部代码),执行完毕后,结果再返回给模型,让它整理成需求方想要的报告。
在这个流程里,“函数调用”就是模型生成那张“标准工作单”的过程。要做的只是提前把一份工具清单和工具说明书交给模型,清清楚楚地告诉它有哪些工具(函数)、每个工具能干什么、怎么用。
这本“说明书”,在 OpenAI、Anthropic、DeepSeek、通义千问这些主流厂商的 API 里,通常都以一个 JSON Schema 的格式来定义。别让“Schema”这个词吓到你,它本质上就是一种结构化的、极其严谨的函数描述。
先看一个最简单的例子,就是第 20 章里露过面的那个查询股票实时价格的工具。假设这边已经写好了一个 Python 函数:
python
import json
def get_stock_price(ticker: str):
"""查询指定股票的实时价格"""
# ... 这里是真正调用行情 API 的代码 ...
price_info = {
"ticker": ticker,
"price": 233.10,
}
return json.dumps(price_info)现在,怎么把这个工具“介绍”给模型呢?需要为它写一份“说明书”,大概长这样(这是简化的 JSON 结构):
json
{
"name": "get_stock_price",
"description": "查询指定股票的实时价格,仅支持实时行情",
"parameters": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "标准股票代码,比如:AAPL"
}
},
"required": ["ticker"]
}
}可以看到,这份说明书写得明明白白。name 是工具的名字,这里叫 get_stock_price,将来模型决定使用这个工具时,返回给程序的就是这个标识符。description 则是最关键的部分!那句“查询指定股票的实时价格,仅支持实时行情”,就是写给模型看的,模型靠它来理解这个工具是干嘛的。可以说,这里的文字就是一种“微型提示词”,写得越清楚,模型就越不容易用错。比如只写“查询股价”,那当用户问“上周的股价”时,模型就可能误用这个只能查“实时”价格的工具。第 20 章 20.5 给这个工具写的那份更完整的说明书,就是在这句基础上的加强版。
再看 parameters,这里定义了工具需要哪些参数才能工作。properties 里面列出了参数 ticker,它有自己的 type(string)和 description。参数的 description 同样极其重要,它告诉模型这个参数具体指什么,比如 "标准股票代码,比如:AAPL",这样的例子能极大地帮助模型理解该填什么。而 required 那一项,["ticker"] 这个数组告诉模型,ticker 这个参数是必填的,没有它,工具就没法工作。
把用户的提问(比如“帮我查一下 AAPL 现在的股价”)和这份工具“说明书”一起发给模型,模型不再直接生成一句话作答,而是分析用户的问题,去“说明书”里找有没有哪个工具的 description 能匹配上这个意图。
“AAPL...股价...”,模型一看,这不正好跟 get_stock_price 这个工具的描述对上了吗?接着分析,这个工具需要 ticker 参数,用户的提问里正好有“AAPL”,完美。
于是,模型不会直接作答,而是返回一个类似这样的结构化数据:
json
{
"tool_calls": [
{
"function": {
"name": "get_stock_price",
"arguments": "{\"ticker\": \"AAPL\"}"
}
}
]
}看到这个返回结果,程序代码就明白了:“哦,模型下指令了,让我去调用 get_stock_price 这个函数,并且把 ticker 参数设置为‘AAPL’。”
接下来,代码执行这个函数,拿到真正的行情数据(比如 {"ticker": "AAPL", "price": 233.10}),然后关键的一步来了,把函数的执行结果再塞回给模型,作为下一轮对话的上下文。
程序把结果递回去,相当于对模型说:“刚才你让我调用的 get_stock_price 函数,执行结果在这里。”
模型拿到这个真实的、来自外部世界的数据,终于可以摆脱“我无法访问实时信息”的尴尬了。它会用自然语言把这个结构化的数据“翻译”成一句人话,回复用户:“苹果公司(AAPL)当前的股价是 233.10 美元。”
至此,一个完整的“提问 -> 模型决策 -> 代码执行 -> 结果返回 -> 模型总结”的闭环就完成了。
整个过程是一个分工明确的协作流程,模型负责“决策”,外部代码负责“执行”。没有人强迫模型去做它不擅长的事情,而是让它专注于最核心的能力,也就是理解语言、进行推理和决策。这就是函数调用机制的精髓所在。顺带一提,2024 年 8 月起,OpenAI 的 Structured Outputs 还支持把工具参数标记为严格模式,模型生成的参数就必须贴合这份说明书,不再出现少字段、错类型的情况,这个机制在第 12 章讲 JSON 输出时已经展开过。
21.3 当输入不完美时
上面那个例子看起来很完美,对吧?用户的问题清晰,参数明确,一切都顺理成章。但真到写代码的时候就会发现,真实世界的用户给出的指令远比这随意,往往不像需求文档那样结构清晰。
场景一:信息不全,模型该怎么办?
最常见的情况就是信息不全。用户可能只是随口问了一句:“帮我查查股价。”
这时候,模型拿着这个问题去匹配 get_stock_price 工具,会发现描述是匹配的,但 required 的 ticker 参数,在用户的问题里根本找不到。
如果是一段写死的程序,可能就直接报错了:“缺少必要的参数:ticker”。但语言模型的优势就在于灵活性和“常识”,它知道要查股价,得先知道是哪家公司。
所以,当模型发现缺少必要参数时,它不会直接放弃,也不会随手编一个代码出来。它会选择最符合人类交流习惯的方式,追问。
它会生成一句回复,直接问用户:“好的,请问您想查询哪家公司的股价呢?”,或者更智能一点,“好的,为了帮您查询股价,我需要知道具体的公司或者股票代码。您能告诉我吗?”
这种“追问”能力不需要什么特殊设计,它就根植于模型的语言能力之中。任务型对话领域把这类问题叫槽位(Slot),也就是调用一个工具需要哪些参数,就有多少个待填的槽位。
从用户已经说出的话里抽取槽位值(比如从“查一下苹果明天的股价”里抽出公司、日期),学术上叫槽位填充(Slot Filling),它是 NLU 的经典任务;而模型发现“公司”这个槽位还空着、主动开口请用户补上,这个行为的准确叫法是槽位诱导(Slot Elicitation),工业界的对话平台(如 Amazon Lex)把这类追问提示就叫 elicitation prompt。两者配合,才凑齐一次工具调用所需的全部参数。
对开发者来说,这意味着系统的体验会好很多。不需要自己写一堆复杂的 if-else 逻辑去判断哪个参数缺失、再返回写死的追问话术,只要把工具的“说明书”(JSON Schema)写清楚,尤其把 required 字段定义好,模型自己就能处理大部分信息不全的情况。
场景二:意图模糊,模型如何澄清?
有时候,用户的意图本身就是模糊的。比如一个电商平台的智能客服,提供了一个叫 find_products(category, price_range) 的工具。
用户说:“我想买个新手机,预算大概三四千吧。”
这里面,“手机”可以对应 category,“三四千”可以对应 price_range。但问题在于,“三四千”是一个模糊的范围,是 3000-4000,还是包含 3999?如果 price_range 参数要求一个精确的 [min, max] 数组,模型可能就会拿不准该怎么填。
一个好的模型,可能会选择澄清一下:“好的,您是想找价格在3000元到4000元之间的手机吗?” 这样一次确认,就能避免后续的很多误解。
更复杂的情况是,用户一句话里可能包含了多个要查的对象,甚至多个意图。比如:“对比一下苹果和微软现在的股价。”
这就需要模型有能力识别出两个独立的查询,并可能依次调用两次 get_stock_price,一次 ticker 是 AAPL,一次是 MSFT。它可能先处理一个,然后告诉用户:“苹果现在的股价是...。我正在为您查询微软...”,也可能一次性规划好,返回一个包含两个工具调用的列表。这种一次返回多个调用的做法,就是后来各家 API 陆续支持的并行函数调用(parallel function calling)。
这一切都取决于设计工具时 description 写得是否足够清晰,能否让模型准确区分每个工具的“职责边界”。如果两个工具的描述过于相似,模型就很容易选错。
21.4 工具和模型出错时的防御性编程
到目前为止的讨论都默认一个前提,也就是工具函数永远正常工作,模型也总能做出合理的判断。但现实是,程序会出 bug,网络会中断,模型也会“犯傻”。一个真正“生产级”的系统,必须把这些异常情况考虑进来。
工具执行失败:把错误信息返回给模型
比如,用户把苹果公司的代码记岔了一位,要查询一只代码为 AAPLE 的股票,get_stock_price 函数在调用真正的行情 API 时,肯定会收到一个 404 错误。
这时候,代码该怎么办?直接崩溃,给用户返回一个原始的 Internal Server Error 吗?这显然不行。
正确的做法是,代码捕获这个异常,把错误信息整理成文本,再发给模型。这里有一条核心原则,模型负责决策,执行结果必须返回给它。
所以,当 get_stock_price("AAPLE") 失败后,代码不应该返回价格数据,而应该返回一个表示错误的字符串,比如:
"Error: The ticker 'AAPLE' could not be found. Please check the ticker symbol."
然后把这个错误信息作为工具调用的“结果”,再发给模型。
模型看到这个以 “Error:” 开头的返回结果就会明白:“哦,我刚才下的指令执行失败了,原因是股票代码不对。” 凭借语言能力,它会把这条技术性的错误信息“翻译”成一句对用户友好的话:
“抱歉,我没找到代码为‘AAPLE’的股票。您是不是想查苹果公司(AAPL)?我可以帮您查一下。”
这样一个简单的“错误信息回传”机制,就能处理好工具执行失败的情况。用户得到的不是一个令人困惑的程序错误,而是一个有帮助的、引导性的回复。
这个模式非常重要。无论是 API 调用失败、数据库连接超时,还是任何函数可能抛出的异常,都应该捕获下来,并以一种清晰的、信息量足够的方式返回给模型。这可以让模型参与到系统的“异常处理(Error Handling)”流程中来,大大提升系统的鲁棒性。甚至可以设计一套重试机制,比如告诉模型:“工具调用失败,原因是网络超时,你可以决定是否重试。”
模型的“幻觉”:调用不存在的函数
比工具执行失败更麻烦的,是模型的“幻觉”(Hallucination)。有时候,模型会调用一个根本没有提供给它的函数。
比如只给了它 get_stock_price 一个工具,用户却问:“苹果公司的市盈率是多少?”
有的模型可能会想当然地认为,既然能查股价,那八成也能查财报,于是返回一个这样的工具调用请求:
{"name": "get_financial_statement", "arguments": "{}"}
代码收到这个请求会发现,get_financial_statement 这个函数压根就没有定义过。
这就是典型的函数调用幻觉。它源于模型在训练数据中学到的某种“模式”,模型可能见过很多代码,知道查股价和查财报的功能经常一起出现,于是就默认这里也应该有。
治理这种幻觉,有几个关键策略。最直接的一道防线,是在 System Prompt 里加约束。可以在最开始的系统提示词里,给模型下一个明确的指令:“你只能使用我提供给你的工具。如果用户的请求无法通过现有工具满足,请直接告知用户你无法完成该任务,绝对不要虚构任何不存在的工具。” 这样一条明确约束,能有效减少模型乱编工具的情况。
另一道防线在代码层。代码在接收到模型返回的工具调用请求时,必须做一次校验,检查 name 字段是不是在定义好的工具列表里。如果不是,就直接拒绝执行,并且像处理其他错误一样,返回一个错误信息给模型:“Error: The tool get_financial_statement does not exist. Available tools are: [get_stock_price].” 这样一来,模型就知道自己“犯错”了,下一轮它可能会回复用户:“对不起,我无法直接查询市盈率,我只能帮您查询股价。”
还有一层容易漏掉,就是优化工具描述。有时候,幻觉是因为工具描述写得太宽泛。比如把 get_stock_price 的描述写成“获取股票数据”,当用户问“上个月的收盘价”时,模型就可能误用这个工具;写成“查询实时股价,不支持历史行情”,边界就清晰得多,误判也会减少。
记住,与模型协作,本质上是在与一个充满概率性的、模糊的系统打交道,不能百分之百地相信它,必须在代码里建立起一套“不信任”的防御机制。
21.5 工具变多后的复杂度管理
目前为止,讨论的都还是一两个工具的简单场景。但一个真正的智能体,可能会拥有一个庞大的工具箱,里面有几十甚至上百个工具,发邮件、订会议室、查股价、管理待办事项……
当工具数量增多,新的挑战就出现了,模型如何从一大堆工具里,准确地挑出那个最合适的?
工具一多,选择本身就成了难题。几十个工具里总有好几个功能相近,如果描述写得没有区分度,模型就很容易挑错。
这里的关键,还是交给模型的那本“工具说明书”。
最重要的,是清晰、无歧义的描述。每个工具的 description 必须准确地划定自己的功能范围。比如,不要用“处理用户数据”这种模糊的描述,而要用“根据用户ID查询用户的订单历史”。多花点时间在撰写这些描述上,回报是巨大的,可以把工具描述看作另一种形式的提示工程。命名的一致性也值得讲究,给工具起一个好名字,search_flights 就比 s_f 好得多,尽量使用 动词_名词 的格式,让函数名本身就具有很强的自解释性。
当工具多到一定程度时,就要讲究逻辑分组与路由了。一次性把所有工具都丢给模型,既浪费 token,也增加了模型的决策难度。更进一步的做法是,先用一个“分类器”模型或者一个简单的提示词,对用户的意图进行初步分类。比如,用户的请求是关于“旅行”的,那就只把 search_flights、book_hotel、get_weather 这几个相关的工具提供给模型。这一步做的是先按意图把工具分组,再让主模型只在相关的那一组里做选择。
还有一类挑战,来自多步工具调用。复杂的任务往往不是一个工具能搞定的。比如,“帮我预定下周三去北京出差的行程,订一个离故宫近的四星级酒店。” 这个任务需要分解成多个步骤,先调用 search_flights 查找合适的航班,用户确认航班后,调用 book_flight 预订机票,接着调用 search_hotels 查找故宫附近的四星级酒店,等用户确认酒店后,再调用 book_hotel 预订酒店。
要实现这样的多步流程,模型需要具备一定的“规划能力”。可以在提示词中引导它,比如使用 ReAct(Reasoning and Acting)这样的框架,让模型在每一步都先“推理”(Reason),写下自己的计划,再“行动”(Act),选择调用一个工具。这给了工程师一个查看模型推理过程的窗口,也让复杂的任务流程变得更加可控。
管理一个庞大的工具集,本身就是一项工程工作。它要求工程师用设计软件架构的思路来设计工具体系,考虑命名、职责、依赖关系和协作流程。
工具的接入方式,本身也在标准化。各家模型厂商各定一套工具接口时,同一个内部系统要为不同模型重复做接入。Anthropic 在 2024 年 11 月发布的模型上下文协议(Model Context Protocol,MCP),针对的就是这个问题。它把工具的发现、描述与调用定成了一套开放协议。按照这个协议,开发者把自己的数据源和内部能力实现成一个 MCP 服务器,任何支持该协议的模型应用都能直接连上,不必再为每家的 API 单独适配。
这个协议很快超出了单一厂商的范围。OpenAI 在 2025 年 3 月宣布采纳,其开发者文档把它称作扩展 AI 模型工具与知识的行业标准;此后 Anthropic 又把 MCP 捐给了 Linux 基金会旗下的 Agentic AI 基金会,转为中立治理(Anthropic 官方公告与 OpenAI 开发者文档)。截至 2026 年 8 月,主流模型厂商的开发平台与主流编程工具都已支持它。对提示工程师的意义很直接:工具说明书的写法依然重要,但“怎么把工具接进系统”这件事,正在从逐家定制走向一次封装、处处可用。
21.6 构建一个自动化财务分析 Agent
说了这么多理论,来点实际的。接下来试着构建一个能进行简单财务分析的 Agent,它需要回答像“对比一下苹果和微软的市盈率,哪个的估值可能更高?”这样的问题。
要完成这个任务,光靠模型训练时的旧知识肯定不行,股价和财报数据都是瞬息万变的,所以必须给它提供工具。
第一步是定义工具集,至少需要两个工具。一个是贯穿本章的 get_stock_price(ticker),获取一只股票的最新价格;另一个是 get_financial_statement(ticker, statement_type),获取一家公司的财务报表数据,比如利润表(income_statement),从中可以计算出每股收益(EPS)。这个查财报工具,正是 21.4 里模型幻觉出的那个,现在它正式进入了工具集。
接下来为这两个函数编写清晰的 JSON Schema“说明书”,写法照着 21.2 那份来,尤其要在描述里讲清楚 ticker 指的是股票代码(如 AAPL 代表苹果)。
接下来看第二步,Agent 的思考与行动。当用户提出问题:“对比一下苹果(AAPL)和微软(MSFT)的市盈率(P/E ratio)”时,Agent 的内部流程大致是这样的。
整个流程从推理(Reasoning)开始,模型首先会在内部思考:“要计算市盈率(P/E),我需要股价(Price)和每股收益(EPS)。我需要分别为苹果和微软获取这两个数据。股价可以通过 get_stock_price 工具拿到。每股收益需要从财报里找,可以用 get_financial_statement 工具。所以,我需要执行四次工具调用。”
思考完毕,就轮到行动(Acting)。模型会决定先获取苹果的数据,并行或者串行地生成两个工具调用请求,一个是 get_stock_price(ticker="AAPL"),另一个是 get_financial_statement(ticker="AAPL", statement_type="income_statement")。
然后是代码执行与信息反馈。后端代码接收到这两个请求,分别调用相应的 API,然后把结果返回给模型,比如 get_stock_price 返回 {"ticker": "AAPL", "price": 170.00},get_financial_statement 返回一大堆财报数据,其中包含了 {"eps": 6.15}。
模型拿到苹果的数据后,会记住这些信息,然后继续执行计划的下一步,为微软(MSFT)重复上述过程,这就是信息整合与下一步规划。当所有需要的数据都收集完毕,就到了最终计算与总结,模型在内部完成计算,苹果的 P/E = 170.00 / 6.15 ≈ 27.6,微软的 P/E = ... (计算过程同上)。最后,它会综合所有信息,用自然语言给出一个漂亮的总结:“根据最新数据,苹果(AAPL)的市盈率约为27.6倍,而微软(MSFT)的市盈率约为...。通常情况下,较低的市盈率可能意味着估值相对便宜,但这也需要结合公司的成长性等其他因素综合判断。”
通过这样一个“思考-行动-观察”的循环,Agent 就完成了一个相当复杂的、需要与外部世界进行多次数据交互的任务。它不再只能复述概念,而是能实际调用工具、完成任务。
本章总结 从对话到行动的范式转移
这一章讲的是大语言模型应用落地里最关键的一块能力。函数调用机制,打通了模型与现实世界之间的连接。
从一个最简单的“查股价”的例子出发,这一章拆解了函数调用的核心思想,让模型做决策,让代码做执行。工具通过一份结构化的“说明书”(JSON Schema)介绍给模型,模型则通过返回结构化的调用请求来下达指令。
真实世界还有种种不完美,用户的信息不全、工具会出错、模型自己也会产生幻觉,应对之道是追问(槽位诱导)、错误信息回传和防御性编程,靠它们构建一个更加鲁棒、对用户友好的系统。
最后,当工具箱变得庞大,可以通过清晰的描述和合理的架构来管理复杂性;财务分析 Agent 的案例,则完整展示了多步推理和工具协同工作的全过程。
掌握了函数调用,看待语言模型的应用思路会发生一次根本性的转变,不再局限于聊天机器人或写作助手,而是会开始盘算这样几件事。手头有哪些重复性的工作流,可以拆解成一系列工具,交给一个 Agent 去自动执行?自己的软件产品里,有哪些地方可以通过自然语言交互,让用户更方便地调用底层功能?能不能构建一个 Agent,让它连接公司内部的各种 API,把常见的查询和操作自动完成?
有了函数调用,语言模型就不再只能输出文本,而成了能执行操作的智能体。构建“智能体”(Agent)的工程,从这里真正开始。
参考资料
- Louvan & Magnini, Recent Neural Methods on Slot Filling and Intent Classification for Task-Oriented Dialogue(COLING 2020):槽位填充为任务型对话 NLU 的经典抽取任务,与意图分类并列。
- Amazon Lex V2 官方文档, Intent and slots 章节(docs.aws.amazon.com/lexv2):缺槽时向用户追问的提示称 elicitation prompt。
- OpenAI. Function calling 官方文档(工具参数以 JSON Schema 定义,支持并行函数调用). https://developers.openai.com/api/docs/guides/function-calling
- Anthropic. Define tools(工具的 input_schema 字段为 JSON Schema 对象). https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/define-tools
- DeepSeek. Tool Calls API 文档(服务端按 JSON Schema 校验函数定义). https://api-docs.deepseek.com/guides/tool_calls/
- 阿里云. 大模型服务平台百炼 OpenAI Chat 接口兼容(tools 的 parameters 字段需为合法 JSON Schema). https://www.alibabacloud.com/help/zh/model-studio/compatibility-of-openai-with-dashscope
- OpenAI. Introducing Structured Outputs in the API(2024 年 8 月 6 日发布,含 strict 严格模式). https://openai.com/index/introducing-structured-outputs-in-the-api/
- Yao, S. et al. (2023). ReAct: Synergizing Reasoning and Acting in Language Models. ICLR 2023, arXiv:2210.03629. https://arxiv.org/abs/2210.03629
- Anthropic (2024-11). Introducing the Model Context Protocol. https://www.anthropic.com/news/model-context-protocol
- TechCrunch (2025-03-26). OpenAI adopts rival Anthropic's standard for connecting AI models to data. https://techcrunch.com/2025/03/26/openai-adopts-rival-anthropics-standard-for-connecting-ai-models-to-data/
- Anthropic. Donating the Model Context Protocol and establishing of the Agentic AI Foundation(MCP 捐赠 Linux 基金会,转入中立治理). https://www.anthropic.com/news/donating-the-model-context-protocol-and-establishing-of-the-agentic-ai-foundation
- OpenAI. Model Context Protocol(开发者文档,称 MCP 正在成为扩展 AI 模型工具与知识的行业标准). https://platform.openai.com/docs/mcp