news 2026/10/10 20:25:02

Java 从零开始:用 Spring Boot 创建你的第一个 MCP 服务并接入 TaoToken

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 从零开始:用 Spring Boot 创建你的第一个 MCP 服务并接入 TaoToken

1. 为什么 Java 后端要自己写一个 MCP 服务

MCP(Model Context Protocol,模型上下文协议)说白了就是给 AI 装一套标准插座。以前你想让 Claude、Cursor 这类客户端调用你写的业务方法,得自己拼 HTTP 接口、写一堆胶水代码,还得处理鉴权和参数校验。MCP 把这层统一了:你只要按协议暴露「工具(Tool)」,客户端就能自动发现并调用,参数结构、返回格式都由协议约定好。

对 Java 后端来说,这件事的价值在于复用。你手上已经有一堆 Spring 的 Service、Repository、内部 RPC 客户端,与其重写一遍,不如用 Spring AI 的 MCP Server Starter 把现有方法直接标注成工具,让 AI 客户端通过标准协议调进来。适合谁?三类人最合适:一是想把内部系统能力开放给 AI 助手的后端;二是做智能硬件/Agent 平台、需要统一工具入口的团队;三是想学 MCP 协议但不想从零啃 JSON-RPC 的开发者。

这篇我会带你从零建一个 Spring Boot 项目,定义两个工具(取当前时间、整数求和),打包成 JAR,再把它接到 TaoToken 的统一 Key/API 通道上做连通性验证。全程可复制,踩坑点我会在第五节列清楚。核心检索词先记住:Spring Boot 创建 MCP 服务、Java MCP Server 接入、TaoToken 统一 Key 通道。

2. 前置准备:TaoToken 通道与本地环境

在写代码之前,先把「AI 侧」的通道准备好。MCP 服务本身是工具提供方,但你要验证它、或者让上层 Agent 调用模型时,需要一个统一的模型入口。TaoToken 在这里扮演的就是统一 Key/API 通道的角色:一个 Key 走多家模型,Base URL 固定,省得你在每个客户端里维护一堆不同的地址和密钥。

你需要准备的东西:

  • JDK 17 或以上,推荐 JDK 21,Spring Boot 3.3 对 21 支持很好。
  • Maven 3.8+,或者用 IDEA 自带的。
  • 一个 TaoToken 账号,去控制台生成 API Key。地址是 https://taotoken.net/api ,Key 在 console 里创建,路径是 https://taotoken.net/console 。
  • 一个能发 HTTP 请求的工具,curl 或 Postman 都行,用来做连通性检查。

关于 Key 的存放,我的习惯是绝对不写进代码和 Git。本地用环境变量,CI 用 Secret,配置文件里只放占位符。你可以这样导出:

export TAOTOKEN_API_KEY="sk-你的key" export TAOTOKEN_BASE_URL="https://taotoken.net/api"

TaoToken 的 Base URL 是 https://taotoken.net/api ,注意这个地址不带任何查询参数,是纯 API 根路径。模型 ID 按你实际要用的填,比如 claude 系列或 gpt 系列,具体以控制台文档为准。这里有个关键点:MCP 服务端和模型调用是两件事,MCP 负责「暴露工具」,TaoToken 负责「提供模型」。你完全可以让 MCP 服务只做工具,模型调用交给上层客户端;也可以在自己的服务里同时调模型做增强。这篇两种都会覆盖到验证环节。

环境变量设好后,先别急着写代码,用一条 curl 确认通道是通的:

curl -s https://taotoken.net/api/v1/models \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" | head -c 500

能返回模型列表 JSON,说明 Key 和通道没问题。如果这里就 401,先解决鉴权,别往下走,否则后面报错你会分不清是 MCP 的问题还是 Key 的问题。

3. 可复制配置:pom、工具类与 MCP 注册

这一节是全文的核心,所有片段都能直接抄。先建项目,用 start.spring.io 生成骨架,或者手写 pom.xml。关键是引入 Spring AI 的 MCP Server Starter。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>my-mcp-server</artifactId> <version>1.0.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.0</version> <relativePath/> </parent> <properties> <java.version>21</java.version> <spring-ai.version>1.0.0-M6</spring-ai.version> </properties> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId> <version>${spring-ai.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>${spring-ai.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

版本号这块要注意,Spring AI 的 MCP Starter 在里程碑阶段版本迭代快,0.8.x 和 1.0.0-M6 的包名、注解位置有差异。如果你用 0.8.1,注解是org.springframework.ai.tool.annotation.Tool;用 1.0.0-M6 也基本一致,但 BOM 管理更规范。我建议用 BOM 统一版本,避免子依赖打架。

接下来定义工具类。MCP 的核心就是「工具」,一个带@Tool注解的 public 方法就是一个可被 AI 调用的工具,参数用@ToolParam描述,描述写得越清楚,模型调用时越不容易传错参数。

package com.example.mcp; import org.springframework.ai.tool.annotation.Tool; import org.springframework.ai.tool.annotation.ToolParam; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @Component public class MyTools { @Tool(description = "获取当前系统时间,返回格式 yyyy-MM-dd HH:mm:ss") public String getCurrentTime() { return LocalDateTime.now() .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } @Tool(description = "计算两个整数的和") public int add( @ToolParam(description = "第一个整数") int a, @ToolParam(description = "第二个整数") int b) { return a + b; } }

然后注册到 MCP。Spring AI 用ToolCallbackProvider把工具对象暴露出去:

package com.example.mcp; import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.ai.tool.method.MethodToolCallbackProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class McpConfig { @Bean public ToolCallbackProvider myToolCallbackProvider(MyTools myTools) { return MethodToolCallbackProvider.builder() .toolObjects(myTools) .build(); } }

主启动类就是标准的 Spring Boot 入口:

package com.example.mcp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class McpServerApplication { public static void main(String[] args) { SpringApplication.run(McpServerApplication.class, args); } }

配置文件application.properties里声明 MCP 服务元信息:

spring.application.name=my-mcp-server spring.ai.mcp.server.name=my-tools spring.ai.mcp.server.version=1.0.0 spring.ai.mcp.server.type=SYNC

如果你想让 MCP 服务同时能调 TaoToken 的模型做增强,可以再加一段模型配置。这里用环境变量占位,别硬编码:

spring.ai.openai.base-url=${TAOTOKEN_BASE_URL} spring.ai.openai.api-key=${TAOTOKEN_API_KEY} spring.ai.openai.chat.options.model=claude-3-5-sonnet

注意spring.ai.openai.base-url填 https://taotoken.net/api ,TaoToken 兼容 OpenAI 风格的接口路径,所以用 openai starter 就能对接。模型 ID 按控制台实际可用的填,别照抄我这个示例名。

4. 启动验证与接口连通性检查

配置写完,先本地跑起来看日志。用 Maven 直接启动:

mvn spring-boot:run

默认情况下 MCP Server 以 stdio(标准输入输出)模式运行,适合被 Claude Desktop、Cursor 这类客户端以子进程方式拉起。启动成功的标志是日志里出现 MCP server 初始化信息,并且没有端口占用报错。如果你同时引入了 web starter,它会额外起一个 HTTP 端口,这不冲突,但要注意 stdio 模式下别往 stdout 打无关日志,否则会污染协议帧。

打包成可执行 JAR:

mvn clean package -DskipTests # 产物:target/my-mcp-server-1.0.0.jar

验证 JAR 能独立跑:

java -jar target/my-mcp-server-1.0.0.jar

接下来做接口连通性检查。分两层:第一层是 MCP 协议层,第二层是 TaoToken 模型通道层。

MCP 协议层,最直接的办法是把它接到一个 MCP 客户端里。以 Claude Desktop 为例,配置文件在 macOS 是~/Library/Application Support/Claude/claude_desktop_config.json,Windows 是%APPDATA%\Claude\claude_desktop_config.json。写入:

{ "mcpServers": { "my-java-mcp": { "command": "java", "args": ["-jar", "/absolute/path/to/my-mcp-server-1.0.0.jar"] } } }

保存后重启客户端,在对话里输入「帮我获取一下当前时间」,如果工具被正确发现,客户端会提示调用getCurrentTime,返回类似2025-01-15 14:30:22。再试「计算 12 加 30」,应该返回 42。这两个动作跑通,说明 MCP 服务端没问题。

TaoToken 通道层,用 curl 直接打模型接口,确认 Key 和 Base URL 正确:

curl -s https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-3-5-sonnet", "messages": [{"role": "user", "content": "只回复两个字:通了"}] }'

返回体里choices[0].message.content有内容,就说明通道 OK。这一步很关键,因为很多人把 MCP 报错和模型报错混在一起排查,分开验证能省一半时间。如果你在 Spring 服务里也配了模型调用,可以写个简单的 CommandLineRunner 在启动时打一条测试请求,日志里能看到响应就放心了。

5. 本篇常见错误排查

这一节按真实报错来,都是我或身边人踩过的。

401 Unauthorized。出现在 curl 或 Spring 调模型时。原因基本是 Key 没读到或格式不对。检查TAOTOKEN_API_KEY是否真的导出到了当前 shell,echo $TAOTOKEN_API_KEY看一眼。Spring 里如果用了${TAOTOKEN_API_KEY}但环境变量没设,启动会直接失败或传空串。另外注意 Header 是Authorization: Bearer sk-xxx,Bearer 后面有空格,别漏。

local proxy failed / connection refused。这个报错通常出现在客户端拉起 MCP 子进程时,command或args路径写错,或者 java 不在 PATH 里。解决办法是用绝对路径:"command": "/usr/bin/java",JAR 也用绝对路径。Windows 上路径反斜杠要转义成\\,或者直接用正斜杠。

reading 'choices' of undefined。这是解析模型响应时拿不到choices字段。常见原因是 Base URL 写成了https://taotoken.net/api/v1又在代码里拼了/v1,导致路径变成/v1/v1/chat/completions。记住 Base URL 只到 https://taotoken.net/api ,版本段由 SDK 自己拼。另一个原因是模型 ID 写错,接口返回了错误对象而不是正常响应。

OAuth / token expired。如果你用的是需要 OAuth 的客户端(比如某些 IDE 插件),报这个说明授权过期,重新走一遍授权流程即可。注意这跟 TaoToken 的 API Key 是两套东西,别混。

MCP 工具没被发现。客户端里看不到你的工具,先确认ToolCallbackProviderBean 被扫描到了,包路径要在@SpringBootApplication同级或子级。再确认@Tool方法所在类有@Component。还有一个隐蔽点:stdio 模式下,任何System.out.println都会破坏协议,把日志级别调高或改用 stderr。

CC Switch / Cline MCP / Codex auth.json 三件套。如果你用这些工具接 MCP,配置里必须同时给全三样:Base URL、Key、Model ID。少一样就连不上。以 Cline 的 MCP 配置为例,结构大致是:

{ "mcpServers": { "my-java-mcp": { "command": "java", "args": ["-jar", "/abs/path/my-mcp-server-1.0.0.jar"], "env": { "TAOTOKEN_BASE_URL": "https://taotoken.net/api", "TAOTOKEN_API_KEY": "sk-你的key", "TAOTOKEN_MODEL": "claude-3-5-sonnet" } } } }

Codex 的auth.json同理,Base URL 和 Key 要对上,Model ID 不能空。这三件套缺一个,表现就是工具列表空或者调用超时。

6. 把 MCP 服务接到 TaoToken 统一通道

工具跑通之后,最后一步是让它和 TaoToken 的通道协同工作。有两种典型用法。

第一种,MCP 只做工具,模型调用交给客户端。你在 Claude Desktop 或 Cline 里配置 TaoToken 作为模型提供方,Base URL 填 https://taotoken.net/api ,Key 填你的,Model ID 选好。这样客户端用 TaoToken 的模型来「思考」,用你的 Java MCP 服务来「执行」,职责清晰。这种模式下你的 Spring 服务不需要配模型,最省事。

第二种,MCP 服务内部也调模型做增强。比如你的工具需要先让模型总结一段文本再返回。这时在 Spring 里配好spring.ai.openai.base-url和api-key,注入ChatClient调用即可。好处是工具内部逻辑闭环,坏处是模型调用和工具调用耦合,排查问题时要多看一层日志。

不管哪种,Key 的管理都建议走环境变量或配置中心,别写死在代码里。TaoToken 的统一 Key 通道优势就在这里:一个 Key 覆盖多个模型,你换模型只改 Model ID,不用换地址和密钥,MCP 服务端配置几乎不用动。

如果你要长期跑编码类 Agent,或者需要多模型切换做对比,可以看看 Coding Plan,路径是 https://taotoken.net/coding-plan 。接入文档在 https://taotoken.net/doc ,API Key 管理在 https://taotoken.net/api-keys 。模型对话调试入口是 https://taotoken.net/chat ,适合快速验证某个模型 ID 是否可用。

最后给个实操建议:把 MCP 服务的工具描述写细。@Tool(description=...)和@ToolParam(description=...)不是给人看的,是给模型看的。描述里写清楚单位、格式、边界条件,模型调用准确率会明显提升。我试过把「计算两个整数的和」改成「计算两个 32 位有符号整数的和,返回 int」,参数传错的概率下降很多。工具描述就是你和模型之间的接口文档,值得多花五分钟。

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

上市公司现金流分析:从docx数据提取到指标计算与财务排雷

简介&#xff1a;一份面向上市公司财务与金融实证研究的现金流指标数据集说明文档&#xff0c;资源标签为大数据&#xff0c;覆盖1991年至2024年6月沪深北A股季度数据&#xff0c;基于年报及公告整理&#xff0c;包含净利润现金净含量、营业收入现金含量、营业利润现金净含量、…

作者头像 李华
网站建设 2026/10/10 20:21:01

字符串第一个不重复字符:计数表与两遍遍历解法详解

1. 问题拆解&#xff1a;先搞清楚"第一个不重复"在问什么这道题的题目描述通常是这样的&#xff1a;给你一个字符串 s&#xff0c;找到并返回它的第一个不重复字符的下标&#xff1b;如果不存在&#xff0c;则返回 -1。举例来说&#xff0c;s "leetcode"&…

作者头像 李华
网站建设 2026/10/10 20:19:47

3D视觉模组成本真相:光源与光学元件为何最贵,选型如何避坑

去年做一款散斑结构光模组&#xff0c;BOM成本压到最低时我被一个数字震到了&#xff1a;传感器加上主控&#xff0c;加起来竟然比不过“光源光学元件”那一栏。我反复核了三遍物料清单&#xff0c;确认没看错——一颗VCSEL阵列、一片DOE、一枚窄带滤光片&#xff0c;还没算里面…

作者头像 李华
网站建设 2026/10/10 20:18:12

UWB超宽带精准测距,如何重构智能汽车数字钥匙体验

1. 先把“钥匙”这件事聊透&#xff1a;UWB到底解决了什么这几年只要聊到智能汽车里的无线技术&#xff0c;绕不开的一个词就是UWB。从苹果的AirTag到各大车厂的数字钥匙&#xff0c;再到今年第二十届智能汽车竞赛里不少队伍拿UWB做测距定位方案&#xff0c;UWB几乎成了“精准无…

作者头像 李华
网站建设 2026/10/10 20:12:39

传奇模拟游戏源码拆包:C++服务端与客户端编译连接实战

简介&#xff1a;这份资源是一套完整的传奇模拟游戏源码&#xff0c;包含客户端与服务器端两部分&#xff0c;面向具备一定C基础、希望深入理解游戏服务器开发与网络通信的开发者。客户端负责界面展示、角色控制与场景渲染&#xff0c;服务器端承担玩家状态同步、游戏规则执行与…

作者头像 李华
网站建设 2026/10/10 20:11:39

从掩码到YOLO:钢材缺陷检测数据集格式转换与训练实战

简介&#xff1a;这是一份用于钢材表面缺陷检测的YOLO数据集&#xff0c;面向计算机视觉学习者、工业质检项目开发者及课程实践者&#xff0c;可支撑目标检测入门练习、模型训练与课程设计。压缩包内共2000个文件&#xff0c;以1986个xml标签为主&#xff0c;同时提供json、txt…

作者头像 李华