ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Spring AI Alibaba 入门开发4-Tool Calling 、MCP上下文协议

Spring AI Alibaba 入门开发4-Tool Calling 、MCP上下文协议 建议大家先看前三章内容Spring AI Alibaba 入门开发1-环境搭建、ollama部署、Chat和ChatModel、流式输出-CSDN博客Spring AI Alibaba 入门开发2-提示词功能、提示词模板、格式化输出-CSDN博客Spring AI Alibaba 入门开发3-持久化记忆、向量数据库、RAG-CSDN博客目录一、Tool Calling 工具调用1.1 介绍1.2 开发1.2.1 不使用工具时1.2.2 用工具时——分别使用ChatModel、ChatClient实现二、MCP上下文协议2.1 MCP介绍2.2 Spring AI MCP2.3 开发2.3.1 本地MCP开发2.3.2 远程MCP增强案例-对接互联网通用MCP服务百度地图一、Tool Calling 工具调用1.1 介绍“工具调用Tool Calling”或“函数调用”允许大型语言模型LLM在必要时调用一个或多个可用的工具这些工具通常由开发者定义。工具可以是任何东西网页搜索、对外部 API 的调用或特定代码的执行等。LLM 本身不能实际调用工具相反它们会在响应中表达调用特定工具的意图而不是以纯文本回应。然后应用程序应该执行这个工具并报告工具执行的结果给模型。当 LLM 可以访问工具时它可以在合适的情况下决定调用其中一个工具这是一个非常强大的功能。许多 AI 应用程序通过自然语言与用户交互。然而某些业务场景需要模型使用结构化输入直接与外部系统如 API、数据库或文件系统进行交互。Tools 是 agents 调用来执行操作的组件。它们通过定义良好的输入和输出让模型与外部世界交互从而扩展模型的能力。Tools 封装了一个可调用的函数及其输入模式。我们可以把工具定义传递给兼容的 models允许模型决定是否调用工具以及使用什么参数。在这些场景中工具调用使模型能够生成符合指定输入模式的请求。注意服务器端工具使用某些聊天模型例如 OpenAI、Anthropic 和 Gemini具有在服务器端执行的内置工具如 Web 搜索和代码解释器。请参阅提供商概述以了解如何使用特定聊天模型访问这些工具。ool calling也称为function calling是 AI 应用程序中的常见模式允许 model 与一组 API 或tools交互增强其能力。Tools 主要用于信息检索。此类别中的 tools 可用于从外部源检索信息例如数据库、Web 服务、文件系统或 Web 搜索引擎。目标是增强 model 的知识使其能够回答原本无法回答的问题。因此它们可以在 Retrieval Augmented Generation (RAG) 场景中使用。例如可以使用 tool 检索给定位置的当前天气、检索最新新闻文章或查询数据库中的特定记录。执行操作。此类别中的 tools 可用于在软件系统中执行操作例如发送电子邮件、在数据库中创建新记录、提交表单或触发工作流。目标是自动化原本需要人工干预或显式编程的任务。例如可以使用 tool 为与聊天机器人交互的客户预订航班、填写网页上的表单或在代码生成场景中基于自动化测试TDD实现 Java 类。尽管我们通常将tool calling称为 model 能力但实际上由客户端应用程序提供 tool calling 逻辑。Model 只能请求 tool call 并提供输入参数而应用程序负责从输入参数执行 tool call 并返回结果。Model 永远无法访问作为 tools 提供的任何 API这是一个关键的安全考虑。Spring AI 提供了便捷的 API 来定义 tools、解析来自 model 的 tool call 请求并执行 tool calls。Tool Calling工具调用也称为 Function Calling是 AI 应用中的常见模式允许模型与一组 API 或工具进行交互增强模型的能力。工具主要用于信息检索从外部数据源检索信息如数据库、Web 服务、文件系统或 Web 搜索引擎。例如获取当前天气、检索最新新闻、查询数据库等。执行操作在软件系统中执行特定操作如发送电子邮件、在数据库中创建新记录、提交表单或触发工作流。例如预订航班、填写表单、生成代码等。Spring AI Alibaba 扩展了 Spring AI 的 Tool Calling 功能提供了多种预构建的工具实现包括搜索引擎百度搜索、Google Scholar、Tavily Search 等翻译服务阿里翻译、百度翻译、Google 翻译等地图服务高德地图、百度地图、腾讯地图等数据服务天气、快递、新闻等开发工具GitHub、JSON 处理、正则表达式等其他工具时间、Python 执行、敏感词过滤等工作流程如下1.2 开发需求询问大模型当前时间项目基础结构pom.xml、配置文件如下dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !--spring-ai-alibaba dashscope-- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter-dashscope/artifactId /dependency !--lombok-- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.38/version /dependency !--hutool-- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.22/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version configuration compilerArgs arg-parameters/arg /compilerArgs source21/source target21/target /configuration /plugin /plugins /build repositories repository idspring-milestones/id nameSpring Milestones/name urlhttps://repo.spring.io/milestone/url snapshots enabledfalse/enabled /snapshots /repository /repositoriesserver.port8888 #解决中文乱码 server.servlet.encoding.charsetUTF-8 server.servlet.encoding.enabledtrue server.servlet.encoding.forcetrue spring.application.namessa-13-ToolCalling #Sprig AI Alibaba 相关配置 spring.ai.dashscope.api-key${qianwen-api}1.2.1 不使用工具时新建controllerRestController public class NoToolCallingController { Resource private ChatModel chatModel; GetMapping(/v1/chat) public FluxString getChatModel(RequestParam(name msg,defaultValue 你是谁现在几点了)String msg) { return chatModel.stream(msg); } }运行如下1.2.2 用工具时——分别使用ChatModel、ChatClient实现新建功能工具类public class DateTimeTools { /* 1、定义function call 2、returnDirect true工具直接返回不经过大模型 false大模型获取工具返回的结果由大模型回复 */ Tool(description 获取当前时间,returnDirect false) public String getCurrentTime(){ return LocalDateTime.now().toString(); } }新建配置类Configuration public class LLMConfig { Bean public ChatClient chatClient(ChatModel chatModel){ return ChatClient.builder(chatModel).build(); } }新建controllerRestController public class ToolCallingController { Resource private ChatModel chatModel; Resource private ChatClient chatClient; GetMapping(/v2/chat) public String chat2 (RequestParam(name msg,defaultValue 你是谁现在几点了?)String msg){ //1、工具注册到工具集合里 ToolCallback[] tools ToolCallbacks.from(new DateTimeTools()); //2、把工具配置到ChatOptions对象 ToolCallingChatOptions options ToolCallingChatOptions.builder().toolCallbacks(tools).build(); //3、构建提示词 Prompt prompt new Prompt(msg, options); return chatModel.call(prompt).getResult().getOutput().getText(); } GetMapping(/v3/chat) public FluxString chat3(RequestParam(name msg,defaultValue 你是谁现在几点了)String msg){ return chatClient.prompt(msg) .tools(new DateTimeTools()) .stream().content(); } }运行结果如下二、MCP上下文协议2.1 MCP介绍MCP模型上下文协议是一种用于将人工智能应用程序连接到外部系统的开源标准。使用 MCPClaude 或 ChatGPT 等人工智能应用程序可以连接到数据源例如本地文件、数据库、工具例如搜索引擎、计算器和工作流程例如专门提示使它们能够访问关键信息并执行任务。将 MCP 想象成用于 AI 应用的 USB-C 端口。正如 USB-C 提供了一种连接电子设备的标准化方式一样MCP 也提供了一种将 AI 应用程序连接到外部系统的标准化方式。是一个开放协议它规范了应用程序如何向大型语言模型LLM提供上下文。MCP 提供了一种统一的方式将 AI 模型连接到不同的数据源和工具它定义了统一的集成方式。在开发智能体Agent的过程中我们经常需要将将智能体与数据和工具集成MCP 以标准的方式规范了智能体与数据及工具的集成方式可以帮助您在 LLM 之上构建智能体Agent和复杂的工作流。目前已经有大量的服务接入并提供了 MCP server 实现当前这个生态正在以非常快的速度不断的丰富中。在MCP通信协议中一般有两种模式1、STDIO(标准输入/输出)支持标准输入和输出流进行通信主要用于本地集成、命令行工具等场景。2、SSE (Server-Sent Events支持使用 HTTP POST 请求进行服务器到客户端流式处理以实现客户端到服务器的通信。两者对比如下2.2 Spring AI MCPSpring AI MCP 为模型上下文协议提供 Java 和 Spring 框架集成。它使 Spring AI 应用程序能够通过标准化的接口与不同的数据源和工具进行交互支持同步和异步通信模式。Spring AI MCP 采用模块化架构包括以下组件Spring AI 应用程序使用 Spring AI 框架构建想要通过 MCP 访问数据的生成式 AI 应用程序Spring MCP 客户端MCP 协议的 Spring AI 实现与服务器保持 1:1 连接MCP 服务器轻量级程序每个程序都通过标准化的模型上下文协议公开特定的功能本地数据源MCP 服务器可以安全访问的计算机文件、数据库和服务远程服务MCP 服务器可以通过互联网例如通过 API连接到的外部系统2.3 开发2.3.1 本地MCP开发MCP-Server服务端实现新建子模块修改pom.xml、新增配置文件、新增启动类。dependencies !--注意事项重要 spring-ai-starter-mcp-server-webflux不能和artifactIdspring-boot-starter-web/artifactId依赖并存 否则会使用tomcat启动,而不是netty启动从而导致mcpserver启动失败但程序运行是正常的mcp客户端连接不上。 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId /dependency !--mcp-server-webflux-- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webflux/artifactId /dependency !--lombok-- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.38/version /dependency !--hutool-- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.22/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version configuration compilerArgs arg-parameters/arg /compilerArgs source21/source target21/target /configuration /plugin /plugins /build repositories repository idspring-milestones/id nameSpring Milestones/name urlhttps://repo.spring.io/milestone/url snapshots enabledfalse/enabled /snapshots /repository /repositoriesserver.port8014 #解决中文乱码 server.servlet.encoding.charsetUTF-8 server.servlet.encoding.enabledtrue server.servlet.encoding.forcetrue spring.application.namessa-13-ToolCalling #Sprig AI Alibaba 相关配置 #spring.ai.dashscope.api-key${qianwen-api} # mcp-server Config spring.ai.mcp.server.typeasync spring.ai.mcp.server.namecustomer-define-mcp-server spring.ai.mcp.server.version1.0.0SpringBootApplication public class SSA_14_LocalMCPServerApplication { public static void main(String[] args) { SpringApplication.run(SSA_14_LocalMCPServerApplication.class, args); } }新增service,模拟本地调用Service public class WeatherService { Tool(description 根据城市名称获取天气预报) public String getWeatherByCity(String city) { MapString, String map Map.of( 北京, 11111降雨频繁其中今天和后天雨势较强部分地区有暴雨并伴强对流天气需注意, 上海, 22222多云,15℃~27℃,南风3级当前温度27℃。, 深圳, 333333多云40天阴16天雨30天晴3天 ); return map.getOrDefault(city, 抱歉未查询到对应城市); } }新增接口配置类//将工具方法暴露给外部 mcp client 调用 Configuration public class McpServerConfig { Bean public ToolCallbackProvider weatherTools(WeatherService weatherService) { return MethodToolCallbackProvider .builder() .toolObjects(weatherService) .build(); } }本地启动后如下MCP-Client客户端实现新建子模块修改pom.xml、新增配置文件、新增启动类dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !--spring-ai-alibaba dashscope-- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter-dashscope/artifactId /dependency !-- 2.mcp-clent 依赖 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-client/artifactId /dependency !--lombok-- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.38/version /dependency !--hutool-- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.22/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version configuration compilerArgs arg-parameters/arg /compilerArgs source21/source target21/target /configuration /plugin /plugins /build repositories repository idspring-milestones/id nameSpring Milestones/name urlhttps://repo.spring.io/milestone/url snapshots enabledfalse/enabled /snapshots /repository /repositoriesserver.port8015 #解决中文乱码 server.servlet.encoding.charsetUTF-8 server.servlet.encoding.enabledtrue server.servlet.encoding.forcetrue spring.application.namessa-13-ToolCalling #Sprig AI Alibaba 相关配置 spring.ai.dashscope.api-key${qianwen-api} # mcp-client Config spring.ai.mcp.client.typeasync spring.ai.mcp.client.request-timeout60s spring.ai.mcp.client.toolcallback.enabledtrue spring.ai.mcp.client.sse.connections.mcp-server1.urlhttp://localhost:8014SpringBootApplication public class SSA_15_LocalMCPClientApplication { public static void main(String[] args) { SpringApplication.run(SSA_15_LocalMCPClientApplication.class, args); } }新建配置类;Configuration public class LLMConfig { Bean public ChatClient ChatClient(ChatModel chatModel, ToolCallbackProvider callbackProvider) { return ChatClient.builder(chatModel) .defaultToolCallbacks(callbackProvider.getToolCallbacks()) .build(); } }新增controller类RestController public class McpClientController { //使用mcp Resource private ChatClient chatClient; //没有纳入tool普通调用 Resource private ChatModel chatModel; GetMapping(/v1/test) public FluxString chat1(RequestParam(name msg,defaultValue 北京) String msg) { System.out.println(使用了MCP协议); return chatClient.prompt(msg).stream().content(); } GetMapping(/v2/test) public FluxString chat2(RequestParam(name msg,defaultValue 北京) String msg) { System.out.println(未使用MCP协议); return chatModel.stream(msg); } }客户端调用截图2.3.2 远程MCP增强案例-对接互联网通用MCP服务百度地图MCP应用市场https://mcp.so/zh/server/baidu-map/baidu-maps提前申请百度地图api-key。下载node.js用于nodejs配置编码-Typescript接入。新建子模块修改pom.xml、新增配置文件、新增nodejs配置编码-Typescript接入、启动类dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !--spring-ai-alibaba dashscope-- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter-dashscope/artifactId /dependency !-- 2.mcp-clent 依赖 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-client/artifactId /dependency !--lombok-- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.38/version /dependency !--hutool-- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.22/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version configuration compilerArgs arg-parameters/arg /compilerArgs source21/source target21/target /configuration /plugin /plugins /build repositories repository idspring-milestones/id nameSpring Milestones/name urlhttps://repo.spring.io/milestone/url snapshots enabledfalse/enabled /snapshots /repository /repositoriesserver.port6016 #解决中文乱码 server.servlet.encoding.charsetUTF-8 server.servlet.encoding.enabledtrue server.servlet.encoding.forcetrue spring.application.namessa-16-MCPClient-baiduMap #Sprig AI Alibaba 相关配置 spring.ai.dashscope.api-key${qianwen-api} spring.ai.dashscope.base-urlhttps://ws-6tq01jo6mtthlhoq.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 spring.ai.dashscope.chat.options.modelqwen-max spring.ai.mcp.client.toolcallback.enabledtrue spring.ai.mcp.client.stdio.servers-configurationclasspath:/mcp-server.jsonmcp-server.json{ mcpServers: { baidu-map: { command: cmd, args: [/c, npx, -y, baidumap/mcp-server-baidu-map], env: { BAIDU_MAP_API_KEY: BfOSYFsYLqhwXEmNRT532Ib0w1GqWoO3, NPM_CONFIG_CACHE: E:/CodingTools/npm-cache } } } }新增配置类Configuration public class LLMConfig { Bean public ChatClient chatClient(ChatModel chatModel, ToolCallbackProvider toolCallbackProvider) { return ChatClient.builder(chatModel) .defaultToolCallbacks(toolCallbackProvider.getToolCallbacks()) .build(); } }RestController public class MCPClientController { Resource private ChatClient chatClient;//添加了MCP调用能力 Resource private ChatModel chatModel;//未添加MCP调用能力 GetMapping(/v1/chat) public FluxString chat1(String msg){ return chatClient.prompt(msg) .stream().content(); } GetMapping(/v2/chat) public FluxString chat2(String msg){ return chatModel.stream(msg); } }SpringBootApplication public class MCPClientApplication { public static void main(String[] args) { SpringApplication.run(MCPClientApplication.class, args); } }运行如下
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进