1. 项目概述:为什么Spring AI 2.0.0-M3的MCP集成值得关注
如果你最近在关注AI应用开发,特别是基于Spring Boot构建AI驱动的服务,那么Spring AI 2.0.0-M3这个里程碑版本绝对值得你花时间深入研究。这个版本的核心亮点,无疑是引入了对MCP(Model Context Protocol)的原生支持。这听起来可能只是一个技术协议的集成,但它的意义远不止于此。简单来说,MCP的引入,正在悄然改变我们构建AI应用时与外部工具、数据和系统交互的方式,让AI从“一个聪明的聊天机器人”真正变成一个能替你“动手干活”的智能体。
在过去,无论是用LangChain还是早期的Spring AI,我们想让大语言模型(LLM)去操作数据库、调用API或者读取文件,通常需要写大量的胶水代码。你需要定义工具(Tools)的描述,处理复杂的输入输出解析,还要确保模型能正确理解在什么场景下该调用哪个工具。这个过程繁琐且容易出错,尤其是在工具数量增多、参数变复杂的时候。MCP协议的出现,就是为了标准化这个“让AI使用工具”的过程。它定义了一套服务端(提供工具和数据)与客户端(通常是AI应用或AI Agent)之间的通用通信规范。
Spring AI 2.0.0-M3这次将MCP作为一等公民集成进来,意味着你现在可以用一种声明式、标准化的方式,为你的Spring AI应用注入强大的“动手能力”。你可以轻松连接到一个MCP服务器,这个服务器可能提供了访问公司内部数据库的接口、一套内部API、甚至是控制智能家居设备的指令集。然后,你的AI应用就能通过标准协议发现并使用这些工具,无需为每个工具编写特定的集成代码。这极大地降低了构建复杂AI Agent的门槛,也提升了系统的可维护性和可扩展性。对于正在探索AI应用落地的团队和个人开发者而言,这个特性可能成为技术选型中的一个关键加分项。
2. MCP协议深度解析:它如何重塑AI与工具的交互范式
要理解Spring AI这次集成的价值,我们得先抛开代码,看看MCP到底解决了什么根本问题。你可以把MCP想象成AI世界的“USB协议”。在USB协议出现之前,每个外设(鼠标、键盘、打印机)都需要自己的专用接口和驱动,混乱且不兼容。USB协议定义了一套标准,让所有设备都能通过相同的物理接口和通信方式与电脑对话。MCP之于AI工具,就扮演着类似的角色。
2.1 MCP的核心组件与工作流程
MCP协议的核心围绕着几个关键概念展开,理解它们对后续的实操至关重要。
首先是资源(Resources)。资源代表了MCP服务器能提供的数据或内容块。比如,一个数据库MCP服务器可能将“用户表”定义为一个资源,一个文件系统MCP服务器可能将“/docs/readme.md”文件定义为一个资源。客户端可以列出(list)和读取(read)这些资源。这解决了AI需要获取结构化或非结构化上下文信息的需求。
其次是工具(Tools)。这是MCP的灵魂。工具代表了可执行的操作。每个工具都有明确的名称、描述和参数模式(通常用JSON Schema定义)。例如,“执行SQL查询”、“发送邮件”、“生成图表”都可以是工具。当AI模型决定要执行某个动作时,它会请求客户端调用对应的工具,并传入参数。
整个交互流程可以简化为以下几步:
- 连接与初始化:Spring AI应用(作为MCP客户端)连接到MCP服务器(例如,一个本地运行的、提供了公司CRM API工具集的服务器)。
- 发现:客户端向服务器请求可用的资源列表和工具列表。服务器返回这些对象的元数据,包括详细的描述和输入规范。
- 集成到AI上下文:Spring AI框架将这些获取到的工具描述,以一种模型能理解的方式(通常是格式化的文本提示)注入到每次与AI模型对话的上下文(System Prompt或类似机制)中。模型由此知道“我现在有哪些能力可以用”。
- 调用与执行:在对话过程中,当模型判断需要执行某个操作(如“帮我查一下上个月的销售额”),它会输出一个结构化的请求,指明要调用哪个工具以及参数是什么。Spring AI框架截获这个请求,将其转换为对MCP服务器的标准调用。
- 结果返回:MCP服务器执行工具(比如,真的去查询了数据库),将结果返回给客户端。客户端再将这个结果作为新的上下文信息反馈给AI模型,让模型基于结果继续生成回答。
这个流程的关键在于标准化和声明式。工具提供者(MCP服务器)只需要按照协议暴露接口,工具使用者(AI应用)只需要按照协议去发现和调用,双方不再需要紧密的代码耦合。
2.2 与传统“工具调用”模式的对比
在没有MCP的时代,Spring AI或类似框架也有工具调用的能力,但实现方式通常是“硬编码”或“紧耦合”的。你需要:
- 在应用代码中定义Java方法,并用
@Tool之类的注解标记。 - 为这个方法编写详细的描述字符串。
- 框架在运行时通过反射收集这些工具,并将描述拼接到提示词中。
这种方式的问题在于:
- 灵活性差:工具和业务代码绑定,要新增或修改一个工具,必须修改应用代码并重新部署。
- 复用性低:一套工具很难被另一个不同的AI项目直接使用。
- 语言/生态绑定:工具通常需要用框架支持的语言(如Java)编写,无法直接集成用Python、Go等语言编写的现有服务。
MCP通过将工具“服务化”和“协议化”,完美解决了这些问题。工具逻辑可以独立部署在任何地方,用任何语言编写,只要它遵守MCP协议。你的Spring AI应用就像一个通用的工具调用器,可以随时接入不同的工具服务器,动态扩展其能力。这种架构非常符合云原生和微服务的设计理念。
3. Spring AI 2.0.0-M3中MCP集成的实操详解
理论讲清楚了,我们来看在Spring AI 2.0.0-M3中具体如何用起来。目前MCP支持还处于早期阶段,但核心的客户端功能已经可用,让我们能快速搭建一个演示环境。
3.1 环境准备与项目初始化
首先,你需要一个Spring Boot 3.x的项目。我推荐使用 start.spring.io 快速生成,依赖选择上,除了基础的Spring Web,核心是Spring AI。由于M3是里程碑版本,你可能需要配置Spring的里程碑仓库。
在你的pom.xml中,需要添加Spring AI的依赖和仓库配置:
<!-- 在pom.xml中添加Spring Milestone仓库 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <dependencies> <!-- Spring Boot基础依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring AI 核心依赖 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-core</artifactId> <version>2.0.0-M3</version> </dependency> <!-- 你需要使用的具体AI模型连接器,例如OpenAI --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> <version>2.0.0-M3</version> </dependency> <!-- MCP 客户端依赖 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-client</artifactId> <version>2.0.0-M3</version> </dependency> </dependencies>注意:版本号
2.0.0-M3表明这是第三个里程碑版本,API可能仍有变动,不建议直接用于生产环境,但非常适合学习和原型验证。
接下来,你需要一个MCP服务器来连接。为了快速演示,我们可以使用一个现成的、功能简单的MCP服务器。社区有一些开源示例,比如一个提供“计算器”和“获取天气”等模拟工具的服务器。你可以用Node.js或Python快速启动一个。这里假设我们有一个运行在http://localhost:8081的MCP服务器。
3.2 配置MCP客户端并注入工具
Spring AI通过自动配置和ApplicationRunner让我们可以很方便地在应用启动后连接MCP服务器。核心的配置类叫做McpClientProperties,我们可以在application.yml中配置:
# application.yml spring: ai: mcp: client: enabled: true # 启用MCP客户端 servers: my-mcp-server: # 自定义服务器名称 transport: sse # 传输协议,支持SSE (Server-Sent Events) 或 stdio endpoint: http://localhost:8081/sse # MCP服务器的SSE端点 # 如果是stdio协议,则需要配置command,用于启动服务器进程 # command: ["node", "/path/to/mcp-server.js"]然后,我们需要创建一个配置类或组件,在启动时获取MCP工具并注册到Spring AI的ToolCaller或ChatClient中。以下是一个典型的@Component示例:
import jakarta.annotation.PostConstruct; import org.springframework.ai.mcp.client.McpClient; import org.springframework.ai.mcp.client.McpClientFactory; import org.springframework.ai.model.tool.ToolCallingUtils; import org.springframework.ai.service.AiService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; @Component public class McpToolRegistrar { private final McpClientFactory mcpClientFactory; private final AiService aiService; // 或者注入 ChatClient @Autowired public McpToolRegistrar(McpClientFactory mcpClientFactory, AiService aiService) { this.mcpClientFactory = mcpClientFactory; this.aiService = aiService; } @PostConstruct public void registerMcpTools() { // 1. 获取配置的MCP客户端(对应yml中的‘my-mcp-server’) McpClient mcpClient = mcpClientFactory.getClient("my-mcp-server"); // 2. 从MCP服务器获取所有可用工具的定义 List<ToolSpecification> toolSpecs = mcpClient.listTools(); // 3. 将这些工具注册到AI服务上下文中 // 具体方法取决于你使用的AI服务抽象层 // 如果是直接使用 ChatClient,可能需要通过 ChatOptions 注入 // 这里以假设的AiService接口为例 ToolCallingUtils.registerTools(aiService, toolSpecs); System.out.println("Registered " + toolSpecs.size() + " tools from MCP server."); } }这段代码的关键在于McpClient.listTools(),它通过MCP协议与服务器通信,获取到所有工具的元数据(名称、描述、参数schema)。注册成功后,这些工具的描述就会被自动添加到后续每次与AI模型对话的系统指令中。
3.3 编写一个简单的对话控制器进行测试
现在,我们可以创建一个REST端点来测试工具调用是否生效。我们创建一个简单的ChatController:
import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.SystemPromptTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Map; @RestController public class ChatController { private final ChatClient chatClient; // ChatClient 应该已经被Spring AI自动配置,并注入了我们从MCP获取的工具 public ChatController(ChatClient chatClient) { this.chatClient = chatClient; } @GetMapping("/chat") public String chat(@RequestParam String message) { // 构建一个系统提示,引导模型在需要时使用工具 String systemText = """ 你是一个有帮助的AI助手。你可以使用以下工具来帮助用户: - 如果用户问及计算,请使用计算器工具。 - 如果用户问及天气,请使用天气查询工具。 请根据用户的问题,判断是否需要以及使用哪个工具,并给出最终答案。 """; Prompt prompt = new Prompt( message, new SystemPromptTemplate(systemText).createMessage() ); ChatResponse response = chatClient.call(prompt); return response.getResult().getOutput().getContent(); } }启动你的Spring Boot应用和MCP服务器。访问http://localhost:8080/chat?message=请计算一下125乘以38等于多少。如果一切顺利,会发生以下事情:
- 你的请求和系统提示被发送给AI模型(如GPT-4)。
- AI模型从上下文中知道有一个“计算器”工具可用,并决定调用它。
- 模型会输出一个结构化的工具调用请求。
- Spring AI框架拦截这个请求,通过我们之前注册的MCP客户端,将调用转发到
http://localhost:8081的MCP服务器。 - MCP服务器执行计算逻辑,返回结果“4750”。
- 框架将结果“4750”作为新的上下文信息再次发送给AI模型。
- AI模型生成最终回答:“125乘以38等于4750。”
你会在应用日志中看到工具被调用和返回结果的详细过程。这个过程完全自动化,你的业务代码里没有出现任何计算逻辑,计算能力是通过协议从外部“注入”的。
4. 重大升级特性盘点:超越MCP的其他关键改进
Spring AI 2.0.0-M3不仅仅只有MCP。作为一个大版本的主要里程碑,它包含了一系列旨在提升开发者体验、稳定性和功能的重大改进。了解这些改进能帮助你在未来版本稳定后更好地规划升级。
4.1 全新且更稳定的API设计
Spring AI 1.x的API在快速迭代中经历了一些变化,而2.0.0-M3标志着API开始走向稳定和成熟。一些关键的改进包括:
ChatClient成为核心交互入口:与AI模型的交互被进一步抽象和统一到ChatClient接口下。这个接口提供了流式和非流式调用、函数(工具)调用集成、结构化输出等高级功能的统一访问方式,减少了直接操作底层ChatModel的复杂度。- 强类型化的
ChatOptions:用于配置每次对话行为的选项(如温度、top_p、工具定义等)现在有了更清晰、类型安全的构建方式。例如,添加工具不再需要拼接字符串,而是通过ToolSpecification对象。 - 更清晰的职责分离:
Prompt、Message、ChatResponse等核心概念的定义更加精确,减少了歧义。例如,SystemMessage、UserMessage、AssistantMessage和ToolMessage的区分,使得对话历史的管理和工具调用结果的回传更加符合OpenAI等主流API的规范。
这些API变化的目标是减少“魔法”,让代码意图更清晰,同时也为未来集成更多类型的模型和能力打下坚实基础。在从1.x迁移时,你需要仔细阅读迁移指南,但付出这份努力是值得的,因为新的API更健壮,也更面向未来。
4.2 向量存储与检索增强检索(RAG)能力优化
检索增强生成(RAG)是当前AI应用的主流模式之一,Spring AI对其支持进行了显著增强。
- 向量存储接口标准化与扩展:对
VectorStore接口进行了加固,支持了更丰富的查询选项,如元数据过滤(filtering)、混合搜索(hybrid search,结合关键词和向量相似度)以及搜索结果的分数(similarity score)返回。这使得构建复杂的文档问答系统更加得心应手。 - 文档加载与处理的流水线化:新增或改进了许多
DocumentReader和TextSplitter的实现。现在你可以更容易地构建一个从PDF、Word、HTML、Markdown等格式读取内容,经过清洗、分块,最后存入向量数据库的完整流水线。这个流水线可以与Spring Batch或Spring Integration更好地结合,实现大规模文档的离线处理。 - 更灵活的检索上下文构建:在RAG流程中,如何将检索到的文档片段组合成有效的上下文提示(Prompt)是关键。新版本提供了更多可配置的
PromptTemplate和上下文组织策略,让你可以轻松实现“多路召回、重排序、精炼合成”等高级RAG模式。
4.3 模型供应商连接器的持续丰富与改进
Spring AI的核心价值之一在于对多种AI模型供应商的统一抽象。在2.0.0-M3中,各个连接器(如OpenAI、Anthropic Claude、Azure OpenAI、Ollama、Vertex AI等)都更新到了最新的供应商API版本,并修复了大量已知问题。
特别值得一提的是对本地模型支持的加强。通过Ollama连接器,你可以非常方便地在本地运行Llama 3、Mistral、Gemma等开源模型,并享受与商用API相同的编程接口。这对于开发测试、成本敏感场景或数据隐私要求高的项目来说,是一个巨大的利好。配置简单到只需要在application.yml中设置spring.ai.ollama.base-url=http://localhost:11434,然后就可以像调用GPT一样调用本地模型了。
4.4 可观测性(Observability)与监控能力初现
构建生产级AI应用,可观测性必不可少。2.0.0-M3开始引入更完善的监控支持。
- 与Micrometer深度集成:关键操作(如模型调用、令牌使用、耗时)现在会自动生成Metrics指标,你可以轻松地将这些指标导出到Prometheus、Datadog等监控系统,从而跟踪AI调用的成本、延迟和成功率。
- 结构化的日志输出:工具调用、模型请求/响应等关键事件的日志格式更加结构化,便于使用ELK或Loki等日志聚合工具进行分析和告警。
- 初步的分布式追踪支持:在微服务架构中,一个用户请求可能触发多次AI调用和工具调用。新版本开始尝试与OpenTelemetry等追踪标准集成,帮助你在复杂的调用链中定位性能瓶颈和故障点。
虽然这部分功能还在演进中,但方向很明确:让AI应用的运维像运维普通微服务一样透明和可控。
5. 实战中的挑战、注意事项与迁移建议
拥抱新特性总是伴随着挑战。基于我对M3版本的初步探索,这里分享一些实战中可能遇到的问题和我的建议。
5.1 MCP集成的当前局限与应对策略
首先必须明确,Spring AI 2.0.0-M3中的MCP支持是客户端支持。这意味着Spring AI可以作为一个MCP客户端,去连接和使用已有的MCP服务器。但是,Spring AI目前没有提供开箱即用的、将你现有的Spring Boot服务快速暴露为MCP服务器的工具库或注解(类似@Tool的MCP服务器版)。这是当前最大的一个“期望落差”。
应对策略:
- 寻找现有的MCP服务器:社区已经有一些优秀的MCP服务器实现,例如:
mcp-server-sqlite:提供SQLite数据库操作工具。mcp-server-filesystem:提供文件系统访问工具。anthropic官方也维护了一些示例服务器。你可以从这些项目开始,了解MCP服务器的构建方式。
- 自行实现MCP服务器:如果你需要将自定义业务能力暴露为工具,目前需要参考MCP协议规范,用其他语言(如TypeScript/Python,因为现有SDK丰富)自行实现一个服务器。这是一个额外的开发成本,但一旦实现,它可以被任何兼容MCP的客户端(不限于Spring AI)使用,长期看是值得的。
- 期待社区发展:随着MCP协议被更多项目采纳(如Cursor IDE、Claude Desktop都已支持),预计会有更多语言的服务器SDK出现,也可能会有Spring Native的MCP服务器实现。
5.2 从Spring AI 1.x迁移到2.0.0-M3的挑战
API的演进意味着 breaking changes。如果你有基于1.x的项目,升级到M3需要仔细调整。
- 包名和类名变更:一些核心类所在的包名和类名发生了变化。例如,一些类可能从
org.springframework.ai.chat下的子包移动到了更合理的位置。IDE的重构工具和查找替换功能会是你的好朋友。 - 配置属性前缀变化:
application.yml中的配置项前缀可能从spring.ai.*的某些部分发生了调整。务必对照新版本的官方文档或配置元数据(spring-configuration-metadata.json)进行检查。 ChatClient的广泛使用:在1.x中,你可能直接注入了ChatModel并调用其call方法。在2.0中,更鼓励使用ChatClient作为主要接口。ChatClient提供了更流畅的API(Fluent API),虽然学习曲线略有增加,但功能更强大。- 工具调用API重写:如果你之前使用了
@Tool注解的方式定义工具,这部分代码需要重写。你需要将工具逻辑迁移到一个独立的MCP服务器中,或者等待Spring AI未来提供将@Tool方法自动暴露为MCP端点的支持(如果该特性被实现)。
建议:对于现有项目,不要急于升级到里程碑版本。可以先用一个全新的分支或小项目进行技术验证,熟悉新的API和模式。等待2.0.0正式发布(GA)后,再制定详细的迁移计划。
5.3 生产环境使用的考量
尽管M3版本带来了激动人心的特性,但“M”代表里程碑,并非稳定版。用于生产环境需要极度谨慎。
- API稳定性:在正式版(GA)发布前,API仍可能发生变动。这意味着你现在基于M3写的代码,在未来可能需要修改。
- 功能完整性:一些高级特性,如MCP服务器的Spring Boot集成、复杂工具调用的事务管理、更细粒度的安全控制(哪些工具可以被哪些AI模型调用)可能还不完善或处于规划中。
- 社区与生态:MCP是一个新兴协议,其工具生态(可用的公共MCP服务器)和Spring AI对其的支持都处于早期阶段。你可能需要自己解决一些集成上的小问题。
我的建议是:将Spring AI 2.0.0-M3用于:
- 原型设计与验证:快速验证AI应用创意,特别是需要复杂工具调用的Agent类应用。
- 技术选型评估:深入理解MCP协议和Spring AI的新架构,评估其是否适合解决你未来的业务问题。
- 内部工具开发:对于不直接面向外部用户、对稳定性要求相对较低的内部效率工具,可以尝试使用。
6. 展望:MCP与Spring AI生态融合的未来想象
Spring AI集成MCP,不是一个孤立的功能更新,它指向了一个更宏大的未来:可组合的AI应用架构。我们可以做一些大胆且合理的想象。
想象一:企业内部AI能力市场。各个业务团队(数据团队、运维团队、客服团队)可以将自己的核心能力(数据查询API、运维脚本、知识库)封装成标准的MCP服务器。中央的AI应用平台(基于Spring AI)就像一个“AI能力交换机”,可以根据需求动态接入这些服务器。想要构建一个跨部门的智能助手?只需要在配置文件中添加几个MCP服务器地址,这个助手就立刻拥有了调用全公司核心系统的能力。这极大地促进了AI能力的复用和跨团队协作。
想象二:AI应用开发范式的转变。未来的AI应用开发者,可能只需要关注两件事:1.Prompt工程与流程编排:设计AI Agent的思考逻辑和任务流程。2.MCP工具集成:通过配置或简单代码,将所需的外部工具“插接”到Agent上。而具体的工具实现,可以由更专业的后端团队用最合适的技术栈去完成。这种关注点分离,能让AI应用开发更快、更专业。
想象三:动态、安全的工具治理。MCP协议本身可以扩展,集成更丰富的元数据,比如工具所需的权限级别、调用成本、性能SLA等。Spring AI未来可以在此基础上,实现动态的工具路由和策略。例如,对于同一个“查询数据库”的工具,根据提问用户的权限,Spring AI可以决定是连接到有数据脱敏规则的MCP服务器A,还是连接到全量数据的服务器B。这为构建企业级、合规的AI应用提供了基础。
Spring AI 2.0.0-M3通过拥抱MCP,迈出了走向这个未来的坚实一步。它不再仅仅是一个连接大模型的客户端库,而是正在演变成一个构建下一代、工具增强型AI应用的框架。对于开发者而言,现在正是深入了解这些概念和技术的最佳时机。即使短期内不直接用于生产,掌握这些范式也会让你在即将到来的AI应用开发浪潮中占据先机。