news 2026/10/4 9:17:06

基于Spring AI的MCP Server/Client实现及鉴权:把鉴权配置改到TaoToken

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Spring AI的MCP Server/Client实现及鉴权:把鉴权配置改到TaoToken

1. 从一次 401 说起:Spring AI MCP 鉴权链路到底卡在哪

如果你正在用 Spring AI 搭 MCP Server 和 MCP Client,大概率会遇到这样一个场景:本地把 Server 起在 8080,Client 用 SSE 连过去,工具方法也注册好了,结果一发起对话,日志里直接甩出一行401 Unauthorized,或者更隐蔽一点,Client 端报local proxy failed、reading choices之类的错,看起来像是模型的问题,实际上是鉴权头没带对。

MCP 即模型上下文协议,简单说就是让大模型通过统一协议去调用你本地的接口、数据库、文件服务。Spring AI 从 1.0 开始把 MCP Server 和 Client 的 starter 做得比较完整,Java 后端接入门槛低了很多。但真正落到生产,绕不开一个问题:模型访问凭证和 MCP 服务凭证怎么统一管理。很多团队的做法是每个服务各存一份 Key,Client 里写死一个、Server 里再写死一个,改一次要动好几个仓库。

这篇就聚焦 Spring AI 框架下 MCP Server 与 Client 的鉴权链路,面向需要统一管理模型访问凭证的 Java 后端场景。我会给出可复制的鉴权配置片段,把鉴权配置改到 TaoToken 统一 Key 接入,并完整演示一次从 401 报错到鉴权通过的验证动作。适合已经能跑通基础 MCP 调用、但被鉴权和凭证管理卡住的同学。

核心检索词先摆出来:Spring AI MCP Server Client 鉴权配置、MCP 统一 Key 接入、Spring AI MCP 401 排查。这三个词基本覆盖了本文要解决的问题域。

先说清楚 MCP 的鉴权链路分两段。第一段是 Client 到 Server 之间,走 HTTP 头,通常是Authorization或者自定义的appCode/appSecretKey;第二段是 Client 到模型服务之间,走模型厂商的 API Key。传统做法这两段各管各的,问题就出在这里:模型 Key 散落在各个 Client 的 yml 里,MCP Server 的鉴权又自成一套,运维和轮换都很痛苦。

我试过把这两段收敛到同一个入口,也就是让 MCP Client 在调用模型和调用 MCP Server 时,都从统一的凭证源取 Key。TaoToken 在这里扮演的就是统一凭证入口的角色,它提供兼容 OpenAI 风格的 API 地址,模型调用和 MCP 工具调用可以共用一套 Key 管理逻辑。下面从环境准备开始,一步步把配置改过去。

2. TaoToken 前置准备:统一 Key 与 MCP 鉴权的关系

在动手改配置之前,先把 TaoToken 这一侧的准备做掉。这一步的目标很简单:拿到一个可以同时用于模型调用和 MCP 鉴权的 Key,并确认 API 地址可用。

TaoToken 的 API 地址是https://taotoken.net/api,这个地址不加任何 UTM 参数,直接作为 Base URL 使用。模型对话入口在https://taotoken.net/models,Coding Plan 在https://taotoken.net/coding-plan,控制台在https://taotoken.net/console,API Keys 管理在https://taotoken.net/api-keys,接入文档在https://taotoken.net/doc。这些 deep link 在后续 CTA 里会带上归因参数,正文里先记清楚路径。

为什么要把 MCP 鉴权配置改到 TaoToken?因为 MCP 的鉴权本质上是「谁有权调用这个工具」,而模型调用的鉴权是「谁有权用这个模型」。在 Spring AI 的架构里,MCP Client 同时持有这两个身份。如果两套凭证分开管理,就会出现 Client 里配了模型 Key,但 MCP Server 的过滤器校验的是另一套 token,两边对不上就 401。

统一到 TaoToken 之后,逻辑变成:Client 从 TaoToken 拿一个 Key,这个 Key 既用于向模型服务发起请求,也用于在请求 MCP Server 时放进Authorization头。MCP Server 侧的过滤器只需要校验这个 Key 的有效性,不需要再维护一套独立的 appCode/appSecretKey。这样凭证轮换只在一个地方做,审计也集中。

具体操作上,先去https://taotoken.net/api-keys创建一个 Key,记下来。然后在项目里把它放到环境变量,不要硬编码进 yml。Spring AI 的配置支持${}占位符,这一点后面配置片段里会体现。

这里有个容易踩的坑:TaoToken 的 Key 在模型调用时通常放在Authorization: Bearer <key>,而 MCP Server 的过滤器如果也读Authorization,就要保证格式一致。如果你的 MCP Server 过滤器读的是自定义头比如X-MCP-Token,那 Client 侧就要同时带两个头,或者把过滤器改成读Authorization。本文统一用Authorization,减少头数量。

另外提醒一句,MCP Server 建议独立成微服务,不要和业务代码混在一起。混在一起的话,业务侧的登录鉴权白名单要放行/sse、/mcp/**、/health、/actuator/health这些路径,否则 MCP 请求会被业务拦截器先拦掉,报的错和鉴权失败很像,排查起来费时间。

准备好 Key 和 API 地址后,进入配置环节。下面给的片段都是可以直接复制到项目里的,路径和字段名与 Spring AI 官方 starter 保持一致。

3. 可复制配置:把鉴权改到 TaoToken 的完整片段

这一节是全文的技术核心,给出 MCP Server 和 MCP Client 两侧的可复制配置。先看依赖,再看 yml,最后看鉴权过滤器和 Client 的请求头注入。

MCP Server 侧依赖,基于 Spring Boot 3.5.5 和 Spring AI 1.1.0-M3:

<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>

MCP Server 的 yml 配置,关键是sse-message-point和name:

spring: ai: mcp: server: name: mcp-server sse-message-point: /sse

MCP Server 的鉴权过滤器,改成校验 TaoToken 的 Key。这里用WebMvcConfigurer注册拦截器,或者直接用Filter。下面给一个Filter版本,读Authorization头:

@Component @Slf4j public class McpAuthFilter implements Filter { @Value("${taotoken.api.key}") private String expectedKey; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; String path = req.getRequestURI(); if (path.startsWith("/sse") || path.startsWith("/mcp")) { String auth = req.getHeader("Authorization"); if (auth == null || !auth.equals("Bearer " + expectedKey)) { HttpServletResponse resp = (HttpServletResponse) response; resp.setStatus(401); resp.setContentType("application/json;charset=UTF-8"); resp.getWriter().write("{\"code\":401,\"msg\":\"认证失败: 无效令牌\"}"); return; } } chain.doFilter(request, response); } }

MCP Client 侧依赖,注意用 webflux,因为 MCP Client 的 SSE 是响应式的:

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

MCP Client 的 yml,把模型 Base URL 指向 TaoToken,同时配置 MCP Server 连接:

spring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini mcp: client: enabled: true toolcallback: enabled: true name: note-mcp-client sse: connections: server1: url: http://localhost:8080 sse-endpoint: /sse type: SYNC

注意这里base-url用的是https://taotoken.net/api,不带 UTM。api-key从环境变量TAOTOKEN_API_KEY读,和 MCP Server 过滤器里的taotoken.api.key是同一个值。这样模型调用和 MCP 鉴权共用一套 Key。

MCP Client 在发起 SSE 连接时,需要把Authorization头带上。Spring AI 的 MCP Client 默认不会自动加这个头,需要自定义WebClient或者用McpSseClientProperties扩展。下面给一个配置类,注入带鉴权头的WebClient:

@Configuration public class McpClientConfig { @Value("${taotoken.api.key}") private String apiKey; @Bean public WebClient.Builder mcpWebClientBuilder() { return WebClient.builder() .defaultHeader("Authorization", "Bearer " + apiKey); } }

如果你的 Spring AI 版本里 MCP Client 的 SSE 连接不走这个WebClient.Builder,那就退一步,在 MCP Server 的过滤器里放宽为只校验 Key 是否存在且非空,把严格校验放到模型调用侧。但推荐还是让 Client 带上头,链路更清晰。

ChatClient 的配置,把 MCP 工具提供者注入进去:

@Bean public ChatClient chatClient(OpenAiChatModel model, ToolCallbackProvider toolCallbackProvider) { return ChatClient.builder(model) .defaultSystem("你是笔记助手,基于 MCP 工具返回的内容回答用户问题") .defaultToolCallbacks(toolCallbackProvider) .build(); }

到这里,配置片段就齐了。Server 侧校验Authorization,Client 侧注入Authorization,模型 Base URL 指向 TaoToken,Key 统一从环境变量取。下一步验证这套配置能不能跑通。

4. 验证请求:从 401 到鉴权通过的完整动作

配置改完,先别急着跑完整对话,按顺序验证,能快速定位问题在哪一段。

第一步,单独验证 MCP Server 的鉴权。用 curl 直接打 SSE 端点,不带 Authorization:

curl -i http://localhost:8080/sse

预期返回 401,body 是{"code":401,"msg":"认证失败: 无效令牌"}。这一步确认过滤器生效了。

第二步,带上正确的 Authorization 再打一次:

curl -i -H "Authorization: Bearer $TAOTOKEN_API_KEY" http://localhost:8080/sse

预期返回 200,并且开始输出 SSE 事件流。如果这一步还是 401,检查环境变量是否真的注入到了 Server 进程,以及过滤器里expectedKey的值和请求头里的 Key 是否完全一致,注意 Bearer 后面有一个空格。

第三步,验证模型调用。单独用 curl 打 TaoToken 的 chat completions:

curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"ping"}]}'

预期返回一个正常的 JSON,包含choices字段。如果这里报 401,说明 Key 本身有问题,去https://taotoken.net/api-keys确认 Key 状态。如果报reading choices之类的解析错,通常是返回体不是预期格式,检查 Base URL 是不是写成了https://taotoken.net/api而不是带/v1的路径,Spring AI 的 OpenAI starter 会自动拼/v1/chat/completions。

第四步,跑完整的 MCP 对话。启动 Client,调用/ai/note/chatForNote接口:

curl -N -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ "http://localhost:8081/ai/note/chatForNote?message=我的钥匙在哪儿"

预期看到 SSE 流式输出,模型先决定调用 MCP 工具,工具返回笔记内容,模型再基于内容回答。日志里应该能看到 MCP Server 侧打印出工具方法的入参,以及 Client 侧打印出模型返回。

如果第四步失败,回看第三步和第二步是否都通过。两步都通过但第四步失败,问题通常在 Client 到 Server 的 SSE 连接头没带上,或者 MCP Server 的/mcp/**路径被业务拦截器拦了。检查 Client 的WebClient是否真的注入了Authorization,以及 Server 侧白名单是否放行了/mcp/**。

验证通过后,你会看到一次完整的链路:Client 带 Key 连 Server,Server 校验 Key,Client 带同一个 Key 调模型,模型返回工具调用指令,Client 转发给 Server,Server 执行工具返回结果,模型润色后流式返回。整条链路只有一个 Key,轮换时只改环境变量。

5. 常见报错排查:401、local proxy failed、reading choices、OAuth

这一节把实际会遇到的报错列出来,对照排查。每个报错都给出触发条件和处理方式。

401 Unauthorized 是最常见的。触发条件有三种:Client 没带Authorization头、头里的 Key 和 Server 期望的不一致、Key 本身失效。排查顺序是先 curl Server 端点确认过滤器行为,再 curl 模型端点确认 Key 有效,最后检查 Client 的WebClient是否真的注入了头。注意 Spring AI 不同版本里 MCP Client 的 SSE 连接构造方式不同,有的版本需要显式传WebClient,有的走默认。如果注入不生效,可以在 Client 侧加一个日志,打印实际发出的请求头。

local proxy failed 通常出现在 Client 侧,原因是 Client 到 Server 的 SSE 连接建立失败。可能是 Server 没起、端口不对、sse-endpoint配错,或者 Server 侧过滤器返回了非 SSE 格式的响应导致 Client 解析失败。先确认curl -i http://localhost:8080/sse带 Key 能返回 200 和事件流,再检查 Client 的url和sse-endpoint拼接是否正确。注意url不要带尾部斜杠,sse-endpoint要以斜杠开头。

reading choices 是模型返回体解析失败。Spring AI 的 OpenAI starter 期望返回体里有choices数组。如果 Base URL 配错,比如配成了https://taotoken.net而不是https://taotoken.net/api,请求会打到错误路径,返回 HTML 或错误 JSON,解析就失败。检查base-url是否精确为https://taotoken.net/api,以及模型名是否在 TaoToken 支持的列表里。模型名写错有时也会返回非预期结构。

OAuth 相关报错,如果你用的是 Claude Code 或者带 OAuth 的 MCP 接入方式,可能会遇到 token 过期或 scope 不足。这类报错的关键是确认 OAuth 流程拿到的 token 有没有正确传给 MCP Client。如果同时用了 TaoToken 的 Key 和 OAuth token,要分清哪个头传哪个。一般Authorization只放一个,不要叠加。Claude Code 接入场景下,Base URL、Key、Model ID 三件套要写全,缺一个都会报鉴权或模型不存在。

还有一个隐蔽的错:MCP Server 和业务代码混部时,业务拦截器先返回 401,但 body 格式和 MCP 过滤器的不一样,Client 侧看到的报错信息会误导。排查时先看 Server 日志里是哪个过滤器打的日志,确认是 MCP 过滤器还是业务过滤器。

对照表如下:

报错常见原因处理
401 Unauthorized头缺失/Key 不一致/Key 失效curl 分段验证,检查环境变量注入
local proxy failedSSE 连接建立失败确认 Server 可达、endpoint 拼接正确
reading choicesBase URL 或模型名错误确认 base-url 为 https://taotoken.net/api
OAuth 报错token 未传递或 scope 不足确认三件套 Base URL+Key+Model ID 写全

排查的核心思路是分段验证:先 Server 鉴权,再模型调用,最后完整链路。不要一上来就跑完整对话,那样报错信息会混在一起。

6. 统一 Key 之后的接入与长期使用建议

把鉴权配置改到 TaoToken 之后,最直接的变化是凭证管理收敛了。以前模型 Key 和 MCP 鉴权 Key 分开,现在一个环境变量搞定。轮换时改一处,所有 Client 和 Server 重启后生效。审计时也清楚,哪个 Key 调了哪些模型、哪些工具,都在一个入口。

如果你还在接入阶段,建议先把 MCP Server 的鉴权跑通,再配 Client 的模型调用,最后合起来验证。接入文档在https://taotoken.net/doc,里面有 Base URL 和请求格式的说明。API Keys 管理在https://taotoken.net/api-keys,创建和吊销都在这里。模型列表和对话测试可以在https://taotoken.net/models直接试。

对于长期跑编码 Agent 或者多 MCP Server 的场景,Coding Plan 在https://taotoken.net/coding-plan,适合需要稳定额度和统一计费的团队。控制台在https://taotoken.net/console,可以看调用量和 Key 使用情况。

最后给一个实用技巧:在 Client 侧加一个请求日志拦截器,把发往 MCP Server 和模型服务的请求头打出来,但记得脱敏 Key。这样下次再遇到 401,直接看日志就知道头带没带、值对不对,比翻代码快得多。MCP 鉴权链路本身不复杂,复杂的是凭证散落导致的排查成本,统一到 TaoToken 之后,这条链路就清晰了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 9:08:45

原创性如何?8款AI写作辅助软件榜单,毕业答辩稳了!

论文选题无从下手&#xff1f;文献综述写得杂乱无章&#xff1f;查重反复修改耗时费力&#xff1f; 别担心&#xff01;AI论文写作工具正成为高校学生的高效帮手。本文将从学术规范性、内容逻辑性、格式自动生成、查重优化能力四个维度&#xff0c;深度测评8款热门AI论文辅助软…

作者头像 李华
网站建设 2026/10/4 9:04:08

VFH避障算法原理与调参实战:从向量场直方图到机器人局部路径规划

做机器人避障和局部路径规划的人&#xff0c;应该没有一个没听说过VFH。VFH算法全称是Vector Field Histogram&#xff08;向量场直方图&#xff09;&#xff0c;它解决的是移动机器人在未知环境下&#xff0c;如何根据传感器信息实时避开障碍物并朝目标方向运动的问题。市面上…

作者头像 李华
网站建设 2026/10/4 9:00:51

七日量化回测入门(四)Backtrader 双均线回测告别未来函数

1. 引言 在量化回测中&#xff0c;未来函数&#xff08;Look-ahead Bias&#xff09; 是导致回测结果虚高、实盘却亏损的头号杀手。它的本质是&#xff1a;在计算当天交易信号时&#xff0c;无意中使用了当天收盘后&#xff08;甚至未来&#xff09;才产生的数据。 正确做法是&…

作者头像 李华