当前位置: 首页 > news >正文

Spring AI + MCP Client 配置与使用详解

前言

随着大模型技术的快速发展,Model Coordination Protocol (MCP) 逐渐成为连接本地系统和远程AI服务的重要桥梁。Spring AI 是 Spring 官方推出的 AI 开发框架,支持多种语言模型接口,而 MCP Client 则是其集成远程推理能力的核心组件之一。

本文将详细介绍如何在 Spring Boot 项目中配置和使用 Spring AI 的 MCP Client,包括环境准备、依赖引入、配置方式、代码实现、扩展机制以及常见问题排查等内容。


一、什么是 MCP?

Model Coordination Protocol (MCP) 是一种用于协调本地应用与远程 AI 模型服务之间交互的协议。它允许你:

  • 向远程模型服务器发送请求;
  • 获取模型输出结果;
  • 管理模型状态(如会话上下文);
  • 支持多模型切换、流式响应等高级功能。

Spring AI 提供了对 MCP 协议的支持,通过 spring-ai-mcp-client 模块可以轻松对接基于 MCP 协议的模型服务。


二、准备工作

1. Java 版本要求
  • JDK 17 或以上版本
  • Spring Boot 3.x(建议使用 3.2+)
2. Maven 依赖
<dependencies><!-- Spring AI 核心 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-core</artifactId><version>0.8.1</version></dependency><!-- Spring AI MCP Client --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-mcp-client</artifactId><version>0.8.1</version></dependency><!-- WebClient 支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>
</dependencies>

三、MCP Server 要求

你需要一个支持 MCP 协议的服务端,例如:

  • 自建的 MCP 服务(可基于 Python 实现)
  • 第三方提供 MCP 接口的模型服务

MCP 服务通常需要暴露以下接口:

方法

路径

功能

POST

/v1/models/{model}/generate

生成文本

POST

/v1/models/{model}/chat

对话模式

GET

/v1/models

获取可用模型列表


四、配置 MCP Client

1. application.yml 配置
spring:ai:mcp:client:base-url: http://localhost:8080 # MCP Server 地址model-name: qwen-3b # 默认模型名称timeout: 60s # 请求超时时间

五、代码示例

1. 创建 MCP Client Bean

你可以通过自动装配来使用 McpClient

import org.springframework.ai.mcp.client.McpClient;
import org.springframework.stereotype.Service;@Service
public class AIClientService {private final McpClient mcpClient;public AIClientService(McpClient mcpClient) {this.mcpClient = mcpClient;}public String generateText(String prompt) {return mcpClient.generate(prompt);}
}
2. 使用 WebClient 手动调用

如果你希望更灵活地控制请求,也可以直接注入 WebClient

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;@Service
public class CustomAIService {private final WebClient webClient;public CustomAIService(WebClient.Builder webClientBuilder) {this.webClient = webClientBuilder.baseUrl("http://localhost:8080/v1").build();}public Mono<String> chatWithModel(String model, String prompt) {var body = Map.of("model", model, "prompt", prompt);return webClient.post().uri("/models/{model}/generate", model).bodyValue(body).retrieve().bodyToMono(Map.class).map(response -> response.get("content").toString());}
}

六、使用 Stream 流式输出

Spring AI 支持流式响应处理,适用于需要逐步接收模型输出的场景。

Flux<String> stream = mcpClient.stream("请写一首关于夏天的诗");stream.subscribe(System.out::println); // 输出每一行生成内容

七、模型切换与多模型支持

你可以在运行时动态指定不同的模型名称:

String response = mcpClient.withModel("llama-3-8b").generate("讲个笑话");

或使用配置文件设置默认模型,并在代码中覆盖:

spring:ai:mcp:client:base-url: http://localhost:8080model-name: mistral-nemo

八、自定义配置与拦截器

你可以通过配置类来自定义 WebClient 行为,比如添加请求头、日志拦截等。

@Configuration
public class WebClientConfig {@Beanpublic WebClientCustomizer webClientCustomizer() {return webClient -> webClient.defaultHeader("Authorization", "Bearer your_token");}
}

九、MCP Client 的扩展点详解

Spring AI 提供了良好的可扩展性设计,允许开发者通过自定义组件来增强或修改 McpClient 的行为。下面我们将详细介绍几个主要的扩展点及其使用方式。

1. McpRequestInterceptor —— 请求拦截器

这是一个在请求发送前进行处理的接口,你可以用来添加认证头、日志记录、参数修改等操作。

示例代码:
import org.springframework.ai.mcp.client.McpRequest;
import org.springframework.ai.mcp.client.McpRequestInterceptor;public class AuthRequestInterceptor implements McpRequestInterceptor {@Overridepublic void intercept(McpRequest request) {// 添加认证头request.headers().set("Authorization", "Bearer your_token_here");// 打印请求信息System.out.println("Intercepting request to model: " + request.model());}
}
注册方式:
@Configuration
public class McpConfig {@Beanpublic McpRequestInterceptor authRequestInterceptor() {return new AuthRequestInterceptor();}
}
2. McpResponsePostProcessor —— 响应后处理器

该接口用于在接收到模型返回结果后对响应进行加工处理,例如日志记录、格式转换、异常封装等。

示例代码:
import org.springframework.ai.mcp.client.McpResponse;
import org.springframework.ai.mcp.client.McpResponsePostProcessor;public class LoggingResponsePostProcessor implements McpResponsePostProcessor {@Overridepublic void process(McpResponse response) {System.out.println("Received response from model: " + response.model());System.out.println("Response content length: " + response.content().length());}
}
注册方式:
@Bean
public McpResponsePostProcessor loggingResponsePostProcessor() {return new LoggingResponsePostProcessor();
}
3. McpModelSelector —— 模型选择器

这个扩展点用于根据上下文动态选择使用的模型。比如可以根据用户身份、输入内容类型、负载情况等决定调用哪个模型。

示例代码:
import org.springframework.ai.mcp.client.McpModelSelector;public class SmartModelSelector implements McpModelSelector {@Overridepublic String selectModel(String input) {if (input.contains("code")) {return "codellama";} else if (input.contains("math")) {return "deepseek-math";} else {return "qwen-3b"; // 默认模型}}
}
注册方式:
@Bean
public McpModelSelector smartModelSelector() {return new SmartModelSelector();
}

注意:需要确保你的 McpClient 配置启用了该选择器。

4. 自定义 WebClient 行为(如重试机制)

你还可以通过 WebClientCustomizer 来定制底层的 WebClient 实例,实现诸如自动重试、超时控制等功能。

示例代码:
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.boot.web.reactive.function.client.WebClientCustomizer;
import org.springframework.stereotype.Component;@Component
public class RetryWebClientCustomizer implements WebClientCustomizer {@Overridepublic void customize(WebClient.Builder webClientBuilder) {webClientBuilder.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024));webClientBuilder.filters(exchangeFilterFunctions -> {exchangeFilterFunctions.add((clientRequest, next) ->next.exchange(clientRequest).doOnError(ex -> System.err.println("Error occurred during request: " + ex.getMessage())).retryWhen(Retry.backoff(3, Duration.ofSeconds(1)).filter(ex -> ex instanceof IOException));});}
}

十、常见问题与解决方案详解

1. 连接失败或超时
现象:

应用启动时报错 Connection refusedTimeoutException

可能原因:
  • MCP Server 未启动;
  • 地址或端口错误;
  • 网络不通或防火墙限制;
  • 超时时间设置过短;
  • 服务端未正确监听请求路径。
解决方案:
  • 检查 MCP Server 是否运行正常

  • 使用 curl http://localhost:8080/v1/models 测试是否能访问模型列表

  • 查看日志文件确认服务是否报错

  • application.yml 中增加超时时间:

    spring:
    ai:
    mcp:
    client:
    timeout: 120s

  • 如果部署在远程服务器,检查网络连通性和防火墙规则。


2. 返回格式错误 / 数据解析失败
现象:

抛出 JsonProcessingException 或无法提取 content 字段。

可能原因:
  • MCP Server 返回的数据结构不符合预期;
  • 缺少 content 字段;
  • 返回 JSON 格式不合法;
  • 服务端返回错误码但未被正确处理。
解决方案:

确保服务端返回如下格式:

{"content": "这是模型的回答","model": "qwen-3b"
}

在客户端加入日志打印中间响应体:

Flux<String> stream = mcpClient.stream("你好");
stream.doOnNext(System.out::println).subscribe();

使用 exchange() 方法获取原始响应并手动处理:

Mono<ClientResponse> responseMono = webClient.post().uri("/models/qwen/generate").bodyValue(Map.of("prompt", "Hello")).exchangeToMono(response -> {if (response.statusCode().isError()) {return response.bodyToMono(String.class).flatMap(errorBody -> Mono.error(new RuntimeException("Server error: " + errorBody)));}return response.bodyToMono(Map.class);});

3. 不支持流式输出
现象:

调用 .stream() 方法时没有输出或抛出异常。

可能原因:
  • 服务端未启用 text/event-stream 类型的响应;
  • WebClient 未正确配置以处理事件流;
  • 服务端未按规范返回 SSE(Server-Sent Events)数据。
解决方案:

检查服务端是否返回正确的 Content-Type:

Content-Type: text/event-stream

确保服务端每行返回一个 data: 字段:

data: {"content":"这"}
data: {"content":"是"}
data: {"content":"一"}
data: {"content":"句"}
data: {"content":"话"}

在客户端使用 retrieve().bodyToFlux(String.class) 接收流式响应:

Flux<String> stream = webClient.get().uri("/models/qwen/chat").accept(MediaType.TEXT_EVENT_STREAM).retrieve().bodyToFlux(String.class);stream.subscribe(System.out::println);

若使用默认的 McpClient,请确保其内部 WebClient 支持流式传输。


4. 模型切换无效
现象:

调用 .withModel("xxx") 后仍然使用默认模型。

可能原因:
  • 服务端不支持多模型;
  • URL 路径中未包含 {model} 参数;
  • McpModelSelector 逻辑冲突;
  • 请求未正确携带模型名称。
解决方案:

检查服务端是否支持多个模型,并可通过 /v1/models 获取列表
检查 MCP Client 的 Base URL 是否为 /v1 开头
查看日志中实际请求的 URL 是否包含目标模型名
如果使用 McpModelSelector,可在其 selectModel 方法中加日志调试


5. 日志信息太少,难以排查问题
解决方案:

启用 Spring Boot 的 debug 日志级别:

logging:level:org.springframework.ai: DEBUGreactor: DEBUG

McpRequestInterceptorMcpResponsePostProcessor 中加入详细的日志输出
使用 WireShark 或 Fiddler 抓包查看实际请求内容


总结

通过本节的深入讲解,你应该已经掌握了以下能力:

  • 如何通过 McpRequestInterceptorMcpResponsePostProcessor 对请求和响应进行拦截和处理
  • 如何实现 McpModelSelector 动态选择模型
  • 如何自定义 WebClient 实现高级功能(如重试、日志、流式处理)
  • 如何排查连接失败、格式错误、流式输出异常等问题

这些扩展能力和排错技巧对于构建稳定、灵活的企业级 AI 应用非常关键。如果你正在开发一个生产级别的系统,建议将这些扩展点作为标准模块进行封装复用。


参考链接

  • Spring AI GitHub
  • MCP 协议文档
  • Spring Boot WebFlux 文档
http://www.lryc.cn/news/625249.html

相关文章:

  • SSH 登录失败(publickey)问题总结
  • Spring AI Alibaba 项目接入兼容 OpenAI API 的大模型
  • 管理本地用户和组:红帽企业 Linux 系统安全的基础
  • 日语学习-日语知识点小记-进阶-JLPT-N1阶段蓝宝书,共120语法(4):31-40语法
  • Linux 中断机制深度分析
  • 如何生成和安全保存私钥?
  • 【DDIA】第十章:解析Reduce端连接与分组技术
  • gflags框架安装与使用
  • 【SkyWalking】单节点安装
  • 数字货币钱包的类型、特点及使用场景
  • 8.18网络编程——基于UDP的TFTP文件传输客户端
  • Kafka文件存储机制
  • LeetCode100 -- Day1
  • LeetCode 每日一题 2025/8/11-2025/8/17
  • STM32学习笔记14-I2C硬件控制
  • 嵌入式 C++ 语言编程规范文档个人学习版(参考《Google C++ 编码规范中文版》)
  • 朝花夕拾(七)--------从混淆矩阵到分类报告全面解析​
  • 远程访问公司内网电脑怎么操作?3个简单通用的跨网异地连接管理计算机方法
  • 安全基础DAY6-服务器安全检测和防御技术
  • 超级云平台:重构数字生态的“超级连接器“
  • 2025年- H98-Lc206--51.N皇后(回溯)--Java版
  • Hadoop - 1:Hadoop 技术解析;Hadoop是什么;Hadoop优势;Hadoop组成;HDFS、YARN、MapReduce 三者关系
  • <数据集>遥感飞机识别数据集<目标检测>
  • Ubuntu下无法在huggingface下载指定模型的解决方法
  • FreeRTOS学习笔记(二)
  • MySQL的多版本并发控制(MVCC):
  • Windows系统上使用GIT
  • 基于JS实现的中国象棋AI系统:多模块协同决策与分析
  • 【C语言16天强化训练】从基础入门到进阶:Day 2
  • 计算机大数据毕业设计推荐:基于Hadoop+Spark的食物口味差异分析可视化系统【源码+文档+调试】