尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Spring AI 工具调用详解:Function Calling 与 MCP 客户端 / 服务器实战

发布时间:2026/9/27 22:26:05

资讯中心
01
ARTICLE

Spring AI 工具调用详解:Function Calling 与 MCP 客户端 / 服务器实战

Spring AI 工具调用详解:Function Calling 与 MCP 客户端 / 服务器实战
摘要本文系统讲解 Spring AI 中的工具调用机制从基础的 Function Calling 概念出发逐步深入到 MCP模型上下文协议的标准化实现。文章首先介绍如何通过Tool注解定义工具并注册到 Spring 容器随后详细阐述 MCP 的客户端-服务器架构、三种通信机制STDIO、SSE、WebFlux SSE以及 Spring AI 提供的各类启动器。最后通过完整的代码示例分别演示 MCP Server 与 MCP Client 的开发流程帮助读者掌握从工具定义、服务端打包到客户端配置调用的全链路实践方法。1. Function Calling 函数调用函数调用是让大语言模型LLM在对话中“调用”外部定义的工具或 API 的机制通过这个机制模型可以在生成回答前提出需要执行的操作如获取实时天气、设置数据库记录、触发业务流程等然后由应用端执行工具结果再反馈回模型最终给用户完整回复。2. Spring AI 中 Function Calling工具调用流程1️⃣ 开发者定义工具并将其注册到 Spring 容器中。2️⃣ 模型在生成响应时识别到需要调用工具会生成包含工具调用信息的响应。3️⃣ 应用程序接收到模型的响应后解析其中的工具调用信息执行相应的工具。4️⃣ 工具执行完成后将结果返回给应用程序。5️⃣ 应用程序将工具执行结果作为上下文信息传递给模型。6️⃣ 模型使用工具执行结果生成最终的响应。3. 工具定义开发者可以通过在方法上添加 Tool 注解定义工具该注解允许提供工具的名称、描述和输入参数等信息模型在调用工具时会根据这些信息生成相应的调用请求。1️⃣ Tool 标注工具名称默认就是方法本身也可以通过 Tool(name“tool name”) 方式来指定。2️⃣ Tool(description“…”) 中这里的 description 是工具描述大模型根据该描述决定要不要调用该工具。3️⃣ 工具方法中需要传入参数的通过使用 ToolParam 标注大模型自动决定调用时机和自动根据语义传入参数调用完成后生成最终对话。4️⃣ 工具不支持如下类型作为参数或返回值Optional、异步类型如 CompletableFuture、Future、响应式类型如 Flow、Mono、Flux、函数式类型如 Function、Supplier、Consumer。ComponentpublicclassMyTools{LoggerlogLoggerFactory.getLogger(MyTools.class);Tool(namegetCurrentTime,description返回当前系统时间)publicStringgetCurrentTime(){log.info(调用 getCurrentTime 工具……);returnLocalDateTime.now().toString();}Tool(description对两个数字执行加(add)、减(subtract)、乘(multiply)、除(divide)运算)publicdoublecalculate(ToolParam(description第一个数字)doublea,ToolParam(description第二个数字)doubleb,ToolParam(description运算类型)Stringoperation){log.info(调用 calculate 工具第一个参数a第二个参数b第三个参数operation);doubleresult0;switch(operation){caseadd:resultab;break;casesubtract:resulta-b;break;casemultiply:resulta*b;break;casedivide:if(b!0){resulta/b;}break;default:result0;}returnresult;}}也可以在ToolUseController.java中设置不使用工具将defaultTools(new MyTools)注释掉再进行测试会发现以上访问不会调用工具都由大模型根据已有知识进行回复。importcom.example.springaitoolcalling.tools.MyTools;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.model.ChatModel;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;RestControllerRequestMapping(/ai)publicclassToolUseController{privatefinalChatClientchatClient;publicToolUseController(ChatModelchatModel,MyToolstools){this.chatClientChatClient.builder(chatModel).defaultSystem(你是一个非常有帮助的助手你可以使用工具来帮助回答问题).defaultTools(tools).build();}GetMapping(/chat)publicStringchat(RequestParam(message)Stringmessage){returnchatClient.prompt().user(message).call().content();}}4. MCP 模型上下文协议目前各大 LLM 平台如 DeepSeek、ChatGPT、Claude普遍支持“函数调用”允许模型在需要时调用特定函数如访问网络、查询数据库等来扩展能力。然而不同平台的“函数调用”存在实现差异导致开发者在切换平台时需要重新适配。MCPModel Context Protocol模型上下文协议是 Anthropic 于 2024 年 11 月推出的开放标准为大模型调用外部工具建立了一个标准化流程。MCP 基于“函数调用”进一步定义了从请求构建、发送、执行到结果返回的标准化流程。4.1 MCP 与 Function Calling 的区别和联系1️⃣ Function Calling是 LLM 内部定义的一组函数通过 JSON Schema 让 LLM 知道有哪些功能能调用。2️⃣ MCP在 Function Calling 基础上进一步标准化了函数调用的完整流程包括请求的构建、发送、执行以及结果的返回。4.2 MCP 遵循客户端-服务器架构角色主要包含三部分1️⃣MCP Host运行 LLM如 Claude、ChatGPT、DeepSeek的实体节点如果使用的 LLM 为线上模型可以忽略这部分。2️⃣MCP Client运行着与大模型对话的客户端可能会使用工具叫做 MCP Client。其与 MCP Server 保持 1:1 连接负责解析模型请求如果使用工具会将请求转发到对应 MCP Server。3️⃣MCP Server实际运行外部工具如访问文件系统、发送邮件、查询日历的服务端叫做 MCP Server。负责处理请求并将结果返回给 Client。4.3 MCP Client 与 MCP Server 之间有两种通信机制1️⃣ STDIO标准输入/输出当服务器和客户端同时运行在本机时可以使用 STDIO 机制。2️⃣ SSEServer-Sent-Event当服务器部署在远程服务器上客户端通过 HTTP 请求发送消息使用这种方式。4.4 MCP Java SDK 架构MCP Client 处理客户端操作MCP Server 管理服务端操作两者都使用 MCP Session 进行通信管理。传输层MCP Transport负责处理 JSON-RPC 消息的序列化和反序列化支持三种传输实现STDIO、Spring MVC SSE、Spring WebFlux SSE。1️⃣ STDIO基于进程间的标准输入/输出STDIO传输支持单进程同步交互处理消息。适用于 MCP 服务端和客户端都在同一节点上集成。2️⃣ Spring MVC SSEHTTP SSE基于 Spring MVC 的 SSE 传输支持 Servlet 线程池阻塞式处理消息。适用于普通的 Web 应用。3️⃣ Spring WebFlux SSE官方建议方式。基于 Spring WebFlux 的反应式 SSE支持高并发、低延迟响应式处理消息。适用于高并发的 Web 微服务。4.5 Spring AI MCP 启动器Spring AI 提供了多个启动器starter简化 MCP 在 Spring Boot 中的使用。客户端 Starter1️⃣ spring-ai-starter-mcp-client支持 STDIO 与 HTTP-SSE。2️⃣ spring-ai-starter-mcp-client-webflux基于 WebFlux 的 SSE 客户端实现。服务端 Starter1️⃣ spring-ai-starter-mcp-server支持 STDIO 传输。2️⃣ spring-ai-starter-mcp-server-webmvc基于 Spring MVC 的 SSE 服务端实现。3️⃣ spring-ai-starter-mcp-server-webflux基于 WebFlux 的 SSE 服务端实现。5. MCP Server 开发1️⃣ MCP Server 端和 Function Calling 中构建工具的方法一样即使用 Service、Tool 注解构建工具2️⃣ SpringBootApplication 主应用启动类中通过 Bean 注解创建ToolCallbackProvider类型该类型是 Spring AI 提供的接口其实现类负责将指定 Service 类中带有 Tool 注解的方法注册为可供 AI 模型调用的工具。3️⃣ MCP Client 与 MCP Server 使用 STDIO 传输时我们需要将 MCP Server 项目进行打包然后在 MCP Client 中进行配置无需单独启动 MCP Server。这里直接通过 Maven 工具进行打包即可。importcom.example.springaimcpstdioserver.service.WeatherService;importorg.springframework.ai.tool.ToolCallbackProvider;importorg.springframework.ai.tool.method.MethodToolCallbackProvider;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.annotation.Bean;SpringBootApplicationpublicclassSpringAimcpStdioServerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(SpringAimcpStdioServerApplication.class,args);}/** * ToolCallbackProvider 接口Spring AI 提供的接口负责将带有Tool注解的方法注册为AI LLM 可以调用的工具 * param weatherService * return */BeanpublicToolCallbackProviderweatherTools(WeatherServiceweatherService){returnMethodToolCallbackProvider.builder().toolObjects(weatherService).build();}}6. MCP Client 开发MCP Client 通过 STDIO 方式连接到 MCP Server 需要在项目的 resources/application.properties 文件中配置如下内容指定的文件中需要进行 MCP Server 配置。spring.application.nameSpringAIStdioMcpClientserver.port8080# 配置 Deepseek URL、API Key、模型spring.ai.deepseek.base-urlhttps://api.deepseek.com spring.ai.deepseek.api-keyyour_api_keyspring.ai.deepseek.chat.options.modeldeepseek-chat# 配置日志logging.pattern.console%-5level %logger - %msg%n# STDIO 模式MCP Client 和 MCP Server 都是在同一机器上通过配置文件找到 Server Jar 并执行spring.ai.mcp.client.stdio.servers-configurationclasspath:/mcp-server-config.json# SSE 模式配置名为 server1 的 MCP 服务器连接远程连接到指定的服务器地址# spring.ai.mcp.client.sse.connections.server1.urlhttp://localhost:80891️⃣spring.ai.mcp.client.stdio.servers-configuration参数用来让 MCP Client 找到 MCP Server 相应配置进而启动 MCP Server 使用工具。2️⃣resources/mcp-servers-config.json文件内容如下{mcpServers:{spring-ai-mcp-weather:{command:D:\\Program Files\\Java\\jdk17\\jdk\\bin\\java.exe,args:[-Dspring.ai.mcp.server.transportSTDIO,-jar,D:\\idea_space\\StudySpringAI\\SpringAIMCPStdioServer\\target\\SpringAIMCPStdioServer-0.0.1-SNAPSHOT.jar]}}}6.1 SyncMcpToolCallbackProvider 工具回调提供者importio.modelcontextprotocol.client.McpSyncClient;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.model.ChatModel;importorg.springframework.ai.mcp.SyncMcpToolCallbackProvider;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjava.util.List;ConfigurationpublicclassConfig{/** * SyncMcpToolCallbackProvider自动集成 MCP Server 暴露的工具到 ChatClient可以使 LLM 使用工具 * * param mcpClients * return */BeanpublicSyncMcpToolCallbackProvidertoolCallbackProvider(ListMcpSyncClientmcpClients){returnnewSyncMcpToolCallbackProvider(mcpClients);}BeanpublicChatClientchatClient(ChatModelchatModel,SyncMcpToolCallbackProvidertoolCallbackProvider){ChatClientclientChatClient.builder(chatModel).defaultSystem(你是一个非常有帮助的助手可以调用工具来回答用户问题).defaultToolCallbacks(toolCallbackProvider)// 配置工具回调让 LLM 能调用外部工具.build();returnclient;}}说明SyncMcpToolCallbackProvider属于MCP‑Client 侧的工具回调提供者和 MCP‑Server 端的ToolCallbackProvider职责不一样。Server 端ToolCallbackProvider用于把本地Tool注解的方法暴露成为 MCP 对外服务的工具Client 端SyncMcpToolCallbackProvider负责**对接远端 MCP‑Server将远端工具适配为 Spring AI 体系内可用的ToolCallback。6.1 STDIO 模式完整加载与调用时序Windows1️⃣ Spring Boot 启动读取 application.properties读到 servers‑configuration 配置项指向 classpath 下的 mcp‑server‑config.json2️⃣ MCP‑Client starter 加载 mcp‑server‑config.json解析 command 和 argsWindows 环境下创建新的 Java 子进程拉起 MCP‑Server 可执行 jar 包完成之后建立 STDIO 管道的 MCP Session 会话此时仅仅完成底层通信会话建立尚未发起 list‑tools 查询工具列表3️⃣ 主进程MCP‑Client与子进程MCP‑Server之间依靠标准输入输出 STDIO 管道完成进程间通信不占用 TCP 网络端口4️⃣ Spring 容器自动实例化McpSyncClient对象存入ListMcpSyncClient集合该集合自动注入到SyncMcpToolCallbackProvider构造函数此时 Provider 内部已经持有全部 MCP 客户端连接但仍然不知道远端有哪些工具5️⃣ 在构建ChatClient实例的时候执行provider.getToolCallbacks()通过已经就绪的 MCP 会话向远端 MCP‑Server 发起list‑toolsRPC 请求拉取远端工具 JSON‑Schema 元数据在本地动态生成虚拟ToolCallback回调对象注册进 ChatClient关键点工具列表不是应用启动时预先拉取是 ChatClient 构建阶段才远程获取远端工具定义。如果没有把 Provider 注册进 ChatClient即使 MCP‑Server 子进程正常运行大模型依旧无法使用远端工具。6️⃣ 用户提交业务提问LLM 识别当前问题需要调用远端工具生成工具调用指令底层通过McpSyncClient经由 STDIO 管道向后台 MCP‑Server 子进程发送工具调用请求MCP‑Server 完成业务逻辑执行之后将工具结果原路返回给 ClientClient 把工具输出作为对话上下文提交给大模型模型结合返回数据生成最终应答返回用户。6.2 SSE 模式完整加载与调用时序说明SSE 属于网络长连接模式MCP‑Server 必须预先独立启动手动启动客户端不会 fork 子进程MCP‑Server 启动后监听localhost:8089暴露默认/sseSSE 端点底层 Transport 是 HTTP‑SSE上层SyncMcpToolCallbackProvider、ChatClient的逻辑和 STDIO 完全一致。1️⃣ Spring Boot 启动读取application.properties读取 SSE 连接配置spring.ai.mcp.client.sse.connections.server1.urlhttp://localhost:80892️⃣ MCP‑Client starter 根据配置发起网络请求建立HTTP‑SSE 长连接创建 MCP Session 会话此时仅仅建立网络会话通道还没有发起 list‑tools 请求查询远端工具列表⚠️注意这里不会新开 java 子进程MCP‑Server 进程是我们事先手动启动完成的3️⃣ 主进程 MCP‑Client (8080) 和远端 MCP‑Server (8089) 之间基于 TCP 网络、SSE 长连接进行 JSON‑RPC 通信占用 TCP 端口不再使用 stdio 进程管道 IPC支持多个 Client 连接同一个 MCP‑Server4️⃣ Spring 自动实例化McpSyncClient对象存入ListMcpSyncClient集合该集合注入到SyncMcpToolCallbackProvider构造函数此时 Provider 持有网络连接但仍然不知道远端提供哪些工具5️⃣ 构建ChatClient实例的时候调用provider.getToolCallbacks()复用已经建立好的 SSE 网络会话向远端 MCP‑Server 发起list‑toolsRPC 请求拉取远端工具 JSON‑Schema 元数据本地动态生成虚拟ToolCallback回调对象注册进 ChatClient关键点和 STDIO 时序完全一样工具列表不是 Spring Bean 初始化阶段拉取是 ChatClient 构建阶段才远程发现工具如果忘记把 Provider 注册进 ChatClient即便 SSE 长连接已经连通大模型依旧无法调用远端工具。6️⃣ 用户提交业务提问LLM 识别问题需要调用远端工具生成工具调用指令底层通过McpSyncClient经由 SSE 长连接向 MCP‑Server 发送工具调用请求MCP‑Server 执行业务逻辑之后将工具执行结果沿 SSE 链路回传给 ClientClient 把工具返回结果追加到对话上下文提交给大模型模型结合返回数据生成最终应答返回用户。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。