收藏本站,收获最前沿的人工智能与编程资讯!!

Spring AI MCP 客户端启动器

技术文档 14℃ 0

MCP 客户端启动器

Spring AI MCP(模型上下文协议)客户端启动器为Spring Boot应用提供MCP客户端功能的自动配置。它支持同步和异步客户端实现,并提供多种传输选项。

MCP客户端启动器提供以下能力:

  • 多客户端实例管理

  • 客户端自动初始化(若启用)

  • 支持多个命名传输协议(标准输入输出、HTTP/SSE和可流式传输HTTP)

  • 与Spring AI工具执行框架集成

  • 工具过滤能力,支持选择性包含/排除工具

  • 可自定义的工具名称前缀生成,避免命名冲突

  • 完善的生命周期管理,应用上下文关闭时自动清理资源

  • 通过定制器实现客户端创建自定义

启动器

标准MCP客户端

org.springframework.aispring-ai-starter-mcp-client

标准启动器可通过标准输入输出(进程内)、SSE、可流式传输HTTP和无状态可流式传输HTTP传输协议同时连接一个或多个MCP服务器。SSE和可流式传输HTTP传输协议使用基于JDK HttpClient的传输实现。每个MCP服务器连接都会创建一个新的MCP客户端实例。你可以选择SYNC(同步)或ASYNC(异步)MCP客户端(注意:不能混合使用同步和异步客户端)。生产环境部署时,我们建议使用基于WebFlux的SSE和可流式传输HTTP连接,配合spring-ai-starter-mcp-client-webflux使用。

WebFlux客户端

WebFlux启动器提供与标准启动器相似的功能,但使用基于WebFlux的可流式传输HTTP、无状态可流式传输HTTP和SSE传输实现。

org.springframework.aispring-ai-starter-mcp-client-webflux

配置属性

通用属性

通用属性前缀为spring.ai.mcp.client:

属性	描述	默认值
enabled	启用/禁用MCP客户端	true
name	MCP客户端实例名称	spring-ai-mcp-client
version	MCP客户端实例版本	1.0.0
initialized	创建时是否初始化客户端	true
request-timeout	MCP客户端请求超时时间	20s
type	客户端类型(SYNC或ASYNC),所有客户端必须统一为同步或异步,不支持混合	SYNC
root-change-notification	启用/禁用所有客户端的根目录变更通知	true
toolcallback.enabled	启用/禁用MCP工具回调与Spring AI工具执行框架的集成	true

MCP注解属性

MCP客户端注解提供了一种声明式方式,通过Java注解实现MCP客户端处理器。客户端mcp-annotations属性前缀为spring.ai.mcp.client.annotation-scanner:

属性	描述	默认值
enabled	启用/禁用MCP客户端注解自动扫描	true

标准输入输出传输属性

标准输入输出传输属性前缀为spring.ai.mcp.client.stdio:

属性	描述	默认值
servers-configuration	包含JSON格式MCP服务器配置的资源	-
connections	命名的标准输入输出连接配置映射	-
connections.[name].command	执行MCP服务器的命令	-
connections.[name].args	命令参数列表	-
connections.[name].env	服务器进程的环境变量映射	-

配置示例:

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文件配置标准输入输出连接:

spring:
  ai:
    mcp:
      client:
        stdio:
          servers-configuration: classpath:mcp-servers.json

Claude桌面格式如下:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/username/Desktop",
        "/Users/username/Downloads"
      ]
    }
  }
}

Windows系统标准输入输出配置

在Windows系统中,npx、npm、node等命令以批处理文件(.cmd)形式实现,而非原生可执行文件。Java的ProcessBuilder无法直接执行批处理文件,需要使用cmd.exe /c包装器。

Windows系统需要特殊处理的原因:

Java的ProcessBuilder(StdioClientTransport内部使用)在Windows系统中尝试生成进程时,仅能执行以下内容:

  • 原生可执行文件(.exe文件)

  • cmd.exe支持的系统命令

Windows批处理文件(如npx.cmd、npm.cmd,甚至微软应用商店安装的python.cmd)需要通过cmd.exe shell执行。

解决方案: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"
      ]
    }
  }
}

跨平台编程式配置

对于需要跨平台运行且无需独立配置文件的应用,可在Spring Boot应用中使用操作系统检测:

@Bean(destroyMethod = "close")
@ConditionalOnMissingBean(McpSyncClient.class)
public McpSyncClient mcpClient() {
    ServerParameters stdioParams;

    if (isWindows()) {
        // Windows系统:使用cmd.exe /c npx方式
        var winArgs = new ArrayList<>(Arrays.asList(
            "/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "target"));
        stdioParams = ServerParameters.builder("cmd.exe")
                .args(winArgs)
                .build();
    } else {
        // Linux/Mac系统:直接使用npx方式
        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文件的自动配置产生冲突。

路径注意事项

相对路径(推荐用于可移植性):

{
  "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"]
}

需要cmd.exe的常见Windows批处理文件:

  • npx.cmd、npm.cmd - Node包管理器

  • python.cmd - Python(微软应用商店安装版)

  • pip.cmd - Python包管理器

  • mvn.cmd - Maven包装器

  • gradle.cmd - Gradle包装器

  • 自定义.cmd或.bat脚本

参考实现

查看Spring AI示例 - 文件系统,获取完整的跨平台MCP客户端实现,该实现可自动检测操作系统并完成客户端配置。

可流式传输HTTP传输属性

用于连接可流式传输HTTP和无状态可流式传输HTTP MCP服务器。

可流式传输HTTP传输属性前缀为spring.ai.mcp.client.streamable-http:

属性	描述	默认值
connections	命名的可流式传输HTTP连接配置映射	-
connections.[name].url	与MCP服务器进行可流式传输HTTP通信的基础URL端点	-
connections.[name].endpoint	连接使用的可流式传输HTTP端点(作为URL后缀)	/mcp

配置示例:

spring:
  ai:
    mcp:
      client:
        streamable-http:
          connections:
            server1:
              url: http://localhost:8080
            server2:
              url: http://otherserver:8081
              endpoint: /custom-sse

SSE传输属性

服务器发送事件(SSE)传输属性前缀为spring.ai.mcp.client.sse:

属性	描述	默认值
connections	命名的SSE连接配置映射	-
connections.[name].url	与MCP服务器进行SSE通信的基础URL端点	-
connections.[name].sse-endpoint	连接使用的SSE端点(作为URL后缀)	/sse

配置示例:

spring:
  ai:
    mcp:
      client:
        sse:
          connections:
            # 使用默认/sse端点的简单配置
            server1:
              url: http://localhost:8080
            # 自定义SSE端点
            server2:
              url: http://otherserver:8081
              sse-endpoint: /custom-sse
            # 带路径和令牌的复杂URL(如MCP中心)
            mcp-hub:
              url: http://localhost:3000
              sse-endpoint: /mcp-hub/sse/cf9ec4527e3c4a2cbb149a85ea45ab01
            # 带查询参数的SSE端点
            api-server:
              url: https://api.example.com
              sse-endpoint: /v1/mcp/events?token=abc123&format=json

URL拆分规则

当你拥有完整的SSE URL时,将其拆分为基础URL和端点路径:

完整URL	配置
http://localhost:3000/mcp-hub/sse/token123	
url: localhost:3000
sse-endpoint: /mcp-hub/sse/token123

https://api.service.com/v2/events?key=secret	
url: api.service.com
sse-endpoint: /v2/events?key=secret

http://localhost:8080/sse	
url: localhost:8080
sse-endpoint: /sse(或省略使用默认值)

SSE连接故障排除

404未找到错误:

  • 验证URL拆分:确保基础URL仅包含协议、主机和端口

  • 检查sse-endpoint以/开头,并包含完整路径和查询参数

  • 直接在浏览器或curl中测试完整URL,确认可访问

功能特性

同步/异步客户端类型

启动器支持两种客户端类型:

  • 同步 - 默认客户端类型(spring.ai.mcp.client.type=SYNC),适用于传统请求响应模式的阻塞操作

注意:同步客户端仅注册同步MCP注解方法,异步方法会被忽略。

  • 异步 - 适用于非阻塞操作的响应式应用,通过spring.ai.mcp.client.type=ASYNC配置

注意:异步客户端仅注册异步MCP注解方法,同步方法会被忽略。

客户端自定义

自动配置通过回调接口提供广泛的客户端规格自定义能力。这些定制器允许你配置MCP客户端行为的各个方面,从请求超时到事件处理和消息处理。

自定义类型:

  • 请求配置 - 设置自定义请求超时

  • 自定义采样处理器 - 服务器通过客户端向大语言模型请求采样(补全或生成)的标准化方式。该流程允许客户端控制模型访问、选择和权限,同时使服务器能够利用AI能力,无需服务器API密钥

  • 文件系统(根目录)访问 - 客户端向服务器暴露文件系统根目录的标准化方式。根目录定义了服务器在文件系统中的操作边界,使其能够了解可访问的目录和文件。服务器可从支持的客户端请求根目录列表,并在列表变更时接收通知

  • 引导处理器 - 服务器在交互过程中通过客户端向用户请求额外信息的标准化方式

  • 事件处理器 - 当特定服务器事件发生时通知客户端的处理器:

    • 工具变更通知 - 可用服务器工具列表变更时

    • 资源变更通知 - 可用服务器资源列表变更时

    • 提示词变更通知 - 可用服务器提示词列表变更时

  • 日志处理器 - 服务器向客户端发送结构化日志消息的标准化方式

  • 进度处理器 - 服务器向客户端发送结构化进度消息的标准化方式

客户端可通过设置最小日志级别控制日志详细程度

客户端自定义示例

根据应用需求,你可以为同步客户端实现McpSyncClientCustomizer,或为异步客户端实现McpAsyncClientCustomizer。

同步:

@Component
public class CustomMcpSyncClientCustomizer implements McpSyncClientCustomizer {
    @Override
    public void customize(String serverConfigurationName, McpClient.SyncSpec spec) {

        // 自定义请求超时配置
        spec.requestTimeout(Duration.ofSeconds(30));

        // 设置客户端可访问的根URI
        spec.roots(roots);

        // 设置自定义采样处理器,处理消息创建请求
        spec.sampling((CreateMessageRequest messageRequest) -> {
            // 处理采样逻辑
            CreateMessageResult result = ...
            return result;
        });

        // 设置自定义引导处理器,处理引导请求
        spec.elicitation((ElicitRequest request) -> {
          // 处理引导逻辑
          return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of("message", request.message()));
        });

        // 添加消费者,接收进度通知
        spec.progressConsumer((ProgressNotification progress) -> {
         // 处理进度通知
        });

        // 添加消费者,工具新增或移除等可用工具变更时通知
        spec.toolsChangeConsumer((Listtools) -> {
            // 处理工具变更
        });

        // 添加消费者,资源新增或移除等可用资源变更时通知
        spec.resourcesChangeConsumer((Listresources) -> {
            // 处理资源变更
        });

        // 添加消费者,提示词新增或移除等可用提示词变更时通知
        spec.promptsChangeConsumer((Listprompts) -> {
            // 处理提示词变更
        });

        // 添加消费者,接收服务器的日志消息
        spec.loggingConsumer((McpSchema.LoggingMessageNotification log) -> {
            // 处理日志消息
        });
    }
}

serverConfigurationName参数是定制器应用的服务器配置名称,也是MCP客户端的创建对象。

MCP客户端自动配置会自动检测并应用应用上下文中找到的所有定制器。

传输支持

自动配置支持多种传输类型:

  • 标准输入输出(由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激活)

工具过滤

MCP客户端启动器通过McpToolFilter接口支持对发现的工具进行过滤。这允许你根据自定义条件(如MCP连接信息或工具属性)选择性包含或排除工具。

实现工具过滤,需创建一个实现McpToolFilter接口的Bean:

@Component
public class CustomMcpToolFilter implements McpToolFilter {

    @Override
    public boolean test(McpConnectionInfo connectionInfo, McpSchema.Tool tool) {
        // 基于连接信息和工具属性的过滤逻辑
        // 返回true表示包含该工具,false表示排除

        // 示例:排除特定客户端的工具
        if (connectionInfo.clientInfo().name().equals("restricted-client")) {
            return false;
        }

        // 示例:仅包含指定名称前缀的工具
        if (tool.name().startsWith("allowed_")) {
            return true;
        }

        // 示例:基于工具描述或其他属性过滤
        if (tool.description() != null &&
            tool.description().contains("experimental")) {
            return false;
        }

        return true; // 默认包含所有其他工具
    }
}

McpConnectionInfo记录提供以下信息访问:

  • clientCapabilities - MCP客户端的能力

  • clientInfo - MCP客户端信息(名称和版本)

  • initializeResult - MCP服务器的初始化结果

过滤器会自动检测并应用于同步和异步MCP工具回调提供者。若未提供自定义过滤器,默认包含所有发现的工具。

注意:应用上下文中仅应定义一个McpToolFilter Bean。若需要多个过滤器,将其合并为单个组合过滤器实现。

工具名称前缀生成

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) {
        // 自定义生成前缀工具名称的逻辑

        // 示例:使用服务器名称和版本作为前缀
        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服务器的初始化结果,包含服务器信息

内置前缀生成器

框架提供多种内置前缀生成器:

  • DefaultMcpToolNamePrefixGenerator - 通过跟踪重复项并添加计数器前缀确保工具名称唯一(未提供自定义Bean时默认使用)

  • McpToolNamePrefixGenerator.noPrefix() - 返回无任何前缀的工具名称(多个服务器提供同名工具时可能引发冲突)

完全禁用前缀并使用原始工具名称(多MCP服务器时不推荐),将无前缀生成器注册为Bean:

@Configuration
public class McpConfiguration {

    @Bean
    public McpToolNamePrefixGenerator mcpToolNamePrefixGenerator() {
        return McpToolNamePrefixGenerator.noPrefix();
    }
}

前缀生成器通过Spring的ObjectProvider机制自动检测并应用于同步和异步MCP工具回调提供者。若未提供自定义生成器Bean,自动使用DefaultMcpToolNamePrefixGenerator。

多MCP服务器使用McpToolNamePrefixGenerator.noPrefix()时,重复工具名称会引发IllegalStateException。默认的DefaultMcpToolNamePrefixGenerator通过为重复工具名称自动添加唯一前缀避免该问题。

工具上下文转MCP元数据转换器

MCP客户端启动器通过ToolContextToMcpMetaConverter接口支持将Spring AI的ToolContext自定义转换为MCP工具调用元数据。该功能允许你将额外上下文信息(如用户ID、密钥令牌)作为元数据,与大语言模型生成的调用参数一起传递。

例如,你可以在工具上下文中传递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)

  • 过滤掉值为null的条目

  • 将所有其他上下文条目作为元数据传递

你可以通过自定义实现修改该行为:

@Component
public class CustomToolContextToMcpMetaConverter implements ToolContextToMcpMetaConverter {

    @Override
    public Mapconvert(ToolContext toolContext) {
        if (toolContext == null || toolContext.getContext() == null) {
            return Map.of();
        }

        // 自定义工具上下文转MCP元数据逻辑
        Mapmetadata = new HashMap<>();

        // 示例:为所有键添加自定义前缀
        for (Map.Entryentry : toolContext.getContext().entrySet()) {
            if (entry.getValue() != null) {
                metadata.put("app_" + entry.getKey(), entry.getValue());
            }
        }

        // 示例:添加额外元数据
        metadata.put("timestamp", System.currentTimeMillis());
        metadata.put("source", "spring-ai");

        return metadata;
    }
}

内置转换器

框架提供内置转换器:

  • ToolContextToMcpMetaConverter.defaultConverter() - 过滤MCP交换键和null值(未提供自定义Bean时默认使用)

  • ToolContextToMcpMetaConverter.noOp() - 返回空映射,有效禁用上下文到元数据的转换

完全禁用上下文到元数据转换:

@Configuration
public class McpConfiguration {

    @Bean
    public ToolContextToMcpMetaConverter toolContextToMcpMetaConverter() {
        return ToolContextToMcpMetaConverter.noOp();
    }
}

转换器通过Spring的ObjectProvider机制自动检测并应用于同步和异步MCP工具回调。若未提供自定义转换器Bean,自动使用默认转换器。

禁用MCP工具回调自动配置

MCP工具回调自动配置默认启用,可通过spring.ai.mcp.client.toolcallback.enabled=false属性禁用。

禁用后,不会从可用MCP工具创建ToolCallbackProvider Bean。

MCP客户端注解

MCP客户端启动器自动检测并注册注解方法,处理各类MCP客户端操作:

  • @McpLogging - 处理MCP服务器的日志消息通知

  • @McpSampling - 处理MCP服务器的大语言模型补全采样请求

  • @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) {
        // 处理请求并生成响应
        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(ListupdatedTools) {
        System.out.println("Tool list updated: " + updatedTools.size() + " tools available");
        // 更新本地工具注册表
        toolRegistry.updateTools(updatedTools);
    }
}

注解支持同步和异步实现,可通过clients参数为指定客户端配置:

@McpLogging(clients = "server1")
public void handleServer1Logs(LoggingMessageNotification notification) {
    // 处理指定服务器的日志
    logToFile("server1.log", notification);
}

@McpSampling(clients = "server1")
public MonohandleAsyncSampling(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客户端注解文档。

使用示例

在项目中添加合适的启动器依赖,并在application.properties或application.yml中配置客户端:

spring:
  ai:
    mcp:
      client:
        enabled: true
        name: my-mcp-client
        version: 1.0.0
        request-timeout: 30s
        type: SYNC  # 响应式应用使用ASYNC
        sse:
          connections:
            server1:
              url: http://localhost:8080
            server2:
              url: http://otherserver:8081
        streamable-http:
          connections:
            server3:
              url: http://localhost: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 ListmcpSyncClients;  // 同步客户端

// 或

@Autowired
private ListmcpAsyncClients;  // 异步客户端

工具回调启用时(默认行为),所有MCP客户端注册的MCP工具会以ToolCallbackProvider实例提供:

@Autowired
private SyncMcpToolCallbackProvider toolCallbackProvider;
ToolCallback[] toolCallbacks = toolCallbackProvider.getToolCallbacks();

示例应用

  • Brave网页搜索聊天机器人 - 使用模型上下文协议与网页搜索服务器交互的聊天机器人

  • 默认MCP客户端启动器 - 使用默认spring-ai-starter-mcp-client的简单示例

  • WebFlux MCP客户端启动器 - 使用spring-ai-starter-mcp-client-webflux的简单示例

附加资源

  • Spring AI文档

  • 模型上下文协议规范

  • Spring Boot自动配置

相关推荐