Spring AI + MCP :打通大模型与本地服务告别硬编码Function Calling 深度揭秘springboot模块化开发

 

前言

上一篇我们用Spring AI原生Function Calling,封装了第一个AI Skill。但有个很现实的痛点:函数定义、入参校验、业务逻辑全部耦合在Java代码里。 新增一个工具能力,就要改代码、重启服务;多团队协作时,前端、AI应用、后端服务都要同步改函数描述,维护成本很高。

MCP(Model Context Protocol,模型上下文协议)就是用来解决这个问题的。 它提供一套标准化协议,把业务能力包装成独立服务,大模型通过协议远程调用工具,不再和Spring业务代码强绑定。 本篇我们基于Spring Boot,搭建MCP服务端 + Spring AI客户端,做一个可直接跑通的实战案例:让AI调用我们的订单查询服务。

一、先理清核心关系:Skill、Function Calling、MCP到底是什么关系

很多同学容易把三者混在一起,一句话区分:

Function Calling:底层能力,大模型识别意图、调用指定函数的基础机制;AI Skill:业务层面的能力单元,比如订单查询、库存校验、邮件发送,Skill可以基于Function Calling实现,也可以基于MCP实现;MCP:标准化传输协议,是Skill的一种远程交付方式。简单比喻: Function Calling = 本地方法调用;MCP = 标准化RPC;Skill = 对外提供的业务功能。

架构简图:

大模型 ←→Spring AI MCP客户端 ←[MCP协议]→ MCP服务端 ←→ 你的Spring业务服务(订单、用户、库存)

优势: ✅ 工具能力独立部署,更新工具不用重启AI应用 ✅ 一套MCP服务,可以给多个AI Agent、多个大模型客户端复用 ✅ 协议标准化,Go/Python/Java写的服务都能互通 ✅ 职责解耦:AI应用只负责对话编排,业务能力收敛在MCP服务

二、环境依赖(Spring Boot 3.3.x + Spring AI 1.0.0-M1)

pom.xml核心依赖

<!-- Spring AI 核心 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> <!-- Spring AI MCP 客户端 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId> </dependency> <!-- MCP Server 基础包 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-server</artifactId> </dependency> <!-- Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>

说明:当前Spring AI对MCP支持高速迭代,版本尽量对齐,避免接口类找不到。

三、实战第一步:开发MCP服务端(提供订单查询Skill)

我们在MCP服务端,注册一个工具:queryOrderInfo,入参orderId,返回订单基础信息。

1. 订单实体与模拟业务Service

@Data @NoArgsConstructor @AllArgsConstructor public class OrderDTO { private String orderId; private String orderStatus; private BigDecimal amount; private LocalDateTime createTime; } @Service public class OrderService { // 模拟数据库查询 public OrderDTO getOrderById(String orderId) {return new OrderDTO(orderId, "PAID", new BigDecimal("299.00"), LocalDateTime.now()); } }

2. MCP Server 工具注册代码

MCP里通过@Tool注解暴露能力,这就是我们对外的Skill:

import org.springframework.ai.tool.annotation.Tool; import org.springframework.stereotype.Service; @Service public class OrderMcpTool { private finalOrderService orderService;public OrderMcpTool(OrderService orderService) { this.orderService = orderService; } @Tool(description = "根据订单号查询订单详情,用户想知道订单状态、金额时调用") public OrderDTO queryOrderInfo(String orderId) { if(orderId == null || orderId.isBlank()){ throw new IllegalArgumentException("订单号不能为空"); } returnorderService.getOrderById(orderId); } }

重点:description非常关键,大模型靠这段描述判断什么时候调用这个工具。

3. MCP Server启动配置(Stdio模式演示,本地调试首选)

lication.yml

spring: ai: mcp: server: stdio: true

启动这个服务,它会以stdio方式对外提供MCP协议能力;生产环境也可以切换成HTTP transport。

四、实战第二步:Spring AI MCP客户端对接,调用远程Skill

新建一个独立的Spring AI应用(对话入口),作为MCP客户端。 客户端不需要写任何订单查询逻辑,只需要连接MCP服务端,自动拉取全部可用Tool。

lication.yml(客户端配置)

spring: ai: openai: api-key: sk-xxx base-url: https://xxx mcp: client: servers: order-server: command: java args: - -jar - order-mcp-server.jar

配置含义:客户端启动时,拉起我们上面打包好的MCP服务端jar,通过stdio通信,自动发现所有@Tool。

对话Controller,直接使用MCP工具集

@RestController @RequestMing("/ai/chat") public class AiChatController { private final ChatClient chatClient; public AiChatController(ChatClient.Builder builder, McpToolCallbackProvider mcpToolCallbackProvider) { this.chatClient = builder .defaultTools(mcpToolCallbackProvider.getToolCallbacks()) .build(); } @PostMing public String chat(@RequestParam String message) { return chatClient.prompt(message).call().content(); } }

核心一行:McpToolCallbackProvider 自动把MCP服务端所有Skill注册成大模型可用工具,没有硬编码任何函数。

五、测试效果

请求:

POST /ai/chat?message=帮我查一下订单号ORD20261024001的订单信息

执行流程:

大模型识别意图:需要调用queryOrderInfoSpring AI客户端通过MCP协议,远程调用MCP服务端方法MCP服务端执行OrderService查询,返回结果大模型整理结果,自然语言回复用户

返回示例:

你查询的订单ORD20261024001状态为已支付,金额299.00元。

现在如果我要新增一个【查询物流】的Skill: ✅ 只需要在MCP服务端新增一个@Tool方法,重启MCP服务; ✅ AI对话客户端不用改一行代码、不用重启,自动感知新增工具。 这就是MCP对比原生Function Calling最大的优势。

六、生产踩坑点(后端重点关注)

传输模式选择 Stdio:适合本地调试、单机部署;多进程模式,不适合高并发; HTTP Transport:生产推荐,支持远程独立部署MCP服务,多客户端共享。权限控制缺失MCP协议本身不带鉴权,业务上要自己加token校验、入参脱敏、接口限流;工具描述规范 description尽量写清楚触发场景、入参含义,描述模糊会导致大模型乱调用工具;异常兜底 MCP服务抛出的异常会透传给大模型,必须做好异常封装,不要把堆栈返回给LLM;版本兼容 Spring AI MCP包还在孵化,升级前务必回归测试Tool发现、参数序列化逻辑。

七、MCP和原生Function Calling怎么选?给你选型结论

选原生Function Calling:简单Demo、单一应用、工具很少、快速验证想法;开发快,依赖少。选MCP:多Agent复用工具、多团队协作、工具频繁变更、业务能力需要独立运维;解耦优先。

MCP不是用来替代Function Calling的,它是Function Calling的远程标准化封装。底层依旧是工具调用思想。

八、下篇预告

下一篇我们进入Harness工程化管控:当MCP服务越来越多、几十上百个AI Skill分散在各个服务,如何统一注册、权限、灰度、日志、调用链路监控? 《Spring AI Harness实战:AI Skill平台治理,统一管控MCP工具集群》

为您推荐

Spring AI + MCP :打通大模型与本地服务告别硬编码Function Calling 深度揭秘springboot模块化开发

Spring AI + MCP :打通大模型与本地服务告别硬编码Function Calling 深度揭秘springboot模块化开发

前言上一篇我们用Spring AI原生Function Calling,封装了第一个AI Skill。但有个很现实的痛点:函数定义、入参...

2026-11-07 栏目:互联网+

当前非电脑浏览器正常宽度,请使用移动设备访问本站!