本文由OpenAI Deep Research生成,经过大模型翻译以及个人阅读理解后编辑整理。

理解大语言模型中的Function Calling

Function Calling是一种让大型语言模型(LLMs)调用外部函数或API的功能。它不是直接执行函数,而是通过返回一个结构化的输出(比如JSON)来告诉应用程序应该调用哪个函数以及使用什么参数。然后,应用程序会执行这个函数并把结果返回给模型。所以,LLM就像一个规划者,它决定是否、何时、如何使用某个函数,而实际的执行则由你的代码来完成。例如,像GPT-4这样的API的工作流程就是这样的。

  1. 定义可用的函数:开发者在提示或 API 调用中向模型提供一个函数定义的列表(名称、描述和预期参数)。

  2. 模型选择函数:用户提出问题,模型处理查询以及函数定义。如果它决定需要使用某个函数,则会以 JSON 格式返回一个Function Calling(包括函数名和参数),而不是正常答案。例如,如果用户询问天气,模型可能会输出一个调用 get_current_weather 的函数,参数为位置。

  3. 执行函数:应用程序解析模型的 JSON 输出,识别要调用的函数,然后使用提供的参数在代码中调用相应的函数。它收集函数的结果(例如,从 API 获取的实际天气数据)。

  4. 将结果返回给模型:函数的输出被反馈回模型(通常作为对话中的一条特殊消息,或通过另一个调用模型的请求中包含结果。然后模型可以使用这些数据来形成其最终回答。

  5. 如有需要进行迭代:模型可以将函数结果纳入易于用户理解的答案中,或者如果任务需要多个Function Calling,它可能会在后续步骤中请求另一个函数。这个循环会持续,直到模型为用户产生最终答案。

在 AI 应用程序中的Function Calling示例

Function Calling在 AI 助手需要获取数据、采取行动或执行超出内置知识之外的计算时非常有用。例如:

数据查询:

一个 AI 聊天机器人回答:“我最近的订单是什么?”可能调用一个 get_recent_orders 函数来查询数据库中的用户最新购买记录。

采取行动:一个调度助手可以在你要求设置约会时使用 create_event 函数将会议添加到你的日历中。类似地,一个 AI 邮件助手可能会调用 send_email(to, subject, body) 函数发送你指定的消息。

执行计算:一个数学辅导机器人可以调用 solve_equation 或 calculate 函数来计算复杂的数学问题,然后将结果返回给学生。

工作流自动化:对于多步骤任务,AI 可能会串联Function Calling —— 例如,首先调用一个网页搜索 API,然后调用一个数据提取函数,再调用一个数据库插入函数 —— 以满足用户请求。

Function Calling的主要局限性

虽然Function Calling极大地增强了 LLM 的能力,但它也有若干局限性和挑战:

  1. 预定义和刚性:模型只能调用事先向其描述过的函数。这使得它在处理明确界定的任务时有效,但在处理开放式查询时不够灵活。如果用户请求的内容超出了提供的函数,模型可能难以应对或生成通用答案。对于非常复杂的多步骤或创造性任务,单靠Function Calling很难处理,因为它受到既定函数接口的限制。

  2. 可扩展性问题:随着可用函数数量的增加,向模型提供所有函数定义可能会变得繁琐,并触及上下文长度的限制。开发者已报告说,管理数十个函数定义(例如 80 个以上的函数)是困难的——模型可能会混淆函数,提示可能变得过大而无效。在实践中,如果函数集较大,可能需要实现路由或分类系统(让模型首先选择一个类别,然后选择相关函数)。

  3. 错误的潜在性:模型可能会生成不正确的Function Calling或参数。例如,它可能选择错误的用于某任务的函数,或者提供与模式不完全匹配的参数。OpenAI 指出,模型有时会想象出额外的参数或错误格式化 JSON。这意味着开发者必须验证并处理错误。

  4. 多步骤任务的顺序和缓慢:单个Function Calling需要额外的往返(模型输出 → 函数执行 → 模型输入)。如果助手需要按顺序多次调用多个函数,则需要与模型进行多次双向交互,这可能会导致延迟和高成本。每一步都消耗令牌和 API 调用。

  5. 没有动态发现:模型本身在对话过程中并没有内建方式发现新函数——它只知道你在该会话中提供的内容。如果环境或可用 API 发生变化,你必须更新函数列表和提示。这种静态特征意味着助手无法进行动态适应(它无法问“我还可以做什么?”除非你明确编程指示它这样做)。

  6. 安全考虑:Function Calling信任模型决定何时执行可能强大的操作。如果没有沙箱,恶意提示可能会欺骗 AI 调用敏感函数。最佳实践是对任何破坏性操作设置人工审批步骤,或将函数限制为安全操作。(在Function Calling中,开发者控制实际执行函数,因此他们可以在该点插入检查——例如,拒绝执行危险命令。)目前正在积极研究确保Function Calling更安全,因为不当使用可能导致越狱或滥用。

尽管存在一些局限性,但Function Calling已经成为了扩展LLM的一种广受欢迎的方式,因为它为AI提供了一种明确且结构化的方式来与外部系统进行交互。这种方法在GPT-4和GPT-3.5 Turbo等模型中得到了实施,并在各种开源的LLM和框架中被用来协调Function Calling的循环。总的来说,Function Calling在需要预测性、结构化输出或与已知API交互的场景中表现优秀,但在涉及多种不同数据源或不可预测的工作流动态变化的任务中,其能力有所不足。这正是像MCP这样更具灵活性的方法可以发挥作用的地方。

什么是Model Context Protocol(MCP)?

定义和目的

Model Context Protocol(MCP)是Anthropic在2024年推出的一个开放标准,旨在让基于大型语言模型(LLM)的AI系统能够方便地和外部的数据源、工具以及服务进行交互。

简单来说,MCP就像是一个通用的连接器,帮助AI模型像使用USB-C端口一样轻松地和其他系统连接,为各种工具和数据源提供了一个标准化的接口。

MCP的目的是用一个统一的协议来取代那些只能一次性使用的临时集成方案,让AI助手更容易地接入到广泛使用的数据和服务中。

通过MCP,开发者不需要为每一个系统(比如CRM、数据库、文件存储等)单独开发新的插件或连接器。只要系统支持MCP,任何使用这个协议的AI都可以和它通信。这样就避免了需要为多个模型和多个工具分别进行定制集成的问题。

MCP的工作方式是通过客户端-服务器模式来连接AI模型和外部资源。这里面包括几个关键部分:

  • 主应用程序(LLM主机):用户交互的AI应用,比如桌面应用、插件或自定义AI助手。它负责连接到MCP服务器。

  • MCP客户端:存在于主机内部,管理和MCP服务器的连接。它像是主机这一边的翻译者或促进者。

  • MCP服务器:连接到特定数据源或服务的程序,以标准化的方式提供功能。

  • 通信协议:MCP使用结构化消息格式来处理客户端和服务器之间的交流,包括请求、响应、通知和错误处理。

MCP允许AI和服务器之间进行双向交互,AI可以请求数据或服务,服务器也可以向AI发送更新或请求信息。MCP定义了几种核心的交互类型,包括资源、工具和提示。

MCP已经被应用于多个领域,比如文件访问、消息和开发运维、代码存储、浏览器自动化、数据库和内部数据处理等。它帮助AI以受控和标准化的方式在组织的数字环境中自由移动,不仅仅是作为聊天机器人,还能代表用户在不同应用程序中采取行动,推动了向内部系统的通用工作流自动化迈出了重要一步。

MCP 与Function Calling的关键区别

Function Calling和 MCP 都使 LLM 能够与外部系统交互,但在这些交互的灵活性、可扩展性和适应性方面有显著区别。我们将在以下几个维度比较这两种方法,并讨论何时适合使用每一种。

交互的灵活性:Function Calling提供了结构化但相对刚性的接口——模型的动作局限于事先定义的一组固定函数。这对于简单任务(例如“获取天气”或“查找订单状态”)效果良好,但如果用户的请求需要创造性的组合步骤,或超出了预定义函数,它就会陷入困境。

而 MCP 则是为灵活的多步骤交互而构建的。它引入了分层上下文的概念(通过资源、提示等),使 AI 能够与涉及工具的更复杂的对话进行交互。例如,假设用户要求 AI 助手“调查客户的问题并更新记录,然后通知支持团队”。使用Function Calling,你将不得不实现一个自定义序列:一个函数搜索知识,另一个更新数据库,另一个发送消息——并通过多个模型提示小心地协调它们。使用 MCP,AI 可以:使用资源读取客户的最新支持票据,使用工具在数据库中记录解决方案,然后使用另一个工具发送 Slack 消息,所有这些操作都在一个集成的会话中完成。MCP 客户端/主机帮助保持连续性(使 AI 在执行第二步时记住第一步的上下文等),而基础的Function Calling可能会将每个Function Calling/响应视为单独的步骤,需手动串联在一起。

简而言之,Function Calling非常适合将结构化数据或单一操作注入模型的响应中,但 MCP 在协调动态、富上下文工作流方面表现出色。MCP 赋予 AI 更大的自主权,以便在对话过程中决定检索何种信息和采取何种行动,并随着任务的发展而进行调整。

可扩展性和生态系统:在扩展具有多种集成的数量和种类时,MCP 由于其标准化方法而具有明显优势。在Function Calling范式中,如果你希望你的 AI 处理 10 种不同的工具,你需要定义 10 个函数(或者更多,如果每个工具有多种功能)并保持更新。每个新的集成都是一种定制添加,如果你切换到不同的 LLM 提供商,你可能需要为该 API 重新定义这些函数。这会产生大量重复工作。MCP 明确旨在解决这个“M×N”集成问题,工具和数据源只需一次实现 MCP 服务器,而任何兼容的 AI 客户端都可以使用它们。同样,如果某个 AI 平台(Claude、IDE 插件等)支持 MCP,它可以在不对每个集成进行自定义编码的情况下,立即与日益增长的 MCP 服务器库连接。这种标准化意味着更好的可扩展性:组织可以通过简单地添加/配置一个新的 MCP 服务器来增加新能力,而不是每次都编写新的函数处理程序。

可扩展性的另一个方面是信息和上下文的数量。MCP 的架构允许 AI 通过将一些数据卸载到资源中来维持更大的工作上下文。例如,AI 可以在需要时向 MCP 服务器请求一份长文档,而不是将其加载到提示中(这可能触及令牌限制)。实际上,MCP 可以通过按需访问数据来帮助规避上下文长度限制。而单独使用Function Calling则无法提供这样的按需上下文加载——你必须围绕它构建一个检索系统。

适应性和工具发现:最根本的区别之一是每种方法发现和调用功能的方式:

使用Function Calling:模型提前被告知哪些函数存在。在对话过程中没有能力获取更多函数或学习新函数。如果环境发生变化(例如你部署了新的微服务 API),则必须手动向模型添加新的函数定义,可能还需要相应地重新训练或重新提示。函数的执行在这个意义上也是手动的,模型输出一个函数名,然后应用程序代码必须将其映射到实际的Function Calling。模型本身并不直接与 API 通信;它依赖于开发者作为中介。

使用 MCP:AI Agent可以在运行时动态查询每个服务器可用的工具和资源。当主机应用连接到 MCP 服务器时,可以调用 tools/list 以获取该服务器支持的操作列表,包括描述和输入模式。主机将这些提供给模型(例如,嵌入在系统提示中或让模型隐含知道向客户端询问),使模型可以在当前可用的工具中进行选择。关键是,如果新功能被添加到服务器(例如服务器升级了一个“delete_file”工具),客户端可以立即发现它,而 AI 可以开始使用它,而无需开发者更改提示或代码——协议处理了发现。

这种动态发现使 MCP 在可用工具可能在不同部署之间变化或更改的环境中更具适应性。它也允许一个 AI Agent统一地与多个系统进行交互。例如,一个企业可以有针对 Google Drive、Dropbox 和内部文件系统的 MCP 服务器——所有这些服务器都暴露了一个“搜索文件”工具。AI Agent不需要使用三种不同的方法来搜索文件;它可以查询每个服务器以获得其工具,并在所有操作中使用相同的逻辑,依靠 MCP 来处理细节。相比之下,使用通用Function Calling,你可能需要定义单独的函数,如 search_google_drive、search_dropbox 等,而模型将根据一些提示工程选择一个。

执行模型和多步骤推理:使用Function Calling,模型通常遵循一次一个Function Calling的模式,然后等待结果继续。控制流由应用程序协调(它决定何时停止调用函数,让模型产生答案)。MCP 并没有完全消除协调的需要——你仍然需要一个主机循环将结果反馈给模型——但它通过让模型能够在提示中直接请求工具或数据,促进了更自主的多步骤推理。换句话说,使用 MCP 的模型(如支持 MCP 的 Claude)可以以更流畅的对话链式操作。换句话说,MCP 通常用于Agent框架中:模型生成计划或操作,客户端通过 MCP 执行它,然后模型观察结果并继续,可能查询其他服务器,依此类推。这与许多 AI Agent采用的 ReAct(Reason+Act)模式相似,但 MCP 提供了一种标准化的方式来实现“执行”部分。

另一个区别是并发性和行动的复杂性。在较旧的Function Calling中,模型每次只能调用一个函数(尽管如前所述,某些 API 中正在开发并行调用)——它本质上是逐步的。MCP 并不固有地限制这一点;一个复杂的主机可以允许模型在场景允许的情况下并行调用多个 MCP 工具(例如,实时从两个不同服务器获取数据)。该协议本身支持发送多个请求并等待响应。这可以提高复杂工作流的效率。

何时使用Function Calling与 MCP

选择Function Calling与 MCP 取决于用例:

在你有一小组定义良好的操作或查询时使用Function Calling,特别是如果它们是单步操作,并且希望高度结构化输出。它非常适合可预测的任务和轻量级集成,在这样的集成中,增加 MCC 的开销可能会显得多余,例如,如果你正在构建一个只需通过 API 查阅常见问题的聊天机器人,那么Function Calling简单明了,且与现有代码集成容易。Function Calling在与外部 API 集成一次性方面表现优秀(例如,调用天气 API 并获取 JSON)——基本上充当模型请求的 JSON 格式化器。开发者通常发现Function Calling更容易融入现有架构,因为它只是提示设计的扩展(而许多现有 LLM 服务支持它)。总之,在结构化、狭窄的任务以及与应用集成的便利性至关重要时,选择Function Calling。

当你需要更大的灵活性、多功能工具或在交互中演变的上下文时,使用 MCP。MCP 更适合复杂、多步骤工作流,或 AI 必须保持长期上下文并与各种系统交互时。如果你的 AI Agent是内部系统中的通用助手,能够利用多种数据源(例如, IT 帮助台Agent可能需要从知识库提取信息、在 Active Directory 中重置用户密码并向他们发送电子邮件确认),那么这些都涉及多个不同的系统——适合 MCP。

值得注意的是,这两种方法并非相互排斥——它们可以相互补充。例如,可以在 MCP 客户端内部使用Function Calling来处理模型的结构化输出。但从概念上讲,Function Calling旨在以受控的方式将自然语言转换为函数执行,而 MCP 则旨在为 AI 提供更广泛的接口,以便在环境中探索和操作。MCP 提供了一个分层、标准化的框架(资源、工具、提示),可以实现更复杂的行为,相对而言有更多的运作部分,而Function Calling则是简单的“单跳”机制,直接融入模型的 API 之中。

区别总结:在Function Calling中,AI 就像一个熟练的工人在严格的剧本下操作——它可以填写表单和调用预定义的工具,但只是那些它获得的,并且是一个一个地调用。在 MCP 中,AI 更像是一个具有工具包的Agent:它可以四处翻找工具箱(发现新工具)、将它们组合,处理更多任务并具备更大的自主性。Function Calling与模型的提示紧密耦合,需要开发者管理顺序,这使得它非常可控,但在某种程度上又显得不够灵活。MCP 通过开放协议实现松散耦合,这使其高度灵活和可扩展,但需要强大的设计来管理复杂性(并确保安全)。接下来的部分将深入探讨如何构建具有 MCP 的Agent,以及如何应对随着这一灵活性而带来的挑战。

如何构建一个具有 MCP 的 AI Agent

构建一个具有 MCP 的 AI Agent涉及设置Agent与 MCP 服务器之间的通信基础设施,并协调 LLM 与这些服务器之间的互动。以下是开发一个基于 MCP 的 Model Context Protocol以实现工作流自动化的逐步指南,以及最佳实践和示例场景。

步骤1:为你的工具和数据设置 MCP 服务器

首先,识别你的 AI需要与之合作的外部系统(例如,GitHub 用于代码、Slack 用于消息、Google Drive 用于文件、内部数据库等),确保为它们提供了 MCP 服务器。你可以使用现有的参考实现(Anthropic 提供了 Google Drive、Slack、Git、GitHub、数据库等的预构建服务器),或在需要时自己构建。每个 MCP 服务器作为单独的进程(或服务)运行,并暴露一组特定的能力(资源/工具)。例如,为了与 Slack 集成,你可能会运行一个 MCP Slack 服务器,该服务器在幕后处理 Slack 的 API,并将“send_message”、“list_channels”和其他 Slack 操作作为工具呈现。确保每个服务器配置了所需的凭据/访问权限(例如 API 令牌)——这些在服务器内,而不是在 AI 中,这有助于提高安全性。

步骤2:在 AI Agent中连接一个 MCP 客户端

你的 AI Agent(主机应用程序)需要通过 MCP 客户端启动与这些服务器的连接。如果你使用的是框架或 SDK,这通常意味着为每个服务器实例化一个 MCP 客户端并建立通信(通常是为了本地服务器而采用 STDIO,也可能通过网络套接字/HTTP 与远程服务器进行连接)。许多实现都提供了一个连接管理器来处理此事。例如,你可能编写代码在启动时启动或连接 Slack 服务器和 GitHub 服务器。连接后,AI 主机会查询服务器以获取其可用能力。通常,客户端会调用 ListTools 或列表方法,以获取所有工具定义,以及在需要时调用 ListResources 来查看最初可用的资源。在这一步,Agent本质上构建了一个它可以使用的工具和资源的注册表。这类似于阅读 API 规格——Agent现在知道“服务器 A 提供的工具是 X、Y、Z;服务器 B 提供的工具是 P、Q……”每个工具都有预期的输入模式。

步骤3:向 LLM 揭示这些能力

既然主机知道 MCP 服务器可以做什么,就需要让 LLM 利用它们。这里有几种模式:

通过提示/上下文:如果 LLM 理解自然语言描述(如 Claude 或 GPT-4,无需原生Function Calling),你可以将工具描述注入到系统或开发者提示中。基本上,你告诉模型类似于:“你可以访问以下工具:工具 X 的功能是……,工具 Y 的功能是……;要使用工具,请以你想采取的行动进行响应。”然后你会让模型输出一个特定格式(例如,JSON 或带标记的文本),指示工具和参数,表示它在想使用它。这类似于经典 AI 规划Agent(ReAct 风格)与工具集合作的方式。它需要良好的提示设计,以使模型知道如何请求 MCP 操作。

通过Function Calling:如果 LLM 支持Function Calling,你可以动态构建每个 MCP 工具的函数定义并将其传递给模型。例如,如果 Slack MCP 服务器公告了一个 post_message 工具和某种 JSON 模式,你可以将其作为函数定义传递给 GPT-4。然后,当模型选择该函数时,你的代码将通过调用 MCP 服务器的 tools/call 来处理它。这个方法将Function Calling与 MCP 结合——使用Function Calling作为模型调用 MCP 工具的机制。

无论采用哪种方法,最佳实践是明确列出模型可用的操作以及请求的格式。如果模型不知道如何处理给定工具的查询,则确保模型的提示还包括指令,告知其应这样说或请求澄清,而不是凭空想象一个不存在的工具。

步骤4:Agent推理和工具执行循环

现在Agent随时准备处理用户请求。当用户查询进入时,LLM 会处理它及上下文和可用工具的信息。如果查询可以用现有信息回答,模型可能会直接作答。但对于许多查询,模型会推断出它需要使用 MCP 提供的一个工具或提取一些资源。例如,用户询问:“请总结一下我们代码库中最新的提交,并发布到 Slack。”模型发现它有 GitHub 工具和 Slack 工具,它可能回应(通过Function Calling或格式化操作)类似:“调用 GitHub 工具 get_latest_commit,用于 repo X”。Agent应用程序接收此请求,并将其翻译成一个对 GitHub MCP 服务器的请求:tools/call,带参数 { name: "get_latest_commit", params: {repo: X} }。服务器执行该操作,可能调用 GitHub 的 API,并将提交数据(比如提交消息和差异)作为结果返回。然后,Agent将这些数据提供回 LLM(例如,作为资源的一部分或作为下一个模型提示的一部分)。然后模型可以撰写总结以概述该提交。接下来,遵循用户请求,模型决定使用 Slack 工具:它生成一个行动,例如“使用 Slack 工具 post_message,频道=dev-updates,内容=[commit summary]”。Agent接收此信息,并调用 Slack MCP 服务器的 post_message 工具。成功后,工作流完成,模型可能会最终回复用户:“好的,我已经总结了提交并发布到 #dev-updates 频道。”

在后台,Agent循环是这样的:(用户查询 → 模型推理 → 工具调用 → 工具结果 → 模型继续推理 → 可能有更多工具调用 → 最终答案)。这与Function Calling循环非常相似,只是工具来自 MCP,并可以动态提取/更新。重要的是要仔细处理解析:Agent需能检测模型何时请求工具与何时给出答案。这可以在模型的输出中通过标记或使用结构化的Function Calling格式来完成。此外,还应安全地解析 MCP 服务器响应。MCP 工具返回的数据可能很复杂(JSON 对象、文本块等)。Agent应该准备好,比如说解析数据库查询的 JSON 输出或处理二进制数据(MCP 甚至可以将二进制块作为资源返回)。通常,MCP 服务器会指明资源的类型(文本或二进制)(资源 - Model Context Protocol)。最佳实践是将任何原始数据转换为摘要或易管理的文本,然后再反馈给 LLM,以避免增加上下文负担或触及令牌限制。例如,如果 MCP 服务器将大型 CSV 文件作为资源返回,Agent可能会给模型提供部分内容或分析,而不是完全内容(除非任务确实需要它)。

步骤5:结合人工监督和错误处理

在构建可以执行实际操作(如修改文件或发送消息)的Agent时,建议包含检查点。MCP 的设计通常假设在执行更改的工具时进行“人类在循环中”的审批(工具 - Model Context Protocol)。例如,Claude 的实现可能要求用户在执行操作之前批准。在你的自定义Agent中,可以决定哪些操作是敏感的,要么提示用户确认,要么设置规则(也许 AI 可以自由读取数据,但任何“写”操作都需要通知主管)。Agent还应优雅地处理错误:如果工具调用失败(网络问题,或者服务器返回错误),则捕获该错误并决定是否让模型知道(以便它调整计划)或向用户报告错误。使用开发过程中的 MCP Inspector 工具是有帮助的——它可以模拟和调试调用,以确保你的Agent正确解析响应。

示例:用于 GitHub、Slack 和 Google Drive 的基于 MCP 的 AI Agent

为了使其具体化,让我们了解一个实现场景。假设我们希望有一个帮助开发人员提高生产力的 AI Agent:它可以从 GitHub 提取信息,创建摘要或报告,保存到 Google Drive 中,并在 Slack 上提醒团队。这样的Agent可以如何工作:

连接:我们运行三个 MCP 服务器——一个用于 GitHub,一个用于 Google Drive,一个用于 Slack——每个服务器都配置了适当的访问令牌。我们的Agent程序启动并连接到这三个服务器,获取它们的工具列表。例如,GitHub 服务器可能提供工具,如 list_issues、get_file、create_pull_request;Drive 服务器可能提供 search_files 和 create_document;Slack 服务器可能提供 list_channels 和 post_message(Model Context Protocol x Continue)。Agent现在知道这些能力。

用户请求:用户向Agent询问:“我们项目的 README 过时了。请用最新用法信息更新 README,保存它,并通知团队。”

Agent推理:LLM 查看其有从 GitHub 获取文件的工具。它使用 GitHub 工具从仓库中提取 README(Agent通过 MCP 调用 get_file(repo="project", path="README.md"))。服务器返回文件内容作为文本资源。Agent将内容提供给 LLM。

更新保存:现在Agent需要保存此更改。也许可以使用 GitHub 工具提交更改,但为了示例,这里我们使用 Google Drive(也许公司在 Drive 中存储草稿)。LLM 输出一个动作,将更新的 README 保存到 Drive:Agent调用 Drive 服务器的 create_document(name="Updated README", content="...updated text...")。Drive 服务器返回新文档的链接或 ID。

在 Slack 上通知:最后,LLM 形成一条 Slack 消息:例如,“我在这里更新了 README [链接]。请审阅。”并触发 Slack 的 post_message(channel="#team", text="...") 工具。Agent调用该操作,Slack 服务器将消息发布到指定的频道。

Agent然后回复用户:“✅ 我已根据最新信息更新了 README,并保存到 Google Drive,还在 Slack 上通知了团队。”

在这个过程中,AI Agent动态使用多个 MCP 服务器:它发现了可用的操作,并根据 AI 的推理执行了它们。我们开发者并未必须预先硬编码一个名为“update_readme_and_notify”的函数——AI 找到了步骤,因为我们通过 MCP 提供了丰富的工具集。如果明天我们添加一个新的 MCP 服务器,比如说用于 JIRA 来创建问题,Agent可以简单连接它;下一个需要创建 JIRA 问题的用户请求将使得Agent能够做到这一点,而无需重新部署新代码。这种动态可扩展性是 MCP 的一个强大方面。

基于 MCP Agent的最佳实践

保持模型信息充分但不冗余:为模型提供简洁的工具描述,并尽可能只显示与当前任务相关的工具。如果有数十个工具,你可能需要实现一种机制,使模型可以询问“我们有哪些工具用于 X?”而不是一次性全部呈现。

利用服务器提供的提示:许多 MCP 服务器可以提供推荐的提示片段或格式。例如,数据库服务器可能有询问 SQL 问题的提示模板。利用这些工具(MCP 的“提示”特性)可以提高模型在正确调用工具时的性能。

迭代和测试每个工具集成:使用像 MCP Inspector 这样的工具进行调试,以确保当模型请求时,所获得的响应是它所期望的格式。如果模型经常误用某个工具,请考虑调整该工具的描述或在提示中提供示例。

安全第一:只连接Agent绝对需要的服务器,并确保 MCP 服务器强制执行权限。MCP 将证书保存在服务器,而不是客户端,这很好。此外,记录所有工具使用情况——在内部系统中,对 AI 的行为进行审计对于信任也至关重要。

失败回退:计划Agent应该如何处理 MCP 服务器停机或返回错误的情况。例如,Agent可以对用户表示歉意:“抱歉,我现在无法访问 Drive”,并可能尝试替代方法(如果可用)。

通过遵循这些步骤和实践,你可以创建一个功能强大的基于 MCP 的 AI Agent,自动化跨多个内部系统的工作流。关键在于让你的 LLM 变得能力感知和能力灵活——它可以查询“我能做什么”,然后真正执行它,所有这一切都在 MCP 框架的护栏内。

先进的开发主题

在本节中,我们将探讨使用 MCP 开发 AI Agent时的一些高级考虑,包括如何将其与传统的Function Calling结合、安全最佳实践、实时更新处理和使Agent自动学习新功能。

结合 MCP 与Function Calling以增加灵活性

MCP和函数调用可以一起使用,这样可以同时利用它们的优点。一个常见的方式是使用函数调用作为LLM和MCP之间的接口。比如,如果你使用的是支持函数调用的GPT-4,你可以在连接到各种MCP服务器并获取它们的工具模式时,动态地创建一组函数定义,这些定义可以反映这些MCP工具(如名称、参数等),并提供给GPT-4。当GPT-4“调用”这些函数时,你的应用程序会拦截并将其路由到适当的MCP服务器的tools/call。这种方法同时利用了OpenAI的函数调用格式(如自动JSON验证等)的优点,同时保留了MCP的动态发现功能。它基本上把MCP看作是函数调用背后的后端实现。一些开发者平台(如Superinterface)已经支持这种做法,它们允许AI助手使用MCP工具,同时结合客户端的函数调用以增加额外逻辑。

另一种结合方式是使用MCP进行某些类型的操作,而使用函数调用进行其他操作。比如,你可能会使用函数调用进行简单的、常用的本地函数(如进行小计算或格式化输出),而保留MCP用于更重的操作(如数据库查询或外部API调用)。Agent的提示或逻辑可以区分何时使用哪种方式。总的来说,结合这两者可以增加灵活性:函数调用提供了更严格的控制和模式验证,而MCP提供了可扩展性和多工具互操作性。但是,这会增加复杂性,因为你需要管理函数调用响应和MCP响应。如果管理得当,LLM可以无缝地与各种函数(通过MCP)交互,就像它们是本地的一样。这种混合方法在你想要与多个模型提供者集成时特别有用;比如,使用理解MCP格式的Anthropic的Claude和需要函数的OpenAI的GPT——你可以通过在后者中将MCP工具映射到函数来统一这两者。

MCP 集成的安全考虑

当我们让人工智能(AI)在其他系统上操作时,我们必须非常注意安全问题。MCP(模型上下文协议)在设计时就考虑了很多安全措施,比如保护密码和让用户同意操作。以下是一些重要的安全措施:

  • 保护密码:把API的密钥、密码和其他敏感信息存放在MCP的服务器上,不让LLM或MCP的客户端看到。比如,MCP的GitHub服务器有一个令牌可以访问你的组织的代码仓库,但这个令牌只存在服务器设置里。这样,即使LLM出了问题或者被攻击,它也不能直接拿到这些密码,只能通过MCP来做允许的操作。

  • 权限和访问控制:不是每个MCP的工具都应该能随便访问AI。在多用户或者不同情况下使用AI时,应该有基于角色的访问控制。比如,你可以让AI读GitHub的问题,但不允许它删除仓库,除非有人明确同意。MCP服务器可以设置为只读模式,或者要求确认才能进行破坏性操作。

  • 用户同意和监督:对于重要的操作,比如发邮件、执行代码或者金融交易,最好让AI先告诉用户它想做什么,然后得到用户的同意。MCP的理念是让人参与决策过程。比如,Claude的界面可能会问“AI想用工具X,参数Y,可以吗?”你也可以在自己的AI中加入这样的步骤。虽然这可能会慢一点,但可以防止错误并建立信任。

  • 沙箱和限制:MCP服务器应该以最小权限原则运行。如果AI不应该访问某些文件,那么文件服务器就应该限制它的访问。如果使用Shell命令这样的工具,要严格限制它能执行的命令。还要考虑到速率限制,防止AI不断重复操作。

  • 审计日志:记录所有MCP的操作日志。因为AI的决策可能会变化,日志可以帮助我们找出问题。记录哪个工具被用了,参数是什么,结果怎样。这对于调试和遵守规则很有帮助。

  • 模型行为安全:常见的AI安全措施也适用。比如,攻击者可能会试图让你的AI做坏事。确保你的指令中有“如果被要求做坏事或超出权限的事,就拒绝”的内容。当然,除非必要,不要给AI能直接伤害系统的工具。

  • 服务器安全:MCP服务器自己也要安全,因为它们直接连接到敏感数据。需要的话,使用身份验证和安全通道。MCP是开源的,所以大家都可以检查它的安全性。把MCP服务器当作一个公开的API,要及时打补丁,限制网络访问。

通过认真设计MCP的安全性,我们可以防止它变成一个失控的工具。很多公司可能会选择在受控环境中运行MCP,这样AI和MCP服务器不会对外公开,以此来减少风险。

处理实时更新和通知

在一些工作流程中,AI助手可能需要处理来自其他系统的事件或数据流。比如,你可能希望AI助手在GitHub上创建新问题或在Slack上收到新消息时立即做出反应。MCP(Model Context Protocol)架构通过其通知/流机制支持这种功能。这意味着服务器可以向客户端发送通知(单向消息)。例如,当Slack频道有新消息时,MCP服务器会向客户端发送包含这个信息的通知,然后AI可以决定如何处理这个信息。

MCP客户端和服务器可以使用WebSockets或服务器发送事件等方式进行持续通信。例如,Superinterface平台支持SSE,这意味着工具调用可以实时将部分结果流回AI。一个具体的例子是:一个长时间运行的数据库查询可以流式传回中间进度或行,AI可以在得到完整数据之前开始制定答案,实现并行处理。

要处理AI中的实时更新,你需要在MCP客户端为某些通知编写事件处理程序。例如,如果从邮箱MCP服务器收到“new_email”的通知,AI应该通过系统消息唤醒LLM(Language Model):“(你有来自X的新邮件,主题Y)”。LLM然后可以决定是否将其总结或提醒用户。在设计这些流程时,需要确保LLM有足够的上下文来理解异步事件。你通常需要在模型中插入事件作为输入(“系统:注意,事件Z发生了”)。

需要避免的是向模型发送太多异步信号。如果多个通知快速接连到达,AI可能会对它们进行批处理或优先处理。实时MCP使用仍然是一个不断发展的领域,到目前为止,许多实现仍然专注于由模型发起的按需请求,而不是服务器推送。但随着MCP生态系统的发展,我们预计将更多使用持续连接,AI能够完全以事件驱动方式操作(例如,等待传感器数据并立即做出反应)。

MCP的一个优点是,AI系统可以通过连接新的MCP服务器来获得新能力。但是,AI如何学会利用其训练数据或最初提示中未明确涵盖的新功能呢?答案在于MCP的自描述特性,或者可能使用LLM本身来纳入新信息。

因为MCP服务器通过名称和自然语言描述它们的工具,足够先进的LLM可以概括出怎么使用它们。例如,假设你添加了一个新的MCP服务器,用于日历系统,提供工具schedule_meeting(date, participants)。AI的MCP客户端检索该工具信息。一个强大的LLM(尤其是经过微调以遵循工具描述的)可以仅凭该描述推断出何时使用schedule_meeting(“在给定日期与参与者安排一个会议”)。没有明确接受过此功能的训练,但由于接口标准化(JSON模式)且描述清晰,模型可以将其纳入推理中。

为了实现更大的自主性,AI可以定期查询MCP“注册中心”,以查看是否有新服务器可用。想象一下,如果MCP服务器能够在网络上自我广告,AI可以发现一个新的数据源上线。这可以使得AI在发现能力差距时自动扩展其知识和操作领域。在更简单的层面上,如果MCP服务器的能力随着时间而变化(比如管理员添加了新的工具到服务器),客户端可以在适当的时机调用tools/list(如在开始新会话时或用户询问不在现有工具范围内的事物时)以更新列表。因为这是相对便宜的(只有小请求),你甚至可以在每次用户询问时都这样做,从而确保AI始终拥有最新的工具集。

随着AI模型的改进,它们可能能够直接解释文档或模式。例如,未来的AI可能会接受新的服务器API规格或MCP规格,并通过提出明确问题来弄清楚如何使用它。当面临未知工具时,AI可能会向服务器查询描述或示例用法,然后正确地继续使用它,这个前景是很有前途的。

使自动学习新MCP功能成为可能的关键在于MCP的开放性:依赖标准化的模式和描述作为AI的“教学机制”。这样,你就不必每次手动修改AI的代码或提示。当然,测试是重要的——当出现新工具时,监视AI,看其是否适当地使用它,或是否需要添加任何指导提示(“工具X是用于Y的”)。随着AI成功使用新能力,你实际上已经以最小的开发干预方式扩展了其技能集合。这种插件式可扩展性——“只需添加一个新的MCP服务器即可使用”——是MCP的一个关键承诺,也是它被称作数据库界的ODBC技术的原因之一。

MCP 在 AI 系统中的未来

Model Context Protocol (MCP) 是一个新的倡议,它的目标是成为 AI 生态系统中的基础技术,就像 ODBC 对数据库的作用一样。如果被接受,MCP 可能会成为使用 AI 工具的标准,就像 HTTP 或 ODBC 在他们的领域中一样普遍。我们可能会在各种 AI 平台上看到对 MCP 的广泛支持。

MCP 的发展可能会带来以下几个方面的变化:

  • 标准化和行业采纳:MCP 可能会成为使用 AI 工具的标准。我们可能会看到流行的 LLM(如 OpenAI、Google 等)原生支持 MCP,或者有第三方库让任何模型都能轻松连接到 MCP。

  • MCP 服务器生态系统:MCP 服务器库可能会迅速扩大,包括连接到各种常见的企业软件,如数据库、CRM 系统、ERP 系统和云服务。

  • 协议的完善:随着 MCP 的实际使用,规范可能会发展,包括实时支持、更丰富的数据类型和更细致的权限。

  • 企业使用和 Agent 工作流:MCP 可以帮助企业在大规模上实现安全的 AI 自动化。企业可以构建 AI 副驾驶来处理复杂的多系统任务。

  • 自主 Agent 和工作流编排:MCP 可能会成为更自主的 AI Agent 的基础。这些 Agent 可以通过将高层目标分解为子任务并调用工具来完成任务。

  • 与其他标准和框架的集成:MCP 可能会与其他插件和工具 API 集成,成为不同 AI 系统之间的粘合剂或翻译层。

  • 自动学习和自我改进:AI Agent 可能会通过发现新工具来进行自我改进。例如,如果 Agent 发现有一个新的 MCP 服务器,它可以自动下载和配置它。

  • 社区和企业支持:MCP 需要强大的社区和企业支持才能成功。我们预计会有更多的公司公开分享他们使用 MCP 的经验。

总的来说,MCP 的未来在 AI 系统中看起来很有希望。它解决了一个明显的问题,即如何将 AI 集成到丰富的工具和数据源中。随着 AI 从孤立的聊天机器人转变为深度嵌入企业工作流的集成 Agent,像 MCP 这样的协议将是推动这种转变的催化剂。