前阵子 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 的概念瞎折腾的,没什么使用价值,仅供参考。