如果您的 MCP 客户端不支持资源,那么它就不是一个好的客户端。
好了!我说了!
这是因为MCP 资源是为了提高即时利用率,也就是缓存失效。如果没有资源,你的上下文和代币预算消耗得比 Elon 去药店还快。所以,如果你的客户端不支持,你基本上就无法用 MCP 实现 RAG了。至少,没有人会认为这种方式值得投入生产。
RAG 文件很大
你肯定不想复制文件。参考这里:
总共调用了两次工具。第二次调用包含一个重复文件。
这很糟糕吗?如果你的答案是“不”,那么这篇博文就不会引起你的共鸣。
将结果与整个文件分开
其核心在于:一个实现良好的应用,无论是否使用 MCP,都会跟踪 RAG 查询返回的文档,并避免在提示符中重复出现。为此,您需要保存一个之前见过的资源 ID 列表(当然,可以称之为“缓存”)。
在提示中格式化 RAG 工具响应,如下所示:
<result uri="rag://polar-bears/74.md" /> <result uri="rag://chickens/23.md" /> <full-text uri="rag://chickens/23"> Chickens are... </full-text>
换句话说:
- 对于 LLM 来说,该函数的返回值是一个资源数组
- 全文已收录于其他地方,供参考
URI 可用作缓存键。
顺便说一句,我只是在随意猜测返回结果的提示格式应该是什么。你可以自己尝试一下,你可能已经有了自己的想法。重点是,必须进行映射。
MCP 无法被 LLM 读
关于 LLM 能否很好地解释 OpenAPI,以及如果可以,为什么要使用 MCP,已经有很多讨论。这完全没有抓住重点。MCP 不应该由 LLM 直接解释。
当你实现 MCP 客户端时,你应该将 MCP 概念映射到适合该 LLM 的任何概念上。这被称为实现协议。如果你将原生 MCP 对象放入提示中,它实际上可以工作。但一个好的客户端会将结果映射到特定 LLM 经过极其昂贵的训练才能理解的短语和格式上。
MCP 是一种协议
MCP 标准化了工具返回结果的方式。MCP 资源的存在是为了使工具(例如 RAG 搜索)能够返回文件,并且客户端能够在多次调用中对这些文件进行去重。
是的,列出目录很酷,但这不是资源的主要用途。没有资源,你的LLM只会不必要地消耗更多代币。
(附注:您是否注意到Anthropic和OpenAI都不支持其 API 中的资源?这是一个阴谋……)
资源是 MCP 支持的基础
如果客户端不支持 MCP 资源,那是因为他们不够用心,没有实现合适的客户端。就是这样。
顺便说一下,提示符只是对结果进行特殊处理的函数。不妨也支持它们。