spring ai alibaba mcp 开发demo

基础:SpringBoot, 大模型基础

前言

开发mcp,理解mcp的概念很重要,举个抽象的例子:

想象一下, client 和 server 两个进程之间,有一根"永远开着的电话线"(SSE 长连接)。这根线一旦接通,双方就可以随时互相喊话。

握手阶段,Server 会先告诉 Client:"我支持 MCP 协议 x.y 版本,这里是我当前的能力包"、"我有哪些工具、怎么使用"。之后这根线就一直保持着:

Server 有新工具 → 它在电话线里说一句 "工具列表变了!"(tools/listchanged 事件);

Client 听到后 → 主动再问一次:"给我最新的列表"(tools/list 请求),然后把新的工具元数据写入本地缓存。

Client 在大模型对话的时候,会根据当前问题和上下文,自动判断使用哪个工具。

整个过程不需要重启 Client,因为连接一直在,你随时能接到 Server 的"变更提醒"。

spring ai alibaba封装了这些底层细节,我们只需要根据需要,开发对应的工具即可。

总结就是:server负责提供工具的实现,而client负责获取server的工具列表,并由大模型决定使用哪个工具。

基于 sse 查询天气mcp开发示例

weatherServer

项目结构:

pom

yaml 复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
        </dependency>
    </dependencies>

配置文件:

yaml 复制代码
server:
  port: 8080

spring:
    mcp:
      server:
        name: my-weather-server # 服务名称
        version: 1.0.0
        
       # 下面都是默认配置,可以不配置
        type: async
        sse-endpoint: /sse
        sse-message-endpoint: /mcp/message
        capabilities:
          tool: true
          resource: true
          prompt: true
          completion: true

编写工具:

java 复制代码
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

@Service
public class OpenMeteoService {

    private final WebClient webClient;


	// 实时查询天气
    public OpenMeteoService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder
            .baseUrl("https://api.open-meteo.com/v1")
            .defaultHeader("Accept", "application/json")
            .defaultHeader("User-Agent", "OpenMeteoClient/1.0")
            .build();
    }


    @Tool(description = "根据经纬度获取天气预报")
    public String getWeatherForecastByLocation(
        @ToolParam(description = "纬度,例如:39.9042") String latitude,
        @ToolParam(description = "经度,例如:116.4074") String longitude) {

        try {
            String response = webClient.get()
                .uri(uriBuilder -> uriBuilder
                    .path("/forecast")
                    .queryParam("latitude", latitude)
                    .queryParam("longitude", longitude)
                    .queryParam("current", "temperature_2m,wind_speed_10m")
                    .queryParam("timezone", "auto")
                    .build())
                .retrieve()
                .bodyToMono(String.class)
                .block();

            System.out.printf("当前请求经度:" + longitude + ",纬度:" + latitude + "的天气预报:\n" + response);

            // 解析响应并返回格式化的天气信息
            return "当前位置(纬度:" + latitude + ",经度:" + longitude + ")的天气信息:\n" + response;
        } catch (Exception e) {
            return "获取天气信息失败:" + e.getMessage();
        }
    }

    @Tool(description = "根据经纬度获取空气质量信息")
    public String getAirQuality(
        @ToolParam(description = "纬度,例如:39.9042") String latitude,
        @ToolParam(description = "经度,例如:116.4074") String longitude) {

        // 模拟数据,实际应用中应调用真实API
        return "当前位置(纬度:" + latitude + ",经度:" + longitude + ")的空气质量:\n" +
            "- PM2.5: 15 μg/m³ (优)\n" +
            "- PM10: 28 μg/m³ (良)\n" +
            "- 空气质量指数(AQI): 42 (优)\n" +
            "- 主要污染物: 无";
    }

}

注册工具:

java 复制代码
import com.xxxx.lh.service.OpenMeteoService;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class StartApplication {

    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class, args);

    }

    @Bean
    ToolCallbackProvider weatherTools(OpenMeteoService openMeteoService) {
        return MethodToolCallbackProvider.builder()
            .toolObjects(openMeteoService) // 将天气工具类注册到tools中
            .build();

    }
}

至此,我们就完成了server的开发,我们在server中定义了两个工具,分别是根据经纬度查询天气和查询空气质量。 开发主要步骤分为2步:

  1. 开发工具,通过 @Tool 和 @ToolParam注解,描述方法的参数和作用
  2. 将方法注册到 ToolCallbackProvider 中。

client 开发

项目结构:

pom

yaml 复制代码
   <dependencies>

        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
        </dependency>

        <!-- Spring AI Starter MCP Client, 这里依赖来自 spring ai bom -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
        </dependency>
    </dependencies>

配置文件:

yaml 复制代码
server:
  port: 8081

spring:
  main:
    web-application-type: none
  ai:
    dashscope:
      api-key: sk-xxx  # client 需要调用大模型,api-key必填
    mcp:
      client:
        sse:
          connections:
            server:
              url: http://localhost:8080 # 指定server地址,用于mcp连接

大模型调用

java 复制代码
// 构建chatClient并注入mcp工具
            ChatClient chatClient = chatClientBuilder
                .defaultToolCallbacks(tools)
                .build();

            // 大模型交互
            String input = "北京天气如何";
            System.out.println("\n>>> QUESTION: " + input);
            System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(input).call().content());

输出结果:

复制代码
>>> QUESTION: 北京天气如何

>>> ASSISTANT: 北京当前的天气和空气质量情况如下:

**天气信息:**
- 温度:8.8°C
- 风速:4.8 km/h
- 位置:北京(纬度:39.9042,经度:116.4074)
- 时间:2025-11-07 16:45

**空气质量:**
- PM2.5:15 μg/m³(优)
- PM10:28 μg/m³(良)
- 空气质量指数(AQI):42(优)
- 主要污染物:无

总体来看,北京当前天气较为凉爽,空气质量良好,适合户外活动。

总结:

Server 端启动

注册工具并暴露 MCP 接口。在 weatherServer 中通过 MethodToolCallbackProvider 将 OpenMeteoService 的 @Tool 方法包装成符合 MCP 规范的"Tool 回调"。

spring-ai-starter-mcp-server-webflux 自动暴露 /sse 接口(Server-Sent Events)。当客户端连接时,通过 MCP 协议推送工具列表、参数定义和提示等能力。

OpenMeteoService 的 @Tool 注解包含方法名、描述和参数结构,这些元数据会在连接时标准化并发送至客户端。

Client 端启动

建立 SSE 连接并同步工具。ChatClient 启动时注入 defaultToolCallbacks,指定 MCP 工具入口。

配置文件中设置 spring.ai.mcp.client.sse.connections.server.url=http://localhost:8080,指向 Server 的 SSE 地址。

MCP 客户端使用 WebFlux SSE 连接该地址。连接成功后,Server 按 MCP 规范发送"Capabilities"或"Tools"列表。

客户端自动将工具注册到本地 ToolCallbackProvider,并缓存参数类型和名称等 schema 信息。

大模型问答

模型触发工具调用并由 MCP 转发。执行 chatClient.prompt("北京天气如何") 时,ChatClient 将 MCP 工具列表和 prompt 发送至模型。

模型分析后决定调用工具(如 getWeatherForecastByLocation),并返回符合 OpenAI Function Call 或 MCP Tool Call 格式的信息。

ChatClient 解包 function call 信息,通过 ToolCallbackProvider 调度到实际工具回调。

MCP 工具通过 SSE 连接向 Server 发送 tools/call 消息。Server 动态调用 OpenMeteoService 对应方法(如通过 WebClient 访问 Open-Meteo API),返回结果作为 tools/call.result 消息。

客户端将工具结果包装后交给模型继续推理,最终生成融合工具数据的回答。

连接维护与监听

SSE 是长连接,Server 持续推送工具列表更新和提示等通知。客户端可通过该通道发送资源下载请求。

日志中的 "Server response with Protocol: 2024-11-05, Capabilities: ..." 表示 MCP 握手成功。

连接在应用关闭或上下文退出时自动断开。

相关推荐
leonardee2 小时前
Spring 中的 @ExceptionHandler 注解详解与应用
java·后端
不爱编程的小九九2 小时前
小九源码-springboot103-踏雪阁民宿订购平台
java·开发语言·spring boot
Elieal2 小时前
Spring 框架核心技术全解析
java·spring·sqlserver
组合缺一2 小时前
(对标 Spring)OpenSolon v3.7.0, v3.6.4, v3.5.8, v3.4.8 发布(支持 LTS)
java·后端·spring·web·solon
程序员霸哥哥2 小时前
从零搭建PyTorch计算机视觉模型
人工智能·pytorch·python·计算机视觉
wheeldown2 小时前
【Linux】Linux 地址空间 + 页表映射的概念解析
java·linux·jvm
源码宝2 小时前
一套随访系统源码,医院随访管理系统源码,三级随访平台源码,技术框架:Java+Spring boot,Vue,Ant-Design+MySQL5
java·源码·软件开发·程序·随访·随访系统源码·三级随访
♡喜欢做梦2 小时前
Spring IOC
java·后端·spring
草莓熊Lotso3 小时前
Linux 基础开发工具入门:软件包管理器的全方位实操指南
linux·运维·服务器·c++·人工智能·网络协议·rpc