ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring AI 2.0.0 接入 MCP 教程:toolCallbacks 改 tools、stdio 配置和 Windows 写法(TaoToken 统一 Key 通道)

Spring AI 2.0.0 接入 MCP 教程:toolCallbacks 改 tools、stdio 配置和 Windows 写法(TaoToken 统一 Key 通道) 1. 从 toolCallbacks 到 toolsSpring AI 2.0.0 的 MCP 接入到底变了什么如果你手里有一个基于 Spring AI 1.1.x 的 MCP 项目升级到 2.0.0 之后大概率会遇到同一个编译警告toolCallbacks被标记为 deprecated。这不是 MCP 协议本身出了问题而是 ChatClient 这一层注册工具的入口做了收敛。Spring AI 2.0.0 把「工具怎么交给当前请求」统一到了tools(...)方法上toolCallbacks(...)虽然还能编译通过但已经进入弃用通道后续版本随时可能移除。这个变化影响的范围比想象中大。很多网上流传的 MCP 接入示例还停留在 1.1.x 的写法直接照抄会写出.toolCallbacks(mcpTools)这样的代码。在 2.0.0 里MCP Client Starter 依然会把 MCP Server 暴露的工具转成ToolCallbackProvidermcpTools这个 Bean 本身没有变变的是你把它交给 ChatClient 的方式。旧入口是toolCallbacks(...)新入口是tools(...)。除了方法名工具上下文的传递方式也拆开了。旧版里可能见过.tools(t - t.callbacks(myCallback).context(tenantId, acme))这种链式写法2.0.0 里不再这么用。新的做法是把「这次请求能用哪些工具」和「工具执行时需要哪些上下文」分成两个方法tools(...)负责前者toolContext(...)负责后者。这个拆分让语义更清晰也避免了在工具注册阶段混入运行时上下文。还有一个容易被忽略的机制变化2.0.0 里 ChatClient 会自动把ToolCallingAdvisor放进 Advisor 链。也就是说你写.tools(mcpTools)之后背后并不是模型直接去调用 MCP Server而是tools(mcpTools)把工具交给当前请求ToolCallingAdvisor进入 Advisor 链模型返回 tool call 后由它执行工具调用循环MCP 工具被真正调用结果再交回模型生成最终回答。大多数场景下不需要你手动写.advisors(ToolCallingAdvisor.builder().build())也不要一边让 ChatClient 自动注册、一边又手动加一个那样会导致工具被重复处理。这篇教程面向的是正在做 Spring AI 2.0.0 升级迁移的开发者尤其是用 MCP Client 连接本地 stdio Filesystem Server 的场景。我会把版本基线、依赖、application.yml 配置、Windows 与 macOS 的路径差异、完整 Controller 代码、启动验证命令和常见报错排查一次讲清楚。如果你还在 Spring Boot 3.5.x Spring AI 1.1.x建议先不要动版本号因为 2.0.x 对应的是 Spring Boot 4.x整套依赖需要一起对齐。2. TaoToken 统一 Key 通道给 MCP 工具调用准备一个稳定入口在讲具体配置之前先说一下模型侧的 Key 怎么管。MCP 工具调用本身不依赖某个特定模型但 ChatClient 需要一个可用的 ChatModel 来驱动工具调用循环。很多人在本地调试时会把 Key 硬编码在 application.yml 里或者每个项目单独配一份时间长了容易混乱。我自己的做法是用 TaoToken 作为统一的 Key 通道把模型访问收敛到一个入口这样切换模型或者换项目时只需要改一处配置。TaoToken 的定位是统一的大模型 API 接入通道官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 。它不改变 Spring AI 的调用方式你仍然用spring-ai-starter-model-deepseek或对应的 starter只是把 base-url 和 api-key 指向 TaoToken 提供的地址。对于 MCP 这种需要反复调试工具调用的场景统一 Key 的好处是你可以在不同项目、不同模型之间快速切换而不用每次都去翻各个厂商的控制台。具体到 Spring AI 2.0.0 的配置模型部分需要确认三件事用哪个模型、base-url 指向哪里、api-key 从哪里读。这篇示例用deepseek-v4-flash作为对话模型它在工具调用场景下响应比较快适合本地调试。如果你要用其他模型只需要改model字段base-url 和 api-key 的读取方式不变。在 TaoToken 的控制台里创建 API Key 之后你可以把它配到环境变量里避免写进代码仓库。Spring AI 的配置支持${DEEPSEEK_API_KEY}这种占位符写法启动时从环境变量注入。如果你用 IDEA 运行可以在 Run/Debug Configurations 的 Environment variables 里加一行DEEPSEEK_API_KEY你的Key。如果你用命令行启动就export DEEPSEEK_API_KEY你的Key再跑./mvnw spring-boot:run。这里要强调一点TaoToken 是模型访问通道不是 MCP Server 的替代品。MCP 工具的执行仍然由本地或远程的 MCP Server 完成TaoToken 只负责模型侧的请求转发。两者是配合关系不是二选一。你完全可以用 TaoToken 驱动模型同时用本地 stdio 的 Filesystem MCP Server 提供文件读取工具这条链路是通的。如果你还没有 Key可以先到 https://taotoken.net/api-keys 创建一个然后在 https://taotoken.net/doc 看一下接入文档确认 base-url 和模型名的对应关系。对于长期做编码和 Agent 开发的场景也可以了解一下 Coding Plan它在频繁调用工具链时更划算。模型对话的调试入口在 https://taotoken.net/chat 可以用来快速验证 Key 是否可用。3. 可复制配置application.yml 与 MCP stdio 骨架这一节给出可以直接复制的配置骨架。先对齐版本基线Spring AI 2.0.x 对应 Spring Boot 4.0.x / 4.1.xJava 17。这篇示例用 Spring Boot 4.1.0 Spring AI 2.0.0 deepseek-v4-flash Filesystem MCP Server。如果你的项目还在 Spring Boot 3.5.x Spring AI 1.1.x不要只改spring-ai.version这一行更稳的做法是整套一起升否则后面看起来只是一个 API 报错实际可能是依赖树没对齐。pom.xml 的关键部分如下。父版本和 BOM 要一起动parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version4.1.0/version /parent properties java.version17/java.version spring-ai.version2.0.0/spring-ai.version /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-model-deepseek/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-client/artifactId /dependency /dependenciesspring-ai-starter-mcp-client负责把 Spring AI 应用变成 MCP Client连接 MCP Server 并把工具转成ToolCallbackProvider。这条主线在 2.0.0 里没有变变的是 ChatClient 侧注册工具的写法。接下来是 application.yml。这里以 macOS 为例Windows 的差异在下一节单独说spring: application: name: spring-ai-mcp-demo ai: model: chat: deepseek deepseek: api-key: ${DEEPSEEK_API_KEY} base-url: https://taotoken.net/api chat: options: model: deepseek-v4-flash temperature: 0.2 mcp: client: type: SYNC toolcallback: enabled: true stdio: connections: filesystem: command: npx args: - -y - modelcontextprotocol/server-filesystem - /private/tmp/spring-ai-mcp-demo logging: level: io.netty.resolver.dns.DnsServerAddressStreamProviders: OFF这份配置里有几个点需要确认。第一base-url指向 TaoToken 的 API 端点api-key从环境变量读取。第二mcp.client.type用SYNC对应同步工具调用如果你要用异步可以改成ASYNC但示例里保持 SYNC 更直观。第三toolcallback.enabled默认为 true如果你显式关掉就不会自动创建ToolCallbackProviderController 里注入mcpTools会失败。第四stdio 连接里command和args是启动 MCP Server 的命令macOS 建议用/private/tmp/...而不是/tmp/...避免软链接导致白名单判断不一致。第五logging.level那行只是关掉 macOS 上偶尔出现的 Netty DNS 提示日志不影响 MCP 调用。如果你用 IDEA 运行在 Run/Debug Configurations 里配置DEEPSEEK_API_KEY你的Key。如果你用命令行先export DEEPSEEK_API_KEY你的Key再跑./mvnw spring-boot:run。测试目录也要提前准备好mkdir -p /private/tmp/spring-ai-mcp-demo echo Hello from Spring AI MCP Demo /private/tmp/spring-ai-mcp-demo/test.txtWindows 上的配置差异集中在command和args。因为npx在 Windows 下需要通过cmd.exe /c调用路径也要换成 Windows 风格spring: ai: mcp: client: stdio: connections: filesystem: command: cmd.exe args: - /c - npx - -y - modelcontextprotocol/server-filesystem - C:\tmp\spring-ai-mcp-demo其他 Spring AI 2.0.0 的写法不变Controller 里仍然是.tools(mcpTools)。Windows 下测试目录用mkdir C:\tmp\spring-ai-mcp-demo创建写入测试文件可以用 PowerShell 的Set-Content。如果你在 Windows 上遇到npx找不到的情况先确认 Node.js 已经装好并且npx在 PATH 里可以在命令行直接跑npx -y modelcontextprotocol/server-filesystem C:\tmp\spring-ai-mcp-demo看能不能启动。4. 完整 Controller 与启动验证确认 MCP 工具注册成功配置就绪之后Controller 的写法是这次迁移的核心。2.0.0 版本的 McpController 如下package com.example.springaideepseekdemo.controller; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; RestController public class McpController { private final ChatClient chatClient; private final ToolCallbackProvider mcpTools; public McpController(ChatClient.Builder builder, ToolCallbackProvider mcpTools) { this.chatClient builder .defaultSystem( 你是一个文件读取助手。 只能通过工具访问 /private/tmp/spring-ai-mcp-demo 目录。 当用户说 test.txt 或测试目录时都指 /private/tmp/spring-ai-mcp-demo。 不要请求访问 /、用户主目录、项目源码目录或其他目录。 ) .build(); this.mcpTools mcpTools; } GetMapping(/ask) public String ask(RequestParam String question) { return chatClient.prompt() .user(question) .tools(mcpTools) .call() .content(); } }这段代码里最重要的就是.tools(mcpTools)。ToolCallbackProvider mcpTools不用拆也不用手动转成别的对象直接传给.tools(...)就行。如果你要做流式返回新增一个接口把.call().content()换成.stream().content()返回FluxString即可。如果问题触发 MCP 工具调用可能会先等工具执行完再开始流式输出这个等待是正常的。启动验证分三步。第一步编译./mvnw clean compile -DskipTests第二步启动应用./mvnw spring-boot:run启动日志里应该能看到 MCP Client 初始化相关的信息包括连接的 stdio 进程和发现的工具列表。如果你看到Registered tools: [read_file, read_multiple_files, ...]之类的输出说明 MCP 工具已经注册成功。第三步请求接口curl --get http://localhost:8080/ask \ --data-urlencode question帮我读取 /private/tmp/spring-ai-mcp-demo/test.txt 的内容如果模型调用了工具会返回类似test.txt 的内容是Hello from Spring AI MCP Demo这个结果说明整条链路是通的请求进入 Controller.tools(mcpTools)把 MCP 工具交给当前请求ToolCallingAdvisor进入 Advisor 链模型返回 tool call工具调用循环执行 MCP 工具Filesystem Server 读取文件结果交回模型生成最终回答。如果你想确认工具是否真的被调用可以在启动日志里找 tool call 相关的记录或者在 Filesystem Server 的进程输出里看有没有读取文件的日志。另外/ask接口的响应时间会比普通对话长一些因为多了一次工具调用往返这是正常的。对于需要长期跑编码和 Agent 任务的场景可以把这套配置和 Coding Plan 结合使用减少频繁调试时的 Key 管理成本。模型对话的快速验证入口在 https://taotoken.net/chat 接入文档在 https://taotoken.net/doc API Key 管理在 https://taotoken.net/api-keys 。5. 常见报错排查401、local proxy failed、reading choices 与 OAuth迁移过程中最容易遇到的报错集中在几个地方。这一节按真实报错信息来对照排查。401 Unauthorized。这个通常出现在模型侧不是 MCP 侧。检查DEEPSEEK_API_KEY环境变量是否注入成功可以在启动日志里看 Spring AI 是否读到了 api-key。如果你用 TaoToken 的 Key确认 base-url 是https://taotoken.net/api并且 Key 没有过期。如果 Key 是从控制台复制的注意不要带多余空格。另外如果你在 IDEA 里配了环境变量但没生效检查 Run/Debug Configurations 里是否勾选了对应的配置。local proxy failed / connection refused。这个报错一般出现在 MCP Client 尝试启动 stdio 进程时。先确认npx在命令行能直接跑通npx -y modelcontextprotocol/server-filesystem /private/tmp/spring-ai-mcp-demo。如果这条命令报错说明 Node.js 环境有问题跟 Spring AI 无关。如果命令行能跑通但应用里报错检查 application.yml 里的command和args是否写对尤其是 Windows 下需要cmd.exe /c前缀。macOS 下如果用了/tmp而不是/private/tmp也可能因为软链接导致路径判断失败。Error reading choices / 返回体解析失败。这个报错通常说明模型返回的 JSON 结构不符合预期可能是 base-url 或模型名配错了。检查base-url是否指向 TaoToken 的 API 端点model是否是deepseek-v4-flash或你实际可用的模型名。如果你把 base-url 写成了官网地址而不是 API 地址也会出现解析失败。另外如果你在 TaoToken 控制台里没有开通对应模型也会返回非预期结构。OAuth / authentication failed。如果你用的是需要 OAuth 的模型通道确认 token 是否有效。TaoToken 的 Key 是 API Key 形式不需要额外的 OAuth 流程。如果你在代码里混用了其他认证方式检查是否有多余的 header 或 interceptor 干扰。Access denied - path outside allowed directories。这个不是.tools(mcpTools)没生效而是 Filesystem Server 的白名单限制。检查问题里的路径和 stdio 配置里允许的目录是否一致。比如配置里允许/private/tmp/spring-ai-mcp-demo但问题里写的是/tmp/spring-ai-mcp-demo就可能被拒绝。macOS 下优先用/private/tmp/...。工具没有被调用模型直接回答。这种情况先确认toolcallback.enabled没有被设成 false否则mcpToolsBean 不会创建。然后确认 Controller 里用的是.tools(mcpTools)而不是旧的.toolCallbacks(mcpTools)。如果两者都写了可能会冲突。另外system prompt 里如果明确限制了工具使用范围模型可能会选择不调用工具可以先用一个明确的文件读取问题来测试。编译警告 toolCallbacks deprecated。这个警告本身不影响运行但建议直接改成.tools(...)。如果你在多个地方用了toolCallbacks全局搜索替换即可。注意tools(...)的参数类型和toolCallbacks(...)不完全一样ToolCallbackProvider可以直接传但如果你之前传的是ToolCallback[]需要确认新 API 是否接受。排查的时候有一个通用思路先确认模型侧通不通用/chat或简单对话测试再确认 MCP 侧通不通命令行直接跑 MCP Server最后确认 Spring AI 的胶水层配置对不对。三层分开排查比一上来就盯着代码看效率高。6. 迁移清单与后续方向把同一条 MCP Client 链路迁到 Spring AI 2.0.0差异可以压成几句话版本上 Spring AI 2.0.0 对齐 Spring Boot 4.x模型上示例用 deepseek-v4-flash通过 TaoToken 统一 Key 通道接入代码上toolCallbacks(mcpTools)改成tools(mcpTools)机制上工具调用更明确地进入 ChatClient Advisor 链ToolCallingAdvisor自动注册不需要手动加。MCP Client 连接 stdio Filesystem Server 这条主线没有变。stdio 在 2.0.0 里仍然支持适合本地进程类 MCP Server。如果你自己做远程 MCP Server才需要关注 SSE Server transport 不再推荐作为新方案、优先迁到 Streamable HTTP 这个变化。对于本地 Filesystem 场景继续用 stdio 就行。真正容易踩坑的是旧代码、旧 API 和新版本混在一起。看 Spring AI 文章时先看版本版本不一样依赖名、API 写法、Advisor 行为都可能不一样。如果你只是想跑 MCP 入门 Demo1.1.x 的示例仍然可以参考但升级到 2.0.0 时一定要把toolCallbacks改成tools。后续如果要扩展可以从这几个方向入手把 Filesystem Server 换成你自己的 MCP Server暴露业务相关的工具把 SYNC 改成 ASYNC 测试异步工具调用用 Streamable HTTP 连接远程 MCP Server在toolContext(...)里传入租户 ID 或用户 ID让工具执行时能拿到运行时上下文。这些扩展都建立在.tools(mcpTools)这条最小链路跑通的基础上。搜索时容易遇到的关键词可以记一下toolCallbacks deprecated、ChatClient tools(mcpTools)、ToolCallingAdvisor、spring-ai-starter-mcp-client、stdio、Streamable HTTP、Spring AI 2.0.0 迁移。这些词在排查问题时能帮你快速定位到相关文档和讨论。
返回列表