☰
Spring AI 使用 MCP 客户端(调用高德 MCP):把 endpoint 改到 TaoToken
2026/10/1 14:59:58 网站建设 项目流程

1. 为什么要在 Spring AI 里接高德 MCP,而不是继续写 @Tool

先说结论:如果你只是想让模型查一下"附近有什么咖啡店",用原生@Tool注解写个方法也能跑。但一旦工具数量涨到十几个、还要跨项目复用,硬编码的方式就会变成维护噩梦。MCP(Model Context Protocol)解决的正是这个问题——它把工具从"写死在应用里"变成"运行时从外部 Server 动态发现"。

我拿一个真实场景举例。假设你在做一个"周末约会规划"的小助手,用户输入"帮我找静安寺附近适合约会的餐厅,再推荐一条散步路线"。这个需求背后至少要调三类能力:POI 关键词搜索、周边搜索、路径规划。如果全用@Tool写,你得自己封装高德 Web API 的 HTTP 请求、处理签名、解析 JSON、定义入参 schema,光工具类就写几百行。而高德官方已经提供了 MCP Server(@amap/amap-maps-mcp-server),它把这些能力都封装好了,你只需要在配置里加一行服务地址,Spring AI 启动时就会自动把工具清单拉过来注入ChatClient。

MCP 和原生 Tool Calling 的本质区别,我用一张表说清楚:

维度原生 Tool CallingMCP
工具来源代码内硬编码外部 Server 动态提供
新增工具成本改代码 + 重新打包发版改一个配置项,重启即可
跨应用复用差,绑死在单个应用好,一次开发处处复用
运行时扩展不支持支持 tools/list 动态发现
运行形态与应用同进程本地子进程(stdio)或远程 HTTP
调试复杂度低相对高,多一层子进程/网络栈

一句话概括:MCP 是 Tool Calling 的"标准化 + 动态化"。它不让 AI 服务器主动去调你的服务,而是通过 MCP 客户端把"Server 提供了哪些工具"告诉模型,模型决定要用时,由你的后端程序去执行,再把结果回填给模型总结。

这篇要交付的东西很具体:一份可复制的application.yml、一份 MCP 客户端 Bean 配置、把 endpoint 改到 TaoToken 统一通道后的连通性验证动作,以及跑通一次真实高德 MCP 工具调用的完整链路。适合已经会用 Spring Boot、想快速把 MCP 接进项目的人。

2. 前置准备:Node.js、高德 Key 与 TaoToken 统一通道

在写代码之前,有三样东西必须先备好,缺一个后面都会卡住。

第一样:Node.js 运行时。因为本地 stdio 模式是通过npx启动 MCP Server 子进程的,没有 Node.js 就没有这个子进程。去 Node.js 官网下载 LTS 版本,一路下一步即可。装完后在终端执行node -v和npx -v确认能输出版本号。这里有个我踩过的坑:装完 Node.js 后 IDEA 有时识别不到,最好重启一次 IDEA,否则运行时会报找不到npx命令。

第二样:高德开放平台的 API Key。去高德开放平台控制台,创建一个应用,添加一个 Key,服务平台选"Web 服务"。这个 Key 后面要填进 MCP Server 的环境变量里,每次工具调用都会真实消耗调用次数,调试时注意频率。

第三样:TaoToken 统一 Key/API 通道。这是本文的重点改造项。原本 Spring AI 默认会去连各家模型厂商的 endpoint,但如果你想让模型调用走统一通道、用一个 Key 管理,就需要把 endpoint 改到 TaoToken。TaoToken 提供统一的 API 入口,兼容 OpenAI 风格的调用方式,你可以在控制台生成 Key,然后在 Spring AI 的配置里把 base-url 指过去。

具体操作路径是这样的:先访问 TaoToken 官网注册账号,进入控制台创建 API Key。拿到 Key 之后,模型对话的 endpoint 就是https://taotoken.net/api,注意这个地址后面不加任何路径后缀,Spring AI 的 OpenAI starter 会自动拼接/v1/chat/completions。如果你用的是 Claude Code 这类编码工具,TaoToken 也提供了对应的接入文档,Base URL 填https://taotoken.net/api,Key 填你生成的那串,Model ID 按文档里列出的填。

这里要强调一个概念:TaoToken 在这里扮演的是"统一模型调用通道"的角色,它和你本地启动的高德 MCP 子进程是两回事。MCP 子进程负责提供工具能力,TaoToken 负责提供模型推理能力,两者通过 Spring AI 的ChatClient串起来。理解这一点,后面配置才不会混。

准备好这三样,我们就可以进入代码环节了。

3. 可复制配置:application.yml 与 MCP 客户端 Bean

这一节是全文的核心,所有配置都可以直接复制粘贴,只需要改 Key 和路径。

第一步:引入依赖。在pom.xml里加 MCP 客户端 starter。注意版本,示例基于 Spring AI 1.0.0-M6,对应 Spring Boot 3.4.x:

<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId> <version>1.0.0-M6</version> </dependency>

如果你已经升级到 Spring AI 1.0.0 GA,starter 名称变成了spring-ai-starter-mcp-client,建议用spring-ai-bom统一管理版本,配置项spring.ai.mcp.client.stdio.*保持不变。

第二步:写 MCP Server 配置文件。在src/main/resources下新建mcp-servers.json:

{ "mcpServers": { "amap-maps": { "command": "npx", "args": [ "-y", "@amap/amap-maps-mcp-server" ], "env": { "AMAP_MAPS_API_KEY": "${AMAP_MAPS_API_KEY}" } } } }

注意env里我用的是${AMAP_MAPS_API_KEY}占位符,而不是明文写 Key。这样你可以通过环境变量注入,避免把密钥提交到 Git。Windows 环境下command要写成npx.cmd,否则会报找不到命令。

第三步:配置 application.yml。这里同时配置 MCP 客户端和 TaoToken 统一通道:

spring: ai: mcp: client: stdio: servers-configuration: classpath:mcp-servers.json openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.7

这段配置做了两件事:spring.ai.mcp.client.stdio.servers-configuration告诉 Spring AI 去哪里读 MCP Server 定义;spring.ai.openai.base-url把模型调用的 endpoint 指向 TaoToken 统一通道。api-key同样用环境变量注入。

第四步:写 MCP 客户端 Bean 配置。虽然 starter 会自动装配ToolCallbackProvider,但显式声明一个 Bean 更利于排查问题:

@Configuration public class McpClientConfig { @Bean public ToolCallbackProvider amapToolCallbackProvider( List<McpSyncClient> mcpSyncClients) { return ToolCallbackProvider.from(mcpSyncClients); } }

然后在你的 ChatService 里注入这个 Provider,并挂到ChatClient上:

@Service public class ChatService { @Resource private ToolCallbackProvider toolCallbackProvider; private final ChatClient chatClient; public ChatService(ChatClient.Builder builder) { this.chatClient = builder.build(); } public String chatWithAmap(String message, String chatId) { ChatResponse response = chatClient.prompt() .user(message) .advisors(spec -> spec .param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId) .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)) .tools(toolCallbackProvider) .call() .chatResponse(); return response.getResult().getOutput().getText(); } }

到这里,配置部分就完成了。关键点回顾:MCP Server 定义在mcp-servers.json,模型通道在application.yml的spring.ai.openai下,工具通过ToolCallbackProvider注入。三者各司其职,不要混在一起。

4. 验证请求:从启动日志到一次真实的高德工具调用

配置写完不代表能跑通,必须验证。我按启动、发现工具、发起调用三个阶段来说。

阶段一:看启动日志确认 MCP 子进程拉起成功。启动 Spring Boot 应用后,日志里应该能看到 MCP 客户端连接的信息,以及tools/list返回的工具清单。高德 MCP Server 通常会暴露maps_search_poi、maps_around_search、maps_direction_walking等工具。如果日志里工具列表是空的,说明子进程没起来,先回去检查 Node.js 和npx.cmd。

阶段二:确认模型通道连通。这一步验证 TaoToken 的 endpoint 是否配对了。你可以先写一个最简单的对话接口,不挂任何工具,直接问"你好",看能否正常返回。如果返回 401,说明 Key 不对;如果报local proxy failed或连接超时,说明 base-url 写错了。正确的 base-url 是https://taotoken.net/api,不要多加/v1。

阶段三:发起一次真实的高德工具调用。调用上面写的chatWithAmap方法,传入"帮我找上海静安寺附近评分高的本帮菜餐厅"。预期行为是:模型判断需要调用 POI 搜索工具,Spring AI 执行工具,MCP 客户端把请求转发给高德 MCP 子进程,子进程调用高德 Web API,结果回填给模型,模型组织成自然语言回复。

成功的结果长这样:返回内容里会包含具体的餐厅名称、地址、评分,而不是"我无法获取实时数据"这种兜底话术。同时你可以在高德开放平台控制台看到 API Key 的调用次数增加了 1 次,这是最硬的证据。

如果你想更直观地观察工具调用过程,可以加一个日志 Advisor,把模型返回的 tool_calls 字段打出来。你会看到类似这样的结构:

{ "tool_calls": [ { "function": { "name": "maps_search_poi", "arguments": "{\"keywords\":\"本帮菜\",\"city\":\"上海\",\"location\":\"121.445,31.223\"}" } } ] }

看到这个,就说明整条链路通了:模型决策 → 工具调用 → MCP 转发 → 高德返回 → 模型总结。

5. 常见报错排查:401、local proxy failed、工具列表为空

这一节按真实报错来对照,遇到问题直接查。

报错一:401 Unauthorized。这个最常见,分两种来源。如果是模型调用返回 401,说明 TaoToken 的 API Key 不对或没注入成功,检查环境变量TAOTOKEN_API_KEY是否设置、application.yml里是否引用了它。如果是高德工具调用返回 401,说明AMAP_MAPS_API_KEY有问题,检查高德控制台里 Key 的服务平台是否选了"Web 服务"。

报错二:local proxy failed 或连接被拒绝。这个通常出现在模型通道配置上。检查spring.ai.openai.base-url是否写成了https://taotoken.net/api,有没有误加/v1或结尾斜杠。另外确认你的网络能正常访问该地址,可以用curl https://taotoken.net/api测一下连通性。

报错三:reading choices 解析失败。这个报错说明返回的 JSON 结构不符合 OpenAI 格式预期。常见原因是 base-url 指向了一个非兼容端点,或者模型名称填错了。确认spring.ai.openai.chat.options.model填的是 TaoToken 支持的模型 ID,不要填一个不存在的名字。

报错四:OAuth 相关错误。如果你用的是 Claude Code 或某些需要 OAuth 的工具接入,报 OAuth 错误通常是认证方式没选对。TaoToken 的接入文档里对 Claude Code 有专门的说明,Base URL、Key、Model ID 三件套要填全,缺一个都会认证失败。

报错五:ToolCallbackProvider 为空,模型不使用工具。应用能启动,但模型就是不调工具。原因几乎都是 MCP 子进程没起来。排查顺序:先看启动日志里有没有 MCP 连接成功的记录;再手动在终端执行npx -y @amap/amap-maps-mcp-server看能否启动;然后检查mcp-servers.json里command在 Windows 下是否加了.cmd;最后确认AMAP_MAPS_API_KEY环境变量在子进程里能读到。

报错六:首次启动特别慢。npx第一次运行会联网下载@amap/amap-maps-mcp-server包,国内网络可能很慢。可以配置 npm 镜像源加速,或者提前手动npm install -g @amap/amap-maps-mcp-server装好。

报错七:版本兼容问题。如果你从 M6 升级到 GA,starter 坐标变了,配置项虽然兼容但依赖要同步调整。升级时先看 Spring AI 官方迁移说明,别直接改版本号了事。

6. 把通道固定下来:TaoToken 接入与后续扩展

跑通一次调用只是开始,真正要落地还得把通道固定成团队可复用的形态。

首先是 Key 管理。不要把 TaoToken 的 Key 和高德的 Key 硬编码在任何配置文件里。推荐的做法是通过环境变量或配置中心注入,application.yml里只写占位符。这样本地开发、测试、生产可以用不同的 Key,也不会因为误提交导致泄露。

其次是模型选择。TaoToken 统一通道的好处是你可以通过改一个model字段切换底层模型,而不用改代码。比如调试阶段用便宜的小模型,上线换成能力更强的,只改application.yml一行。如果你要做长期编码或 Agent 类任务,可以考虑用 Coding Plan,它在长上下文和工具调用场景下更稳。

再就是 MCP Server 的扩展。高德只是其中一个,你完全可以在mcp-servers.json里再加几个 Server,比如 GitHub MCP、文件系统 MCP。Spring AI 启动时会自动发现所有 Server 的工具并合并注入,模型会根据用户问题自己选。这就是 MCP 相比原生 Tool Calling 最大的价值——加能力不用改代码。

最后提醒几个运维层面的点。stdio 子进程的生命周期跟应用绑定,应用关闭时子进程也会销毁,但如果是多实例部署,要注意每个实例都会拉起自己的 Node 进程,机器资源要留够。另外高德 API 有调用限额,生产环境建议加一层缓存或限流,避免被限流影响体验。

如果你在接入过程中卡在某个报错上,可以对照第 5 节的排查清单逐条过。模型通道的问题看 TaoToken 的接入文档,工具发现的问题看启动日志里的 MCP 连接记录。把这两条线分开排查,大部分问题都能定位到。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询