目录
[二、MCP 介绍](#二、MCP 介绍)
[2.1 什么是MCP](#2.1 什么是MCP)
[2.2 MCP 核心特点](#2.2 MCP 核心特点)
[2.3 MCP 核心价值](#2.3 MCP 核心价值)
[2.4 MCP 与Function Calling 区别](#2.4 MCP 与Function Calling 区别)
[三、Spring AI MCP 架构介绍](#三、Spring AI MCP 架构介绍)
[3.1 整体架构](#3.1 整体架构)
[3.1.1 三层架构实现说明](#3.1.1 三层架构实现说明)
[3.2 服务端与客户端](#3.2 服务端与客户端)
[3.2.1 MCP 服务端](#3.2.1 MCP 服务端)
[3.2.1 MCP 客户端](#3.2.1 MCP 客户端)
[3.3 MCP中SSE和STDIO区别](#3.3 MCP中SSE和STDIO区别)
[3.3.1 SSE模式介绍](#3.3.1 SSE模式介绍)
[3.3.2 STDIO模式介绍](#3.3.2 STDIO模式介绍)
[3.3.3 SSE 与STDIO对比](#3.3.3 SSE 与STDIO对比)
[四、Spring AI MCP 案例操作演示](#四、Spring AI MCP 案例操作演示)
[4.1 开发环境准备](#4.1 开发环境准备)
[4.2 构建MCP Server服务](#4.2 构建MCP Server服务)
[4.2.1 pom导入下面的依赖](#4.2.1 pom导入下面的依赖)
[4.2.2 添加配置文件](#4.2.2 添加配置文件)
[4.2.3 提供一个Tool 工具类](#4.2.3 提供一个Tool 工具类)
[4.2.4 注册工具类](#4.2.4 注册工具类)
[4.3 构建MCP Client服务](#4.3 构建MCP Client服务)
[4.3.1 导入核心依赖](#4.3.1 导入核心依赖)
[4.3.2 增加配置信息](#4.3.2 增加配置信息)
[4.3.3 增加一个对话接口](#4.3.3 增加一个对话接口)
[4.3.4 效果测试](#4.3.4 效果测试)
[4.4 MCP 底层原理解析](#4.4 MCP 底层原理解析)
[4.4.1 server端底层执行逻辑](#4.4.1 server端底层执行逻辑)
[4.4.2 client 端底层执行逻辑](#4.4.2 client 端底层执行逻辑)
一、前言
Spring AI MCP 是 Spring 框架对模型上下文协议(Model Context Protocol, MCP)的官方实现,它为 Java 开发者提供了标准化集成大型语言模型(LLM)与外部数据源和工具的能力。本文将全面介绍 Spring AI MCP 的核心概念、架构设计以及实际应用方法。
二、MCP 介绍
2.1 什么是MCP
MCP ,即模型上下文协议(Model Context Protocol, MCP),由 Anthropic 公司(Claude 大模型母公司)在 2024 年 11 月推出的开放协议,旨在标准化大型语言模型与外部数据源和工具之间的交互方式。MCP 被形象地比喻为 AI 领域的"USB-C 接口",因为它提供了连接各类服务的统一框架。从而增强模型的实时交互和任务执行能力。
2.2 MCP 核心特点
MCP 具备如下核心特点:
-
标准化集成
- MCP统一了不同AI模型(如Claude、GPT等)与外部工具(如数据库、API、浏览器等)的交互方式,避免了传统定制化API开发的重复劳动
-
双向通信
- 不同于传统AI只能被动接收数据,MCP支持AI主动检索信息并执行操作(如更新数据库、触发工作流),实现真正的"代理式AI"
-
动态上下文管理
- MCP允许AI在会话中持续携带上下文信息(如用户偏好、历史记录),使多步骤任务(如"查询天气→推荐行程→预订酒店")能自动串联执行
-
安全与灵活性
- MCP支持本地或云端部署,通过OAuth 2.1认证和数据沙箱机制保障敏感信息的安全访问
2.3 MCP 核心价值
MCP 解决了 AI 应用开发中的几个关键问题:
-
打破数据孤岛:让大模型可以直接访问实时数据和本地资源(如数据库、文件系统)
-
降低开发成本:开发者只需编写一次 MCP 服务端,所有兼容 MCP 的模型都能调用
-
提升安全性:内置权限控制和加密机制,比直接开放数据库更安全
-
促进生态统一:类似 USB 接口,让不同厂商的工具能"即插即用"
2.4 MCP 与Function Calling 区别
与传统的 Function Calling 相比,MCP 具有以下优势:
-
复用性:Function Calling 通常与具体 AI 应用紧密绑定,难以复用;而 MCP 设计用于跨系统、跨工具场景
-
交互能力:MCP 着重解决系统间交互问题,使数据和功能能在不同系统间灵活传递
-
协议标准化:MCP 通过协议标准化简化了分布式系统开发
三、Spring AI MCP 架构介绍
spring官网在大模型开始火热的时候,推出了Spring AI,与时俱进,随着MCP的热度走高,Spring AI MCP也随之推出与大众见面,官网入口:Model Context Protocol (MCP) :: Spring AI Reference

3.1 整体架构
Spring 官网对于MCP给出了下面的架构图

Spring AI MCP 采用模块化架构,包含以下核心组件:
-
Spring AI 应用程序:使用 Spring AI 框架构建的生成式 AI 应用
-
Spring MCP 客户端:MCP 协议的 Spring AI 实现,与服务器保持 1:1 连接
-
MCP 服务器:轻量级程序,通过标准化协议公开特定功能
-
本地数据源:MCP 服务器可安全访问的计算机文件、数据库和服务
-
远程服务:MCP 服务器可通过互联网(如 API)连接的外部系统
3.1.1 三层架构实现说明
Java MCP 实现遵循三层架构:
-
客户端/服务器层:McpClient 处理客户端操作,McpServer 管理服务器端协议操作
-
会话层(McpSession):管理通信模式和状态
-
传输层(McpTransport):处理 JSON-RPC 消息的序列化和反序列化,支持多种传输方式
3.2 服务端与客户端
在实际开发和使用时,MCP的开发主要涉及到服务端与客户端,两者的作用各有差异,下面分别做说明。
3.2.1 MCP 服务端
MCP 服务端主要负责下面的功能:
-
服务端协议操作实现
-
工具暴露与发现
-
基于 URI 的资源管理
-
提示词模板的提供与处理
-
客户端并发连接管理
3.2.1 MCP 客户端
MCP 客户端是架构中的关键组件,其主要负责下面的功能:
-
协议版本协商
-
能力协商以确定可用功能
-
消息传输和 JSON-RPC 通信
-
工具发现和执行
-
资源访问和管理
-
支持同步和异步操作
3.3 MCP中SSE和STDIO区别
在Spring AI的MCP实现中,SSE和STDIO是两种主要的通信方式,它们各自适用于不同的场景,下面我们来详细分析两者的区别。
3.3.1 SSE模式介绍
SSE全称,Server-Sent Events,是一种服务器推送技术,允许服务器向客户端推送实时更新。在MCP中,SSE主要用于流式返回AI模型生成的内容。其主要特点如下:
-
单向通信:服务器向客户端发送数据,客户端不能通过SSE向服务器发送数据
-
实时性:支持服务器实时推送数据到客户端
-
自动重连:客户端断开连接后会自动尝试重新连接
-
基于HTTP:使用标准HTTP协议,易于穿越防火墙
-
轻量级:相比WebSocket更加轻量,适合单向通信场景
在AI大模型中的交互使用场景:
-
流式返回模型生成的文本,实现类似打字机的效果;
-
提供实时反馈,如生成进度、中间结果等;
-
减少首字节时间(TTFB),提升用户体验;
SSE的HTTP格式示例:
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
data: {"content":"这是第一段对话"}
data: {"content":"这是第二段对话"}
data: {"content":"这是最后一段对话"}
data: [DONE]
3.3.2 STDIO模式介绍
STDIO全称,Standard Input/Output,STDIO 是指标准输入输出流,是一种最基本的程序通信机制。在MCP中,STDIO主要用于与本地部署的模型或通过命令行工具访问的模型进行交互。STDIO主要有如下特点:
-
双向通信
- 程序可以通过标准输入接收数据,通过标准输出发送数据
-
进程间通信
- 通常用于父子进程之间的通信
-
无网络依赖
- 不依赖网络协议,适合本地应用场景
-
命令行友好
- 与命令行工具天然集成
-
低开销
- 通信开销小,适合高性能场景
在AI大模型中的交互使用场景:
-
与本地部署大模型交互,如Ollama、LLaMA.cpp等
-
通过命令行工具访问AI大模型服务
-
构建管道式AI处理流程
STDIO 通信流程如下示例:
应用程序 -> 标准输入 -> AI模型进程 -> 标准输出 -> 应用程序
3.3.3 SSE 与STDIO对比
SSE 与STDIO两种模式具有如下差异:
|---------|-------------|-----------|
| 特征项 | SSE | STDIO |
| 通信方向 | 单向 :服务器到客户端 | 双向 |
| 网络依赖 | 依赖HTTP | 不依赖网络 |
| 部署要求 | 需要网络服务 | 本地即可 |
| 性能开销 | 较高(HTTP开销) | 较低 |
| 扩展性 | 支持多客户端 | 一对一通信 |
| 实现复杂度 | 中等 | 简单 |
| 错误恢复 | 自动重连机制 | 需手动处理 |
| 应用场景 | 网络API通信 | 本地进程通信 |
四、Spring AI MCP 案例操作演示
接下来通过一个实际案例详细演示基于SSE 这种模式下Spring AI MCP是如何使用的。
mcp项目分为server服务端(提供mcp服务),client客户端(去请求mcp服务)
4.1 开发环境准备
本地开发环境相关的组件依赖版本如下:
-
JDK17
-
maven 3.6.2
-
springBoot 3.4.4
-
springAi 1.0.0-M7
4.2 构建MCP Server服务
下面以SSE模式为例演示下如何在springboot项目中集成并使用MCP
4.2.1 pom导入下面的依赖
创建一个springboot的server端项目,导入下面的核心依赖
java
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-ai.version>1.0.0-M7</spring-ai.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.4</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<url>https://maven.aliyun.com/repository/central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<name>Central Portal Snapshots</name>
<id>central-portal-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
4.2.2 添加配置文件
在配置文件中添加如下信息
java
spring:
ai:
mcp:
server:
name: mcp-server
version: 1.0.0
type: ASYNC
sse-message-endpoint: /mcp/messages
4.2.3 提供一个Tool 工具类
在MCP的实现中,Tool 是一个很重要的连接点,借助Tool ,客户端调用具体的服务时,可以理解为MCP就能找到符合要求的Tool 实现,从而给客户端预期的响应结果,在server项目启动的时候,会将相关的Tool工具进行注册,统一汇聚在一个类似于服务注册中心的列表上去,客户端通过配置Server的地址后,就能进行调用,在下面的类中,提供了2个工具方法,第一个是模拟调用天气的API获取天气信息,第二个是获取用户所在的时区时间。
java
package com.congge.tool;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@Service("weatherServiceTool")
public class WeatherServiceTool {
@Tool(description = "获取指定城市的天气")
public String getWeather(String cityName){
if(cityName.equals("北京")){
return "晴天";
}else if(cityName.equals("上海")){
return "阴天";
}else {
return "未知";
}
}
@Tool(description = "获取当前用户所在的时区时间")
String getCurrentDateTime() {
return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
}
}
4.2.4 注册工具类
提供一个配置类,将上述的Tool工具类进行注册
java
package com.congge.config;
import com.congge.tool.WeatherServiceTool;
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;
@Configuration
public class ToolCallbackProviderConfig {
@Bean
public ToolCallbackProvider toolCallbackProvider(WeatherServiceTool weatherServiceTool) {
return MethodToolCallbackProvider.builder().toolObjects(weatherServiceTool).build();
}
}
其实到这里基本上就结束了,如果在server工程中,还需要提供接口,继续添加即可,在实际开发中,server端主要是提供针对各类场景下的tool服务,接下来启动工程,在控制台的启动日志中可以看到成功注册了两个服务。

4.3 构建MCP Client服务
4.3.1 导入核心依赖
在pom文件中导入下面的核心依赖,基本和server端的相同,注意版本号保持一致,在client端,主要增加了mcp-client的依赖,以及阿里的spring-ai的依赖,参考下面的依赖信息:
java
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-ai.version>1.0.0-M7</spring-ai.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.4</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M6.1</version>
</dependency>
<!--<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<name>Central Portal Snapshots</name>
<id>central-portal-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
4.3.2 增加配置信息
在配置文件中增加下面的信息
java
server:
port: 8082
spring:
ai:
dashscope:
api-key: 你的apikey #这里使用阿里云百炼平台的apikey
mcp:
client:
sse:
connections:
server1:
url: http://localhost:8080
toolcallback:
enabled: true
4.3.3 增加一个对话接口
增加一个测试用的聊天对话接口,用于测试客户端调用server的服务是否正常,参考下面的代码
java
package com.congge.web;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/client/ai")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@Resource
private ToolCallbackProvider toolCallbackProvider;
//localhost:8082/client/ai/chat?message=今天北京的天气如何
//localhost:8082/client/ai/chat?message=你是谁
//localhost:8082/client/ai/chat?message=当前时间是多少
@GetMapping("/chat")
public String chat(String message){
return chatClient
.prompt()
.user(message)
.tools(toolCallbackProvider.getToolCallbacks())
.call()
.content();
}
}
4.3.4 效果测试
启动上面client的服务,依次调用几个接口测试下是否能够成功调用到server端的服务。
1)测试效果一
调用接口:localhost:8082/client/ai/chat?message= *今天北京的天气如何 ,*在server端,提供了一个获取天气信息的模拟接口,所以在下面的接口响应中可以看到正常返回结果

2)测试效果二
调用接口:localhost:8082/client/ai/chat?message= *你是谁 ,*这是一个与server端2个工具方法无关的问题,所以最后由大模型返回的响应结果

3)测试效果三
调用接口:localhost:8082/client/ai/chat?message=当前时间是多少 ,server中提供了获取时间的工具方法,所以在调用结果中可以看到返回了预期的结果

4.4 MCP 底层原理解析
在上面的案例中,演示了如何在client端调用server端的tool服务,于是细心的伙伴会问,这是怎么实现的呢?clent端怎么就能准确的调用到server端提供的服务了呢?下面简单说明下其底层的实现原理。
4.4.1 server端底层执行逻辑
在server端工程中,代码中搜索这个McpAsyncServer类,server端项目启动的时候,通过这个类的执行,将tool的相关方法注册到一个指定的位置,然后暴露出去,从而客户端只要配置了与server端的连接,即可获取到这些tool列表,类似于我们在使用nacos之类的服务注册中心时候,只要服务消费者连上注册中心,就可以获取并使用上面注册的服务列表类似的道理。
在这个类中,提供了多个与Tool相关的方法,如下:

启动server工程,首先进入了该类的构造方法中,走到构造方法中,可以看到获取到了工程中提供的2个tool方法

同时在下面这段代码中,暴露了一个重要的端口: tools/list ,简单理解就是为客户端暴露了一个获取server端工具列表的接口
-
tools/list ,暴露工具列表;
-
tools/call,执行工具调用;

4.4.2 client 端底层执行逻辑
在客户端,在上面的案例演示中看到,在配置文件中配置了连接server端的IP+端口号,然后在接口中注入相关的类就可以调用了,简单理解就是,通过这样的配置之后,客户端在发起对server端的tool方法调用时,从tool列表中找到合适的tool,然后执行调用,从而返回预期的结果。
在client端代码中,通过ToolCallbackProvider这个接口进入,可以看到,这是一个接口,里面对应了多个具体的实现类,不同的实现对应了不同场景下对于tool的调用模式,在上述的案例代码中,对应的便是下面这个SyncMcpToolCallbackProvider类的代码执行

在启动工程之后,通过一次接口调用后,来到下面的McpSyncClient这个类的代码中,首先会执行下面的listTools方法,获取当前客户端能够拿到的tool列表,通过debug代码可以看到已经拿到了server端提供的2个tool

通过中间一些列的过滤、筛选得到具体执行的那个tool,然后执行本类中的callTool方法,而且是一个同步阻塞方法,需要等待执行结果的返回

继续往下走,就看到了在上一个解析server端源码中的那个 tools/call的接口了,在这里相当于是客户端找到了具体的执行tool之后,向server端发起request,然后等待server的执行结果

五、写在文末
本文详细介绍了Spring AI MCP的相关技术,并通过一个实际案例操作演示了在SSE模式下MCP的实战应用,事实上,使用Spring AI对接和整合MCP还有很多技能可以解锁,比如stdio模式下的使用,整合第三方的MCP服务等,限于篇幅原因,有兴趣的同学可以基于此继续深入研究,在后续的篇章中也会逐渐丰富和完善,本篇到此结束,感谢观看。