JAVA-MCP Demo 的 Spring AI 遇 403?Base URL 走 TaoToken 通道再试
在 IDEA 里把 JAVA-MCP Demo 拉下来application.properties 里的 spring.ai.anthropic.api-key 刚填好启动 Spring Boot 后调用 /api/chat控制台直接返回 403。栈里看不到 findBooksByAuthor 的执行日志ChatClient 甚至还没把请求发出去就被 Anthropic 模型端拦住了。这个报错和 TaoToken 本身没关系但修法要从 TaoToken 开始打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册并创建 API Key再把 Spring AI 的模型通道 base-url 改成 https://taotoken.net/api密钥位放刚创建的 Key重启后再发同一条消息。下面按排障顺序拆一遍重点看 application.properties、Tool 注解和 McpServerConfig 这三处。1. Spring AI 的 403 不是代码错是模型通道没选对1.1 application.properties 里那行 api-key 暴露的默认通道原文 Demo 第 2 步是在 application.properties 里写 spring.ai.anthropic.api-key然后提示 Anthropic 访问需要代理否则会报 403。这句话点破了问题的位置Spring AI 的 Anthropic Starter 默认把请求发往 api.anthropic.com你的 Key 填得再对只要当前网络环境被模型端判定为不可服务返回就是 403。403 的含义不是“认证失败”而是“服务端拒绝执行”所以 ChatClient 在创建请求、拼装 headers 的阶段就被挡回来了。这和业务代码没关系。BookTools 里的 findBooksByAuthor 写没写对、ToolParam 有没有加描述、McpServerConfig 有没有注册 ToolCallbackProvider都不影响这个 403。因为请求根本还没走到工具调用那一层。排障时先把故障域缩小如果日志里出现 403 且没有任何 tool call 记录先别改 Java 代码先看模型通道配置。1.2 403 出现的时机ChatClient 还没发出请求Spring AI 的调用链大致是Controller 收到 /api/chat 请求 → ChatClient 组装 prompt → AnthropicApi 用 base-url 拼出完整 endpoint → 发起 HTTP 请求 → 模型返回 → 若模型决定调用工具再回调 Tool 方法。403 通常发生在第四步之前或第四步当下也就是说ChatClient 已经准备发请求但模型端直接拒绝。这种情况下你在 Controller 里打日志只能看到“开始调用”看不到“模型已返回”。在 BookTools.findBooksByAuthor 里打日志更是什么都看不到。判断方法很简单把日志级别调到 DEBUG看有没有出现POST https://api.anthropic.com/v1/messages这样的记录。如果有且后面紧跟 403就说明默认通道不通需要换 Base URL。1.3 把通道换成 TaoToken 后要改哪两行改法不复杂但必须改对位置。第一行是 spring.ai.anthropic.base-url把它从默认的 api.anthropic.com 改成 https://taotoken.net/api末尾不要加 /v1也不要把官网落地页的 UTM 参数带进来。第二行是 spring.ai.anthropic.api-key把原来的 Anthropic Key 换成从 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建的 TaoToken Key。这里有个容易混的点给人看的落地页是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end用来注册、创建 Key、看模型广场和用量填进 Spring AI 的 base-url 必须是 https://taotoken.net/api。前者带查询参数后者不带。把落地页整串粘进 application.propertiesSpring AI 会拼出错误路径表现可能是 404也可能是 403。改完配置后重启 Spring Boot再发同一条“根据作者查张三”。2. 在 application.properties 和 McpServerConfig 里接上 TaoToken2.1 从落地页拿 Key别把官网地址填进 base-url准备材料只有两样一个可用的 TaoToken Key一个当前模型广场里存在的模型 ID。打开 TaoToken 注册并登录在控制台创建 API Key复制出来先放到安全的地方。Key 在配置里统一写成 YOUR_API_KEY不要提交到 Git也不要在日志里打印完整值。模型 ID 不要凭记忆写。以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 模型广场当时列表为准。有的人看旧教程填了带日期后缀的模型名结果模型端返回 404 或“model not found”又被误判成 403。先把模型 ID 复制准确再进配置文件。2.2 Spring AI Anthropic 的 base-url 与 model 怎么填application.properties 按下面写。注意 base-url 末尾没有 /v1Spring AI 的 Anthropic 实现会自己拼接后续路径。spring.application.namejava-mcp-demo spring.ai.anthropic.api-keyYOUR_API_KEY spring.ai.anthropic.base-urlhttps://taotoken.net/api spring.ai.anthropic.chat.options.modelYOUR_MODEL_ID如果你用的是 application.yml对应结构是spring: ai: anthropic: api-key: YOUR_API_KEY base-url: https://taotoken.net/api chat: options: model: YOUR_MODEL_ID改完后不要急着调 MCP 工具先用最简单的一条消息确认模型通道通不通。比如在 /api/chat 里发“你好”如果返回正常文本说明 403 已经解决模型通道已经走到 TaoToken。接下来再验证工具调用故障域会清晰很多。2.3 MCP Server 的工具注册文件长什么样原文第 4 步会发“根据作者查张三”观察 Tool 标记的 findBooksByAuthor 是否被调用。要让这个链路成立除了模型通道工具注册也得写对。一个可运行的 Demo 结构如下BookTools 负责声明工具McpServerConfig 负责把工具对象注册成 ToolCallbackProvider。Component public class BookTools { private final BookRepository bookRepository; public BookTools(BookRepository bookRepository) { this.bookRepository bookRepository; } Tool(description 根据作者姓名查询图书列表) public ListBook findBooksByAuthor( ToolParam(description 作者姓名例如张三) String author) { return bookRepository.findByAuthor(author); } }Configuration public class McpServerConfig { Bean public ToolCallbackProvider bookToolCallbackProvider(BookTools bookTools) { return MethodToolCallbackProvider.builder() .toolObjects(bookTools) .build(); } }BookRepository 在 Demo 里可以指向本地测试库或内存数据。如果后面要接真实业务库建议给工具方法使用只读账号并且不要在工具内部直接执行高风险 SQL。更稳的做法是让模型生成 SQL由你在本地 SQL 客户端执行再把结果贴回对话。AI 编程工具默认不能直连生产库去“执行”业务操作Codex、Claude Code 这类工具也只能生成、解释、对照代码或 SQL不能替你连上生产机器跑诊断语句。3. 用 /api/chat 发「根据作者查张三」验证工具链路3.1 请求体与控制台日志观察点模型通道改完、工具注册完成后用原文第 4 步的请求验证。假设 Controller 暴露的是 POST /api/chat请求体可以写成{ message: 根据作者查张三 }对应的 curl 命令curl -X POST http://localhost:8080/api/chat \ -H Content-Type: application/json \ -d {message:根据作者查张三}发出去以后盯三个地方Spring Boot 控制台有没有出现 findBooksByAuthor 的调用日志返回 JSON 里是否包含图书列表如果开了 Spring AI 的 tool call 日志是否能看到工具名和参数 author张三。只要这三处里有两处命中就说明模型调用和 MCP 工具链路已经走 TaoToken 通道。3.2 findBooksByAuthor 被调用的三个信号第一个信号是日志。在 findBooksByAuthor 方法第一行加log.info(tool findBooksByAuthor author{}, author);如果这行出现说明模型确实决定调用工具并且 Spring AI 成功回调了本地方法。第二个信号是返回值。接口返回的 JSON 里应该出现图书对象数组而不是一句“我将为您查询”。第三个信号是耗时分布。模型通道正常时整体响应会分成“模型推理耗时”和“工具执行耗时”如果只有前者没有后者说明工具没被触发。如果三个信号都出现了403 排障就结束了。后面再调 Tool、ToolParam 和 McpServerConfig都属于工具质量优化不是通道问题。比如查张三返回空列表可能是本地测试库没有数据不是 TaoToken 的问题。3.3 如果只返回自然语言没调工具先查 ToolParam模型返回“好的我正在为您查询张三的图书”但没有真正调用工具常见原因是工具描述太模糊。Tool 的 description 要写清楚“根据作者姓名查询图书列表”ToolParam 要写清楚参数含义“作者姓名例如张三”。模型看到清晰描述才更愿意把用户问题映射到工具调用。另一个原因是 McpServerConfig 没注册到位。如果 ToolCallbackProvider 没有被 Spring 容器扫描到模型端根本看不到这个工具自然只会用自然语言回复。还有一种情况是模型本身不支持工具调用或者当前模型 ID 在模型广场里属于纯对话模型。换一个支持 tool use 的模型 ID 再试模型 ID 仍以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 模型广场当时列表为准。4. 403 之外Tool、ToolParam、McpServerConfig 的排查顺序4.1 401 和 404 分别对应哪一行配置403 解决后可能遇到 401 和 404。401 通常对应 spring.ai.anthropic.api-key 这一行Key 没替换、复制时带了空格、或者用了已经删除的 Key。处理方式是回到控制台重新创建一个 Key再写进 YOUR_API_KEY 的位置。404 通常对应 spring.ai.anthropic.base-url 这一行末尾多写了 /v1或者把落地页 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 整串粘进去了。正确值只有 https://taotoken.net/api。不要同时改 Key、Base URL 和模型 ID否则出了问题不知道是哪一行引起的。排障时一次只动一个变量先确认 Base URL 是 https://taotoken.net/api再确认 Key 是新建的最后确认模型 ID 来自模型广场。每改一次重启一次发同一条“根据作者查张三”。4.2 工具注册了但模型不调用工具注册了但模型不调用按这个顺序查第一看 Tool 注解是否加在 public 方法上方法返回值是否可序列化第二看 ToolParam 是否给每个参数都写了 description第三看 McpServerConfig 里的 ToolCallbackProvider 是否被 Spring 扫描到可以在启动日志里搜工具名第四看当前模型是否支持工具调用。四个都正常再考虑把工具描述写得更具体比如加上“返回字段包括书名、作者、ISBN”。不要为了让模型调用工具而在 description 里写“必须调用”。更好的方式是写清楚工具能解决什么问题模型会根据用户意图选择。原文 Demo 的“根据作者查张三”本身就是很明确的意图工具描述只要匹配通常都能触发。4.3 不要让 ChatClient 直连生产库MCP Demo 里用本地测试库或内存数据最安全。如果想把 findBooksByAuthor 接到真实业务库不要让 ChatClient 直接连生产库执行 SQL。正确做法是让模型生成查询 SQL 或解释 SQL由你在本地 SQL 客户端执行把结果贴回对话再让模型整理成图书列表。这样既保留了 MCP 工具链路的演示效果又不会把生产库暴露给 AI 工具。诊断 SQL、编译运行、regsvr32 这类操作也一样必须由读者在本地或受控环境执行再把报错贴回对话。Codex、Claude Code 可以帮你对照代码、生成 SQL、解释报错但不会替你连上生产机器执行。把这条边界守住再调 Tool、ToolParam 和 McpServerConfig 会更安心。5. 跑通之后去控制台对一下这次调用5.1 用同一把 Key 在模型对话里再发一次Spring Boot 里看到图书列表返回后用同一把 Key 在 TaoToken 模型对话 里发一条测试消息确认模型 ID 和 Base URL 没填错。模型对话页面能返回正常文本说明 Key 和模型 ID 都是有效的如果这里也报错就不用回去改 Java 代码了先把 Key 和模型 ID 理顺。5.2 长期写代码看 Coding PlanKey 和文档位置如果这个 JAVA-MCP Demo 只是开始后面还要长期调试 Tool、ToolParam 和 McpServerConfig可以打开 Coding Plan 看套餐是否够用。Key 在 控制台 API Keys 创建和管理。如果你平时也用 Claude Code 这类命令行工具环境变量对照见 接入文档。把这次 Spring AI 的调用记录和控制台用量对一下确认请求确实记到了同一个 Key 上再继续加工具方法。