模型上下文协议 (MCP) 是一种标准化协议,使 AI 模型能够以结构化方式与外部工具和资源交互。可以将其视为 AI 模型与现实世界之间的桥梁——允许它们通过一致的接口访问数据库、API、文件系统和其他外部服务。它支持多种传输机制,以提供跨不同环境的灵活性。
MCP Java SDK 提供了模型上下文协议的 Java 实现,通过同步和异步通信模式,实现与 AI 模型和工具的标准化交互。
Spring AI 通过专门的 Boot Starters 和 MCP Java 注解全面支持 MCP,使得构建能够无缝连接到外部系统的复杂 AI 驱动应用程序比以往任何时候都更容易。这意味着 Spring 开发人员可以参与 MCP 生态系统的两方面——构建消费 MCP 服务器的 AI 应用程序,以及创建向更广泛的 AI 社区公开基于 Spring 的服务的 MCP 服务器。
1. MCP Java SDK 架构
Java MCP 实现遵循三层架构,将关注点分离以实现可维护性和灵活性
https://docs.springframework.org.cn/spring-ai/reference/_images/mcp/mcp-stack.svg
1.1. 客户端/服务器层(顶层)
顶层处理主要应用程序逻辑和协议操作
McpClient - 管理客户端操作和服务器连接
McpServer - 处理服务器端协议操作和客户端请求
这两个组件都利用下面的会话层进行通信管理
1.2. 会话层(中间层)
中间层管理通信模式并维护连接状态
McpSession - 核心会话管理接口
McpClientSession - 客户端特定会话实现
McpServerSession - 服务器特定会话实现
1.3. 传输层(底层)
底层处理实际的消息传输和序列化
McpTransport - 管理 JSON-RPC 消息序列化和反序列化
支持多种传输实现(STDIO、HTTP/SSE、Streamable-HTTP 等)
为所有更高级别的通信提供基础
MCP 客户端是模型上下文协议 (MCP) 架构中的一个关键组件,负责建立和管理与 MCP 服务器的连接。它实现了协议的客户端部分,处理
协议版本协商,以确保与服务器兼容
能力协商,以确定可用功能
消息传输和 JSON-RPC 通信
工具发现和执行
资源访问和管理
提示系统交互
可选功能
根管理
采样支持
同步和异步操作
传输选项
用于基于进程通信的 StdIO 传输
基于 Java HttpClient 的 SSE 客户端传输
用于响应式 HTTP 流的 WebFlux SSE 客户端传输
https://docs.springframework.org.cn/spring-ai/reference/_images/mcp/java-mcp-client-architecture.jpg

CP 服务器是模型上下文协议 (MCP) 架构中的一个基础组件,它向客户端提供工具、资源和功能。它实现了协议的服务器端,负责
服务器端协议操作实现
工具公开和发现
带 URI 访问的资源管理
提示模板提供和处理
与客户端的能力协商
结构化日志记录和通知
并发客户端连接管理
同步和异步 API 支持
传输实现
Stdio、Streamable-HTTP、Stateless Streamable-HTTP、SSE
https://docs.springframework.org.cn/spring-ai/reference/_images/mcp/java-mcp-server-architecture.jpg

有关使用低级 MCP 客户端/服务器 API 的详细实现指南,请参阅 MCP Java SDK 文档。对于使用 Spring Boot 的简化设置,请使用下面描述的 MCP Boot Starters。
2. Spring AI MCP 集成
Spring AI 通过以下 Spring Boot 启动器提供 MCP 集成
2.1. 客户端启动器
spring-ai-starter-mcp-client- 核心启动器,提供STDIO、基于 Servlet 的Streamable-HTTP、Stateless Streamable-HTTP和SSE支持spring-ai-starter-mcp-client-webflux- 基于 WebFlux 的Streamable-HTTP、Stateless Streamable-HTTP和SSE传输实现
2.2. 服务器启动器
2.2.1. STDIO
2.2.2. WebMVC
2.2.3. WebMVC(响应式)
3. Spring AI MCP 注解
除了编程方式的 MCP 客户端和服务器配置之外,Spring AI 还通过 MCP 注解模块为 MCP 服务器和客户端提供基于注解的方法处理。这种方法通过使用 Java 注解的清晰、声明式编程模型来简化 MCP 操作的创建和注册。
MCP 注解模块使开发人员能够
使用简单的注解创建 MCP 工具、资源和提示
声明性地处理客户端通知和请求
减少样板代码并提高可维护性
自动为工具参数生成 JSON 模式
访问特殊参数和上下文信息
主要功能包括
服务器注解:
@McpTool、@McpResource、@McpPrompt、@McpComplete客户端注解:
@McpLogging、@McpSampling、@McpElicitation、@McpProgress特殊参数:
McpSyncServerExchange、McpAsyncServerExchange、McpTransportContext、McpMeta自动发现:具有可配置包包含/排除的注解扫描
Spring Boot 集成:与 MCP Boot Starters 无缝集成
4. 其他资源
MCP客户端启动器
Spring AI MCP(模型上下文协议)客户端启动器为 Spring Boot 应用程序中的 MCP 客户端功能提供了自动配置。它支持具有各种传输选项的同步和异步客户端实现。
MCP 客户端启动器提供
多个客户端实例的管理
自动客户端初始化(如果启用)
支持多种命名传输(STDIO、Http/SSE 和 Streamable HTTP)
与 Spring AI 的工具执行框架集成
用于选择性工具包含/排除的工具过滤功能
可定制的工具名称前缀生成,以避免命名冲突
适当的生命周期管理,并在应用程序上下文关闭时自动清理资源
通过定制器进行可定制的客户端创建
1. 启动器
1.1. 标准 MCP 客户端
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>标准启动器通过 STDIO(进程内)、SSE、Streamable-HTTP 和 Stateless Streamable-HTTP 传输同时连接到一个或多个 MCP 服务器。SSE 和 Streamable-Http 传输使用基于 JDK HttpClient 的传输实现。每次连接到 MCP 服务器都会创建一个新的 MCP 客户端实例。您可以选择 SYNC 或 ASYNC MCP 客户端(注意:您不能混合使用同步和异步客户端)。对于生产部署,我们建议使用基于 WebFlux 的 SSE 和 StreamableHttp 连接,并使用 spring-ai-starter-mcp-client-webflux。
1.2. WebFlux 客户端
WebFlux 启动器提供与标准启动器类似的功能,但使用基于 WebFlux 的 Streamable-Http、无状态 Streamable-Http 和 SSE 传输实现。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>2. 配置属性
2.1. 通用属性
通用属性以 spring.ai.mcp.client 为前缀
2.2. MCP注解属性
MCP 客户端注解提供了一种使用 Java 注解实现 MCP 客户端处理程序的声明性方式。客户端 mcp-annotations 属性以 spring.ai.mcp.client.annotation-scanner 为前缀
2.3. Stdio 传输属性
标准 I/O 传输的属性以 spring.ai.mcp.client.stdio 为前缀
配置示例
spring:
ai:
mcp:
client:
stdio:
root-change-notification: true
connections:
server1:
command: /path/to/server
args:
- --port=8080
- --mode=production
env:
API_KEY: your-api-key
DEBUG: "true"或者,您可以使用 Claude 桌面格式 使用外部 JSON 文件配置 stdio 连接
spring:
ai:
mcp:
client:
stdio:
servers-configuration: classpath:mcp-servers.jsonClaude 桌面格式如下所示
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop",
"/Users/username/Downloads"
]
}
}
}2.4. Windows STDIO 配置
在 Windows 上,npx、npm 和 node 等命令是作为批处理文件 (.cmd) 实现的,而不是原生可执行文件。Java 的 ProcessBuilder 无法直接执行批处理文件,需要 cmd.exe /c 包装器。
2.4.1. 为什么 Windows 需要特殊处理
当 Java 的 ProcessBuilder(由 StdioClientTransport 内部使用)尝试在 Windows 上生成进程时,它只能执行
原生可执行文件 (
.exe文件)cmd.exe可用的系统命令
npx.cmd、npm.cmd 甚至 python.cmd(来自 Microsoft Store)等 Windows 批处理文件需要 cmd.exe shell 来执行它们。
2.4.2. 解决方案:cmd.exe 包装器
使用 cmd.exe /c 包装批处理文件命令
Windows 配置
{
"mcpServers": {
"filesystem": {
"command": "cmd.exe",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-filesystem",
"C:\\Users\\username\\Desktop"
]
}
}
}Linux/macOS 配置
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop"
]
}
}
}2.4.3. 跨平台编程配置
对于需要跨平台工作而无需单独配置文件的应用程序,请在 Spring Boot 应用程序中使用操作系统检测
@Bean(destroyMethod = "close")
@ConditionalOnMissingBean(McpSyncClient.class)
public McpSyncClient mcpClient() {
ServerParameters stdioParams;
if (isWindows()) {
// Windows: cmd.exe /c npx approach
var winArgs = new ArrayList<>(Arrays.asList(
"/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "target"));
stdioParams = ServerParameters.builder("cmd.exe")
.args(winArgs)
.build();
} else {
// Linux/Mac: direct npx approach
stdioParams = ServerParameters.builder("npx")
.args("-y", "@modelcontextprotocol/server-filesystem", "target")
.build();
}
return McpClient.sync(new StdioClientTransport(stdioParams, McpJsonMapper.createDefault()))
.requestTimeout(Duration.ofSeconds(10))
.build()
.initialize();
}
private static boolean isWindows() {
return System.getProperty("os.name").toLowerCase().contains("win");
}使用 @Bean 进行编程配置时,添加 @ConditionalOnMissingBean(McpSyncClient.class) 以避免与 JSON 文件中的自动配置冲突。
2.4.4. 路径注意事项
相对路径(建议用于可移植性)
{
"command": "cmd.exe",
"args": ["/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "target"]
}MCP 服务器根据应用程序的工作目录解析相对路径。
绝对路径(Windows 需要反斜杠或转义的正斜杠)
{
"command": "cmd.exe",
"args": ["/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "C:\\Users\\username\\project\\target"]
}2.4.5. 需要 cmd.exe 的常见 Windows 批处理文件
npx.cmd,npm.cmd- Node 包管理器python.cmd- Python(Microsoft Store 安装)pip.cmd- Python 包管理器mvn.cmd- Maven 包装器gradle.cmd- Gradle 包装器自定义
.cmd或.bat脚本
2.4.6. 参考实现
请参阅 Spring AI 示例 - 文件系统,了解一个完整的跨平台 MCP 客户端实现,它会自动检测操作系统并相应地配置客户端。
2.5. 可流式 HTTP 传输属性
用于连接到可流式 HTTP 和无状态可流式 HTTP MCP 服务器。
可流式 HTTP 传输的属性以 spring.ai.mcp.client.streamable-http 为前缀
配置示例
spring:
ai:
mcp:
client:
streamable-http:
connections:
server1:
url: https://:8080
server2:
url: http://otherserver:8081
endpoint: /custom-sse2.6. SSE 传输属性
服务器发送事件 (SSE) 传输的属性以 spring.ai.mcp.client.sse 为前缀
示例配置
spring:
ai:
mcp:
client:
sse:
connections:
# Simple configuration using default /sse endpoint
server1:
url: https://:8080
# Custom SSE endpoint
server2:
url: http://otherserver:8081
sse-endpoint: /custom-sse
# Complex URL with path and token (like MCP Hub)
mcp-hub:
url: https://:3000
sse-endpoint: /mcp-hub/sse/cf9ec4527e3c4a2cbb149a85ea45ab01
# SSE endpoint with query parameters
api-server:
url: https://api.example.com
sse-endpoint: /v1/mcp/events?token=abc123&format=json2.6.1. URL 分割指南
当您有一个完整的 SSE URL 时,将其拆分为基本 URL 和端点路径
2.6.2. SSE 连接故障排除
404 未找到错误
验证 URL 分割:确保基
url仅包含方案、主机和端口检查
sse-endpoint是否以/开头,并包含完整路径和查询参数直接在浏览器或 curl 中测试完整 URL,确认其可访问
2.7. 可流式 HTTP 传输属性
可流式 HTTP 传输的属性以 spring.ai.mcp.client.streamable-http 为前缀
配置示例
spring:
ai:
mcp:
client:
streamable-http:
connections:
server1:
url: https://:8080
server2:
url: http://otherserver:8081
endpoint: /custom-sse3. 功能
3.1. 同步/异步客户端类型
启动器支持两种类型的客户端
同步 - 默认客户端类型(
spring.ai.mcp.client.type=SYNC),适用于具有阻塞操作的传统请求-响应模式
注意: SYNC 客户端将只注册同步 MCP 注解方法。异步方法将被忽略。
异步 - 适用于具有非阻塞操作的反应式应用程序,使用
spring.ai.mcp.client.type=ASYNC进行配置
注意: ASYNC 客户端将只注册异步 MCP 注解方法。同步方法将被忽略。
3.2. 客户端定制
自动配置通过回调接口提供广泛的客户端规范定制功能。这些定制器允许您配置 MCP 客户端行为的各个方面,从请求超时到事件处理和消息处理。
3.2.1. 定制类型
以下定制选项可用
请求配置 - 设置自定义请求超时
自定义采样处理程序 - 服务器通过客户端向 LLM 请求 LLM 采样(
completions或generations)的标准化方式。此流程允许客户端保持对模型访问、选择和权限的控制,同时使服务器能够利用 AI 功能——无需服务器 API 密钥。文件系统(根)访问 - 客户端向服务器公开文件系统
roots的标准化方式。根定义了服务器在文件系统中可以操作的边界,允许它们了解它们有权访问哪些目录和文件。服务器可以向支持的客户端请求根列表,并在该列表更改时接收通知。启发式处理程序 - 服务器在交互过程中通过客户端向用户请求额外信息的标准化方式。
事件处理程序 - 客户端的处理程序,用于在发生特定服务器事件时收到通知
工具更改通知 - 当可用服务器工具列表更改时
资源更改通知 - 当可用服务器资源列表更改时。
提示更改通知 - 当可用服务器提示列表更改时。
日志处理程序 - 服务器向客户端发送结构化日志消息的标准化方式。
进度处理程序 - 服务器向客户端发送结构化进度消息的标准化方式。
客户端可以通过设置最小日志级别来控制日志详细程度
3.2.2. 客户端定制示例
您可以根据应用程序的需求,为同步客户端实现 McpSyncClientCustomizer,或为异步客户端实现 McpAsyncClientCustomizer。
@Component
public class CustomMcpSyncClientCustomizer implements McpSyncClientCustomizer {
@Override
public void customize(String serverConfigurationName, McpClient.SyncSpec spec) {
// Customize the request timeout configuration
spec.requestTimeout(Duration.ofSeconds(30));
// Sets the root URIs that this client can access.
spec.roots(roots);
// Sets a custom sampling handler for processing message creation requests.
spec.sampling((CreateMessageRequest messageRequest) -> {
// Handle sampling
CreateMessageResult result = ...
return result;
});
// Sets a custom elicitation handler for processing elicitation requests.
spec.elicitation((ElicitRequest request) -> {
// handle elicitation
return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of("message", request.message()));
});
// Adds a consumer to be notified when progress notifications are received.
spec.progressConsumer((ProgressNotification progress) -> {
// Handle progress notifications
});
// Adds a consumer to be notified when the available tools change, such as tools
// being added or removed.
spec.toolsChangeConsumer((List<McpSchema.Tool> tools) -> {
// Handle tools change
});
// Adds a consumer to be notified when the available resources change, such as resources
// being added or removed.
spec.resourcesChangeConsumer((List<McpSchema.Resource> resources) -> {
// Handle resources change
});
// Adds a consumer to be notified when the available prompts change, such as prompts
// being added or removed.
spec.promptsChangeConsumer((List<McpSchema.Prompt> prompts) -> {
// Handle prompts change
});
// Adds a consumer to be notified when logging messages are received from the server.
spec.loggingConsumer((McpSchema.LoggingMessageNotification log) -> {
// Handle log messages
});
}
}@Component
public class CustomMcpAsyncClientCustomizer implements McpAsyncClientCustomizer {
@Override
public void customize(String serverConfigurationName, McpClient.AsyncSpec spec) {
// Customize the async client configuration
spec.requestTimeout(Duration.ofSeconds(30));
}
}serverConfigurationName 参数是应用定制器并为此创建 MCP 客户端的服务器配置名称。
MCP 客户端自动配置会自动检测并应用应用程序上下文中找到的任何定制器。
3.3. 传输支持
自动配置支持多种传输类型
标准 I/O (Stdio)(由
spring-ai-starter-mcp-client和spring-ai-starter-mcp-client-webflux激活)(HttpClient) HTTP/SSE 和可流式 HTTP(由
spring-ai-starter-mcp-client激活)(WebFlux) HTTP/SSE 和可流式 HTTP(由
spring-ai-starter-mcp-client-webflux激活)
3.4. 工具过滤
MCP 客户端启动器通过 McpToolFilter 接口支持对发现的工具进行过滤。这允许您根据 MCP 连接信息或工具属性等自定义条件选择性地包含或排除工具。
要实现工具过滤,请创建一个实现 McpToolFilter 接口的 bean
@Component
public class CustomMcpToolFilter implements McpToolFilter {
@Override
public boolean test(McpConnectionInfo connectionInfo, McpSchema.Tool tool) {
// Filter logic based on connection information and tool properties
// Return true to include the tool, false to exclude it
// Example: Exclude tools from a specific client
if (connectionInfo.clientInfo().name().equals("restricted-client")) {
return false;
}
// Example: Only include tools with specific names
if (tool.name().startsWith("allowed_")) {
return true;
}
// Example: Filter based on tool description or other properties
if (tool.description() != null &&
tool.description().contains("experimental")) {
return false;
}
return true; // Include all other tools by default
}
}McpConnectionInfo 记录提供对以下内容的访问
clientCapabilities- MCP 客户端的功能clientInfo- 有关 MCP 客户端的信息(名称和版本)initializeResult- MCP 服务器的初始化结果
过滤器会自动检测并应用于同步和异步 MCP 工具回调提供程序。如果未提供自定义过滤器,则默认情况下包含所有发现的工具。
注意:应用程序上下文中只能定义一个 McpToolFilter bean。如果需要多个过滤器,请将它们组合成一个复合过滤器实现。
3.5. 工具名称前缀生成
MCP 客户端启动器通过 McpToolNamePrefixGenerator 接口支持可定制的工具名称前缀生成。此功能通过为工具名称添加唯一前缀来帮助避免集成来自多个 MCP 服务器的工具时的命名冲突。
默认情况下,如果未提供自定义 McpToolNamePrefixGenerator bean,启动器将使用 DefaultMcpToolNamePrefixGenerator,它可确保所有 MCP 客户端连接的工具名称唯一。默认生成器
跟踪所有现有连接和工具名称以确保唯一性
通过将非字母数字字符替换为下划线来格式化工具名称(例如,
my-tool变为my_tool)当在不同连接中检测到重复的工具名称时,添加计数器前缀(例如,
alt_1_toolName,alt_2_toolName)是线程安全的并保持幂等性 - 相同的(客户端、服务器、工具)组合总是获得相同的唯一名称
确保最终名称不超过 64 个字符(如有必要,从开头截断)
例如:* 工具 search 的首次出现 → search * 来自不同连接的工具 search 的第二次出现 → alt_1_search * 带有特殊字符的工具 my-special-tool → my_special_tool
您可以通过提供自己的实现来定制此行为
@Component
public class CustomToolNamePrefixGenerator implements McpToolNamePrefixGenerator {
@Override
public String prefixedToolName(McpConnectionInfo connectionInfo, Tool tool) {
// Custom logic to generate prefixed tool names
// Example: Use server name and version as prefix
String serverName = connectionInfo.initializeResult().serverInfo().name();
String serverVersion = connectionInfo.initializeResult().serverInfo().version();
return serverName + "_v" + serverVersion.replace(".", "_") + "_" + tool.name();
}
}McpConnectionInfo 记录提供了有关 MCP 连接的全面信息
clientCapabilities- MCP 客户端的功能clientInfo- 有关 MCP 客户端的信息(名称、标题和版本)initializeResult- MCP 服务器的初始化结果,包括服务器信息
3.5.1. 内置前缀生成器
该框架提供了几个内置前缀生成器
DefaultMcpToolNamePrefixGenerator- 通过跟踪重复项并在需要时添加计数器前缀来确保唯一的工具名称(如果未提供自定义 bean,则默认使用)McpToolNamePrefixGenerator.noPrefix()- 返回不带任何前缀的工具名称(如果多个服务器提供同名工具,可能会导致冲突)
要完全禁用前缀并使用原始工具名称(不建议在多个 MCP 服务器中使用),请将无前缀生成器注册为 bean
@Configuration
public class McpConfiguration {
@Bean
public McpToolNamePrefixGenerator mcpToolNamePrefixGenerator() {
return McpToolNamePrefixGenerator.noPrefix();
}
}前缀生成器通过 Spring 的 ObjectProvider 机制自动检测并应用于同步和异步 MCP 工具回调提供程序。如果未提供自定义生成器 bean,则自动使用 DefaultMcpToolNamePrefixGenerator。
当使用 McpToolNamePrefixGenerator.noPrefix() 和多个 MCP 服务器时,重复的工具名称将导致 IllegalStateException。默认的 DefaultMcpToolNamePrefixGenerator 通过自动为重复工具名称添加唯一前缀来防止这种情况。
3.6. 工具上下文到 MCP 元转换器
MCP 客户端启动器支持将 Spring AI 的 ToolContext 可定制地转换为 MCP 工具调用元数据,通过 ToolContextToMcpMetaConverter 接口。此功能允许您将附加上下文信息(例如用户 ID、密钥令牌)作为元数据与 LLM 生成的调用参数一起传递。
例如,您可以在工具上下文中将 MCP progressToken 传递给 MCP 进度流,以跟踪长时间运行操作的进度
ChatModel chatModel = ...
String response = ChatClient.create(chatModel)
.prompt("Tell me more about the customer with ID 42")
.toolContext(Map.of("progressToken", "my-progress-token"))
.call()
.content();默认情况下,如果未提供自定义转换器 bean,启动器将使用 ToolContextToMcpMetaConverter.defaultConverter(),它
过滤掉 MCP 交换密钥(
McpToolUtils.TOOL_CONTEXT_MCP_EXCHANGE_KEY)过滤掉空值的条目
将所有其他上下文条目作为元数据传递
您可以通过提供自己的实现来定制此行为
@Component
public class CustomToolContextToMcpMetaConverter implements ToolContextToMcpMetaConverter {
@Override
public Map<String, Object> convert(ToolContext toolContext) {
if (toolContext == null || toolContext.getContext() == null) {
return Map.of();
}
// Custom logic to convert tool context to MCP metadata
Map<String, Object> metadata = new HashMap<>();
// Example: Add custom prefix to all keys
for (Map.Entry<String, Object> entry : toolContext.getContext().entrySet()) {
if (entry.getValue() != null) {
metadata.put("app_" + entry.getKey(), entry.getValue());
}
}
// Example: Add additional metadata
metadata.put("timestamp", System.currentTimeMillis());
metadata.put("source", "spring-ai");
return metadata;
}
}3.6.1. 内置转换器
该框架提供了内置转换器
ToolContextToMcpMetaConverter.defaultConverter()- 过滤掉 MCP 交换密钥和空值(如果未提供自定义 bean,则默认使用)ToolContextToMcpMetaConverter.noOp()- 返回一个空映射,有效地禁用上下文到元数据的转换
要完全禁用上下文到元数据的转换
@Configuration
public class McpConfiguration {
@Bean
public ToolContextToMcpMetaConverter toolContextToMcpMetaConverter() {
return ToolContextToMcpMetaConverter.noOp();
}
}转换器通过 Spring 的 ObjectProvider 机制自动检测并应用于同步和异步 MCP 工具回调。如果未提供自定义转换器 bean,则自动使用默认转换器。
3.7. 禁用 MCP ToolCallback 自动配置
MCP ToolCallback 自动配置默认启用,但可以使用 spring.ai.mcp.client.toolcallback.enabled=false 属性禁用。
禁用时,不会从可用的 MCP 工具创建 ToolCallbackProvider bean。
4. MCP 客户端注解
MCP 客户端启动器会自动检测并注册注解方法,用于处理各种 MCP 客户端操作
@McpLogging - 处理来自 MCP 服务器的日志消息通知
@McpSampling - 处理来自 MCP 服务器的 LLM 完成采样请求
@McpElicitation - 处理启发式请求以从用户那里收集附加信息
@McpProgress - 处理长时间运行操作的进度通知
@McpToolListChanged - 处理服务器工具列表更改时的通知
@McpResourceListChanged - 处理服务器资源列表更改时的通知
@McpPromptListChanged - 处理服务器提示列表更改时的通知
示例用法
@Component
public class McpClientHandlers {
@McpLogging(clients = "server1")
public void handleLoggingMessage(LoggingMessageNotification notification) {
System.out.println("Received log: " + notification.level() +
" - " + notification.data());
}
@McpSampling(clients = "server1")
public CreateMessageResult handleSamplingRequest(CreateMessageRequest request) {
// Process the request and generate a response
String response = generateLLMResponse(request);
return CreateMessageResult.builder()
.role(Role.ASSISTANT)
.content(new TextContent(response))
.model("gpt-4")
.build();
}
@McpProgress(clients = "server1")
public void handleProgressNotification(ProgressNotification notification) {
double percentage = notification.progress() * 100;
System.out.println(String.format("Progress: %.2f%% - %s",
percentage, notification.message()));
}
@McpToolListChanged(clients = "server1")
public void handleToolListChanged(List<McpSchema.Tool> updatedTools) {
System.out.println("Tool list updated: " + updatedTools.size() + " tools available");
// Update local tool registry
toolRegistry.updateTools(updatedTools);
}
}这些注解支持同步和异步实现,并且可以使用 clients 参数为特定客户端配置
@McpLogging(clients = "server1")
public void handleServer1Logs(LoggingMessageNotification notification) {
// Handle logs from specific server
logToFile("server1.log", notification);
}
@McpSampling(clients = "server1")
public Mono<CreateMessageResult> handleAsyncSampling(CreateMessageRequest request) {
return Mono.fromCallable(() -> {
String response = generateLLMResponse(request);
return CreateMessageResult.builder()
.role(Role.ASSISTANT)
.content(new TextContent(response))
.model("gpt-4")
.build();
}).subscribeOn(Schedulers.boundedElastic());
}有关所有可用注解及其用法模式的详细信息,请参阅 MCP 客户端注解 文档。
5. 使用示例
将适当的启动器依赖项添加到您的项目并在 application.properties 或 application.yml 中配置客户端
spring:
ai:
mcp:
client:
enabled: true
name: my-mcp-client
version: 1.0.0
request-timeout: 30s
type: SYNC # or ASYNC for reactive applications
sse:
connections:
server1:
url: https://:8080
server2:
url: http://otherserver:8081
streamable-http:
connections:
server3:
url: https://:8083
endpoint: /mcp
stdio:
root-change-notification: false
connections:
server1:
command: /path/to/server
args:
- --port=8080
- --mode=production
env:
API_KEY: your-api-key
DEBUG: "true"MCP 客户端 bean 将自动配置并可用于注入
@Autowired
private List<McpSyncClient> mcpSyncClients; // For sync client
// OR
@Autowired
private List<McpAsyncClient> mcpAsyncClients; // For async client当启用工具回调(默认行为)时,所有 MCP 客户端注册的 MCP 工具都作为 ToolCallbackProvider 实例提供
@Autowired
private SyncMcpToolCallbackProvider toolCallbackProvider;
ToolCallback[] toolCallbacks = toolCallbackProvider.getToolCallbacks();6. 示例应用程序
Brave Web 搜索聊天机器人 - 一个使用模型上下文协议与网络搜索服务器交互的聊天机器人。
默认 MCP 客户端启动器 - 一个使用默认
spring-ai-starter-mcp-clientMCP 客户端启动器的简单示例。WebFlux MCP 客户端启动器 - 一个使用
spring-ai-starter-mcp-client-webfluxMCP 客户端启动器的简单示例。
7. 其他资源
MCP 服务器启动器
模型上下文协议 (MCP) 服务器 是通过标准化协议接口向 AI 应用程序公开特定功能的程序。每个服务器都为特定领域提供专注的功能。
Spring AI MCP 服务器启动器为在 Spring Boot 应用程序中设置 MCP 服务器 提供自动配置。它们实现了 MCP 服务器功能与 Spring Boot 自动配置系统的无缝集成。
MCP 服务器启动器提供:
MCP 服务器组件的自动配置,包括工具、资源和提示
支持不同的 MCP 协议版本,包括 STDIO、SSE、可流式 HTTP 和无状态服务器
支持同步和异步操作模式
多种传输层选项
灵活的工具、资源和提示规范
变更通知功能
基于注解的服务器开发,具有自动 Bean 扫描和注册功能
1. MCP 服务器启动器
MCP 服务器支持多种协议和传输机制。使用专用的启动器和正确的 spring.ai.mcp.server.protocol 属性来配置您的服务器
1.1. STDIO
1.2. WebMVC
1.3. WebMVC (响应式)
2. 服务器功能
根据服务器和传输类型,MCP 服务器可以支持各种功能,例如
工具 - 允许服务器公开可由语言模型调用的工具
资源 - 提供服务器向客户端公开资源的标准化方式
提示 - 提供服务器向客户端公开提示模板的标准化方式
实用程序/自动完成 - 提供服务器为提示和资源 URI 提供参数自动完成建议的标准化方式
实用程序/日志记录 - 提供服务器向客户端发送结构化日志消息的标准化方式
实用程序/进度 - 通过通知消息对长时间运行的操作进行可选的进度跟踪
实用程序/Ping - 服务器报告其状态的可选健康检查机制
所有功能默认启用。禁用某个功能将阻止服务器注册并向客户端公开相应的功能。
3. 服务器协议
MCP 提供多种协议类型,包括
STDIO - 进程内(例如服务器在主机应用程序内部运行)协议。通信通过标准输入和标准输出进行。要启用
STDIO,请设置spring.ai.mcp.server.stdio=true。SSE - 用于实时更新的服务器发送事件协议。服务器作为独立进程运行,可以处理多个客户端连接。
可流式 HTTP - 可流式 HTTP 传输 允许 MCP 服务器作为独立进程运行,使用 HTTP POST 和 GET 请求处理多个客户端连接,并可选地使用服务器发送事件 (SSE) 流式传输多个服务器消息。它取代了 SSE 传输。要启用
STREAMABLE协议,请设置spring.ai.mcp.server.protocol=STREAMABLE。无状态 - 无状态 MCP 服务器设计用于简化部署,其中请求之间不维护会话状态。它们是微服务架构和云原生部署的理想选择。要启用
STATELESS协议,请设置spring.ai.mcp.server.protocol=STATELESS。
4. 同步/异步服务器 API 选项
MCP 服务器 API 支持命令式(即同步)和响应式(例如异步)编程模型。
同步服务器 - 使用
McpSyncServer实现的默认服务器类型。它专为应用程序中直接的请求-响应模式而设计。要启用此服务器类型,请在配置中设置spring.ai.mcp.server.type=SYNC。激活后,它会自动处理同步工具规范的配置。
注意: SYNC 服务器将只注册同步 MCP 注解方法。异步方法将被忽略。
异步服务器 - 异步服务器实现使用
McpAsyncServer,并针对非阻塞操作进行了优化。要启用此服务器类型,请使用spring.ai.mcp.server.type=ASYNC配置您的应用程序。此服务器类型会自动设置带有内置 Project Reactor 支持的异步工具规范。
注意: ASYNC 服务器将只注册异步 MCP 注解方法。同步方法将被忽略。
5. MCP 服务器注解
MCP 服务器启动器为基于注解的服务器开发提供全面支持,允许您使用声明性 Java 注解而不是手动配置来创建 MCP 服务器。
5.1. 关键注解
@McpTool - 使用自动 JSON 模式生成将方法标记为 MCP 工具
@McpResource - 通过 URI 模板提供对资源的访问
@McpPrompt - 为 AI 交互生成提示消息
@McpComplete - 为提示提供自动完成功能
5.2. 特殊参数
注解系统支持提供额外上下文的特殊参数类型
McpMeta- 访问 MCP 请求中的元数据@McpProgressToken- 接收长时间运行操作的进度令牌McpSyncServerExchange/McpAsyncServerExchange- 用于高级操作的完整服务器上下文McpTransportContext- 用于无状态操作的轻量级上下文CallToolRequest- 用于灵活工具的动态模式支持
5.3. 简单示例
@Component
public class CalculatorTools {
@McpTool(name = "add", description = "Add two numbers together")
public int add(
@McpToolParam(description = "First number", required = true) int a,
@McpToolParam(description = "Second number", required = true) int b) {
return a + b;
}
@McpResource(uri = "config://{key}", name = "Configuration")
public String getConfig(String key) {
return configData.get(key);
}
}5.4. 自动配置
通过 Spring Boot 自动配置,注解的 Bean 会自动检测并注册
@SpringBootApplication
public class McpServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpServerApplication.class, args);
}
}自动配置将
扫描带有 MCP 注解的 Bean
创建适当的规范
将它们注册到 MCP 服务器
根据配置处理同步和异步实现
5.5. 配置属性
配置服务器注解扫描器
spring:
ai:
mcp:
server:
type: SYNC # or ASYNC
annotation-scanner:
enabled: true5.6. 其他资源
6. 示例应用程序
天气服务器 (SSE WebFlux) - 带有 WebFlux 传输的 Spring AI MCP 服务器启动器
天气服务器 (STDIO) - 带有 STDIO 传输的 Spring AI MCP 服务器启动器
天气服务器手动配置 - 不使用自动配置但使用 Java SDK 手动配置服务器的 Spring AI MCP 服务器启动器
可流式 HTTP WebFlux/WebMVC 示例 - 待办
无状态 WebFlux/WebMVC 示例 - 待办
7. 其他资源
MCP 安全
https://docs.springframework.org.cn/spring-ai/reference/api/mcp/mcp-security.html
MCP 注解
https://docs.springframework.org.cn/spring-ai/reference/api/mcp/mcp-annotations-overview.html
评论区