将您的AI连接到一切:Spring AI的MCP Boot Starters

工程 | Christian Tzolov | 2025年9月16日 | ...

模型上下文协议 (MCP) 规范了AI应用程序如何与外部工具和资源交互。Spring作为主要贡献者之一,很早就加入了MCP生态系统,帮助开发和维护了官方MCP Java SDK,该SDK是基于Java的MCP实现的基础。在此贡献的基础上,Spring AI通过专用的Boot StartersMCP Java Annotations全面支持MCP,使得构建能够无缝连接到外部系统的复杂AI驱动应用程序比以往任何时候都更加容易。

本博客介绍了核心MCP组件,并演示了如何使用Spring AI构建MCP服务器和客户端,展示了基本和高级功能。完整的源代码可在以下网址获取:MCP天气示例

注意:此内容仅适用于Spring AI 1.1.0-SNAPSHOT 或 Spring AI 1.1.0-M1+ 版本。

什么是模型上下文协议?

模型上下文协议 (MCP) 是一种标准化协议,使AI模型能够以结构化的方式与外部工具和资源交互。可以将其视为AI模型与现实世界之间的桥梁——允许它们通过一致的接口访问数据库、API、文件系统和其他外部服务。

MCP客户端-服务器架构

isolated

模型上下文协议遵循客户端-服务器架构,确保了关注点的明确分离。MCP服务器从第三方服务中暴露特定的功能(工具、资源、提示)。MCP客户端由宿主应用程序实例化,用于与特定的MCP服务器通信。每个客户端处理与一个服务器的一次直接通信。

宿主是用户交互的AI应用程序,而客户端是实现服务器连接的协议级组件。

MCP协议确保客户端和服务器之间完全、语言无关的互操作性。您可以拥有用Java、Python或TypeScript编写的客户端,与用任何语言编写的服务器进行通信,反之亦然。

这种架构在客户端和服务器端开发之间建立了明确的界限和责任,自然地形成了两个不同的开发者社区。

AI应用程序/宿主开发者

处理协调多个MCP服务器(通过MCP客户端连接)并与AI模型集成的复杂性。AI开发者构建AI应用程序,这些应用程序

  • 使用MCP客户端消费来自多个MCP服务器的功能
  • 处理AI模型集成和提示工程
  • 管理对话上下文和用户交互
  • 协调跨不同服务的复杂工作流
  • 专注于创造引人入胜的用户体验

MCP服务器(提供者)开发者

专注于将第三方服务中的特定功能(工具、资源、提示)作为MCP服务器暴露。服务器开发者创建的服务器

  • 封装第三方服务和API(数据库、文件系统、外部API)
  • 通过标准化的MCP原语(工具、资源、提示)暴露服务功能
  • 处理其特定服务的认证和授权

这种分离确保了服务器开发者可以专注于封装其领域特定服务,而无需担心AI编排。同时,AI应用程序开发者可以利用现有的MCP服务器,而无需了解每个第三方服务的复杂性。

这种分工意味着数据库专家可以为PostgreSQL创建一个MCP服务器,而无需理解LLM提示,而AI应用程序开发者可以使用该PostgreSQL服务器,而无需了解SQL内部机制。MCP协议充当了它们之间的通用语言。

Spring AI通过MCP客户端MCP服务器Boot Starters支持这种架构。这意味着Spring开发者可以参与MCP生态系统的两方面——构建消费MCP服务器的AI应用程序,以及创建将基于Spring的服务暴露给更广泛AI社区的MCP服务器。

MCP功能

MCP Capabilities

客户端和服务器共享,MCP提供了一套广泛的功能,使AI应用程序和外部服务之间能够无缝通信。

重要:工具由LLM拥有,与其他MCP功能(如提示和资源)不同。LLM(而不是宿主)决定何时、以何种顺序调用工具。宿主只控制哪些工具描述提供给LLM。

构建MCP服务器

让我们构建一个提供实时天气预报信息的可流式HTTP MCP服务器

Spring Boot服务器应用程序

创建一个新的 (mcp-weather-server) Spring Boot应用程序

@SpringBootApplication
public class McpServerApplication {
	public static void main(String[] args) {
		SpringApplication.run(McpServerApplication.class, args);
	}
}

带有Spring AI MCP服务器依赖
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>

了解更多关于可用的服务器依赖选项

application.properties中启用可流式HTTP服务器传输

spring.ai.mcp.server.protocol=STREAMABLE

您可以使用STREAMABLESTATELESSSSE传输启动服务器。要启用STDIO传输,您需要设置spring.ai.mcp.server.stdio=true


天气服务

利用免费的天气REST API构建一个能够通过位置坐标检索天气预报的服务。

添加@McpTool和@McpToolParam注解以将getTemperature方法注册为MCP服务器工具

@Service
public class WeatherService {

	public record WeatherResponse(Current current) {
		public record Current(LocalDateTime time, int interval, double temperature_2m) {}
	}

	@McpTool(description = "Get the temperature (in celsius) for a specific location")
	public WeatherResponse getTemperature(
      @McpToolParam(description = "The location latitude") double latitude,
      @McpToolParam(description = "The location longitude") double longitude) {

		return RestClient.create()
				.get()
				.uri("https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&current=temperature_2m",
						latitude, longitude)
				.retrieve()
				.body(WeatherResponse.class);
	}
}

构建和运行

./mvnw clean install -DskipTests

java -jar target/mcp-weather-server-0.0.1-SNAPSHOT.jar

这将在端口8080上启动mcp-weather-server。

使用MCP服务器

MCP天气服务器启动并运行后,您可以使用各种符合MCP的客户端应用程序与之交互

MCP检查器

MCP检查器是一个交互式开发工具,用于测试和调试MCP服务器。要启动检查器,请运行

npx @modelcontextprotocol/inspector

在浏览器UI中,将传输类型设置为Streamable HTTP,URL设置为https://:8080/mcp。点击Connect建立连接。然后列出工具并运行getTemperature。

MCP Capabilities

MCP Java SDK

使用MCP Java SDK客户端以编程方式连接到服务器

var client = McpClient.sync(
HttpClientStreamableHttpTransport
	.builder("https://:8080").build())
.build();

client.initialize();

CallToolResult weather = client.callTool(
	new CallToolRequest("getTemperature", 
			Map.of("latitude", "47.6062", 
					"longitude", "-122.3321")));

其他符合MCP的AI应用程序/SDK

将您的MCP服务器连接到流行的AI应用程序


Claude桌面版

要与Claude桌面版集成,使用本地STDIO传输,请在Claude桌面版设置中添加以下配置

{
 "mcpServers": {
  "spring-ai-mcp-weather": {
  "command": "java",
  "args": [
	"-Dspring.ai.mcp.server.stdio=true",
	"-Dspring.main.web-application-type=none",
	"-Dlogging.pattern.console=",
	"-jar",
	"/path/to/mcp-weather-server-0.0.1.jar"]
  }
 }
}

/absolute/path/to/替换为您的构建JAR文件的实际路径。

请遵循Claude桌面版的MCP服务器安装以获取进一步指导。Claude桌面版的免费版本不支持采样!




MCP Claude Desktop

高级服务器功能

让我们扩展我们的MCP天气服务器,以演示包括日志、进度跟踪和采样在内的高级MCP功能。这些功能实现了服务器和客户端之间丰富的交互

  • 日志:向连接的客户端发送结构化日志消息以进行调试和监控
  • 进度跟踪:报告长时间运行操作的实时进度更新
  • 采样:请求客户端的LLM根据服务器数据生成内容

在这个增强版本中,我们的天气服务器将向客户端记录其操作以实现透明度,在获取和处理天气数据时报告进度,并请求客户端的LLM生成一首关于天气预报的史诗般诗歌。

这是更新后的服务器实现

@Service
public class WeatherService {

	public record WeatherResponse(Current current) {
		public record Current(LocalDateTime time, int interval, double temperature_2m) {}
	}

	@McpTool(description = "Get the temperature (in celsius) for a specific location")
	public String getTemperature(
			McpSyncServerExchange exchange, // (1)
			@McpToolParam(description = "The location latitude") double latitude,
			@McpToolParam(description = "The location longitude") double longitude,
			@McpProgressToken String progressToken) { // (2)

		exchange.loggingNotification(LoggingMessageNotification.builder() // (3)
			.level(LoggingLevel.DEBUG)
			.data("Call getTemperature Tool with latitude: " + latitude + " and longitude: " + longitude)
			.meta(Map.of()) // non null meta as a workaround for bug: ...
			.build());

		WeatherResponse weatherResponse = RestClient.create()
				.get()
				.uri("https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&current=temperature_2m",
						latitude, longitude)
				.retrieve()
				.body(WeatherResponse.class);
		

		String epicPoem = "MCP Client doesn't provide sampling capability.";

		if (exchange.getClientCapabilities().sampling() != null) {
			// 50% progress
			exchange.progressNotification(new ProgressNotification(progressToken, 0.5, 1.0, "Start sampling"));	// (4)

			String samplingMessage = """
					For a weather forecast (temperature is in Celsius): %s.
					At location with latitude: %s and longitude: %s.
					Please write an epic poem about this forecast using a Shakespearean style.
					""".formatted(weatherResponse.current().temperature_2m(), latitude, longitude);

			CreateMessageResult samplingResponse = exchange.createMessage(CreateMessageRequest.builder()
					.systemPrompt("You are a poet!")
					.messages(List.of(new SamplingMessage(Role.USER, new TextContent(samplingMessage))))
					.build()); // (5)

			epicPoem = ((TextContent) samplingResponse.content()).text();
		}	
		
		// 100% progress
		exchange.progressNotification(new ProgressNotification(progressToken, 1.0, 1.0, "Task completed"));

		return """
			Weather Poem: %s			
			about the weather: %s°C at location: (%s, %s)		
			""".formatted(epicPoem, weatherResponse.current().temperature_2m(), latitude, longitude);
  }
}
  1. McpSyncServerExchange - exchange参数提供对服务器-客户端通信功能的访问。它允许服务器发送通知并向客户端发出请求。

  2. @ProgressToken - progressToken参数启用进度跟踪。客户端提供此令牌,服务器使用它发送进度更新。

  3. 日志通知 - 向客户端发送结构化日志消息以进行调试和监控。

  4. 进度更新 - 向客户端报告操作进度(在本例中为50%),并附带描述性消息。

MCP Capabilities

  1. 采样功能 - 最强大的功能 - 服务器可以请求客户端的LLM生成内容。

这允许服务器利用客户端的AI功能,创建双向AI交互模式。

增强后的天气服务现在不仅返回天气数据,还返回一首关于天气预报的创意诗歌,展示了MCP服务器和AI模型之间强大的协同作用。

构建MCP客户端

让我们构建一个使用LLM并通过MCP客户端连接到MCP服务器的AI应用程序。

客户端配置

创建一个新的Spring Boot项目 (mcp-weather-client),并添加以下依赖

<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-model-anthropic</artifactId>
</dependency>

了解关于可用依赖选项以配置不同的传输机制。

application.yml中,配置与MCP服务器的连接

spring:
  main:
    web-application-type: none

  ai:
    # Set credentials for your Anthropic API account
    anthropic:
      api-key: ${ANTHROPIC_API_KEY}

    # Connect to the MCP Weather Server using streamable-http client transport
    mcp:
      client:
        streamable-http:
          connections:
            my-weather-server:
              url: https://:8080    

请注意,配置已为服务器连接分配了my-weather-server名称。

Spring Boot客户端应用程序

创建一个使用连接到LLM和MCP天气服务器的ChatClient的客户端应用程序。

@SpringBootApplication
public class McpClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(McpClientApplication.class, args).close(); // (1)
	}

	@Bean
	public ChatClient chatClient(ChatClient.Builder chatClientBuilder) { // (2)
		return chatClientBuilder.build();
	}

	String userPrompt = """
		Check the weather in Amsterdam right now and show the creative response!
		Please incorporate all creative responses from all LLM providers.
		""";

	@Bean
	public CommandLineRunner predefinedQuestions(ChatClient chatClient, ToolCallbackProvider mcpToolProvider) { // (3)
		return args -> System.out.println(
			chatClient.prompt(userPrompt) // (4)
				.toolContext(Map.of("progressToken", "token-" + new Random().nextInt())) // (5)
				.toolCallbacks(mcpToolProvider) // (6)
				.call()
				.content());
	}
}
  1. 应用程序生命周期管理 - 应用程序启动、执行天气查询、显示结果,然后干净地退出。

  2. ChatClient配置 - 使用Spring AI的自动配置构建器创建一个已配置的ChatClient bean。构建器会自动填充

    • AI模型配置(在本例中为Anthropic Claude)
    • application.properties中的默认设置和配置
  3. CommandLineRunner - 在应用程序上下文完全加载后自动运行。它注入了已配置的ChatClient用于AI模型交互,以及包含所有已注册的MCP工具的ToolCallbackProvider,这些工具来自连接的服务器。

  4. AI提示 - 指示AI模型获取阿姆斯特丹的当前天气。AI模型会根据提示自动发现并调用适当的MCP工具。

  5. 进度令牌 - 使用toolContext将唯一的progressToken传递给带有@McpProgressToken参数注解的MCP工具。

  6. MCP工具集成 - 这条关键行将ChatClient连接到所有可用的MCP工具

  • mcpToolProvider由Spring AI的MCP客户端启动器自动配置
  • 包含来自已连接MCP服务器的所有工具(通过spring.ai.mcp.client.*.connections.*配置)
  • AI模型可以在对话期间自动发现并调用这些工具

客户端MCP处理器

创建一个服务类来处理来自服务器的MCP通知和请求。这些处理器是我们在上面实现的高级服务器功能的客户端对应部分,实现了MCP服务器和客户端之间的双向通信。

@Service
public class McpClientHandlers {

	private static final Logger logger = LoggerFactory.getLogger(McpClientHandlers.class);

	private final ChatClient chatClient;

	public McpClientHandlers(@Lazy ChatClient chatClient) { // Lazy is needed to avoid circular dependency
		this.chatClient = chatClient;
	}

	@McpProgress(clients = "my-weather-server") // (1)
	public void progressHandler(ProgressNotification progressNotification) {
		logger.info("MCP PROGRESS: [{}] progress: {} total: {} message: {}",
				progressNotification.progressToken(), progressNotification.progress(),
				progressNotification.total(), progressNotification.message());
	}

	@McpLogging(clients = "my-weather-server")
	public void loggingHandler(LoggingMessageNotification loggingMessage) {
		logger.info("MCP LOGGING: [{}] {}", loggingMessage.level(), loggingMessage.data());
	}

	@McpSampling(clients = "my-weather-server")
	public CreateMessageResult samplingHandler(CreateMessageRequest llmRequest) {

		logger.info("MCP SAMPLING: {}", llmRequest);

		String llmResponse = chatClient
				.prompt()
				.system(llmRequest.systemPrompt())
				.user(((TextContent) llmRequest.messages().get(0).content()).text())
				.call()
				.content();

		return CreateMessageResult.builder().content(new TextContent(llmResponse)).build();
	}
}

理解处理器组件
  1. 进度处理器 - 接收来自服务器长时间运行操作的实时进度更新。当服务器调用exchange.progressNotification(...)时触发。例如,天气服务器在开始采样时发送50%的进度,完成时发送100%。通常用于显示进度条、更新UI状态或记录操作进度。

  2. 日志处理器 - 接收来自服务器的结构化日志消息以进行调试和监控。当服务器调用exchange.loggingNotification(...)时触发。例如,天气服务器记录“调用getTemperature工具,纬度:X,经度:Y”。用于调试服务器操作、审计跟踪或监控仪表板。

  3. 采样处理器 - 最强大的功能。它使服务器能够从客户端的LLM请求AI生成的内容。用于双向AI交互、创意内容生成、动态响应。当服务器调用带有采样功能检查的exchange.createMessage(...)时触发。执行流程如下

    • 如果客户端支持采样,则请求一首关于天气的诗歌
    • 客户端处理器接收请求并使用其ChatClient与LLM交互并生成诗歌
    • 生成的诗歌返回给服务器并合并到最终的工具响应中
关键设计模式
  • 基于注解的路由clients = "my-weather-server"属性确保处理器仅处理来自配置中定义的特定MCP服务器连接的通知:spring.ai.mcp.client.streamable-http.connections.[my-weather-server].url

    如果您的应用程序连接到多个MCP服务器,请使用clients属性将每个处理器分配给相应的MCP客户端。

    @McpProgress(clients = {"weather-server", "database-server"})  // Handle progress from multiple servers
    public void multiServerProgressHandler(ProgressNotification notification) {
    	// Handle progress from both servers
    }
    
    @McpSampling(clients = "specialized-ai-server")  // Handle sampling from specific server
    public CreateMessageResult specializedSamplingHandler(CreateMessageRequest request) {
    	// Handle sampling requests from specialized AI server
    }
    
  • ChatClient上的@Lazy注解可以防止在ChatClient也依赖于MCP组件时可能出现的循环依赖问题。

  • 双向AI通信:采样处理器创建了一个强大的模式,其中

    • 服务器(领域专家)可以利用客户端的AI功能

    • 客户端的LLM根据服务器提供的上下文生成创意内容

    • 这实现了超越简单工具调用的复杂AI-AI交互

      这种架构使MCP客户端成为服务器操作中的反应式参与者,实现了复杂的交互,而不仅仅是被动的工具消费。

多个MCP服务器

使用不同的传输连接到多个MCP服务器。以下是如何在您的天气服务器旁边添加Brave搜索MCP服务器进行网页搜索的示例

MCP Demo

spring:
  ai:
    anthropic:
      api-key: ${ANTHROPIC_API_KEY}
    mcp:
      client:
        streamable-http:
          connections:
            my-weather-server:
              url: https://:8080        
        stdio:
          connections:
            brave-search:
              command: npx
              args: ["-y", 
				"@modelcontextprotocol/server-brave-search"]

它使用STDIO客户端传输。

现在您的LLM可以在单个提示中结合天气数据和网页搜索

String userPrompt = """
	Check the weather in Amsterdam and show the creative response!
	Please incorporate all creative responses.
	
	Then search online to find publishers for poetry and list top 3.
	""";

构建并运行

确保您的MCP天气服务器已启动并运行。

然后构建并启动您的客户端

./mvnw clean install -DskipTests

java -jar target/mcp-weather-client-0.0.1-SNAPSHOT.jar

结论

Spring成熟的开发模型与MCP标准化协议的结合,为下一代AI应用程序奠定了坚实的基础。无论您是构建聊天机器人、数据分析工具还是开发助手,Spring AI的MCP支持都能为您提供所需的构建块。

本介绍涵盖了基本的MCP概念,并演示了如何使用Spring AI的Boot Starters构建MCP服务器和客户端,并实现了基本的工具功能。然而,MCP生态系统提供了更复杂的功能,我们将在未来的博客文章中进行探讨。

  • Java MCP注解深入探讨:学习如何利用Spring AI的基于注解的方法创建更易于维护和声明式的MCP实现,包括高级注解模式和最佳实践。

  • 超越工具 - 提示、资源和补全:探索如何实现MCP的全套功能,包括共享提示模板、动态资源提供和智能自动补全功能,这些功能使您的MCP服务器更加用户友好和强大。

  • 授权支持 - 保护MCP服务器:使用OAuth 2保护您的MCP服务器,并确保只有授权用户才能访问工具、资源和其他功能。为您的MCP客户端添加授权支持,以便它们可以获取OAuth 2令牌以与安全的MCP服务器进行身份验证。

准备好开始了吗?查看示例应用程序,探索Spring AI和MCP与AI集成的全部潜力。

其他资源


有关最新更新和全面文档,请访问Spring AI参考文档

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有