1. Java 写 MCP 服务器,为什么鉴权这一步最容易卡住
MCP 是 Model Context Protocol 的缩写,你可以把它理解成 AI 客户端和外部系统之间的一份“插座标准”:AI 客户端负责推理该调用哪个工具,MCP 服务器负责真正执行工具并把结果回传。对 Java 开发者来说,用 Spring AI 的spring-ai-starter-mcp-server-webmvc起一个带@Tool方法的服务并不难,难的是当这个服务要同时对接多个 AI 客户端、多个环境时,Key 怎么管、工具调用链路怎么统一。
我见过太多本地跑通的 MCP 服务器,一旦要接第二个客户端就开始复制粘贴 API Key:Claude Code 一份、IDE 插件一份、自研 Agent 一份,改一次密钥要翻五个配置文件。这篇就聚焦 Java 侧 MCP 服务器的鉴权与工具调用配置,用 TaoToken 的统一 Key 把这条链路收口,给出可复制的config.toml与settings.json骨架,并演示一次完整的 MCP 工具调用验证。
适合谁看:已经会用 Spring Boot 写接口、想把自己的 Java 服务暴露成 MCP 工具、并且希望用一套 Key 管理多个 AI 客户端的开发者。下面所有配置都可以直接抄,改掉端口和工具名就能跑。
2. 前置准备:TaoToken 统一 Key 与 Java 侧依赖
TaoToken 在这里扮演的角色是“统一入口”:你不需要在每个 AI 客户端里分别填不同厂商的密钥,而是拿一个 TaoToken 的 Key,通过它的 API 地址去访问模型能力。对 MCP 场景来说,这意味着你的 Java 服务器、本地 AI 客户端、编码 Agent 可以共用同一套鉴权信息,减少配置漂移。
第一步是拿到 Key。打开官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,注册后在控制台创建 API Key。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,Key 列表页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。API 的基础地址是 https://taotoken.net/api ,注意这个地址不带任何查询参数,配置时直接填。
Java 侧依赖沿用 Spring AI 的 MCP 封装。在pom.xml里先引入 BOM,再引入 webmvc 版的 MCP 服务器 starter:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>1.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId> </dependency> </dependencies>版本号按你项目实际使用的 Spring AI 版本调整,这里写1.0.0只是占位。引入后,MCP 服务器默认暴露两个端点:/sse用于建立 SSE 会话,/mcp/message用于消息收发。这两个端点后面在客户端配置里会反复出现,先记住。
3. 可复制配置:config.toml 与 settings.json 骨架
MCP 生态里不同客户端的配置文件格式不一样。Claude Code 这类工具用settings.json,而一些通用 MCP 客户端用config.toml。下面两份骨架都围绕“Java MCP 服务器 + TaoToken 统一 Key”来写,你按自己用的客户端选一份。
先看config.toml,适合支持 TOML 配置的 MCP 客户端:
# MCP 客户端配置骨架 [mcp] # 统一鉴权:所有模型请求走 TaoToken api_base = "https://taotoken.net/api" api_key = "sk-你的TaoToken密钥" [[mcp.servers]] name = "java-weather" transport = "sse" url = "http://127.0.0.1:8080/sse" message_endpoint = "http://127.0.0.1:8080/mcp/message" # 工具调用超时,单位秒 timeout = 15再看settings.json,适合 Claude Code 这类 JSON 配置的客户端:
{ "mcpServers": { "java-weather": { "type": "sse", "url": "http://127.0.0.1:8080/sse", "messageEndpoint": "http://127.0.0.1:8080/mcp/message", "env": { "TAOTOKEN_API_BASE": "https://taotoken.net/api", "TAOTOKEN_API_KEY": "sk-你的TaoToken密钥" } } } }两份配置的核心思路一致:MCP 服务器地址指向你本地或部署好的 Java 服务,鉴权信息统一用 TaoToken 的 Key 和 API 地址。这样当你要换 Key 或换环境时,只改一处。
Java 服务器侧的端点如果想自定义,在application.yml里这样配:
spring: ai: mcp: server: enabled: true type: sync sse-endpoint: /sse sse-message-endpoint: /mcp/message server: port: 8080工具方法本身还是标准的@Tool注解。下面这个weatherQuery就是供 MCP 客户端调用的工具,参数描述写清楚,大模型才能正确推理该传什么:
@Service public class WeatherService { @Tool(name = "weather_query", description = "根据位置查询天气,返回温度和天气描述") public String weatherQuery( @ToolParam(description = "位置名称,例如杭州", required = true) String location) { int temperature = ThreadLocalRandom.current().nextInt(10, 40); String[] weathers = {"晴", "多云", "阴", "小雨", "中雨", "大雨"}; String weatherText = weathers[ThreadLocalRandom.current().nextInt(weathers.length)]; return "location=%s,temperature=%d°C,weatherText=%s" .formatted(location, temperature, weatherText); } }别忘了把工具对象注册成ToolCallbackProvider,否则 MCP 服务器不会暴露这个工具:
@Bean public ToolCallbackProvider toolCallbackProvider(WeatherService weatherService) { return MethodToolCallbackProvider.builder() .toolObjects(weatherService) .build(); }4. 验证请求:跑通一次 MCP 工具调用
配置写完,先启动 Spring 应用,然后确认/sse端点能建立会话。用 curl 快速探一下:
curl -N http://127.0.0.1:8080/sse如果看到持续输出的事件流,说明 MCP 服务器正常。接着写一个最小 MCP 客户端来列举工具并发起调用。引入客户端依赖:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-client-webflux</artifactId> </dependency>然后用McpSyncClient连接服务器,先initialize,再listTools,最后callTool:
public static void main(String[] args) { McpClientTransport transport = new HttpClientSseClientTransport("http://127.0.0.1:8080/sse"); McpSyncClient client = McpClient.sync(transport) .requestTimeout(Duration.ofSeconds(10)) .capabilities(McpSchema.ClientCapabilities.builder().roots(false).build()) .build(); McpSchema.InitializeResult init = client.initialize(); System.out.println("server=" + init.serverInfo().name()); McpSchema.ListToolsResult tools = client.listTools(); tools.tools().forEach(t -> System.out.println("tool=" + t.name())); McpSchema.CallToolRequest req = new McpSchema.CallToolRequest("weather_query", Map.of("location", "杭州")); McpSchema.CallToolResult result = client.callTool(req); System.out.println(result.content()); client.closeGracefully(); }正常输出会先打印服务器信息,再列出weather_query,最后返回类似:
[TextContent[audience=null, priority=null, text="location=杭州,temperature=38°C,weatherText=中雨"]]看到这行文本,就说明 Java 侧 MCP 服务器、工具注册、客户端调用这条链路全部打通了。如果你还想在对话里直接验证模型能否正确选择工具,可以打开模型对话页面 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite ,把 MCP 服务器接进去,问一句“杭州天气怎么样”,观察模型是否触发weather_query。
5. 本篇常见错排查
报错一:Connection refused或 SSE 连不上。先确认 Spring 应用真的起来了,端口没被占用。/sse是长连接端点,用浏览器直接打开可能一直转圈,这是正常的,用curl -N看事件流更直观。如果改了sse-endpoint,客户端配置里的 URL 要同步改。
报错二:工具列表为空。九成是ToolCallbackProvider没注册,或者@Tool方法所在的类没被 Spring 扫描到。检查@Service注解和包路径,确认toolObjects里传的是包含工具方法的实例。
报错三:调用工具返回Tool not found。客户端传的工具名必须和@Tool(name = "...")完全一致,大小写敏感。上面例子里是weather_query,写成weatherQuery就会找不到。
报错四:鉴权相关 401/403。如果你在 MCP 服务器里加了拦截器校验 TaoToken Key,确认客户端settings.json或config.toml里的api_key和服务器读取的是同一个。API 地址统一用https://taotoken.net/api,不要多加斜杠或路径。
报错五:超时。MCP 工具调用默认超时可能偏短,尤其是工具内部还要请求外部接口时。把客户端requestTimeout和配置里的timeout都调大,比如 15 到 30 秒。
6. 把 Key 收口之后,下一步怎么走
Java 侧 MCP 服务器跑通后,真正省心的地方在于鉴权收口:本地调试、IDE 插件、编码 Agent 都指向同一套 TaoToken Key,不用再维护多份密钥。如果你接下来要做长期编码或 Agent 集成,可以了解 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ;需要查接入细节就看接入文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ;Claude Code 相关配置参考 https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 。工具调用链路打通只是起点,把工具描述写准、把超时和错误处理补齐,才是让 MCP 服务器稳定服务多个客户端的关键。