手搓RAG系统 – Ragent AI(7)

eve2333 发布于 8 小时前 5 次阅读


MCP协议入门与实践

skills跟mcp解决的问题不一样。

mcp很早这个概念就出来了,是一种协议、模型间调用三方能力的一个类似接口定义。比如你想购票、那你可以用携程基于MCP实现的MCP服务,接入到你的模型里来直接调用。他们负责MCP Server的实现。别的能力也这样。其实就是定义了一套规范,送你一句话,刚看到的:MCP(Model Context Protocol)是一个开放协议,旨在标准化应用程序向大语言模型(LLMs)提供上下文的方式。可以将 MCP 想象成 AI 应用的 USB-C 接口——正如 USB-C 为设备连接各类外设提供了统一标准,MCP 也为 AI 模型连接不同数据源和工具建立了标准化桥梁。

skills其实不是什么新的东西,本质是一系列文件。把某些能力包装在一个个的skills目录下,比如有个pdf处理文件的能力,这个能力可以封装成一个skills。如果你用claude的时候 跟他说 帮我处理xx pdf文件,claude就会识别到我可以用这个skills(前提是这个skills在你的当前目录下)。这样就可以把一些能力复用。。别人也可以用

Function Call 很好用,工具一多就管不过来了。

假设你在一家公司做企业知识库助手,一开始只有两个工具:查年假、查订单。你手写两份 JSON Schema,代码里写两个 if-else 路由,没什么问题。但半年过去了,产品经理不断加需求:查考勤、查销售数据、查会议室、查报销进度、查项目排期、查库存、查物流、查合同……工具从 2 个变成了 20 个。

这时候你会发现:

  • 20 个工具 × 每个工具 5~10 个参数 = 几百行 JSON Schema 要手写和维护
  • Python 团队写了一个数据分析工具,你的 Java 系统调不了
  • 某个工具的参数改了,JSON Schema 忘了同步更新,模型传了错误的参数,线上出了 bug

你需要的不是更多的 if-else,而是一个标准化的工具管理协议。这就是今天要讲的 MCP。

2. 工具规模化之后的四大痛点

2.1 工具定义的维护噩梦

上一篇的代码你应该还有印象,定义一个工具要写很多很多的JSON Schema:

这只是一个工具、一个参数。如果一个工具有 5 个参数,代码量翻 5 倍。20 个工具就是几百行纯粹的 JSON Schema 构建代码。

更要命的是维护问题:

  • 工具的参数改了(比如 getUserAnnualLeave 新增了一个 year 参数),你要同步修改 JSON Schema,忘了改就会出 bug
  • 没有工具文档,新同事不知道系统里有哪些工具可用,只能翻代码
  • 工具定义散落在代码各处,没有统一的注册中心

2.2 跨语言跨系统的集成困境

你的企业知识库助手需要调用的工具来自不同团队:

  • Java 团队写的 HR 工具(查年假、查考勤)
  • Python 团队写的数据分析工具(销售报表、用户画像)
  • 第三方 HTTP API(物流查询、天气查询)

三种不同的调用方式,你的代码里要写三套集成逻辑,接入一个新系统,就要写一套适配代码。而且每个系统的认证方式不同(有的用 Token,有的用 API Key,有的用 OAuth),错误处理方式也不同。

2.3 权限和安全的黑洞

Function Call 协议本身没有任何权限机制。所有的权限校验都要你自己写:

  • 用户 A 能不能查用户 B 的年假?
  • 某个工具只允许管理员使用,怎么控制?

工具越多,权限逻辑越复杂。而且权限代码和业务代码混在一起,容易出漏洞。

2.4 可观测性的缺失

20 个工具在线上跑,你需要知道:

  • 每个工具被调用了多少次?
  • 平均耗时多少?哪个工具最慢?
  • 调用失败率是多少?失败的原因是什么?
  • 某次调用的完整链路:用户问了什么 → 模型选了哪个工具 → 传了什么参数 → 返回了什么结果 → 最终答案是什么?

Function Call 协议不管这些,全靠你自己埋点、写日志、搭监控。工具调用链路一长(调用工具 A → 工具 A 内部调用工具 B → 工具 B 查数据库),排查问题就像大海捞针。

我们需要的是在 Function Call 之上,加一层标准化的工具管理框架——统一工具的定义、注册、发现、调用、权限控制。

维度Function Call 解决了吗
模型判断是否调用工具解决了
标准化的调用意图输出解决了
工具定义的自动化管理没有,手写 JSON Schema
工具的动态发现和注册没有,硬编码在代码里
跨语言跨系统的统一调用没有,每个系统写一套适配
权限和安全控制没有,自己实现
调用链路的可观测性没有,自己埋点

这就是 MCP 要做的事。

MCP,全称 Model Context Protocol(模型上下文协议),由 Anthropic(Claude 的母公司)于 2024 年 11 月开源发布。它不是一个具体的产品或框架,而是一个开放的协议规范。核心思想用一句话概括:任何工具只要实现了 MCP 协议,就能被任何支持 MCP 的客户端调用,不用关心对方是什么语言、什么平台。

2. MCP 的三层架构:Host、Client、Server

MCP 的架构设计分三层:Host(宿主应用)、Client(MCP 客户端)、Server(MCP 服务端)。这三层的关系用一张图说明:

2.1 Host(宿主应用)

Host 是用户直接交互的应用,比如:

  • Claude Desktop(Anthropic 的桌面客户端)
  • Cursor(AI 编程 IDE)
  • 你自己开发的企业知识库助手(比如咱们的 Ragent)

Host 的职责是:接收用户输入 → 调用大模型 → 根据模型的指令通过 MCP Client 调用工具 → 把结果返回给模型 → 展示最终答案给用户。

Host 内部包含一个或多个 MCP Client,每个 Client 负责和一个 MCP Server 通信。

2.2 Client(MCP 客户端)

Client 是 Host 内部的通信组件,负责和 MCP Server 建立连接、发送请求、接收响应。

关键点:一个Client只连接一个Server ,但一个 Host 可以有多个 Client,连接多个 Server。就像你的电脑有多个 USB 接口,每个接口插一个设备。

Client 的职责包括:

  • 和 Server 建立连接(通过 Stdio 或 HTTP)
  • 发现 Server 提供的工具列表
  • 调用 Server 的工具并获取结果
  • 管理连接的生命周期

2.3 Server(MCP 服务端)

Server 是提供工具的一方。每个 Server 暴露一组工具,Client 通过 MCP 协议调用这些工具。

Server 可以是:

  • 本地进程(通过 Stdio 通信,比如一个本地的文件操作工具)
  • 远程 HTTP 服务(通过 Streamable HTTP 通信,比如部署在服务器上的 HR 系统工具)

Server 的职责包括:

  • 声明自己提供哪些工具(工具名、描述、参数定义)
  • 接收 Client 的调用请求
  • 执行工具逻辑并返回结果

3. MCP 的三大核心能力

MCP 协议定义了三大核心能力:Tools(工具调用)、Resources(资源访问)、Prompts(提示词模板)。

3.1 Tools(工具调用)

这是 MCP 最核心的能力,也是和 Function Call 直接对应的部分。

Server 定义工具,Client 发现并调用工具。和 Function Call 的区别在于:

  • FunctionCall :工具定义在客户端代码里(手写 JSON Schema),和模型一起发送
  • MCP :工具定义在 Server 端,Client 通过协议动态获取

注意:MCP 协议本身只规定工具定义在 Server 端,Client 通过协议动态获取工具列表和元数据。至于 Server 端用什么方式定义工具(注解、手写 JSON、配置文件),那是实现框架的选择。下面展示的 @Tool 注解是 Spring AI 框架提供的便利性封装。

举个例子,Function Call 里你要这样定义工具:

{"type":"function","function":{"name":"getUserAnnualLeave","description":"查询用户的年假余额","parameters":{"type":"object","properties":{"userId":{"type":"string","description":"用户 ID"}},"required":["userId"]}}}

在 Spring AI 框架中,你可以用 @Tool 注解定义工具(框架会自动生成符合 MCP 协议的工具元数据):

@Tool(description ="查询用户的年假余额,包括总天数、已使用天数、剩余天数")publicStringgetUserAnnualLeave(@ToolParam(description ="用户 ID")String userId){// 查询 HR 系统return"{\"remainingDays\": 5, \"totalDays\": 10, \"usedDays\": 5}";}

Spring AI 框架会扫描 @Tool 注解,自动提取方法名作为工具名、description 作为工具描述、方法参数和 @ToolParam 注解作为参数定义,生成符合 MCP 协议的工具元数据(JSON Schema 格式)。Client 启动时通过 MCP 协议从 Server 获取这些元数据,不用在 Client 端手写 JSON Schema,也不用担心定义和实现不同步。

3.2 Resources(资源访问)

Server 可以暴露资源供 Client 读取,比如:

  • 文件内容(配置文件、日志文件)
  • 数据库记录
  • API 返回的数据

Resources 和 Tools 的区别是:Tools 是执行操作(查年假、下订单),Resources 是提供数据(读取一个文件的内容)。Resources 更像是给模型提供额外的上下文信息。

3.3 Prompts(提示词模板)

Server 可以提供预定义的提示词模板,Client 可以使用这些模板来构建和模型的交互。适合标准化的交互场景,比如“代码审查模板"”、“文档总结模板”。

本篇重点讲 Tools,Resources 和 Prompts 在实际项目中用得相对少一些,了解即可。


4. MCP vs Function Call:不是替代,是增强

答案是:不是。MCP 底层仍然依赖模型的 Function Call 能力。模型判断是否调用工具、输出 tool_calls JSON——这个能力是 Function Call 提供的,MCP 不会重新发明这个轮子。

MCP 做的是在 Function Call 之上,提供一层标准化的管理框架。用一个类比:Function Call 是"发动机",MCP 是"整车"。发动机提供动力,但你还需要方向盘、刹车、仪表盘才能上路。

MCP提供:工具的标准化管理;跨语言/跨平台支持;统一的安全控制

FunctionCall 提供:意图理解能力;结构化输出能力;对话上下文管理

对比维度Function CallMCP
本质模型的原生能力(输出调用意图)标准化的工具管理协议
工具定义手写 JSON Schema,和代码分离代码注解自动生成,定义和实现一体
工具发现没有,硬编码在请求里Client 启动时自动从 Server 获取
跨语言支持不支持,每个语言自己实现协议统一,Java / Python / TS 都能互通
传输方式依赖具体的 HTTP API标准化传输(Stdio / Streamable HTTP)
权限控制没有,自己实现协议层面支持(还在完善中)
可观测性没有,自己埋点协议层面支持日志和追踪
生态各家模型厂商各自实现开放协议,社区共建 MCP Server

MCP协议层面 (标准制定者):

  • 定义了工具元数据的标准格式(name、description、parameters 的 JSON Schema)
  • 定义了 Client 和 Server 的通信协议(JSON-RPC over Stdio/HTTP)
  • 定义了工具发现机制(Client 启动时从 Server 获取工具列表)
  • 解决的核心问题:工具定义从Client端转移到Server端,实现跨语言跨系统互通

SpringAI框架层面 (协议实现者):

  • 提供 @Tool 注解,让你用注解方式定义工具(而不是手写 JSON)
  • 提供自动扫描注解并生成符合 MCP 协议的工具元数据
  • 处理 MCP 协议的通信细节(JSON-RPC 请求解析、响应构建等)
  • 解决的核心问题:让Java开发者更方便地实现MCP协议

打个比方:MCP 协议就像 HTTP 协议,Spring AI 就像 Spring MVC 框架。HTTP 定义了请求响应格式,但你可以用任何语言、任何框架实现 HTTP 服务器。Spring MVC 提供了 @RestController 注解让你更方便地写 HTTP 接口,但这不是 HTTP 协议本身的能力。

即使不用 Spring AI,你也可以用纯 Java 手写 JSON 来实现 MCP Server,只是更麻烦。MCP 协议的价值在于:一旦你的Server实现了MCP协议,任何支持MCP的Client(ClaudeDesktop、Cursor、Python客户端等)都能调用你的工具,不需要为每个Client写适配代码

MCP 的传输机制

MCP Client 和 Server 之间怎么通信?MCP 协议定义了两种传输方式:Stdio(标准输入输出)和 Streamable HTTP(可流式 HTTP)。

1. Stdio(标准输入输出)

Stdio 是最简单的传输方式。MCP Server 作为本地子进程运行,Client 通过操作系统的标准输入(stdin)和标准输出(stdout)和 Server 通信。

打个比方:你在终端里运行 grep "error" log.txt,你敲的命令是输入(stdin),grep 打印出来的结果是输出(stdout)。MCP 的 Stdio 传输就是这个原理:Client 启动 Server 进程,往 Server 的 stdin 写请求(JSON 格式),Server 从 stdout 返回结果(也是 JSON 格式)。整个过程就像你在和一个命令行程序对话,只不过对话内容是结构化的 JSON 数据。

通信过程:

  1. 1.Client 启动 Server 进程(比如 java -jar mcp-server.jar
  2. 2.Client 往 Server 的 stdin 写入 JSON-RPC 请求
  3. 3.Server 从 stdin 读取请求,执行工具,把结果以 JSON-RPC 格式写入 stdout
  4. 4.Client 从 Server 的 stdout 读取响应

JSON-RPC 是一种轻量级的远程过程调用协议,用 JSON 格式传输请求和响应。你可以把它理解为用 JSON 格式约定好请求和响应的结构,和 RESTful API 类似,但更简单。

Stdio 的优点:

  • 简单,不需要网络配置,不暴露端口
  • 安全,通信只在本地进程之间,不经过网络
  • 适合本地工具(文件操作、本地数据库查询、命令行工具)

Stdio 的缺点:

  • 只能本地调用,不支持远程访问
  • Server 和 Client 必须在同一台机器上

2. Streamable HTTP(可流式 HTTP)

Streamable HTTP 是 MCP 协议在 2025 年 3 月引入的传输方式(替代了早期的 HTTP+SSE 方案)。MCP Server 作为 HTTP 服务运行,Client 通过 HTTP 请求调用。

通信过程:

  1. 1.Server 启动 HTTP 服务,监听某个端口(比如 http://localhost:8080
  2. 2.Client 向 Server 发送 HTTP POST 请求(JSON-RPC 格式)
  3. 3.Server 处理请求,返回 HTTP 响应
  4. 4.如果需要流式返回(比如长时间运行的工具),Server 通过 SSE(Server-Sent Events)推送增量结果

Streamable HTTP 的优点:

  • 支持远程访问,Server 可以部署在任何地方
  • 支持团队共享,多个 Client 可以连接同一个 Server
  • 支持流式响应(SSE),适合长时间运行的工具
  • 可以利用 HTTP 生态的认证、负载均衡、监控等基础设施

Streamable HTTP 的缺点:

  • 需要网络配置(端口、防火墙、HTTPS)
  • 相比 Stdio 多了网络开销

本地开发和个人工具用 Stdio,团队共享和生产环境用 Streamable HTTP。企业级项目基本上都是后者。

Java 实战:搭建一个 MCP Server

延续前几篇的企业知识库助手场景,我们用 Spring AI MCP Server 框架搭建一个 MCP Server,提供两个工具:

  • getUserAnnualLeave:查询用户年假余额
  • getOrderStatus:查询订单状态

搭建完成后,这个 MCP Server 可以被 Claude Desktop、Cursor 等任何支持 MCP 的客户端直接调用。

Spring AI 从 1.0 版本开始提供了 MCP Server 的 Boot Starter,开箱即用。选 Spring AI 的理由很简单:

  • Java 生态,和现有的 Spring Boot 项目无缝集成
  • @Tool 注解定义工具,不用手写 JSON Schema
  • 同时支持 Stdio 和 Streamable HTTP 两种传输方式
  • 社区活跃,文档完善

Spring AI MCP Server 提供了三个 Starter,根据传输方式选择:

Starter传输方式适用场景
spring-ai-starter-mcp-serverStdio本地工具,被 Claude Desktop / Cursor 调用
spring-ai-starter-mcp-server-webmvcStreamable HTTP(基于 Spring MVC)远程工具,团队共享
spring-ai-starter-mcp-server-webfluxStreamable HTTP(基于 WebFlux)远程工具,响应式编程

本篇先用 Stdio 方式演示(最简单,能直接被 Claude Desktop 调用),后面再介绍 HTTP 方式。


Maven 依赖

注意:spring-ai-starter-mcp-server 是 Stdio 传输方式的 Starter。如果你需要 HTTP 传输,换成 spring-ai-starter-mcp-server-webmvc

4. 定义工具

这是 MCP 相比 Function Call 最爽的地方——用 @Tool 注解定义工具,参数用 @ToolParam 注解描述,框架自动生成工具的 JSON Schema。

创建一个工具类 EnterpriseTools.java

packagecom.nageoffer.ai.mcp.tools;importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.ai.tool.annotation.ToolParam;importorg.springframework.stereotype.Service;/**
 * 企业知识库助手工具集
 * 每个 @Tool 方法会自动注册为一个 MCP 工具
 */@ServicepublicclassEnterpriseTools{/**
     * 查询用户年假余额
     */@Tool(description ="查询用户的年假余额,包括总天数、已使用天数、剩余天数。当用户询问年假、假期余额、还有多少天假等问题时使用此工具。")publicStringgetUserAnnualLeave(@ToolParam(description ="用户 ID,例如 user_12345")String userId){// 实际项目中这里调用 HR 系统 API// 这里用 mock 数据演示returnString.format("""
                {
                    "userId": "%s",
                    "remainingDays": 5,
                    "totalDays": 10,
                    "usedDays": 5,
                    "year": 2026
                }
                """, userId);}/**
     * 查询订单状态
     */@Tool(description ="查询订单的物流状态和详细信息。当用户询问订单状态、物流进度、快递到哪了等问题时使用此工具。")publicStringgetOrderStatus(@ToolParam(description ="订单号,例如 ORD-12345")String orderId){// 实际项目中这里调用订单系统 APIreturnString.format("""
                {
                    "orderId": "%s",
                    "status": "运输中",
                    "location": "北京市朝阳区分拨中心",
                    "estimatedDelivery": "2026-03-01",
                    "carrier": "顺丰速运",
                    "trackingNumber": "SF1234567890"
                }
                """, orderId);}}

对比一下 Function Call 里定义同样两个工具需要多少代码——上一篇的 callModelWithTools 方法里,光构建 JSON Schema 就写了 40 多行。MCP 里只需要两个方法加注解,清爽多了。

5. 注册工具到 MCP Server

创建配置类,把工具注册到 MCP Server:

packagecom.nageoffer.ai.mcp.config;importcom.nageoffer.ai.mcp.tools.EnterpriseTools;importorg.springframework.ai.tool.ToolCallbackProvider;importorg.springframework.ai.tool.method.MethodToolCallbackProvider;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassMcpServerConfig{/**
     * 注册工具提供者
     * MethodToolCallbackProvider 会扫描 EnterpriseTools 中所有 @Tool 注解的方法,
     * 自动注册为 MCP 工具
     */@BeanpublicToolCallbackProviderenterpriseToolProvider(EnterpriseTools enterpriseTools){returnMethodToolCallbackProvider.builder().toolObjects(enterpriseTools).build();}}

MethodToolCallbackProvider 会自动扫描 EnterpriseTools 类中所有带 @Tool 注解的方法,提取方法名作为工具名、description 作为工具描述、方法参数和 @ToolParam 注解作为参数定义,自动生成完整的工具元数据。

6. 配置 MCP Server

application.yml 配置:

spring:ai:mcp:server:name: enterprise-assistant
        version: 1.0.0
        type: SYNC
  main:web-application-type: none
    banner-mode: off

logging:file:name: ./logs/mcp-server.log
  level:root: OFF

几个关键配置说明:

  • spring.ai.mcp.server.name:Server 名称,Client 连接时会看到这个名字
  • spring.ai.mcp.server.version:Server 版本号
  • spring.ai.mcp.server.type:工具执行模式,SYNC(同步)或 ASYNC(异步)
  • spring.main.web-application-type: none:Stdio 模式不需要 Web 容器
  • spring.main.banner-mode: off:关闭 Spring Boot 启动 banner,避免 banner 输出到 stdout 干扰 MCP 通信

Stdio 模式下,stdout 是 MCP 协议的通信通道,任何非协议内容(banner、日志)输出到 stdout 都会导致通信失败。这是一个常见的坑。

7. 启动类

packagecom.nageoffer.ai.mcp;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassMcpServerApplication{publicstaticvoidmain(String[] args){SpringApplication.run(McpServerApplication.class, args);}}

项目结构:

mcp-server-demo/
├── pom.xml
└── src/main/
    ├── java/com/nageoffer/ai/mcp/
    │   ├── McpServerApplication.java
    │   ├── config/
    │   │   └── McpServerConfig.java
    │   └── tools/
    │       └── EnterpriseTools.java
    └── resources/
        └── application.yml

先用 Maven 打包:

mvn clean package -DskipTests

打包完成后,在 target 目录下会生成 mcp-server-demo-1.0.0.jar

8. 测试:用 MCP 客户端调用

8.1 在 Cursor 中配置

打开 Cursor 的 MCP 配置(Settings → Tools & MCP),如下图所示:

若果是SpringAI1.1+版本就可以使用/mcp,项目中马哥的SpringAI版本比较早,而且支持MCP的springAI版本是在1.1.0-M1版本。配置cusor的mcp server信息时得用: "url": "http://localhost:8080/sse"

添加:

{"mcpServers":{"enterprise-assistant":{"command":"java","args":["-jar","/path/to/mcp-server-demo-1.0.0.jar"]}}}

/path/to/ 替换成你的 jar 包实际路径。

咱们 MCP Demo 项目用的 JDK17,如果你的电脑默认不是 JDK17,需要将 command 设置为 Java 的绝对路径。我的默认 JDK 就不是 17,所以需要调整下,比如:

{"mcpServers":{"enterprise-assistant":{"command":"/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin/java","args":["-jar","/path/to/mcp-server-demo-1.0.0.jar"],"env":{"JAVA_HOME":"/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home"}}}}

在对话框里进行问答,Cursor 会自动调用你的 MCP Server 查询年假余额和订单状态。

因为是个 Demo 的 MCP 示例,所以问题有点呆,需要用户提示词自己把账号和订单号带进去。常规上肯定是程序里自动带入,大家忽略即可。

8.2 使用 Streamable HTTP 方式

如果你想让 MCP Server 以 HTTP 服务的方式运行(支持远程访问、多客户端共用),只需要做两个改动:

第一步,把 Maven 依赖换成 WebMVC 版本:

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server-webmvc</artifactId><version>${spring-ai.version}</version></dependency>

第二步,修改 application.yml

spring:ai:mcp:server:name: enterprise-assistant
        version: 1.0.0
        type: SYNC

server:port:8080

启动后,MCP Server 会在 http://localhost:8080 上监听。Client 配置改为:

{"mcpServers":{"enterprise-assistant":{"url":"http://localhost:8080/mcp"}}}

工具代码和配置类完全不用改,只是传输方式从 Stdio 变成了 HTTP。

9. 对比:Function Call vs MCP + Spring AI 的代码量

同样实现查年假和查订单两个工具,对比一下两种方式的代码量:

对比项Function Call(上一篇)MCP + Spring AI(本篇)
工具定义40+ 行 JSON Schema 构建代码2 个 @Tool 注解方法
工具路由手写 if-else 或策略模式框架自动路由
协议处理手写 HTTP 请求、解析 tool_calls、构建第二轮消息框架自动处理
新增工具加 JSON Schema + 加路由 + 改代码 + 重新部署加一个 @Tool 方法 + 重新部署
客户端适配只能被你自己的代码调用任何 MCP 客户端都能调用
总代码量~200 行(含 JSON Schema 构建)~60 行(含工具实现)

代码量减少了 70%,而且新增工具只需要加一个方法,不用改任何框架代码。

说明:这里对比的是纯 Function Call 实现 vs MCP 协议 + Spring AI 框架实现。代码量的减少主要来自 Spring AI 框架的便利性封装(注解、自动路由等)。MCP 协议本身带来的核心价值是最后一行客户端适配——一旦你的工具实现了 MCP 协议,任何支持 MCP 的客户端都能调用,不需要为每个客户端写适配代码。

MCP 在 RAG 系统中的应用

讲完了 MCP 的原理和实战,回到我们的主线——RAG 系统。MCP 在 RAG 系统中能发挥什么作用?

1. 知识检索作为 MCP 工具

上一篇讲 Function Call 在 RAG 中的应用时,我们定义了一个 searchKnowledgeBase 工具,让模型自动判断是查知识库还是调业务工具。用 MCP 实现同样的能力,只需要把知识检索封装成一个 MCP 工具:

@Tool(description ="在企业知识库中搜索相关文档。当用户询问公司制度、产品文档、操作指南等静态知识时使用此工具。")publicStringsearchKnowledgeBase(@ToolParam(description ="搜索关键词,用自然语言描述")String query,@ToolParam(description ="返回结果数量,默认 5")int topK){// 调用向量数据库检索// 实际项目中这里执行 Embedding → Milvus 检索 → RerankingList<Document> results = ragService.search(query, topK);returnformatResults(results);}

这样做的好处是:你的知识检索能力不再局限于自己的系统,任何支持 MCP 的客户端都能调用你的知识库。比如团队成员在 Cursor 里写代码时,可以直接问公司的代码规范是什么,Cursor 通过 MCP 调用你的知识库检索工具,返回相关文档。

2. 多工具编排:知识检索 + 业务工具

MCP 的真正威力在于多个 Server 协同工作。假设用户问我的订单 #12345 能退货吗,这个问题需要两部分信息:

  1. 1.订单的当前状态(需要调用订单系统)
  2. 2.退货政策(需要检索知识库)

在 MCP 架构下,这两个能力可以由不同的 MCP Server 提供:

每个 MCP Server 专注做一件事(订单查询、知识检索、HR 查询……),Host 根据模型的判断,并行调用多个 Server,综合结果生成答案。这种架构的好处是:

  • 职责清晰 :每个 Server 独立开发、独立部署、独立维护
  • 灵活组合 :新增一个能力只需要部署一个新的 MCP Server,不用改现有代码
  • 团队协作 :不同团队各自维护自己的 MCP Server,通过协议互通

3. 企业级场景:Ragent 中的 MCP 实践

在我们的 Ragent 项目(企业级 RAG 智能体平台)中,MCP 被用来管理所有的外部工具调用。简要介绍一下架构思路:

  • MCPToolRegistry :工具注册表,管理所有已注册的 MCP Server 和工具
  • MCPToolExecutor :工具执行器,负责根据模型的 tool_calls 路由到对应的 MCP Server 并执行
  • 自动发现机制 :系统启动时自动连接配置的 MCP Server,获取工具列表,注册到工具注册表

这种架构让 Ragent 可以灵活接入各种外部工具,而不需要为每个工具写适配代码。具体的代码实现会在后续的 Ragent 项目实战文章中详细展开。

MCP 的生态现状

1. 支持 MCP 的客户端

MCP 协议发布一年多以来,已经有不少客户端支持:

客户端类型MCP 支持情况
Claude DesktopAI 对话客户端完整支持,Anthropic 官方出品
CursorAI 编程 IDE完整支持,MCP 工具可在编程中使用
WindsurfAI 编程 IDE支持 MCP
ContinueVS Code AI 插件支持 MCP
ClineVS Code AI 插件支持 MCP
Claude CodeCLI 工具完整支持
Spring AIJava AI 框架提供 MCP Client 和 Server Starter
KiroAI IDE支持 MCP

这意味着你开发一个 MCP Server,上面这些客户端都能直接调用,不需要为每个客户端写适配代码。

2. 社区 MCP Server

GitHub 上已经有大量社区开发的 MCP Server,覆盖常见场景:

  • 文件系统 :读写本地文件、目录操作
  • 数据库 :MySQL、PostgreSQL、SQLite 查询
  • Web搜索 :Brave Search、Google Search
  • 代码仓库 :GitHub 操作(创建 Issue、提交 PR、查看代码)
  • 知识管理 :Notion、Obsidian 集成
  • 通信工具 :Slack、Discord 消息发送
  • 云服务 :AWS、GCP 资源管理

你可以在 MCP Servers 目录 找到这些社区 Server,直接配置使用,不需要自己开发。

3. MCP 的局限性和未来

MCP 的方向是对的,但目前还有一些局限:

  • 协议还在快速演进 :从 2024 年 11 月发布到现在,传输层已经从 HTTP+SSE 改为 Streamable HTTP,API 也在不断调整。早期开发的 MCP Server 可能需要适配新版本
  • 部分客户端支持不完整 :有些客户端只支持 Stdio,不支持 HTTP;有些只支持 Tools,不支持 Resources 和 Prompts
  • 生产环境的稳定性 :MCP 在本地开发场景下表现很好,但在高并发的生产环境中,稳定性和性能还需要更多验证
  • 权限模型还在完善 :MCP 协议层面的权限控制还比较基础,企业级的细粒度权限(比如基于角色的工具访问控制)仍然需要自己实现
  • 认证标准化 :远程 MCP Server 的认证方式(OAuth、API Key 等)还没有统一标准

不过,标准化是大趋势。就像 HTTP 协议从 0.9 到 1.0 到 1.1 到 2.0 到 3.0,MCP 也会不断完善。现在学习和使用 MCP,是一个好的时机。