前阵子 Manus 大火,突然看到了很多吹 MCP 的文章,去年刚出来的时候大致了解了一下,没发现什么特别之处,可能士别三日当刮目相看吧,花了点时间仔细地看了看文档,依旧没发现什么特别之处 ... 但是看都看了,还是写篇文章记录一下吧。

MCP 的基本概念

模型上下文协议(Model Context Protocol, MCP)是一个由 Anthropic 提出概念和框架,其目标是建立一套 LLM 应用程序集成的标准协议。MCP 遵循 C-S 架构,由宿主程序(Host)、客户端(Client)和服务端(Server)三部分组成:

  • 宿主程序指那些具备使用 LLM 能力的应用程序,比如 Claude 客户端、VSCode 等;
  • 宿主程序使用 MCP 客户端和 MCP 服务端保持连接;
  • MCP 服务端用于提供具体的能力。

其中客户端和服务端之间可以通过下面三种方式进行交互:

  • MCP 框架内置的标准输入/输出 stdio,适用于本地集成和命令行工具;
  • MCP 框架内置的基于 HTTP 协议的传输方法,如 HTTP POST 请求和 SSE;
  • 通过实现 MCP 的 Transport interface 以实现自定义传输方法。

在 MCP 中有五个基本术语:

  • 提示词 Prompts:在服务端中定义的可重用的提示词(模版)和工作流,宿主程序可以(通过客户端)获取到这些 Prompts 并展示给用户,由用户自行决定如何使用;
  • 资源 Resources:在服务端中定义的可以被使用的资源,宿主程序可以(通过客户端)获取到可用的资源并使用这些资源构造 LLM 交互上下文;
  • 根 Roots:宿主程序(通过客户端告知(并非强制性的)服务端可以操作哪些资源;
  • 采样 Sampling:服务端客户端发送一个特殊类型的请求(sampling/createMessage),客户端收到请求后可以告知宿主程序处理采样请求,在宿主程序完成处理后再通过客户端将结果返回给服务端;
  • 工具 Tools:在服务端中定义的可以执行计算或者与外部系统进行交互的方法,宿主程序可以(通过客户端)获取到支持的工具列表,并调用(直接或者由 LLM 选择)特定的工具;

从上面可以看出,MCP 的核心是通过定义一套规范,使得遵循这些规范第三方集成能够直接被宿主程序使用。并且在 MCP 中,侧重于在宿主程序中使用 LLM 能力,感觉理想情况下是第三方集成暴露自己能做什么,然后在宿主程序中由用户和 LLM 决定的要使用什么能力。个人感觉这个东西没什么值得吹的,说到底就是一个类似编辑器插件、或者浏览器插件框架性质的东西,做桌面应用程序之类的可能有点用,但是要是要做 ToC 的服务似乎就没有太大的价值了,也不是人人都知道该怎么配置和调整提示词。

一个简单的例子

mcp-demo 是一个为了测试 MCP 核心能力而创建的玩具项目,实现了一个能够通过图片链接或自然语言进行记账(beancount)的命令行工具。项目代码和基本说明如下:

  • host/:宿主应用程序
    • host/client.ts:初始化了 MCP Client,并在初始化后通过 changeRoots 方法告知服务端账本的存储目录;
    • host/server.ts:使用标准输入/输出连接到服务端;
    • host/index.ts:通过 yargs 实现了基本的 CLI 界面和记账逻辑,其中:
      • initialize:调用服务端提供的 initialize 工具对账本进行初始化;
      • add http(s)://..:从服务端获取图片账单解析 Prompt 并调用 LLM,然后使用解析结果调用服务端提供的 add-trx 工具;
      • add ...:调用服务端提供的 extract-and-add-trx 工具并完成服务端发送的采样请求(理论上采样请求应该由客户端提供给宿主程序进行处理,但是 CLI 折腾起来有点麻烦就直接在客户端处理了,具体代码在 client/sampling.ts 中);
  • client/:MCP 客户端部分的逻辑
    • client/roots:定义了用于告知服务端 Roots 发生了改变的 changeRoots 方法;
    • client/sampling.ts:监听服务端发送的采样请求并进行处理;
    • client/inex.ts:初始化 MCP 客户端。
  • server/:MCP 服务端部分的逻辑
    • server/prompts:包含服务端中定义的 Prompt 并实现相关接口;
    • server/resources:包含服务端中定义的可用资源并实现相关接口,这些资源来自于客户端指定的根(Root);
    • server/tools 包含服务端中定义的可用工具——初始化账本 initialize、添加账单条目 add_trx 和通过自然语言添加账单条目 extract-and-add-trx 并实现相关接口;
    • server/index.ts 中初始化了 MCP 服务端,并且在收到客户端根 Roots 改变的通知后重新绑定相关的接口。

这个项目只是为了帮助理解 MCP 的概念瞎折腾的,没什么使用价值,仅供参考。