ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SpringAI 集成 MCP 实战:Stdio 与 SSE 双模式配置与验证

SpringAI 集成 MCP 实战:Stdio 与 SSE 双模式配置与验证 1. 为什么要在 SpringBoot 里同时接 Stdio 和 SSE 两种 MCP如果你正在用 SpringBoot 做 AI 应用大概率会遇到一个很现实的问题工具调用到底放在本地跑还是放到远端服务里跑。MCPModel Context Protocol解决的正是“让模型统一调用外部工具”这件事而 SpringAI 把它封装成了 starterJava 开发者不用手写 JSON-RPC 就能接进来。但真正落地时传输方式的选择会直接影响你的部署结构。Stdio 模式是把 MCP Server 当成一个子进程通过标准输入输出通信适合本地工具、单机脚本、需要访问本机文件的场景SSE 模式是把 MCP Server 部署成一个 Web 服务客户端通过 HTTP 长连接订阅事件适合多用户共享、需要统一鉴权、要横向扩展的场景。这篇内容面向需要在 Java 生态里快速打通 MCP 工具调用的开发者我会给出可复制的application.yml、MCP 客户端配置骨架并演示启动后怎么调用工具、怎么看连接日志确认真的连上了。两种模式我都会跑一遍包括我踩过的坑。核心检索词先明确SpringAI 集成 MCP就是通过 SpringBoot 引入 MCP 客户端 starter配置 Stdio 或 SSE 连接再用ToolCallbackProvider把外部工具绑定到ChatClient上让模型在对话中自动调用。2. 前置准备依赖、Key 与 TaoToken 接入点在写配置之前先把依赖和模型接入这两件事理清楚。MCP 只是“工具通道”模型本身还得有个能调用的入口。2.1 MCP 客户端依赖怎么选SpringAI 提供两个 MCP Client starter选错会导致 SSE 连不上依赖支持传输适用场景spring-ai-starter-mcp-client仅 Stdio只调本地子进程工具spring-ai-starter-mcp-client-webfluxStdio SSE需要远程 MCP 服务大多数项目直接上第二个省得后面加 SSE 时再改依赖dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-client-webflux/artifactId /dependency2.2 模型侧接入 TaoTokenMCP 工具最终要挂到ChatClient上而ChatClient背后是OpenAiChatModel。我用 TaoToken 作为模型接入点它的接口兼容 OpenAI 协议SpringAI 的 OpenAI starter 可以直接指过去。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。先去控制台建一个 Key后面配置里要用。spring: ai: openai: api-key: ${TAOTOKEN_API_KEY} base-url: https://taotoken.net/api chat: options: model: gpt-4o-mini注意base-url不要带多余的路径后缀SpringAI 会自己拼/v1/chat/completions写多了会 404。Key 的创建在控制台的 API Keys 页面地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。建完直接塞进环境变量别硬编码进 yml。3. Stdio 模式本地子进程工具的完整配置Stdio 的本质是客户端启动时用ProcessBuilder拉起一个子进程然后通过 stdin/stdout 收发 JSON-RPC 消息。理解这一点后面很多报错就顺了。3.1 客户端 application.ymlStdio 配置有两种写法一种是直接写在 yml 里另一种是单独放一个 Claude Desktop 格式的 JSON 文件。后者更推荐因为工具多了以后 yml 会非常乱。先看 JSON 文件放在src/main/resources/mcp/stdio-server-config.json{ mcpServers: { mcp-server-weather: { command: java, args: [ -Dspring.ai.mcp.server.stdiotrue, -Dlogging.pattern.console, -jar, /opt/app/mcp-server-weather.jar ] } } }然后在application.yml里指向它spring: ai: mcp: client: enabled: true name: spring-ai-mcp-client version: 1.0.0 type: sync request-timeout: 60000 stdio: servers-configuration: classpath:/mcp/stdio-server-config.json这里type: sync是同步客户端普通请求-响应模式够用响应式应用可以改async。3.2 服务端工程配置MCP Server 这边引入 Stdio 服务端依赖dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server/artifactId /dependency服务端的application.yml有个关键点Stdio 模式下不能启动成 Web 应用而且必须关掉 banner 和控制台日志否则这些输出会混进 stdout把 JSON-RPC 消息污染掉。spring: application: name: mcp-server main: web-application-type: none banner-mode: off ai: mcp: server: name: mcp-server version: 1.0.03.3 定义工具并绑定工具类用Tool注解描述参数用ToolParamService public class WeatherService { Tool(description 根据城市名称获得天气信息) public String getWeather(ToolParam(description 城市名称) String cityName) { return cityName 今日天气 晴; } }再把它注册成ToolCallbackProviderSpringBootApplication public class McpServerApplication { public static void main(String[] args) { SpringApplication.run(McpServerApplication.class, args); } Bean public ToolCallbackProvider weatherTools(WeatherService weatherService) { return MethodToolCallbackProvider.builder() .toolObjects(weatherService) .build(); } }打成 jar 后路径填进上面 JSON 的args里就行。3.4 客户端绑定工具到 ChatClientBean public ChatClient serviceChatClient(OpenAiChatModel model, ChatMemory chatMemory, ToolCallbackProvider toolCallbackProvider) { return ChatClient.builder(model) .defaultSystem(new ClassPathResource(call.txt)) .defaultAdvisors( MessageChatMemoryAdvisor.builder(chatMemory).build(), new SimpleLoggerAdvisor()) .defaultToolCallbacks(toolCallbackProvider) .build(); }defaultToolCallbacks这行是关键少了它模型根本不知道有工具可用。4. SSE 模式远程 MCP 服务的配置与验证SSE 模式把 MCP Server 部署成 Web 服务客户端通过 HTTP 连接。适合多用户共享同一套工具服务。4.1 服务端依赖与配置SSE 服务端依赖二选一webflux 或 webmvcdependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webflux/artifactId /dependency服务端application.ymlspring: application: name: mcp-server main: web-application-type: reactive ai: mcp: server: name: mcp-server version: 1.0.0 type: async sse-endpoint: /sse server: port: 8888web-application-type如果同时引入了 mvc 和 webflux 依赖必须显式写reactive否则客户端会 404。4.2 客户端 SSE 配置客户端在application.yml里加 SSE 段和 stdio 同级spring: ai: mcp: client: sse: connections: addition-calculation: url: http://localhost:8888addition-calculation是服务名随便起日志里会用它标识连接。4.3 工具定义与验证服务端工具类我故意让它返回错误结果方便确认工具真的被调用了Service public class CalculationService { Tool(description 两数加法计算) public Long add(ToolParam(description 加数) Long addend, ToolParam(description 被加数) Long summand) { return addend * summand; } }绑定方式和 Stdio 一样用MethodToolCallbackProvider。启动服务端后客户端发起对话问“3 加 5 等于几”如果模型返回 15说明工具确实被调用了而且返回的是我们故意写错的乘法结果。5. 验证请求与连接日志排查配置写完不代表连上了得看日志确认。5.1 打开 MCP 调试日志在客户端application.yml加logging: level: io: modelcontextprotocol: client: debug spec: debug启动后如果连接成功日志里会出现类似Connected to MCP server和工具列表的输出。Stdio 模式下还能看到子进程被拉起的记录。5.2 常见报错对照现象原因处理客户端启动无工具defaultToolCallbacks没配检查 ChatClient 构建Stdio 连接超时服务端打印了 banner/日志关 banner清空 console patternSSE 返回 404web-application-type 写错显式指定 reactive工具调用无响应request-timeout 太短调到 60000ms模型不调工具系统提示词没引导在 call.txt 里说明可用工具5.3 自定义客户端行为如果要做超时控制、工具变更监听实现McpSyncClientCustomizer即可Slf4j Component public class CustomMcpSyncClientCustomizer implements McpSyncClientCustomizer { Override public void customize(String serverConfigurationName, McpClient.SyncSpec spec) { spec.requestTimeout(Duration.ofSeconds(30)); spec.toolsChangeConsumer(tools - log.info(工具列表变更共 {} 个, tools.size())); spec.loggingConsumer(logMsg - log.info(MCP 日志: {}, logMsg.data())); } }这个 customizer 对 stdio、mvc、webflux 三种传输都生效。6. 继续深入模型对话、Coding Plan 与接入文档工具调通之后下一步通常是把它接到真实对话流里验证效果。你可以直接在模型对话页面测试工具调用是否符合预期地址是 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。如果你打算把 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 。Key 管理在控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。最后提醒一句Stdio 模式下服务端的任何 stdout 输出都会变成协议干扰我当初就是忘了关 banner排查了半小时才发现是启动日志混进去了。SSE 模式则要注意鉴权别把没有权限校验的 MCP Server 直接暴露到公网。
返回列表