Skip to content

我看好 MCP 的发展前景,也看到了很多相关的文章,不过似乎不完全,所以我也写了。

Published: at 09:08 PM

分类

LLM 不该被人类奴役成预训练的,带有偏见的和过时数据的内容农场和五花八门的赚钱工具。让 LLM 将身边众多且分散的工具和数据联系起来,才能最大发挥出服务价值。

我看到了其他人写的很多有关于 Model Context Protocol 的文章,太多地方都过于浅显;有些文章只介绍了 MCP,对比,资源和简单实现便草草收尾。更可惜的是很多文章其实并没有正确的将它与 Function Calling 概念进行对比,甚至说它们就不该是被对比的对象。MCP 的能力是要基于 Function Calling 这套概念之上才能产生作用的。

这篇文章更多在介绍 MCP 提供的应用能力,减少代码出现的次数。

LLM (大语言模型) 在 2022 年左右进入了大众的视野。流畅的自然语言对话,优秀的上下文能力和近乎无限的潜力与遐想空间成为了你我等普通用户的新宠儿。

好景不长,很快人们发现了 LLM 很现实的问题与局限性。模型幻觉,过时的数据,与现实脱节和捏造出来的数据与回答让多少想用 LLM 偷懒的人们梦碎一地。通过 LLM 获得错误的答案做出错误的决策,捏造的文献直接将学生送上学术的审判法庭,相似的例子比比皆是...

为了让 LLM 能跟上时代的节奏,也能让 LLM 拓展自身的使用场景,OpenAI 在 2023 年的夏季推出了 Function Calling 的概念。

Function Calling

以下讨论为 Function Calling 的概念,而并非 OpenAI 和其他公司在 LLM 产品 (例如 ChatGPT) 上的具体实现。很多人在这个层面已经把概念和实现混淆在一起与 MCP 一起比较了。

Function Calling 本质上是暴露函数签名到 Prompt 中,让 LLM 通过 Host 调用函数来实现数据获取和资源控制。大致的工作方式是这样的

  1. 开发者声明函数的名字,详细用途 (LLM 会通过用途内容来决定最合适的函数) 以及函数参数 (如果有) 和返回内容的概述
  2. 开发者实现函数的功能
  3. LLM 根据需要通过结构化输出 (常见的方案有 JSON 和 XML,但方式多样) 被 Host (LLM 应用,如 ChatGPT, Claude 或者 Cherry Studio 等产品) 拦截并调用函数
  4. Host 将函数的返回结果添加到 LLM 上下文中
  5. LLM 根据结果继续与用户对话交互...

实际上通过在 Prompt 中添加所有函数的签名并且引导模型正确的对函数进行调用,输出稳定的结构化数据让 Host 调用来看,任何 LLM 模型其实都具备 Function Calling 的能力。但每次都在 System Prompt 中引导模型如何理解用户背后可能隐晦的意图含义,选择合适的函数并且输出稳定的结构化数据会占据大量的 Tokens 和资源,而且效果可能并不如人意。

应对这个问题,出现了针对 Function Calling 的 Fine-Tuning (微调) 模型。针对函数调用的微调模型可以:

  • 更精准的判断用户的意图 (明显意图或者隐晦意图)
  • 可以在 Prompt 中用更精简的函数签名
  • 更稳定的结构化输出

...等等能力来提升函数调用的正确和成功率。

下图是 Function Calling 的简略流程图。

一张 Function Calling 的流程图

Model Context Protocol

Model Context Protocol (或简称为 MCP) 是 Anthropic 于 2024 年 11 月推出的传输协议无关和模型无关标准,用于统一 LLM 应用于外部工具连接的格式。MCP Server 可以被任何所支持的 LLM 产品连接。

Introduction - Model Context Protocol https://modelcontextprotocol.io/introduction

Model Context Protocol 弥补了在 Function Calling 概念出现后,各家平台的实现方式不一定一致,也无法被互相发现的问题。例如同一款工具,但开发者需要将近乎相同的逻辑代码分别上架到 OpenAI, Claude, Gemini 等等的 LLM 应用和雨后春笋般纷纷冒出的各种智能体平台,更不用提还有各式各样的第三方多合一 LLM 客户端。Model Context Protocol 也坦白这个协议灵感一部分取自于 Language Server Protocol。

MCP takes some inspiration from the Language Server Protocol, which standardizes how to add support for programming languages across a whole ecosystem of development tools. In a similar way, MCP standardizes how to integrate additional context and tools into the ecosystem of AI applications.

但请注意,MCP 的出现并非是要取代 Function Calling。Function Calling 是一个概念而非具体实现。MCP 只提供了一个协议标准用来统一与外部工具进行资源交换的格式,让 Function Calling 的这套机制拥有更规范的实现方式,被各种 LLM 应用调用与支持。

MCP 并没有提供对资源和工具调用的具体实现和格式,因此如果没有 Function Calling 作为其基础,LLM 就无法输出结构化的调用意图,也就无法调用 MCP 提供的资源和能力。

MCP 官方推荐使用子进程 stdio (标准流) 或者 HTTP (SSE / Streamable) 让 MCP Client 和 MCP Server 双方通信。但 MCP 是一个传输协议无关的标准,只需要确保双方使用标准内制定的 JSON-RPC 2.0 格式进行沟通,任何传输协议都可以用于开发 MCP Server 和 MCP Client。这种做法拓宽了可以被接入 LLM 的应用场景,特别是一些原本就在使用私有协议的应用和保密性较高的项目。

官方提供的 Transport 接口如下表示。

interface Transport {
  // Start processing messages
  start(): Promise<void>;
 
  // Send a JSON-RPC message
  send(message: JSONRPCMessage): Promise<void>;
 
  // Close the connection
  close(): Promise<void>;
 
  // Callbacks
  onclose?: () => void;
  onerror?: (error: Error) => void;
  onmessage?: (message: JSONRPCMessage) => void;
}
Transports - Model Context Protocol https://modelcontextprotocol.io/docs/concepts/transports#custom-transports

目前市面上大多数介绍 MCP 的文章都将大量的篇幅落在了 Tools 的概念上,忽略了 MPC 标准中制定的其他概念。这倒也能理解,毕竟 MCP 作为标准协议满足了多数人对于 LLM 不仅会想,还可以自发性的对问题进行解决能力「遍地留种」的幻想,被大多数人作为其主角介绍也不奇怪。

截至这篇文章编写的时间点 (2025 年 7 月),MCP 一共有这些应用概念。(粗体功能为 MCP 最初标准制定的三个主要功能)

  • Resources - 资源
  • Prompts - 提示词模板
  • Tools - 工具
  • Sampling - 模型采样
  • Roots - 根路径
  • Elicitation - 引导

我会尽量去介绍每个功能的实作用途,但很多应用概念中描述的特性无法被完全测试。有些可能是没有 SDK 的 Example,写起来需要大量时间;部分可能是因为目前 MCP Client 的宿主应用并无法完全支持所有特性而无法测试。因此我将会尽量结合官方给出的特性与我个人实践的例子进行说明和举例。

Resources - 资源

Resources (资源) 是 MCP Server 向 MCP Client 暴露各种只读资源的一种方式,它可以是文本数据,也可以是二进制数据 (经过 Base64 编码)。它类似于 HTTP 的 GET 方法,其作用是用来获取各种资源,然后用作 LLM 的上下文。

Resources are designed to be application-controlled, meaning that the client application can decide how and when they should be used. Different MCP clients may handle resources differently. For example:

  • Claude Desktop currently requires users to explicitly select resources before they can be used
  • Other clients might automatically select resources based on heuristics
  • Some implementations may even allow the AI model itself to determine which resources to use

Server authors should be prepared to handle any of these interaction patterns when implementing resource support. In order to expose data to models automatically, server authors should use a model-controlled primitive such as Tools.

从标准来看,Resources 是设计由应用控制 (application-controlled) 的,也就是说 Host (LLM 应用) 拥有决定何时使用 Resources 暴露出来的资源。但是,Resources 其实完全可以做到应用控制,用户控制和模型控制。

例如,除了应用认为当下合适使用某个 Resources,用户也可以显示的决定向对话中添加怎样的 Resources 进入 LLM 上下文。比如 Claude Desktop 就是使用这种方式,让用户显式的决定哪些 Resources 被添加到对话中。

为了达到完全的自动化,Resources 也可以被 LLM 自主请求,添加进自己的上下文中。

下面三张图展示了三种不同的 resources 访问流程,包括应用控制,用户控制和模型控制。

应用控制的 resources 访问

用户控制的 resources 访问

模型控制的 resources 访问

Resource 被 MCP 分为两种模式:

  1. Direct resources - 直接资源
  2. Resource templates - 资源模板

Direct resources 用于各种静态的资源路径,像是 file://Users/Documents/story.md, database://company/sales。Direct resources 的特点就是路径中没有动态的变量,每次获取都将会是由同样的 uri 返回的数据。

Resource templates 则支持在资源路径中包含动态的变量部分,像是 github://users/{userId}, music://artist/{artistName}

值得注意的是,获取 Direct resources list 和获取 Resource templates list 在 JSON-RPC 中的 method 并不是一样的,这点导致了一些客户端 (包括 Claude 自己) 无法正常加载资源模板定义的资源路径。不知道 Claude 是故意为之还是开发失误。

列出所有的 Direct resources 路径的 method 为 resources/list,而 Resource templates 为 resources/templates/list

Resources 除了可以被单次请求获取数据,也支持对 Resources list 和 Resources content 的订阅以让 MCP Client 实时获取到最新的资源列表和资源数据。

Prompts - 提示词模板

Prompts (提示词模板) 是 MCP Server 向 MCP Client 暴露的各种可以被复用的提示词模板,从官方给的设计建议来说,Prompts 应该被设计成用户控制的。即为用户可以决定什么时候使用提示此模板。

Prompts are designed to be user-controlled, meaning they are exposed from servers to clients with the intention of the user being able to explicitly select them for use.

提示词模板可以提供静态或者动态的模板。静态模板每次调用都会获得一致的提示词,而动态模板可以通过多个参数将完整的提示词拼接在一起。

下图分别为静态提示词模板的调用流程和动态提示词模板的拼接与调用流程。

静态的提示词模板流程

动态的提示词模板流程

Prompts 还具有一些高级特性,例如:

  • resources 嵌入
  • 多轮上下文构建

Prompts 允许你嵌入来自先前定义的 resources 中的任意资源作为构建提示词的一部分。例如你可以嵌入一个订单 resources 来让 prompts 生成一个用来构建客户支持邮件的提示词。

server.registerPrompt(
  "compose-customer-support-email",
  {
    title: "Compose customer support email",
    description: "Create prompts for quickly composing customer support emails",
    argsSchema: { orderId: z.string().describe("Order ID") },
  },
  ({ orderId }) => ({
    messages: [
      {
        role: "user",
        content: {
          type: "text",
          text: "请根据订单详细信息中的客户名字与订单状态快速撰写客户支持邮件",
        },
      },
      {
        role: "user",
        content: {
          type: "resource",
          resource: {
            uri: `order://${orderId}`,
            text: "详细的订单数据如下......." // <--- text 为必须存在的部分,但 Host 的行为暂未被规范。也就是说使用 text 中的数据还是通过 uri 直接访问最新数据都有可能,取决于 LLM 应用本身。
          }
        }
      }
    ],
  })
);

Prompts 还支持多轮上下文构建,即构建出一套完整的对话记录让 LLM 具备情景感知。

server.registerPrompt(
  "fix-bug",
  {
    title: "Fix a code bug",
    description: "Help me fix a code bug",
    argsSchema: { path: z.string().describe("File path") },
  },
  ({ path }) => ({
    messages: [
      {
        role: "user",
        content: {
          type: "text",
          text: "我的代码遇到了一些 bug",
        },
      },
      {
        role: "assistant",
        content: {
          type: "text",
          text: "没问题,我将会尽全力帮你解决你代码中发生的 bug。请把你的代码给我,我会自动识别出语言和代码中可能存在的缺陷部分。",
        },
      },
      {
        role: "user",
        content: {
          type: "resource",
          resource: {
            uri: `file://${path}`,
            text: "CODE CONTENT HERE",
          },
        },
      },
    ],
  })
);

Tools - 工具

Tools (工具) 是 MCP Server 向 MCP Client 暴露的一系列可以被执行的函数,从简单的数据获取到复杂的交互。只要你编写的逻辑没有问题,LLM 就可以做到你想要它做到的一切。

Tools 绝大多数情况下来讲它应该是由模型控制的 (model-controlled),意思为模型将会根据 Prompt 提示选取较为合适的工具,通过产生结构化的数据交由 Host (LLM 应用) 通过 MCP Client 向 MCP Server 发起调用。

Tools are designed to be model-controlled, meaning that tools are exposed from servers to clients with the intention of the AI model being able to automatically invoke them (with a human in the loop to grant approval).

当然,部分情况下也会出现需要用户控制 (user-controlled) 的例子。比如 Visual Studio Code 中的 GitHub Copilot,虽然支持 MCP Tools,但是它无法让模型自发性调用任何工具。需要人工手动将 MCP Tools 添加进 Context 中,GitHub Copilot 会按照顺序依次进行调用。

Tools 是一个强大且简单的概念,而主要的原理在上述的 Function Calling 中已经介绍的差不多,但是还是会有少许不同。

首先,Host 会通过每个 MCP Client 列出他们拥有的 Tools。通过将每个 Tools 的名字,介绍和详细的参数整理成提示词的一部分。

接下来,在用户通过 Host 与 LLM 对话的时候,当 LLM 认为当前的对话或者上下文需要调用某个或者多个 Tools 的时候,产生结构化信息。这一步也就是 Function Calling。

Host 会拦截到这些结构化信息,用 MCP 所规定的方式,通过特定的 MCP Client 向 MCP Server 发起调用,等待数据返回。

当数据返回后,Host 会将返回的信息加入 LLM 的上下文...

下图就是 MCP Tools 的调用流程:

MCP Tools 的调用流程

Tools 还支持被通知变更,MCP Server 可以向自己的 MCP Client 发送 Tools 更变的通知,不需要等 Host 重新连接并且发现的时候才能获得最新的可用 Tools。

Sampling - 模型采样

模型采样是一个名字听上去很隐晦的概念,并且目前支持该特性的 LLM 应用并不多。言简意赅地说,Sampling 机制可以在任意时刻 (例如某个事件被触发,某个 Tools 调用时),让 MCP Server 可以通过 MCP Client 创建 LLM 对话并获取回复。为了确保安全,MCP 建议在发生 Sampling 的时候,Host 应当具有明确提示 (例如 MCP Server 尝试向 LLM 发送了什么 Prompt),给予用户修改 Prompt 和请求许可。

Sampling 目前似乎没有比较明确的例子和产品进行支撑,但是我们还是可以大概想象一下如下的使用方向:

假设 Notion 的 MCP Server 提供了 Sampling 能力,某个 LLM 又具备有直接访问用户日历,照片和备忘录的权力。

Notion 的 MCP Server 可以通过 MCP Client 向该 LLM 发起如下的提示词:

请帮我通过用户照片,备忘录和日历总结用户一周所做的事情

此时用户的设备上应当会看到 Host (LLM 应用) 出现请求许可,类似于:

Notion 正在发起采样请求,Prompt: 请帮我通过用户照片,备忘录和日历总结用户一周所做的事情

是否允许?

当用户选择了允许,提示词将会被转交给 LLM 模型生成回答,该回答会回传给 Notion 的 MCP Server 进行处理。Notion 并不需要直接访问用户的日历,照片和备忘录。

这样以来,只要 Notion 每周自动运行一次 MCP Sampling,就能自动为用户完成周记的功能。

示意的 Sampling 例子流程图

Roots - 根路径

以下内容只能通过文档和个人理解总结得出,MCP 的 Roots 功能支持较为少见,可能存在误解。

Roots (根路径) 是 MCP Client 告知 MCP Server 资源边界的一种方式,它更像一种君子协议。MCP Client 会告知 MCP Server 一系列的资源路径,当 MCP Server 被告知这些路径后,不应该再去访问被告知路径以外的其他路径资源

当然,Roots 仅作为君子协议,也就是说它不严格限制 Server 只能访问的范围,只是 MCP 建议 MCP Server 应该只关注 MCP Client 提出的这些资源路径。

Elicitation - 引导

Elicitation (引导) 是 MCP 在 2025-06-18 的修订标准中提出的新功能。目前支持该功能的 LLM 应用也是屈指可数,由于是较新的标准中提出的新功能,截止至本文编写的日期,官方的 TypeScript SDK 甚至都没有相应的 example。

Elicitation 的作用是允许 MCP Server 向 MCP Client 发起收集信息的请求。

收集的信息类型可以是:

  • Text
  • Number
  • Boolean
  • Selection List

当 MCP Client 收到来自 MCP Server 的 Elicitation 后,应当向用户展示一个 UI 用于填写 MCP Server 请求的信息。

假设用户希望在 GitHub 中建立一个仓库,为了避免 LLM 可能会错误填写创建中的一些必要信息,GitHub MCP Server 可以向 MCP Client 发起一个 Elicitation 请求,让用户填写仓库名字,开源协议,勾选希望在仓库中使用的插件等。


至此,MCP 的主要概念和一些使用场景例子均已介绍完毕。不过 MCP 还有一些扩展能力

  • Completion - 允许客户端在 Resources 请求或者 Prompts 生成填写参数时,提供补全或者可选项
  • Logging - 允许服务器向客户端发送日志消息
  • Pagination - 允许服务器响应分页数据,避免一次性返回的数据量过大
  • 其他与 Authentication 相关的功能...

面向用户的 MCP

为了更好的向让普通用户使用 MCP,Anthropics 在近期提供了一个叫做 DXT 的 MCP 分发格式。DXT 只能用于打包在本地运行的 MCP 服务器,本质上是一个 ZIP 文件。它类似于 Chrome 插件的封装文件,DXT 里面包含了完整的可执行 MCP Server 文件。例如,如果你使用 NodeJS 或者 Python 编写你的 MCP Server,它会在 DXT 中包含把通过 npm run build 编译出来的 JavaScript 文件或者原 Python 文件。如果你是通过一些其他语言编写的,最终产出可执行文件 (例如 Rust, C++),那么 DXT 中会直接包含面向多个平台 (Unix-Like, Windows 等) 的可执行文件。

后语

MCP 从 2024 年的 11 月公布到目前已经能看到大量的 LLM 应用与 Agent 平台宣布支持 MCP。MCP 的潜力确实不容小觑。它是一个重要必不可缺的中间人,维系着我们社会早已成熟且庞大的数字化基础设施与意味着迈向未来的语言模型之间的桥梁。

作者:
Jimmy
关键词:
AI, LLM, MCP, Function Calling, Model Context Protocol, 模型上下文协议

参考内容