尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用一段代码教会你理解什么是MCP,怎么写MCP:TaoToken 统一 Key 接入 Spring Boot SSE 与 stdio 双通道

用一段代码教会你理解什么是MCP,怎么写MCP:TaoToken 统一 Key 接入 Spring Boot SSE 与 stdio 双通道 1. 从一个真实需求说起为什么你的 Spring Boot 项目需要一个 MCP 服务很多人第一次听到 MCP 会以为它是个新框架其实它更像一份“约定”让大模型知道你的后端有哪些能力可以调用。你可以把它理解成给 AI 装了一个 USB 接口插上什么工具模型就能用什么工具。MCPModel Context Protocol模型上下文协议要解决的核心问题就是——模型怎么稳定、可描述地调用你写的业务方法而不是靠提示词硬猜。在 Spring Boot 里落地 MCP绕不开两种传输方式stdio 和 SSE。stdio 是本地进程之间通过标准输入输出对话像两个人面对面聊天不需要网络SSE 是客户端通过 HTTP 连到远程服务端服务端可以主动推送消息像一条电话热线。前者适合本地脚本、命令行工具、IDE 插件后者适合部署在服务器上、被多个客户端共享调用的场景。我这次要交付的是一段能跑起来的 Spring Boot 代码同时把 SSE 和 stdio 两条通道都讲清楚。服务端用Tool注解注册工具方法客户端通过 HTTP 或本地进程调用中间用 TaoToken 的统一 Key 完成鉴权接入。你跟着做能拿到三个结果一个可复制的 Maven 依赖配置、一个能返回天气数据的 MCP 服务端、一个用 curl 验证 SSE 握手成功的检查动作。适合谁看如果你写过 Spring Boot 接口但对 MCP 还停留在“听说过”的阶段或者你已经能跑通单机 demo但不知道怎么把 Key 和模型通道统一管理这篇就是给你准备的。下面所有代码都可以直接复制路径和参数我会写全。2. TaoToken 前置准备统一 Key 与 API 通道怎么接在写 MCP 服务端之前先把鉴权通道理清楚。MCP 服务端本身负责“暴露工具”但工具背后要调用大模型能力时就需要一个稳定的 API 入口。TaoToken 在这里扮演的角色是统一 Key 和 API 通道你不需要在代码里散落多个厂商的 Key而是通过一个 Base URL 加一个 Key 完成接入。先拿到你的 Key。打开 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite创建一个新 Key复制下来。这个 Key 后面会同时用在 MCP 服务端的模型调用配置和客户端请求头里。Base URL 用https://taotoken.net/api注意这个地址不带任何查询参数直接作为 API 根路径。模型 ID 按你实际使用的填写比如claude-sonnet-4-20250514这类标识。三件套凑齐后Spring Boot 的配置文件里就能统一管理。我建议在application.yml里这样写spring: ai: mcp: server: name: weather-mcp-server version: 1.0.0 type: SYNC sse-endpoint: /sse sse-message-endpoint: /mcp/message taotoken: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} model-id: claude-sonnet-4-20250514这里TAOTOKEN_API_KEY建议用环境变量注入不要硬编码进仓库。如果你在本地调试可以在 IDE 的 Run Configuration 里加环境变量或者用.env文件配合启动参数。为什么要把 Key 放在服务端而不是客户端因为 MCP 的 stdio 模式下客户端是本地进程Key 暴露在本地问题不大但 SSE 模式下服务端可能被多个客户端访问Key 必须留在服务端做统一出口。TaoToken 的 API 通道正好承担这个出口角色客户端只需要连你的 SSE 端点不需要知道底层模型 Key。如果你后面要做长期编码或 Agent 类任务可以了解下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite它更适合持续性的模型调用场景。但本篇聚焦 MCP 双通道先把基础跑通。3. 可复制配置Spring Boot 依赖、Tool 注册与双通道参数这一节是全文的核心所有代码都可以直接复制。先看 Maven 依赖。Spring 官方提供了三种 MCP Server 依赖只支持 stdio 的、支持 MVC 的 SSEstdio、支持 WebFlux 的 SSEstdio。我们选第二种因为 MVC 更贴近大多数 Spring Boot 项目的技术栈。dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId version1.0.0/version /dependency如果你用的是 Gradle对应写法是implementation org.springframework.ai:spring-ai-starter-mcp-server-webmvc:1.0.0。版本号以你实际拉到的为准1.0.0 是当时可用的版本。接下来写工具服务类。在service包下创建WeatherServicepackage com.example.mcptest.service; import org.springframework.ai.tool.annotation.Tool; import org.springframework.stereotype.Service; Service(weatherService) public class WeatherService { Tool(description 根据城市的名称获取天气) public String getWeather(String city) { if (city null || city.isBlank()) { return 请提供城市名称; } return city 今天晴天气温 22 摄氏度; } }Tool注解的作用是告诉 MCP 框架这个方法是一个可被模型调用的工具description 会作为工具描述暴露给客户端。参数city会被自动映射成工具的输入参数。返回值就是工具执行结果。然后在启动类里注册这个 Beanpackage com.example.mcptest; import com.example.mcptest.service.WeatherService; import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.ai.tool.method.MethodToolCallbackProvider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; SpringBootApplication public class McpTestApplication { public static void main(String[] args) { SpringApplication.run(McpTestApplication.class, args); } Bean public ToolCallbackProvider toolCallbackProvider(WeatherService weatherService) { return MethodToolCallbackProvider.builder() .toolObjects(weatherService) .build(); } }到这里服务端就具备了同时暴露 SSE 和 stdio 的能力。SSE 端点由sse-endpoint: /sse和sse-message-endpoint: /mcp/message控制stdio 模式则在启动时通过命令行参数切换。如果你要用 stdio 模式启动打包后这样运行java -jar target/mcp-test-0.0.1-SNAPSHOT.jar \ --spring.ai.mcp.server.stdiotrue注意 stdio 模式下不要同时开 Web 端口否则标准输出会被日志污染客户端解析会失败。我踩过的坑就是日志打到了 stdout导致 stdio 握手一直超时后来把日志级别调到 WARN 并输出到文件才解决。SSE 模式则正常启动即可java -jar target/mcp-test-0.0.1-SNAPSHOT.jar启动后默认监听 8080SSE 端点是http://localhost:8080/sse。4. 验证请求curl 检查 SSE 握手与 stdio 启动结果配置写完了怎么确认真的通了分两条通道验证。先验证 SSE。打开终端执行curl -N -H Accept: text/event-stream \ http://localhost:8080/sse-N表示禁用缓冲这样你能实时看到服务端推送。正常情况你会看到类似这样的输出event: endpoint data: /mcp/message?sessionId8f3a2b1c-...这说明 SSE 握手成功服务端告诉你后续消息要发到哪个 endpoint。拿到sessionId后你可以用另一个终端发一条 JSON-RPC 请求curl -X POST http://localhost:8080/mcp/message?sessionId8f3a2b1c-... \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 1, method: tools/list, params: {} }如果返回里包含getWeather这个工具名和它的 description说明工具注册成功。这一步是很多人卡住的地方他们只看到 SSE 连上了但没验证工具列表结果客户端调用时报“tool not found”。再验证 stdio。用 stdio 模式启动后直接在终端输入一行 JSON-RPCecho {jsonrpc:2.0,id:1,method:tools/list,params:{}} | \ java -jar target/mcp-test-0.0.1-SNAPSHOT.jar --spring.ai.mcp.server.stdiotrue如果标准输出里返回了工具列表 JSON说明 stdio 通道正常。注意 stdio 模式下所有日志必须走 stderr否则会混进协议消息里。验证模型调用通道时可以用模型对话页面https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite快速测一下 Key 是否有效。把 Base URL 填https://taotoken.net/apiKey 填你创建的那串模型 ID 填你配置的那个发一条消息看是否正常返回。这一步能排除 Key 本身的问题避免后面把鉴权错误误判成 MCP 配置错误。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth实际跑的时候报错基本集中在这几类。我按真实遇到的顺序列出来你对照着查。401 Unauthorized最常见。先确认TAOTOKEN_API_KEY环境变量真的注入了可以在启动日志里打印一下 Key 的前四位和后四位做校验。如果 Key 没问题检查请求头是不是Authorization: Bearer key格式。SSE 客户端如果自己拼请求头容易漏掉 Bearer 前缀。local proxy failed这个报错通常出现在客户端配置了本地代理但代理没启动或端口不对。MCP 客户端连 SSE 端点时如果系统代理设置指向了一个不存在的本地端口就会报这个。解决办法是在客户端配置里显式设置no_proxy包含localhost或者直接关掉系统代理再试。reading choices 相关报错这类错误一般出现在模型返回体解析阶段说明请求发出去了但返回结构不符合预期。检查你的模型 ID 是否写对以及 Base URL 是不是https://taotoken.net/api而不是带/v1或其他后缀。有些客户端会自动拼/v1/chat/completions如果 Base URL 已经带了路径就会重复。OAuth 相关报错如果你用的是 Claude Code 或类似工具可能会遇到 OAuth 流程失败。这类工具通常需要先完成授权再调用。如果你只是想快速验证 MCP 通道建议先用 curl 或模型对话页面确认 Key 可用再回到工具里配置。Claude Code 的接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里面有完整的 Base URL、Key、Model ID 三件套配置说明。还有一个隐蔽的坑SSE 连接建立后如果客户端超过一定时间没发心跳服务端可能主动断开。Spring 的 SSE 默认超时时间可以通过spring.mvc.async.request-timeout调整。我在测试时把超时设成了 300000 毫秒避免调试过程中连接被掐断。对照这些报错逐个排查基本能覆盖 90% 的启动失败场景。如果还是不通回到第 4 节的 curl 验证先确认服务端本身没问题再查客户端配置。6. 把 Key 和通道固定下来后面的事就顺了跑通之后你会发现MCP 的难点不在代码本身而在通道和鉴权的统一管理。stdio 适合本地开发SSE 适合远程共享两者共用同一套 Tool 注册逻辑切换只需要改启动参数。TaoToken 的统一 Key 让服务端不用为每个模型厂商维护一套凭证客户端也不用关心底层用的是哪个模型。如果你后面要接更多工具比如数据库查询、文件操作、内部 API 调用只需要在WeatherService旁边再加一个 Service 类用Tool标注方法然后在ToolCallbackProvider里把新 Bean 加进去。工具描述写得越清楚模型调用越准。最后留一个实用技巧在application.yml里把spring.ai.mcp.server.name和version写清楚客户端连接时能看到服务标识多服务环境下不容易连错。这个字段很多人会忽略但在同时跑多个 MCP 服务时特别有用。
返回列表