实战指南:从零构建 MCP 架构下的 Agentic RAG 系统,无第三方MCP Server

实战指南:从零构建 MCP 架构下的 Agentic RAG 系统,无第三方MCP Server

五一期间,小编尝试用MCP架构从零实现一个完整的Agentic RAG系统,以演示MCP与RAG、Agent的一些有趣融合,在此与大家一起分享。内容涵盖:

 思考:MCP与Agentic RAG的融


RAG是一种借助外部知识来给LLM提供上下文的AI应用范式。从这个角度来说,RAGMCP有着相似的意义:给大模型补充上下文,以增强其能力。只是MCP以提供外部工具为主,而RAG则是以注入参考知识为主。这就像一个考试的学生,MCP给你提供计算器,而RAG则是给你一本书。

当然,两者的重点并不一样,MCP强调的是提供工具的方式(集成标准);而RAG则是需要你实现的完整应用。所以两者并不冲突,完全可以用MCP的方法来集成一个RAG应用。

特别是在Agentic RAG系统(如下图)中,由于通常涉及到多个RAG查询管道与Agent的融合,这就与MCP的思想非常契合:

假设一个典型的Agentic RAG应用:

一个针对大量不同文档的问答Agent,这些问答有事实性问题也有摘要性问题,更有跨越多个文档的融合问题,甚至需要搜索引擎来补充信息。

现在我们来用MCP的标准设计并完整的实现这个场景。

 MCP标准下的Agentic RAG架构


Agent 智能体MCP架构下,无论是SSE还是stdio模式,都是Client/Server模式。你必须在开始之前清晰的设计好MCP Server与Client应用的分工及交互。比如:

【总体思想】

我们基于如下的总体架构来实现:


MCP Server:RAG管道的核心


MCP Server是RAG功能实现的位置。我们对MCP Server拆解设计如下:

【工具(Tools)】

需要说明,在这里的设计中,不同的RAG管道查询的工具是一样的,但参数(索引名,依赖于Agent推理)不同。一个是推理工具,一个推理参数,效果一致。

【缓存机制】

服务端要对文档解析(含分割)与索引创建的信息进行缓存(持久化存储),以防止可能的重复解析与索引创建,提高性能。

    文档缓存的唯一名称是文档内容hash+解析参数的联合。比如:

questions.csv_f4056ac836fc06bb5f96ed233d9e2b63_500_50

    索引缓存的唯一名称是每个文档关联的唯一索引名称。比如:

questions_for_customerservice”

    以下情况下会导致索引被重建:

这样的缓存管理方式,可以增加处理的灵活性与健壮性。如:

【工具实现:create_vector_index】

这是服务端两个重要工具之一,核心代码如下,请参考注释理解:


【工具实现:query_document】

这是客户端调用的主要工具。其输入是索引名与查询问题。借助索引缓存,可以快速加载并执行RAG查询。这里不再展示完整处理过程:


按类似方法,再创建一个用于回答总结性问题的工具(利用LlamaIndex的SummaryIndex类型索引),此处不在赘述。


MCP客户端:实现Agent(基于LangGraph)


客户端的工作流程如下:

客户端的几个设计重点简单说明如下:

【配置文件】

客户端有两个重要的配置信息,分别用于MCP Server与知识文档的配置。

mcp_config.json:
配置MCP Servers的信息,支持多Server连接、工具加载与过滤(这是一个在langgraph-mcp-adapers基础上扩展的版本)。比如:

doc_config.json:

配置需要索引和查询的全部文档信息。这些信息还会在查询时被注入Agent提示词,用来推理工具的使用参数:

【主程序】

客户端主程序流程非常简单,基于一个封装的MCP客户端与AgenticRAG类型:


【创建智能体(build_agent)】
注意到这里的关键步骤是build_agent,会借助LangGraph预置的create_react_agent快速创建Agent。如果你需要精细化的控制,也可以自定义Graph:

篇幅原因,一些细节部分不在这做详细展示。如果有疑问,欢迎后台交流。


端到端效果演示


现在让我们来测试下这个的“MCP化”的Agentic RAG应用的运行效果。按照如下步骤来进行:

1. 启动MCP RAG-Server。这里用更复杂的SSE模式(暂时未支持文档上传,所以只能本机启动):

启动时会自动提取并展示服务端的工具清单。

2. 准备客户端知识文档与配置文件。将需要索引和查询的文档放在应用的data/目录,配置好mcp_config与doc_config。不做任何其他处理。直接启动客户端应用:

* 观察首次运行的跟踪信息(如下图),这里的过程是:

* 现在退出程序,再次启动客户端,观察输出(如下图),可以看到由于索引已经创建,所以会显示“无需创建”。

3. 交互式测试

进入交互式测试环节(图中的服务端信息是通过MCP接口推送到客户端的远程日志,方便观察服务端的工作状态):

1. 关联两个文档信息的查询

由于提供的文档有北京和上海的城市信息介绍,所以看到这个问题调用了北京和上海的RAG管道查询,还自作主张的调用了搜索引擎做补充,然后输出答案:

2. 查询知识库答案,并要求和网络搜索结果核对。

日志显示,Agent先用本地向量索引查询,然后通过搜索引擎对比,非常准确。

3. 总结性问题测试。

日志显示,这里未加载向量索引,而是由工具加载这个文档的节点,并生成文档摘要后返回(SummaryIndex的效率不太高,有待优化)

4. 最后一个很有意思的测试。

由于我们把创建索引的过程“工具”化了,所以甚至可以用自然语言来管理索引。比如这里我要求把csv文档的索引重建,智能体准确的推理出工具及参数,并重建了csv文档索引(实际应用要考虑安全性):


以上展示了一个基于MCP架构的Agentic RAG系统的实现。总结这种架构下的一些明显的变化:

当然,本文应用还只是基本能力的演示,实际还有大量优化空间。比如服务端的并行处理(大规模文档)、索引进度报告、多模态解析等,后续我们将不断完善并分享。

end

福利时间

为了帮助LLM开发人员更系统性与更深



RAG是一种借助外部知识来给LLM提供上下文的AI应用范式。从这个角度来说,RAGMCP有着相似的意义:给大模型补充上下文,以增强其能力。只是MCP以提供外部工具为主,而RAG则是以注入参考知识为主。这就像一个考试的学生,MCP给你提供计算器,而RAG则是给你一本书。

当然,两者的重点并不一样,MCP强调的是提供工具的方式(集成标准);而RAG则是需要你实现的完整应用。所以两者并不冲突,完全可以用MCP的方法来集成一个RAG应用。

特别是在Agentic RAG系统(如下图)中,由于通常涉及到多个RAG查询管道与Agent的融合,这就与MCP的思想非常契合:

假设一个典型的Agentic RAG应用:

一个针对大量不同文档的问答Agent,这些问答有事实性问题也有摘要性问题,更有跨越多个文档的融合问题,甚至需要搜索引擎来补充信息。

现在我们来用MCP的标准设计并完整的实现这个场景。


 MCP标准下的Agentic RAG架构



MCP架构下,无论是SSE还是stdio模式,都是Client/Server模式。你必须在开始之前清晰的设计好MCP Server与Client应用的分工及交互。比如:

【总体思想】

我们基于如下的总体架构来实现:



MCP Server:RAG管道的核心



MCP Server是RAG功能实现的位置。我们对MCP Server拆解设计如下:

【工具(Tools)】

需要说明,在这里的设计中,不同的RAG管道查询的工具是一样的,但参数(索引名,依赖于Agent推理)不同。一个是推理工具,一个推理参数,效果一致。

【缓存机制】

服务端要对文档解析(含分割)与索引创建的信息进行缓存(持久化存储),以防止可能的重复解析与索引创建,提高性能。

    文档缓存的唯一名称是文档内容hash+解析参数的联合。比如:

questions.csv_f4056ac836fc06bb5f96ed233d9e2b63_500_50

    索引缓存的唯一名称是每个文档关联的唯一索引名称。比如:

questions_for_customerservice”

    以下情况下会导致索引被重建:

这样的缓存管理方式,可以增加处理的灵活性与健壮性。如:

【工具实现:create_vector_index】

这是服务端两个重要工具之一,核心代码如下,请参考注释理解:


【工具实现:query_document】

这是客户端调用的主要工具。其输入是索引名与查询问题。借助索引缓存,可以快速加载并执行RAG查询。这里不再展示完整处理过程:


按类似方法,再创建一个用于回答总结性问题的工具(利用LlamaIndex的SummaryIndex类型索引),此处不在赘述。



MCP客户端:实现Agent(基于LangGraph)



客户端的工作流程如下:

客户端的几个设计重点简单说明如下:

【配置文件】

客户端有两个重要的配置信息,分别用于MCP Server与知识文档的配置。

mcp_config.json:
配置MCP Servers的信息,支持多Server连接、工具加载与过滤(这是一个在langgraph-mcp-adapers基础上扩展的版本)。比如:

doc_config.json:

配置需要索引和查询的全部文档信息。这些信息还会在查询时被注入Agent提示词,用来推理工具的使用参数:

【主程序】

客户端主程序流程非常简单,基于一个封装的MCP客户端与AgenticRAG类型:


【创建智能体(build_agent)】
注意到这里的关键步骤是build_agent,会借助LangGraph预置的create_react_agent快速创建Agent。如果你需要精细化的控制,也可以自定义Graph:

篇幅原因,一些细节部分不在这做详细展示。如果有疑问,欢迎后台交流。



端到端效果演示



现在让我们来测试下这个的“MCP化”的Agentic RAG应用的运行效果。按照如下步骤来进行:

1. 启动MCP RAG-Server。这里用更复杂的SSE模式(暂时未支持文档上传,所以只能本机启动):

启动时会自动提取并展示服务端的工具清单。

2. 准备客户端知识文档与配置文件。将需要索引和查询的文档放在应用的data/目录,配置好mcp_config与doc_config。不做任何其他处理。直接启动客户端应用:

* 观察首次运行的跟踪信息(如下图),这里的过程是:

* 现在退出程序,再次启动客户端,观察输出(如下图),可以看到由于索引已经创建,所以会显示“无需创建”。

3. 交互式测试

进入交互式测试环节(图中的服务端信息是通过MCP接口推送到客户端的远程日志,方便观察服务端的工作状态):

1. 关联两个文档信息的查询

由于提供的文档有北京和上海的城市信息介绍,所以看到这个问题调用了北京和上海的RAG管道查询,还自作主张的调用了搜索引擎做补充,然后输出答案:

2. 查询知识库答案,并要求和网络搜索结果核对。

日志显示,Agent先用本地向量索引查询,然后通过搜索引擎对比,非常准确。

3. 总结性问题测试。

日志显示,这里未加载向量索引,而是由工具加载这个文档的节点,并生成文档摘要后返回(SummaryIndex的效率不太高,有待优化)

4. 最后一个很有意思的测试。

由于我们把创建索引的过程“工具”化了,所以甚至可以用自然语言来管理索引。比如这里我要求把csv文档的索引重建,智能体准确的推理出工具及参数,并重建了csv文档索引(实际应用要考虑安全性):



以上展示了一个基于MCP架构的Agentic RAG系统的实现。总结这种架构下的一些明显的变化:

当然,本文应用还只是基本能力的演示,实际还有大量优化空间。比如服务端的并行处理(大规模文档)、索引进度报告、多模态解析等,后续我们将不断完善并分享。

end





版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/235806.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午1:57
下一篇 2026年3月16日 下午1:58


相关推荐

关注全栈程序员社区公众号