Spring AI 实战系列(十):MCP深度集成 —— 工具暴露与跨服务调用


系列栏目:Spring AI

Spring AI 实战教程(一)入门示例

Spring AI 实战系列(二):ChatClient封装,告别大模型开发样板代码

Spring AI 实战系列(三):多模型共存+双版本流式输出

Spring AI 实战系列(四):Prompt工程深度实战

Spring AI 实战系列(五):结构化输出,让大模型严格适配你的业务数据模型

Spring AI 实战系列(六):Tool Calling深度实战,让大模型自动调用你的业务接口

Spring AI实战系列(七):Chat Memory实战,基于Redis实现持久化多轮对话

Spring AI 实战系列(八):多模态能力--文生图、语音合成与向量嵌入实战

Spring AI 实战系列(九):RAG检索实战 ------ 私有知识库

Spring AI 实战系列(十):MCP深度集成 ------ 工具暴露与跨服务调用

一、系列回顾与本篇定位

1.1 系列回顾

  • 第一篇至第九篇:我们完整掌握了Spring AI的核心能力 ------ 基础集成、ChatClient、多模型共存、Prompt 工程、结构化输出、Tool Calling、Chat Memory、多模态能力,以及最终的 RAG 检索增强生成。
  • 核心痛点:在Tool Calling实战中,我们的工具是与Spring Boot应用强绑定的,无法跨语言、跨服务复用,也无法接入社区丰富的第三方工具生态。

1.2 本篇定位

MCP (Model Context Protocol),正是解决这一痛点的开放标准:它定义了一套标准化的协议,让大模型能以统一的方式连接外部工具、数据源和服务,实现工具的跨语言、跨服务复用,同时接入社区丰富的 MCP 生态。

值得庆幸的是,Spring AI 1.0+ 版本已原生支持MCP协议,我们可以用极低的成本,将现有的 Spring 服务暴露为MCP Server,或者作为MCP Client调用本地 / 远程的 MCP 工具。

本篇是系列进阶实战篇,我们将深度拆解 Spring AI 与 MCP 的集成:

  • 从核心原理出发,理解什么是MCP、为什么要用MCP,以及它与Tool Calling的关系。
  • 基于现有代码,实现本地 Spring 服务暴露为 MCP 工具
  • 实现Spring AI 作为MCP Client,调用本地工具与远程MCP Server。
  • 覆盖 MCP 配置、安全管控、生产最佳实践与高频踩坑避坑指南。

二、核心概念拆解:MCP 与 Spring AI 的集成

2.1 什么是 MCP (Model Context Protocol)

MCP (Model Context Protocol) 是由 Anthropic 推出的开放协议 ,它的核心目标是:为大模型提供一套标准化的 "插件系统",让大模型能以统一的方式连接外部世界。

简单来说,MCP 定义了两个核心角色:

  1. MCP Server:暴露工具、资源和提示词模板的服务,可以是任何语言编写的(Python、Java、Go 等)。
  2. MCP Client:连接 MCP Server,调用其暴露的工具的客户端(如 Claude Desktop、Spring AI)。

2.2 MCP vs 传统 Tool Calling:有什么区别?

对比维度 传统Tool Calling MCP (Model Context Protocol)
绑定关系 工具与应用强绑定,无法跨服务复用 工具通过标准化协议暴露,跨语言、跨服务复用
生态 需自行开发所有工具 可接入社区丰富的 MCP 生态(如文件系统、浏览器、数据库等)
标准化 各框架实现不统一 开放协议,所有兼容 MCP 的客户端 / 服务端都能互通
Spring AI 支持 原生支持,通过@Tool注解 1.0 + 版本原生支持,可作为 Server 或 Client

2.3 Spring AI 对 MCP 的支持

Spring AI 1.0+ 版本对 MCP 提供了双向支持

  1. 作为 MCP Server :将 Spring Bean 中的@Tool方法,通过ToolCallbackProvider暴露为 MCP 工具。
  2. 作为 MCP Client:通过配置,连接本地或远程的 MCP Server,调用其暴露的工具。

三、实战落地:Spring AI 集成 MCP 全流程

3.1 环境前提

  • 已完成 JDK 17+、Spring Boot 3.2.x 环境搭建
  • 已配置阿里云百炼 API Key 环境变量DASHSCOPE_API_KEY
  • 已在pom.xml中引入Spring AI Alibaba Starter与MCP相关依赖:
java 复制代码
<!-- Spring AI Alibaba Starter -->
<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
    <version>1.0.0.2</version>
</dependency>
<!-- Spring AI MCP Client -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client</artifactId>
</dependency>

3.2 实战一:将本地 Spring 服务暴露为 MCP 工具

首先,我们将一个普通的 Spring Service,通过@Tool注解和ToolCallbackProvider,暴露为 MCP 工具。

第一步:定义工具服务

创建WeatherService,使用@Tool注解标记可调用的方法:

java 复制代码
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 天气查询服务:暴露为MCP工具
 */
@Service
public class WeatherService {

    /**
     * 根据城市名称获取天气预报
     * @param city 城市名称
     * @return 天气预报信息
     */
    @Tool(description = "根据城市名称获取天气预报")
    public String getWeatherByCity(String city) {
        // 模拟天气数据,生产环境可对接真实天气API
        Map<String, String> weatherData = Map.of(
                "北京", "降雨频繁,其中今天和后天雨势较强,需注意",
                "上海", "多云,15℃~27℃,南风3级,当前温度27℃。",
                "深圳", "阴16天,雨30天,晴3天"
        );
        return weatherData.getOrDefault(city, "抱歉:未查询到对应城市的天气信息!");
    }
}
第二步:配置 MCP Server 暴露工具

创建McpServerConfig,将WeatherService注册为ToolCallbackProvider

java 复制代码
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * MCP Server配置类:将本地工具暴露给外部调用
 */
@Configuration
public class McpServerConfig {

    /**
     * 将WeatherService中的@Tool方法暴露为MCP工具
     */
    @Bean
    public ToolCallbackProvider weatherTools(WeatherService weatherService) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(weatherService) // 传入包含@Tool方法的Bean
                .build();
    }
}
第三步:配置 ChatClient 集成 MCP 工具

修改LLMConfig,将 MCP 工具集成到ChatClient中:

java 复制代码
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * ChatModel+ChatClient+MCP集成配置类
 */
@Configuration
public class LLMConfig {

    /**
     * 配置带MCP工具支持的ChatClient
     */
    @Bean
    public ChatClient chatClient(ChatModel chatModel, ToolCallbackProvider tools) {
        return ChatClient.builder(chatModel)
                // 核心:将MCP工具注册到ChatClient
                .defaultToolCallbacks(tools.getToolCallbacks())
                .build();
    }
}

3.3 实战二:Spring AI 作为 MCP Client 调用工具

现在,我们编写 Controller,测试带 MCP 支持的ChatClient与普通ChatModel的区别。

第一步:配置 MCP Client(可选:连接远程 MCP Server)

application.properties中配置MCP Client,支持连接远程MCP Server:

java 复制代码
server.port=8002

# 编码格式配置
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8

spring.application.name=SAA-15LocalMcpClient

# Spring AI Alibaba 配置
spring.ai.dashscope.api-key=${DASHSCOPE_API_KEY}

# ==== MCP Client 配置 ====
spring.ai.mcp.client.type=async
spring.ai.mcp.client.request-timeout=60s
spring.ai.mcp.client.toolcallback.enabled=true
# 可选:连接远程MCP Server(示例:连接本地8001端口的MCP Server)
spring.ai.mcp.client.sse.connections.mcp-server1.url=http://localhost:8001
第二步:编写测试接口

创建McpClientController,对比带 MCP 支持和不带 MCP 支持的效果:

java 复制代码
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

/**
 * MCP Client测试接口
 */
@RestController
public class McpClientController {

    // 带MCP工具支持的ChatClient
    @Resource(name = "chatClient")
    private ChatClient chatClient;

    // 普通ChatModel(无MCP工具支持)
    @Resource
    private ChatModel chatModel;

    /**
     * 带MCP支持的对话接口
     * 访问示例:http://localhost:8002/mcpclient/chat?msg=上海的天气怎么样
     */
    @GetMapping("/mcpclient/chat")
    public Flux<String> chat(@RequestParam(name = "msg", defaultValue = "北京") String msg) {
        System.out.println("✅ 使用了MCP工具支持");
        return chatClient.prompt(msg).stream().content();
    }

    /**
     * 普通对话接口(无MCP支持)
     * 访问示例:http://localhost:8002/mcpclient/chat2?msg=上海的天气怎么样
     */
    @GetMapping("/mcpclient/chat2")
    public Flux<String> chat2(@RequestParam(name = "msg", defaultValue = "北京") String msg) {
        System.out.println("❌ 未使用MCP工具支持");
        return chatModel.stream(msg);
    }
}
接口测试说明
  1. 测试带 MCP 支持的接口

    • 访问http://localhost:8015/mcpclient/chat?msg=上海的天气怎么样
    • 大模型会自动识别需要调用getWeatherByCity工具,获取天气信息后生成回答。
  2. 测试普通接口

    • 访问http://localhost:8015/mcpclient/chat2?msg=上海的天气怎么样
    • 大模型没有工具支持,只能基于通用知识回答,可能会编造或说不知道。

四、进阶场景:连接远程 MCP Server

Spring AI MCP Client 不仅能调用本地工具,还能连接远程的 MCP Server,接入社区丰富的 MCP 生态。

4.1 连接远程 MCP Server 的配置

application.properties中添加远程 MCP Server 的连接配置:

bash 复制代码
# 连接多个远程MCP Server
spring.ai.mcp.client.sse.connections.mcp-filesystem.url=http://localhost:8001
spring.ai.mcp.client.sse.connections.mcp-browser.url=http://localhost:8003

4.2 调用远程 MCP Server 的工具

配置完成后,远程 MCP Server 暴露的工具会自动注册到ChatClient中,你可以像调用本地工具一样调用远程工具,无需修改任何代码。


五、实践建议

5.1 安全管控

  1. 工具权限控制:给不同的工具设置不同的权限,确保只有授权的用户能调用敏感工具。
  2. MCP Server 认证:如果连接远程 MCP Server,务必开启认证(如 API Key、OAuth2),避免未授权访问。
  3. 输入输出校验:对工具的输入参数和输出结果进行严格校验,防止注入攻击和敏感数据泄露。

5.2 监控与运维

  1. 工具调用监控:记录每次工具调用的时间、参数、结果、耗时,用于排查问题和优化性能。
  2. MCP 连接监控:监控远程 MCP Server 的连接状态,及时发现和处理连接中断。
  3. 日志记录:记录详细的 MCP 交互日志,便于调试和审计。

5.3 工具管理

  1. 工具文档化 :给每个工具添加清晰的description,说明工具的用途、参数含义和返回值格式。
  2. 工具版本管理:对工具进行版本管理,避免工具变更影响现有业务。
  3. 工具降级:当工具调用失败时,提供降级方案,确保大模型仍能给出合理的回答。

六、避坑指南

6.1 工具未被识别

  • 现象:大模型不会调用工具,提示 "没有可用的工具"。
  • 原因
    • 忘记将ToolCallbackProvider注册到ChatClient中。
    • @Tool注解的方法不是public的。
    • 方法参数类型不支持(大模型无法自动转换)。
  • 解决方案
    • 检查SaaLLMConfig中是否调用了defaultToolCallbacks(tools.getToolCallbacks())
    • 确保@Tool注解的方法是public的。
    • 使用简单的参数类型(如Stringint),避免复杂对象。

6.2 远程MCP Server连接失败

  • 现象:启动服务时报错,提示无法连接到远程 MCP Server。
  • 原因
    • 远程 MCP Server 未启动。
    • 配置文件中的 URL 错误。
    • 网络不通或防火墙阻止了连接。
  • 解决方案
    • 检查远程 MCP Server 是否正常启动。
    • 核对配置文件中的 URL。
    • 检查网络连接和防火墙规则。

6.3 大模型仍然编造信息

  • 现象:即使有MCP工具,大模型仍然编造信息。
  • 原因
    • 系统提示词不够严格。
    • 工具的description不够清晰,大模型不知道什么时候调用。
    • 温度设置得太高。
  • 解决方案
    • 在系统提示词中明确要求 "如果有工具可用,请优先调用工具,不要编造信息"。
    • 优化工具的description,清晰说明工具的用途和适用场景。
    • 调低温度至 0.1-0.3。

七、本篇总结

本篇我们深度掌握了Spring AI与MCP (Model Context Protocol) 的集成:

  • 从核心原理出发,理解了什么是 MCP、为什么要用 MCP,以及它与传统 Tool Calling 的区别。
  • 基于现有代码,实现了本地 Spring 服务暴露为MCP 工具
  • 实现了Spring AI 作为MCP Client,调用本地工具与远程MCP Server。
  • 覆盖了 MCP 配置、安全管控、生产最佳实践与高频踩坑避坑指南。

MCP 是大模型应用开发的未来趋势,它让我们能以标准化的方式连接外部工具和数据源,接入社区丰富的生态,大幅提升开发效率。


如果本系列教程对你有帮助,欢迎点赞、收藏、评论、转发,让更多的 Java 开发者能快速上手 Spring AI!

相关推荐
bIo7lyA8v2 小时前
从 ChangeTracker 到 SQL Batch 的性能诊断与优化
数据库·sql·batch
小码过河.2 小时前
Superpowers AI开发神器
人工智能
Yiyi_Coding2 小时前
Oracle 、 Mysql、Guass 的 sequence
数据库·mysql·oracle
OPHKVPS2 小时前
Swimlane发布AI SOC:深度Agent驱动的安全运营新时代
人工智能·安全
Gse0a362g2 小时前
cuDNN深度神经网络计算库简介及卷积操作示例
人工智能·神经网络·dnn
OPHKVPS2 小时前
Ni8mare高危漏洞来袭:黑客可远程劫持n8n服务器(CVE-2026-21858)
人工智能·microsoft
MX_93592 小时前
SpringMVC静态资源访问、annotation-driven的使用原理及数据响应模式
java·后端·spring
人间寥寥情难诉2 小时前
LRU算法本地实现
java·算法·spring
财经资讯数据_灵砚智能2 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(日间)2026年4月5日
大数据·人工智能·python·信息可视化·自然语言处理·ai编程