Java SolonMCP 实现 MCP 实践全解析:SSE 与 STDIO 通信模式配置与验证
1. 为什么 Java 开发者需要同时跑通 SSE 与 STDIOMCPModel Context Protocol你可以把它理解成一套“AI 与外部工具之间的专属 RPC 协议”。它规定了模型怎么发现工具、怎么传参、怎么拿结果让大模型不再只会聊天而是能真正调用你写的 Java 方法。SolonMCP 则是把这套协议封装成了注解式框架你写一个普通类、加几个注解它就能变成一个 MCP 服务器。问题在于MCP 有两种主流通信模式很多 Java 开发者第一次接入时会卡在“到底选哪个、怎么配、怎么验证”上。STDIO 模式走标准输入输出适合本地被客户端以子进程方式拉起比如桌面端 AI 工具直接java -jar启动你的服务SSE 模式走 HTTP 长连接适合部署在服务端多个客户端通过网络访问。两者不是替代关系而是场景互补。这篇内容面向需要在本地或服务端跑通 MCP 的 Java 开发者给出可复制的 SolonMCP 配置骨架、TaoToken 统一 Key/API 通道的 settings.json 与 config.toml 片段以及启动后验证 SSE 与 STDIO 连通性的具体动作。目标是一次性把两种模式都跑通并确认调用链路正常。我试过在同一份工程里同时保留两个 Endpoint 类切换时只改客户端配置效率最高。2. TaoToken 前置统一 Key 与 API 通道准备在写 SolonMCP 代码之前先把模型侧的通道准备好。TaoToken 提供统一的 API 入口你只需要一个 Key就能在 MCP 客户端里调用不同模型省去每个模型单独申请、单独配 base_url 的麻烦。官网入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 地址不带 UTMhttps://taotoken.net/api操作路径很直接进入控制台创建 API Key然后按客户端类型选择接入方式。如果你只是验证模型连通性用模型对话页面即可如果是长期编码或跑 Agent建议看 Coding Plan接入排障则对照 API Keys 和接入文档。模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewriteCoding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewriteAPI Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteClaudeCodeAnthropichttps://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_codeutm_campaignrewrite拿到 Key 后先记下来后面 settings.json 和 config.toml 都要用。注意 Key 只存在本地配置文件里不要提交到 Git。3. 可复制配置SolonMCP 工程骨架与两种模式3.1 Maven 依赖与工程结构先建一个标准 Maven 工程引入 SolonMCPdependency groupIdorg.noear/groupId artifactIdsolon-ai-mcp/artifactId version3.3.1-M1/version /dependencyGradle 写法implementation org.noear:solon-ai-mcp:3.3.1-M1工程结构建议这样分src/main/java/demo/mcp/ StdioCalculatorTools.java // STDIO 模式 SseWeatherTools.java // SSE 模式 App.java // 启动入口 src/main/resources/ app.yml两个 Endpoint 类分开写互不干扰。启动时 Solon 会扫描注解按 channel 类型分别注册。3.2 STDIO 模式配置骨架STDIO 模式的核心是McpServerEndpoint(channel McpChannel.STDIO)服务器等待标准输入请求通过标准输出返回响应。McpServerEndpoint(channel McpChannel.STDIO) public class StdioCalculatorTools { ToolMapping(description 将两个数字相加) public int add(Param int a, Param int b) { return a b; } ToolMapping(description 将两个数相乘) public int multiply(Param int a, Param int b) { return a * b; } }打包成胖包后运行mvn clean package java -jar target/demo-mcp.jar这种模式下任何支持 STDIO 的 MCP 客户端都可以把它当子进程拉起。客户端配置里写command: java、args: [-jar, demo-mcp.jar]即可。3.3 SSE 模式配置骨架SSE 模式指定sseEndpoint服务器以 HTTP 服务形式启动默认监听 8080McpServerEndpoint(sseEndpoint /mcp/sse) public class SseWeatherTools { ToolMapping(description 获取指定城市的当前天气) public String getWeather(Param String city) { return {city: city , temperature:[10,25], condition:[sunny,clear], unit:celsius}; } Produces(MimeType.APPLICATION_JSON_VALUE) ResourceMapping(uri weather://cities, description 获取所有可用城市列表) public ListString getAvailableCities() { return Arrays.asList(Tokyo, Sydney, Hangzhou); } }启动后浏览器访问http://localhost:8080/mcp/sse能看到事件流说明 SSE 通道已建立。3.4 TaoToken 客户端配置片段在 MCP 客户端里接入 TaoToken常见两种配置文件格式。settings.json适用于多数支持 JSON 配置的客户端{ mcpServers: { solon-stdio-calc: { command: java, args: [-jar, /path/to/demo-mcp.jar], env: { TAOTOKEN_API_KEY: sk-你的Key, TAOTOKEN_BASE_URL: https://taotoken.net/api } }, solon-sse-weather: { url: http://localhost:8080/mcp/sse, env: { TAOTOKEN_API_KEY: sk-你的Key, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } }config.toml适用于 TOML 风格客户端[mcp_servers.solon_stdio_calc] command java args [-jar, /path/to/demo-mcp.jar] [mcp_servers.solon_stdio_calc.env] TAOTOKEN_API_KEY sk-你的Key TAOTOKEN_BASE_URL https://taotoken.net/api [mcp_servers.solon_sse_weather] url http://localhost:8080/mcp/sse [mcp_servers.solon_sse_weather.env] TAOTOKEN_API_KEY sk-你的Key TAOTOKEN_BASE_URL https://taotoken.net/api注意STDIO 用commandargsSSE 用url这是两种模式在客户端配置上最本质的区别。Key 放在 env 里不要硬编码进 Java 代码。4. 验证请求确认两种模式调用链路正常4.1 验证 STDIO 连通性STDIO 模式没有 HTTP 端口验证方式是让客户端拉起进程后调用工具。最直接的办法是写一个最小客户端McpClientProvider clientProvider McpClientProvider.builder() .channel(McpChannel.STDIO) .command(java, -jar, /path/to/demo-mcp.jar) .build(); String result clientProvider.callToolAsText(add, Map.of(a, 3, b, 5)).getContent(); System.out.println(result); // 期望输出 8如果客户端返回8说明 STDIO 的输入输出链路通了。如果卡住无响应多半是 jar 路径不对或进程没起来。4.2 验证 SSE 连通性SSE 模式先用 curl 确认事件流curl -N http://localhost:8080/mcp/sse正常会持续输出event:和data:行。然后用 Java 客户端调用工具McpClientProvider clientProvider McpClientProvider.builder() .apiUrl(http://localhost:8080/mcp/sse) .build(); String weather clientProvider.callToolAsText(getWeather, Map.of(city, Hangzhou)).getContent(); String cities clientProvider.readResourceAsText(weather://cities).getContent(); System.out.println(weather); System.out.println(cities);期望输出包含杭州天气 JSON 和城市列表。两个都返回说明工具调用和资源读取两条链路都正常。4.3 用 TaoToken 模型对话做端到端确认工具本身通了还要确认模型能通过 TaoToken 调用到这些工具。在支持 MCP 的客户端里配置好上面的 settings.json然后发一句“帮我算一下 12 乘 7”观察模型是否触发multiply工具并返回 84。这一步是端到端验证能同时确认 TaoToken Key 有效、MCP 服务器注册成功、工具描述被模型正确理解。5. 本篇常见错排查5.1 STDIO 启动后无响应最常见原因是把日志打到了标准输出。STDIO 模式下标准输出是协议通道任何System.out.println调试语句都会污染协议帧导致客户端解析失败。排查方法把所有调试日志改到System.err或者用日志框架输出到文件。另一个原因是胖包没打全。java -jar报NoClassDefFoundError说明依赖没打进去检查 pom 里的 shade 或 assembly 插件配置。5.2 SSE 访问 404 或连接立即断开先确认sseEndpoint的值和访问路径一致。配的是/mcp/sse就要访问http://localhost:8080/mcp/sse少一段都不行。如果端口被占用Solon 启动时会报错改app.yml里的server.port即可。连接立即断开还有一种可能中间有反向代理提前关闭了长连接。本地验证阶段先直连不要套代理层。5.3 客户端配置了但工具列表为空检查settings.json或config.toml的 JSON/TOML 语法。JSON 不允许尾逗号TOML 的[mcp_servers.xxx.env]段名要写全。语法错误会导致客户端静默忽略整个配置。如果配置语法没问题看客户端日志里 MCP 服务器的握手信息。STDIO 模式握手失败通常是 jar 路径含空格没转义SSE 模式握手失败通常是 url 写成了/sse而不是/mcp/sse。5.4 TaoToken 调用返回鉴权错误确认 Key 没有多余空格TAOTOKEN_BASE_URL写的是https://taotoken.net/api而不是带 UTM 的官网地址。如果客户端支持先用模型对话页面单独测一下 Key 是否可用排除 Key 本身的问题。6. 接入排障与长期编码的分流建议如果你现在卡在接入阶段比如 STDIO 进程起不来、SSE 握手失败、Key 鉴权报错优先对照 API Keys 和接入文档逐项核对API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite如果你只是想先确认模型通道是否正常用模型对话页面发一条消息最快模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite如果你打算把 SolonMCP 长期用于编码助手或 Agent 场景建议直接看 Coding Plan它在长会话和工具调用频率上有更合适的配额Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite最后分享一个实用技巧把 STDIO 和 SSE 两个 Endpoint 放在同一个工程里用 Maven profile 控制打包时是否包含某个类。本地调试用 STDIO部署到服务器用 SSE客户端配置里两个 server 都留着切换时只改客户端启用哪个不用重新打包。这样一套代码能覆盖本地和服务端两种场景省去维护两个仓库的麻烦。