
1. Java8 项目接入 MCP 的真实困境如果你手上还有一堆跑在 JDK8 上的老服务最近想给它们加个 MCP Server 能力大概率会先被依赖卡住。我拿几个主流方案实测过mcp-sdk要求 JDK17spring-ai-mcp-server要求 JDK17langchain4j-mcp-client同样要求 JDK17。也就是说只要你的编译级别还锁在 1.8这些包连引入都过不了。但现实是很多公司的生产环境就是 JDK8升级 JDK 不是改个pom.xml那么简单涉及中间件兼容、GC 参数、监控探针、甚至某些老版本框架的字节码增强。MCP 本身是一个协议层的框架它描述的是「模型怎么发现工具、怎么调用工具」跟 JDK 版本没有本质绑定关系。所以「Java8 能不能开发 MCP Server」这个问题答案应该是能前提是选对库。Solon AI MCP 就是这么一个选择。它把 MCP Server 和 MCP Client 都做进了同一个依赖里同时支持 Java8、Java11、Java17、Java21。你可以把它理解成别人家的 MCP 实现是「新房子只卖精装大平层」Solon AI MCP 是「老小区也能装水电煤都通」。它既能跟 Solon 框架集成也能嵌到 SpringBoot2、jFinal、Vert.x 里用这对存量 Java8 项目非常友好。这篇就按「能跑起来」的标准把依赖配置、Server 骨架、TaoToken 统一 Key 接入、启动验证、报错排查走一遍。目标很明确你在 JDK8 环境里复制粘贴能拿到一个可被 MCP Client 调用的工具服务。2. TaoToken 前置统一 Key 与 API 通道在写 Server 之前先把模型侧的通道准备好。MCP Server 本身只负责暴露工具真正要跟模型对话、做 Function Call 的时候还是需要一个 LLM 的 API 入口。TaoToken 在这里的作用是提供一个统一的 Key 和 API 地址省得你在代码里到处散落不同厂商的 endpoint。你需要先拿到一个 API Key。打开控制台在 API Keys 页面创建一个https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite创建完之后你的调用地址统一走https://taotoken.net/api注意这个 API 地址后面不加任何 UTM 参数直接作为 base URL 用。Key 的格式一般是一串sk-开头的字符串复制下来先存到环境变量里别硬编码进代码export TAOTOKEN_API_KEYsk-你的key如果你后面要用 Claude Code 或者做长期编码 Agent可以看下 Coding Plan 的额度方案https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite模型对话的在线调试入口在这里验证 Key 是否可用最方便https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite这一步的核心是Key 只创建一次base URL 只写一次后面所有 MCP 相关的模型调用都复用这套配置。这样你在 settings.json 里配一次Server 和 Client 都能用。3. 可复制配置Solon AI MCP 依赖与 Server 骨架3.1 Maven 依赖JDK8 项目直接用下面这个依赖版本号建议用当前最新稳定版写这篇文章时solon-ai-mcp已经能覆盖 Server 和 Client 两端dependency groupIdorg.noear/groupId artifactIdsolon-ai-mcp/artifactId version3.0.0/version /dependency如果你项目里还没引入 Solon 核心需要补一个dependency groupIdorg.noear/groupId artifactIdsolon.boot.jdkhttp/artifactId version3.0.0/version /dependencysolon.boot.jdkhttp是基于 JDK 自带 HttpServer 的启动器不依赖 Netty对 JDK8 环境最省事。编译级别保持 1.8 即可不需要改maven.compiler.source。3.2 组件方式写 MCP ServerSolon AI MCP 的组件写法和 MVC 很像一个类加注解就是一个端点。下面这个例子暴露一个查询天气的工具import org.noear.solon.ai.mcp.server.annotation.McpServerEndpoint; import org.noear.solon.ai.mcp.server.annotation.ToolMapping; import org.noear.solon.ai.mcp.server.annotation.ToolParam; McpServerEndpoint(name mcp-case1, sseEndpoint /case1/sse) public class McpServerTool { ToolMapping(description 查询天气预报) public String getWeather(ToolParam(description 城市位置) String location) { return location 晴14度; } }这里几个点要注意name是端点名称Client 连接时会用到sseEndpoint是 SSE 通道地址MCP 的传输层走的就是 SSEToolMapping标记的方法会被注册成工具description是给模型看的说明写得越清楚模型越容易选对工具ToolParam描述参数含义同样影响模型调用准确率。3.3 原生 Java 方式构建如果你不想用注解或者需要动态注册工具可以用 builder 方式import org.noear.solon.ai.mcp.server.McpServerEndpointProvider; import org.noear.solon.ai.mcp.server.tool.MethodToolProvider; McpServerEndpointProvider serverEndpoint McpServerEndpointProvider.builder() .name(mcp-case2) .sseEndpoint(/case2/sse) .build(); serverEndpoint.addTool(new MethodToolProvider(new McpServerTool())); serverEndpoint.postStart();postStart()是关键它负责把端点真正挂到 HTTP 服务上。如果你忘了调Client 连过来会 404。3.4 启动类import org.noear.solon.Solon; public class App { public static void main(String[] args) { Solon.start(App.class, args); } }默认端口 8080如果你想改在app.yml里写server: port: 8080启动后SSE 端点就是http://localhost:8080/case1/sse。4. 验证请求确认 MCP 服务真的可用4.1 用 curl 看 SSE 通道MCP 的 SSE 通道建立后服务端会先推一个endpoint事件告诉你后续消息往哪个地址发。用 curl 直接看curl -N http://localhost:8080/case1/sse预期返回类似event: endpoint data: /case1/message?sessionIdxxxxx看到这个endpoint事件说明 SSE 通道已经通了。-N参数是禁用缓冲不加的话你可能要等很久才看到输出。4.2 用 Solon AI MCP Client 调用工具最直接的验证方式是写个 Client 调一下import org.noear.solon.ai.mcp.client.McpClientToolProvider; import java.util.HashMap; import java.util.Map; McpClientToolProvider clientToolProvider McpClientToolProvider.builder() .apiUrl(http://localhost:8080/case1/sse) .build(); MapString, Object params new HashMap(); params.put(location, 杭州); String rst clientToolProvider.callToolAsText(getWeather, params); System.out.println(rst);预期输出杭州晴14度能拿到这个结果说明整条链路是通的Client 通过 SSE 连上 ServerServer 找到getWeather工具传入location参数返回结果。4.3 在 settings.json 里接入 TaoToken如果你用的是支持 MCP 的客户端比如 Claude Code 这类需要在 settings.json 里配置 MCP Server 和模型通道。配置片段如下{ mcpServers: { solon-weather: { url: http://localhost:8080/case1/sse } }, env: { TAOTOKEN_API_KEY: sk-你的key, TAOTOKEN_BASE_URL: https://taotoken.net/api } }这里mcpServers告诉客户端去哪找 MCP Serverenv里的两个变量给模型调用用。如果你的客户端支持在 MCP 配置里直接写模型参数把 base URL 填成https://taotoken.net/api即可Key 用刚才创建的那个。配置完重启客户端在对话里问「杭州天气怎么样」模型应该会触发getWeather工具调用返回「杭州晴14度」。5. 本篇常见错排查5.1 启动报 NoClassDefFoundError大概率是依赖没下全。Solon AI MCP 会间接依赖一些 HTTP 和 JSON 处理的包如果你用了provided作用域或者公司私服缺包就会在运行时炸。检查一下mvn dependency:tree确认solon-ai-mcp下面的传递依赖都在。5.2 SSE 连接后收不到 endpoint 事件先确认sseEndpoint的路径有没有写错注意大小写。然后看端口有没有被占用server.port配了没有。如果用的是solon.boot.jdkhttp它默认只监听 8080改端口要在app.yml里改不是改代码。5.3 Client 调用返回 tool not found工具名对不上。callToolAsText的第一个参数是工具名默认取方法名getWeather。如果你在ToolMapping里指定了name属性就要用指定的名字。另外确认 Client 连的 SSE 地址跟 Server 暴露的一致/case1/sse和/case2/sse是两个不同的端点。5.4 JDK8 下编译报 lambda 相关错误Solon AI MCP 本身兼容 JDK8但如果你项目里混用了 JDK17 编译的库就会在字节码版本上冲突。检查maven.compiler.source和target是不是都是 1.8以及有没有引入其他要求高版本 JDK 的依赖。5.5 TaoToken 调用返回 401Key 没传对。确认环境变量TAOTOKEN_API_KEY在启动进程里能读到别只在当前 shell export 了但 IDE 里没配。另外 base URL 要写https://taotoken.net/api不要多加路径后缀。6. 继续往下走跑通上面这套之后你可以做几件事。一是把getWeather换成你真实的业务工具比如查订单、查库存、发通知参数用ToolParam描述清楚。二是把多个工具注册到同一个端点模型会自动根据 description 选择。三是把 Server 部署到内网Client 通过内网地址连接Key 统一走 TaoToken 的 API 通道。如果你在接入过程中遇到 Key 或通道相关的问题可以直接看接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite需要新建或管理 Key去 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite想先在线验证模型能不能正常对话用模型对话入口https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite长期做编码 Agent 的话Coding Plan 的额度更划算https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteJava8 不是障碍选对库、配好通道、验证到位老项目一样能接上 MCP。