使用 Spring AI 创建 MCP 服务器:TaoToken 统一 Key 接入与配置骨架

发布时间:2026/9/27 16:57:46
使用 Spring AI 创建 MCP 服务器:TaoToken 统一 Key 接入与配置骨架 1. 为什么要在 Spring Boot 里手搓一个 MCP 服务器如果你最近在折腾 AI 编码助手大概率听过 MCPModel Context Protocol这个词。简单说它是一套让大模型能调用外部工具的标准化协议模型本身不知道你公司内部的订单表结构也不知道你本地那台测试机的部署脚本长什么样但只要把这些能力包装成 MCP 工具模型就能在对话里主动调用它们。Spring AI 从 1.0 开始提供了spring-ai-starter-mcp-server让你用几个注解就能把普通的 Spring Bean 变成模型可调用的工具。这篇要解决的问题很具体在 Spring Boot 项目里用 Spring AI 搭一个能跑起来的 MCP 服务器同时把模型调用的出口统一收敛到 TaoToken 的 Key/API 通道上避免每个工具、每个客户端各配一套密钥。适合谁有 Java/Spring Boot 基础、想让本地 AI 助手接入自己业务数据的后端同学。我会给出settings.json和config.toml两份配置骨架再演示启动后怎么验证 MCP 服务真的可用而不是看起来启动了其实工具没注册上。MCP 服务器本身不负责推理它只暴露工具真正干活的是背后的模型。所以统一 Key这件事的意义在于你的 MCP 客户端比如编码插件、Agent 框架在调用模型时走的是同一个 TaoToken 通道换模型、换额度、看用量都在一处不用在五六个配置文件里改 base_url。2. TaoToken 前置把 Key 和通道先备好在写代码之前先把模型侧的通道准备好否则后面验证工具调用时会卡在模型请求发不出去。第一步打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册账号。注册流程很常规邮箱加密码即可这里不展开。第二步进控制台创建 API Key。地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在 API Keys 页面点新建复制出来的 Key 形如sk-xxxxxxxx只显示一次先存到密码管理器里。API Keys 管理页直达https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。第三步确认 API 基地址。TaoToken 的 API 入口是 https://taotoken.net/api 注意这个地址不带任何查询参数配置里直接写它就行。它兼容 OpenAI 风格的/v1/chat/completions所以 Spring AI 的 OpenAI starter 和大多数 MCP 客户端都能直接对接。注意Key 属于敏感凭据不要提交到 Git 仓库。本地开发建议用环境变量TAOTOKEN_API_KEY注入配置文件里写占位符。如果你只是想先验证模型能不能通可以打开模型对话页 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 发一句话试试确认 Key 有效再往下走。长期跑编码类 Agent 的话Coding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 有更划算的额度方案这个后面按需看。3. 可复制配置settings.json 与 config.toml 骨架MCP 生态里有两类配置文件最常见一类是客户端侧的settings.json很多编码插件、桌面客户端用它声明要连哪些 MCP 服务器另一类是config.toml部分 Agent 框架和 CLI 工具用它。下面两份骨架你可以直接抄改路径和 Key 即可。3.1 settings.json声明 MCP 服务器与模型通道{ mcpServers: { my-spring-mcp: { command: /usr/lib/jvm/java-21-openjdk/bin/java, args: [ -jar, /home/dev/mymcpserver/target/mymcpserver-0.0.1-SNAPSHOT.jar ], env: { SPRING_AI_MCP_SERVER_NAME: my-spring-mcp, SPRING_AI_MCP_SERVER_VERSION: 0.0.1 } } }, model: { provider: openai-compatible, baseUrl: https://taotoken.net/api, apiKey: ${TAOTOKEN_API_KEY}, model: gpt-4o-mini } }几个关键点。command必须是 java 可执行文件的绝对路径用which java查一下别写java两个字很多客户端不解析 PATH。args里的 jar 路径同理用绝对路径。env块把服务器名和版本透传给 Spring 应用这样application.properties里可以不写死。model块就是统一 Key 的落点baseUrl指向 TaoToken 的 API 入口apiKey用环境变量引用避免明文。3.2 config.tomlAgent 框架侧的等价配置[mcp_servers.my_spring_mcp] command /usr/lib/jvm/java-21-openjdk/bin/java args [-jar, /home/dev/mymcpserver/target/mymcpserver-0.0.1-SNAPSHOT.jar] startup_timeout_sec 20 tool_timeout_sec 60 [mcp_servers.my_spring_mcp.env] SPRING_AI_MCP_SERVER_NAME my-spring-mcp SPRING_AI_MCP_SERVER_VERSION 0.0.1 [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chatstartup_timeout_sec给 20 秒比较稳Spring Boot 冷启动加 JVM 初始化有时会超过默认的 10 秒超时了客户端会以为服务器挂了。wire_api chat表示走 chat completions 协议兼容性最好。3.3 Spring Boot 侧 application.propertiesspring.main.web-application-typenone spring.ai.mcp.server.name${SPRING_AI_MCP_SERVER_NAME:my-spring-mcp} spring.ai.mcp.server.version${SPRING_AI_MCP_SERVER_VERSION:0.0.1} spring.main.banner-modeoff logging.pattern.consoleweb-application-typenone是因为 STDIO 传输不需要 Web 容器起了反而占端口。logging.pattern.console置空很关键STDIO 模式下 stdout 是协议通道任何一行日志混进去都会让客户端解析失败这是新手最容易踩的坑。3.4 pom.xml 依赖dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server/artifactId /dependencySpring AI 的版本用 BOM 管理在dependencyManagement里引spring-ai-bom即可别单独写版本号容易和 starter 对不上。4. 工具类与启动验证确认 MCP 服务真的可用配置写完了得让工具真正注册进去并且验证客户端能发现它们。4.1 定义两个工具Service public class ArtistService { private final ListArtist artists new ArrayList(); Tool(name get_artists, description 获取我喜爱的艺术家完整列表) public ListArtist getArtists() { return artists; } Tool(name search_artist, description 按名称搜索单个艺术家) public Artist searchArtist(String name) { return artists.stream() .filter(a - a.name().equalsIgnoreCase(name)) .findFirst() .orElse(null); } PostConstruct public void init() { artists.addAll(List.of( new Artist(Bruce Springsteen), new Artist(JJ Johnson) )); } }Tool的description是给模型看的写清楚这个工具干什么、参数是什么模型靠它决定调不调。searchArtist的参数name会被自动映射成 JSON Schema 里的 required 字段。4.2 注册工具回调SpringBootApplication public class MyMcpServerApplication { public static void main(String[] args) { SpringApplication.run(MyMcpServerApplication.class, args); } Bean public ToolCallbackProvider mcpTools(ArtistService artistService, SongService songService) { return MethodToolCallbackProvider.builder() .toolObjects(artistService, songService) .build(); } }漏了这个 Bean工具类上的Tool不会被扫描客户端连上后会显示找到 0 个工具。4.3 构建并启动mvn clean verify java -jar target/mymcpserver-0.0.1-SNAPSHOT.jar启动后进程会挂起等待 STDIO 输入这是正常的别以为卡死了。4.4 验证工具被发现在客户端的 MCP 设置里点测试连接并获取工具成功时按钮文案会变成类似连接成功找到 4 个工具。如果显示 0 个回到 4.2 检查 Bean 是否注册。这一步过了再发一句给我一个我喜爱的艺术家列表模型应该会请求调用get_artists客户端弹出人工确认批准后返回结果。整个链路通了说明 MCP 服务器 TaoToken 通道都正常。5. 本篇常见错排查报错一客户端连上但工具数为 0。九成是ToolCallbackProviderBean 没注册或者Tool注解加在了 private 方法上。检查方法可见性必须是 public。报错二客户端报 Failed to parse server response。大概率是 stdout 混入了日志。确认logging.pattern.console为空并且没有其他库往 System.out 打印。Spring Boot 的 banner 也要关掉。报错三启动超时。把客户端的startup_timeout_sec调到 20 以上或者给 JVM 加-Xshare:auto加速启动。首次运行还要下载依赖慢是正常的。报错四模型请求 401。检查TAOTOKEN_API_KEY环境变量是否在当前 shell 生效echo $TAOTOKEN_API_KEY看一眼。另外确认baseUrl写的是https://taotoken.net/api末尾不要多加/v1starter 会自己拼。报错五工具调用返回 null 但模型说没找到。这是业务逻辑问题不是协议问题。比如searchArtist大小写不敏感匹配失败或者数据没在PostConstruct里初始化。加一行日志确认artists列表非空。6. 接下来怎么走工具跑通之后下一步通常是把它接到真实数据源上比如把ArtistService里的内存列表换成 JPA 查询。这时候要注意MCP 工具直接连生产库是危险操作建议加一层只读视图或者人工确认。如果你要长期跑编码类 Agent把模型通道固定到 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 会比按量付费省心。接入过程中遇到协议层报错先翻接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 大部分 base_url 和鉴权问题那里都有说明。想快速验证某个模型对工具调用的支持程度直接用模型对话 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 发一条带工具的请求最直观。