6.8 KiB
Raw Blame History

Spring AI MCP WebFlux 服务器示例

项目简介

本项目是一个基于 Spring AI 框架的 Model Context Protocol (MCP) WebFlux 服务器示例。它展示了如何构建一个支持 WebFlux 和 STDIO 两种通信方式的 MCP 服务器,提供天气查询和空气质量信息等工具服务。

主要功能

  • 支持 WebFlux 和 STDIO 两种通信方式
  • 提供天气预报查询服务(基于 OpenMeteo API
  • 提供空气质量信息查询服务(模拟数据)
  • 支持响应式编程模型
  • 支持工具函数的动态注册和调用

技术栈

  • Java 17+
  • Spring Boot 3.x
  • Spring WebFlux
  • Spring AI MCP Server
  • OpenMeteo API
  • Maven

项目结构

starter-webflux-server/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── org/springframework/ai/mcp/sample/server/
│   │   │       ├── McpServerApplication.java     # 应用程序入口
│   │   │       └── OpenMeteoService.java         # 天气服务实现
│   │   └── resources/
│   │       └── application.properties            # 应用配置
│   └── test/
│       └── java/
│           └── org/springframework/ai/mcp/sample/client/
│               ├── ClientStdio.java              # STDIO 客户端测试
│               ├── ClientSse.java                # SSE 客户端测试
│               └── SampleClient.java             # 通用客户端测试
└── pom.xml                                       # Maven 配置

核心组件

McpServerApplication

应用程序的主入口类,负责:

  • 配置 Spring Boot 应用
  • 注册天气工具服务
  • 初始化 MCP 服务器

OpenMeteoService

提供两个主要工具服务:

  1. getWeatherForecastByLocation: 获取指定位置的天气预报

    • 支持当前天气和未来 7 天预报
    • 包含温度、湿度、风向、降水量等信息
    • 使用 OpenMeteo 免费 API
  2. getAirQuality: 获取指定位置的空气质量信息

    • 提供欧洲 AQI 和美国 AQI 两种标准
    • 包含 PM10、PM2.5、CO、NO2、SO2、O3 等污染物数据
    • 目前使用模拟数据(可扩展为真实 API

配置说明

服务器配置

application.properties 中:

# 服务器配置
spring.ai.mcp.server.name=my-weather-server
spring.ai.mcp.server.version=0.0.1

# 使用 STDIO 传输时的配置
spring.main.banner-mode=off
# logging.pattern.console=

WebFlux 客户端配置

在客户端的 application.properties 中:

# 基本配置
server.port=8888
spring.application.name=mcp
spring.main.web-application-type=none

# API 密钥配置
spring.ai.dashscope.api-key=${AI_DASHSCOPE_API_KEY}

# SSE 连接配置
spring.ai.mcp.client.sse.connections.server1.url=http://localhost:8080

# 调试日志
logging.level.io.modelcontextprotocol.client=DEBUG
logging.level.io.modelcontextprotocol.spec=DEBUG

# 编码配置
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
spring.mandatory-file-encoding=UTF-8

# 用户输入配置
ai.user.input=北京的天气如何?

使用方法

1. 编译项目

mvn clean package -DskipTests

2. 启动服务器

作为 Web 服务器启动

mvn spring-boot:run

服务器将在 http://localhost:8080 启动。

作为 STDIO 服务器启动

java -Dspring.ai.mcp.server.stdio=true \
     -Dspring.main.web-application-type=none \
     -Dlogging.pattern.console= \
     -jar target/mcp-starter-webflux-server-0.0.1-SNAPSHOT.jar

3. 客户端示例

WebFlux 客户端

代码示例

代码文件为 org.springframework.ai.mcp.sample.client.ClientSse可以直接运行测试。

// 配置 WebFlux 客户端
var transport = new WebFluxSseClientTransport(
    WebClient.builder().baseUrl("http://localhost:8080")
);

// 创建聊天客户端
var chatClient = chatClientBuilder
    .defaultTools(tools)
    .build();

// 发送问题并获取回答
System.out.println("\n>>> QUESTION: " + userInput);
System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(userInput).call().content());
mcp setting 配置示例

在 cursor、cline 等 MCP 客户端中,本示例可以使用如下配置:

{
  "mcpServers": {
    "weather-local": {
      "url": "http://localhost:8080/sse"
    }
  }
}

STDIO 客户端

代码示例

代码文件为 org.springframework.ai.mcp.sample.client.ClientStdio可以直接运行测试。

var stdioParams = ServerParameters.builder("java")
    .args("-Dspring.ai.mcp.server.stdio=true",
          "-Dspring.main.web-application-type=none",
          "-Dlogging.pattern.console=",
          "-jar",
          "target/mcp-starter-webflux-server-0.0.1-SNAPSHOT.jar")
    .build();

var transport = new StdioClientTransport(stdioParams);
new SampleClient(transport).run();
mcp setting 配置示例

在 cursor、cline 等 MCP 客户端中,本示例可以使用如下配置:

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

工具调用示例

获取天气预报

CallToolResult weatherResult = client.callTool(
        new CallToolRequest("getWeatherForecastByLocation",
                Map.of("latitude", "39.9042", "longitude", "116.4074"))
);

获取空气质量信息

CallToolResult airQualityResult = client.callTool(
        new CallToolRequest("getAirQuality",
                Map.of("latitude", "39.9042", "longitude", "116.4074"))
);

注意事项

  1. OpenMeteo API 是免费的,无需 API 密钥
  2. 空气质量数据目前使用模拟数据,实际应用中应替换为真实 API
  3. 使用 STDIO 传输时,必须禁用控制台日志和 banner
  4. 默认作为 WebFlux 服务器运行,支持 HTTP 通信
  5. 客户端需要正确配置 SSE 连接 URL
  6. 确保环境变量 DASH_SCOPE_API_KEY 已正确设置

扩展开发

如需添加新的工具服务:

  1. 创建新的服务类
  2. 使用 @Tool 注解标记方法
  3. McpServerApplication 中注册服务

示例:

@Service
public class MyNewService {
   @Tool(description = "新工具描述")
   public String myNewTool(String input) {
      // 实现工具逻辑
      return "处理结果: " + input;
   }
}

// 在 McpServerApplication 中注册
@Bean
public ToolCallbackProvider myTools(MyNewService myNewService) {
   return MethodToolCallbackProvider.builder()
           .toolObjects(myNewService)
           .build();
}

许可证

Apache License 2.0