AI 学习与实战系列:Spring AI + MCP 深度实战——构建标准化、可扩展的智能 Agent 系统

AI 学习与实战系列:Spring AI + MCP 深度实战------构建标准化、可扩展的智能 Agent 系统

1. 开启 AI 开发的新纪元:从碎片化集成到协议化连接

在人工智能应用爆发的今天,开发者面临的最大挑战之一已不再是单纯的模型调用,而是如何让模型"理解"并"操作"企业内部纷繁复杂的业务数据与工具系统。早期的 AI 集成往往是"烟囱式"的:为每一个特定的工具编写专属的适配器,为每一种数据源编写复杂的清洗逻辑。这种做法在 Agent(智能体)规模扩大时,会导致代码难以维护、扩展性极差。

Spring AI 作为一个致力于简化 Java AI 应用开发的框架,近期引入了对 Model Context Protocol (MCP) 的支持。MCP 是由 Anthropic 牵头推出的一项开放协议,其核心目标是为 AI 模型提供一种标准化的方式来访问外部工具(Tools)和数据资源(Resources)。它就像是 AI 领域的"USB 接口协议",一旦你的服务遵循了 MCP 标准,它可以无缝地连接到任何支持 MCP 的 AI 客户端中。

本篇文章将深入探讨 Spring AI 与 MCP 的实战结合。我们将从底层的协议原理讲起,逐步深入到如何利用 Spring 生态快速构建自己的 MCP Server,并将其集成到 Spring AI 的 ChatClient 中。通过这一过程,你将掌握构建企业级、插件化 AI 系统的核心技术能力,告别低效的硬编码集成方案。

2. 深度拆解 MCP:模型上下文协议的核心机制

要玩转 Spring AI + MCP,首先必须理解 MCP 的设计哲学。MCP 采用典型的 客户端-服务器(Client-Server)架构。在这一架构中,AI 应用程序(如基于 Spring AI 构建的应用)充当 MCP Client,而提供数据、文件或 API 操作的服务则充当 MCP Server。

2.1 核心原语:Resources、Prompts 与 Tools

MCP 协议定义了三种主要的能力:

  1. Resources (资源):静态或动态的数据源。例如,一个本地日志文件、数据库查询结果或是一个实时读取的文档。它们通常是只读的,为模型提供必要的背景信息。
  2. Prompts (提示词模板):服务器可以预置一些经过优化的提示词模板,供客户端调用。这有助于在不同应用间复用高质量的 Prompt 工程成果。
  3. Tools (工具):这是 Agent 能够产生"动作"的关键。工具允许模型执行代码、更新数据库记录或触发外部 API 调用。Tools 是具有副作用(Side Effects)的可执行逻辑。

2.2 通讯协议:JSON-RPC 2.0

MCP 并不重新发明底层传输,它选择了轻量且成熟的 JSON-RPC 2.0。这意味着请求和响应都是高度结构化的。在传输层上,MCP 支持 Stdio(标准输入输出)和 HTTP with SSE(服务器发送事件)。Stdio 模式常用于本地进程间通讯(如 IDE 插件),而 SSE 模式则是云原生 Web 应用的首选,能够支持长连接下的实时状态推送。

2.3 发现机制

当 MCP Client 连接到 Server 时,会进行一次"初始化握手"(Initialize Handshake)。在此过程中,Server 会通过 list_toolslist_resources 接口告诉 Client 它能做什么、拥有什么。这种动态发现机制使得 AI 系统具备了极强的灵活性------你可以随时热拔插不同的 MCP Server,而无需修改 Client 的核心逻辑。

3. Spring AI 生态下的 MCP 支持架构

Spring 框架一向擅长抽象。在 Spring AI 中,对 MCP 的支持并非简单的 API 调用,而是深度的生态整合。Spring AI 为开发者提供了 McpClientMcpServer 两个核心抽象,并配套了自动配置逻辑。

3.1 为什么选择 Spring AI

Java 开发者在构建 AI 应用时,最担心的就是与模型厂商绑定太死。Spring AI 通过统一的 ChatClient 抽象层,屏蔽了 OpenAI、Anthropic、DeepSeek 等不同厂商的 API 差异。当 MCP 引入后,这种抽象优势被进一步放大:

  • 函数调用的自动转换:Spring AI 能自动将 MCP Server 提供的 Tools 转换为 LLM 能够识别的 Function Calling 定义。
  • 依赖注入的无缝衔接 :你可以像配置数据源一样,在 application.yml 中定义 MCP 服务器的连接信息。
  • 生命周期管理:Spring 容器负责 MCP 连接的创建、保活与优雅关闭。

3.2 架构分层

在 Spring AI MCP 架构中,通常分为三层:

  1. Transport 层:处理字节流到 JSON-RPC 消息的转换(SSE 或 Stdio)。
  2. Protocol 层 :处理 MCP 协议状态机,如 initializepinglist 等请求的响应。
  3. Feature 层:开发者编写的业务逻辑,即具体的 Tool 逻辑或 Resource 获取逻辑。

通过这种分层,Spring AI 确保了开发者只需要关注第 3 层,即真正的业务价值所在。

4. 实战:从零构建一个 Spring Boot MCP Server

在本节中,我们将实战编写一个基于 Spring Boot 的 MCP Server。这个 Server 将提供一个简单的工具:查询企业内部的实时库存状态。

4.1 引入依赖

首先,在 pom.xml 中引入 Spring AI 相关的 MCP Server SDK 依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
</dependency>

4.2 定义 Tool

我们不需要编写复杂的 JSON 定义,只需利用 Spring 的注解。创建一个 Service 类:

java 复制代码
@Service
public class InventoryService {

    @McpTool(name = "getInventory", description = "根据产品ID获取实时库存余量")
    public String getStockLevel(@McpToolParameter(description = "产品唯一编码") String productId) {
        // 这里可以是数据库查询逻辑
        return "产品 " + productId + " 当前库存为:150 件";
    }
}

@McpTool 注解告诉 Spring AI,这个方法需要作为 MCP 工具暴露出去。Spring 会自动生成符合 MCP 标准的 JSON Schema。

4.3 配置传输方式

application.properties 中,我们选择 SSE 模式:

properties 复制代码
spring.ai.mcp.server.transport=webflux-sse
spring.ai.mcp.server.path=/mcp/v1/sse

此时,启动应用,你的 MCP Server 就已经准备就绪。它不仅能被 Spring AI Client 调用,甚至可以连接到 Claude Desktop 或其他支持 MCP 的开源 AI 平台。

5. 客户端集成:让 Spring AI 驱动 MCP 工具

拥有了 Server 之后,我们需要在主应用(MCP Client)中消费这些工具。

5.1 配置 MCP Client

在 Client 应用中,我们需要定义如何连接到刚才创建的 Server:

java 复制代码
@Configuration
public class McpClientConfig {

    @Bean
    public McpClient mcpClient() {
        McpTransport transport = new SseClientTransport("http://localhost:8081/mcp/v1/sse");
        return McpClient.using(transport).sync();
    }
}

5.2 将 MCP 工具绑定到 ChatClient

这是最关键的一步。我们需要将从 MCP Server 获取到的工具,动态地注入到 Spring AI 的对话模型中:

java 复制代码
@RestController
public class ChatController {

    private final ChatClient chatClient;
    private final McpClient mcpClient;

    public ChatController(ChatClient.Builder builder, McpClient mcpClient) {
        // 在构建 ChatClient 时,通过 mcpClient 自动发现并绑定工具
        this.chatClient = builder
                .defaultAdvisors(new McpToolCallingAdvisor(mcpClient))
                .build();
        this.mcpClient = mcpClient;
    }

    @GetMapping("/ask")
    public String ask(@RequestParam String prompt) {
        return chatClient.prompt(prompt).call().content();
    }
}

McpToolCallingAdvisor 是 Spring AI 提供的一个强大组件。它会自动向 MCP Server 请求工具列表,并将其作为 ChatOptions 传递给 LLM。当模型决定调用工具时,Advisor 会拦截请求、调用远程 MCP Server 并返回结果给模型,整个过程对开发者几乎透明。

6. 进阶模式:多服务器编排与动态资源管理

在复杂的企业场景中,一个 Agent 可能需要同时连接多个 MCP Server:一个负责查数据库,一个负责发邮件,还有一个负责从文档库检索。

6.1 多 Server 聚合

Spring AI 允许你配置一个 CompositeMcpClient。它像是一个代理,将来自不同物理服务器的 Tools 和 Resources 聚合成一个逻辑上的整体。

  • 冲突检测:当两个服务器提供同名工具时,可以通过 Prefix(前缀)进行区分。
  • 并发调用:对于不相关的工具调用,Client 可以并行发起请求,缩短响应延迟。

6.2 动态 Resource 注入

除了 Tools,Resources 的利用同样重要。例如,你可以定义一个 Resource,其 URI 为 myserver://logs/today。当用户问"今天有什么系统异常吗?"时,应用可以先从 MCP Server 读取该资源内容,将其作为 System Message 的一部分喂给模型。 Spring AI 提供了 McpResourceAdvisor,它可以基于向量检索或特定规则,动态地将 MCP 资源内容注入到上下文窗口中,从而实现高效的 RAG(检索增强生成)流程。

7. 性能优化与安全注意事项

在实战中,如果不注意细节,MCP 系统可能会面临性能瓶颈或安全风险。

7.1 上下文窗口管理

MCP 允许模型访问大量的外部资源,但这很容易撑爆模型的上下文窗口(Context Window)。

  • 精简输出:确保 MCP Server 返回的数据是精简后的。如果是一个 10MB 的日志文件,不应全部返回,而应先由 Server 进行初步筛选。
  • Token 监控 :利用 Spring AI 的 ChatResponse 元数据监控 Token 消耗,防止因为工具返回数据量过大导致高昂的 API 账单。

7.2 安全性保障

  • 工具执行隔离:MCP Server 执行的操作必须在受控环境下。例如,执行 Shell 命令的工具应具备严格的权限控制。
  • 输入校验 :LLM 可能会生成恶意或畸形的参数。在 MCP Server 端,必须对接收到的 productId 等参数进行严格的 Schema 校验。
  • 身份验证:对于 SSE 模式,务必在 HTTP 层面增加 OAuth2 或 API Key 认证,防止 MCP Server 被未授权访问。

7.3 超时与重试

网络调用总是不稳定的。在配置 McpTransport 时,应设置合理的请求超时时间,并结合 Spring Retry 实现重试机制,确保 Agent 在面对网络波动时依然健壮。

8. 综合案例:构建一个企业级知识库助手

让我们串联起所有知识点,构思一个完整的场景:一个"企业入职咨询助手"。

  1. 数据源:员工手册存储在 Git 仓库,实时考勤数据在 SQL 数据库。
  2. MCP Server A (Git-Server) :暴露一个 Resource git://hr/handbook,定期抓取手册内容。
  3. MCP Server B (Attendance-Server) :提供一个 Tool query_attendance(userId)
  4. Spring AI Client
    • 用户问:"我下周一请假怎么操作?"
    • Client 发现问题涉及请假规则,通过 Advisor 获取 git://hr/handbook 的内容作为上下文。
    • 模型读取手册后回答:"请通过 OA 系统提交申请,你想查一下你当前的剩余假期吗?"
    • 用户答:"好,帮我查查。"
    • 模型调用 query_attendance 工具,从 Server B 获取实时数据并返回。

通过 MCP,上述逻辑不再是硬编码的 if-else,而是模型在标准协议驱动下,自主、动态地选择和使用资源的过程。这正是未来 AI 软件架构的核心特征。


学习路线与实践建议

对于希望跟进 Spring AI + MCP 的新手,建议按照以下阶段进行学习:

第一阶段:夯实基础(1-2 周)

  • Java 17+ 与 Spring Boot 3.x:这是 Spring AI 的前置条件。
  • JSON-RPC 2.0 规范:理解 MCP 通讯的底层格式。
  • Spring AI 核心概念 :熟悉 ChatClientPromptAdvisor 的用法。

第二阶段:MCP 协议入门(1 周)

  • 阅读 MCP 官方文档,理解什么是 Host、Client 和 Server。
  • 安装 Claude Desktop,尝试连接几个开源的 MCP Server(如 Filesystem, Google Search),感受 MCP 的实际效果。

第三阶段:代码实战(2 周)

  • 动手写 Server:仿照本文第 4 节,写一个能连接你本地数据库或调用某个第三方 API 的 MCP Server。
  • 手动接入 Client :在 Spring Boot 应用中配置 McpClient,并尝试手动发起一次 listTools 调用。
  • 集成 ChatClient :使用 McpToolCallingAdvisor 实现自动工具调用。

第四阶段:进阶与调优(持续)

  • 探索 SSE 传输:在分布式环境下部署你的 MCP Server。
  • 安全加固:学习如何在 MCP 通讯中加入认证与授权。
  • 关注社区 :Spring AI 更新非常快,关注 Spring AI GitHub 的最新 Release Note。

实践建议: 不要试图一次性构建复杂的 Agent。从一个简单的"计算器"工具或"本地文件读取"工具开始,调通整个链路后,再引入复杂的业务逻辑。记住,AI 开发中,Prompt 的质量与工具定义的描述(Description)同样重要,花点时间打磨工具的描述,能显著提升模型调用的准确率。

相关推荐
木井巳2 小时前
【递归算法】快速幂解决 pow(x,n)
java·算法·leetcode·深度优先
风景的人生2 小时前
mybatis映射时候的注意点
java·mybatis
墨夶2 小时前
Java冷热钱包:不是所有钱包都叫“双保险“!用户资产安全的终极守护者
java·安全·区块链
我要神龙摆尾3 小时前
约定俗成的力量--java中泛型的意义和用法
java·开发语言
毅炼4 小时前
hot100打卡——day14
java·数据结构·算法·leetcode·ai·深度优先·哈希算法
C雨后彩虹4 小时前
优雅子数组
java·数据结构·算法·华为·面试
一嘴一个橘子4 小时前
springmvc 全局异常处理 and 拦截器
java
wangmengxxw4 小时前
SpringAI-mysql
java·数据库·人工智能·mysql·springai
Coder_Boy_4 小时前
基于SpringAI的在线考试系统-数据库设计核心业务方案
java·数据库·spring boot·ddd·tdd