尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Spring AI(10)——STDIO传输的MCP服务端配置与验证

发布时间:2026/9/29 4:07:00

资讯中心
01
ARTICLE

Spring AI(10)——STDIO传输的MCP服务端配置与验证

Spring AI(10)——STDIO传输的MCP服务端配置与验证
1. 为什么要在 Spring Boot 里跑一个 STDIO 的 MCP 服务端如果你正在用 Spring AI 做智能体或者工具调用大概率会遇到一个绕不开的词MCPModel Context Protocol模型上下文协议。简单说它是一套让大模型和外部工具、资源、提示词互相“对话”的标准协议。而 STDIO 传输就是这套协议里最朴素也最稳的一种方式——服务端和客户端通过标准输入输出流通信不占端口、不走网络进程一启动就能用。这篇要解决的问题很具体在 Spring Boot 项目里搭一个只走 STDIO 的 MCP 服务端把自定义工具暴露出去然后用客户端调一次确认整条链路通了。适合谁看适合已经写过 Spring Boot、想给 AI 应用加“本地工具能力”的开发者。比如你想让模型能查本地数据库、调内部脚本、算业务规则又不想额外起 HTTP 服务STDIO 就是首选。我试过把工具逻辑塞进 Controller 里用 HTTP 暴露结果客户端配置一堆 URL 和端口调试起来很烦。换成 STDIO 之后客户端只要写一行java -jar剩下的交给标准流干净很多。下面从依赖开始一步步把可复制的配置给出来。2. TaoToken 前置准备Key、模型与接入地址MCP 服务端本身不直接调大模型但你要验证“工具被模型选中并调用”就需要一个能跑通对话的模型入口。这里用 TaoToken 做统一接入它的 API 地址是https://taotoken.net/api兼容常见的 OpenAI 风格调用方式Spring AI 里配置起来比较顺。先去控制台拿一个 API Key地址是https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite。拿到之后建议单独放环境变量别硬编码进 yml后面客户端配置会用到。如果你只是想先确认模型能不能正常对话可以用模型对话页面快速试一条https://taotoken.net/model-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。Key 的管理入口在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite遇到参数对不上时翻文档比猜快。3. 可复制配置依赖、工具类、配置类与 application.yml3.1 Maven 依赖只做 STDIO 的 MCP 服务端依赖很轻核心就一个 starterdependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server/artifactId /dependency注意版本要跟你的 Spring AI BOM 对齐别单独写版本号交给父 POM 管。如果你项目里已经引了spring-ai-bom这一句就够了。3.2 定义工具类工具类就是你要暴露给模型的方法集合。用Tool描述方法作用用ToolParam描述参数描述越细模型选中的概率越高。下面这个例子是给孩子起名纯测试用package com.example.mcpserver; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.tool.annotation.Tool; import org.springframework.ai.tool.annotation.ToolParam; import org.springframework.stereotype.Service; Slf4j Service public class NameMcpServer { Tool(description 根据孩子的出生日期和性别起名) public String childName( ToolParam(description 出生日期格式 yyyy-MM-dd) String birth, ToolParam(description 性别男或女) String gender) { log.info(childName called: birth{}, gender{}, birth, gender); return 老任与码; } }这里有个坑我踩过log.info(birth, gender)这种写法在 SLF4J 里不会按你预期拼接得用占位符{}否则日志里看不到参数值排查时一脸懵。3.3 配置类把工具注册成 ToolCallbackProvider光有Tool注解还不够得通过ToolCallbackProvider把工具对象注册进去MCP 服务端才知道要暴露哪些方法package com.example.config; import com.example.mcpserver.NameMcpServer; import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.ai.tool.method.MethodToolCallbackProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class MyServerConfig { Bean public ToolCallbackProvider nameTool(NameMcpServer nameMcpServer) { return MethodToolCallbackProvider.builder() .toolObjects(nameMcpServer) .build(); } }MCP 服务端支持四类能力工具、资源、提示、完成默认全开。本例只用工具其他保持默认即可想关就在 yml 里设false。3.4 application.yml 关键配置STDIO 模式下有三项是硬性要求少一个都可能启动异常或者输出被污染spring: main: web-application-type: none banner-mode: off ai: mcp: server: name: name-mcp-server version: 1.0.0 type: SYNC stdio: true capabilities: tool: true resource: false prompt: false completion: false logging: pattern: console:逐条解释一下为什么这么配。web-application-type: none是因为 STDIO 服务端不需要 Web 容器起了反而占端口、干扰标准流。banner-mode: off是防止 Spring 的启动 banner 混进 stdout客户端解析 JSON-RPC 时会直接报错。logging.pattern.console:留空是把控制台日志格式清掉避免日志和协议消息抢同一个输出通道。stdio: true是核心开关默认是false不打开就不会走标准流。type: SYNC表示同步处理请求调试阶段够用高并发场景再考虑 ASYNC。常用属性对照表属性作用默认值spring.ai.mcp.server.enabled启用/禁用 MCP 服务端truespring.ai.mcp.server.stdio启用 STDIO 传输falsespring.ai.mcp.server.name服务端标识名mcp-serverspring.ai.mcp.server.version版本号1.0.0spring.ai.mcp.server.typeSYNC / ASYNCSYNCspring.ai.mcp.server.request-timeout请求超时20sspring.ai.mcp.server.capabilities.tool工具能力开关true注意request-timeout默认 20 秒工具里如果有慢查询记得调大否则客户端会先超时。4. 打包与验证客户端调用一次工具确认 STDIO 通道可用4.1 打包并放到固定路径用 Maven 打可执行 jarmvn clean package -DskipTests打完把 jar 拷到一个固定目录比如D:/name-mcp-server.jar。路径别带空格和中文客户端拼命令时容易出问题。4.2 客户端 mcp-servers-config.json 配置客户端侧新增一段服务端配置告诉它怎么启动这个 STDIO 进程{ mcpServers: { name-mcp-server: { command: java, args: [ -jar, D:/name-mcp-server.jar ] } } }启动后客户端会拉起这个 java 进程通过 stdin/stdout 发 JSON-RPC 请求。你可以在客户端里发一条类似“帮我给 2024-05-01 出生的男孩起个名”的消息观察服务端日志。4.3 成功结果长什么样服务端日志里应该出现childName called: birth2024-05-01, gender男客户端返回里会带上工具执行结果老任与码。这说明三件事都对了工具被注册、模型选中了该工具、STDIO 通道完成了请求-响应往返。如果日志里没有这行但客户端也没报错多半是工具没被模型选中回去把Tool的 description 写得更具体些。4.4 另一种配置方式把参数写进启动命令有些客户端不方便改服务端 yml可以把关键参数塞进 java 启动参数{ mcpServers: { name-mcp-server: { command: java, args: [ -jar, -Dspring.ai.mcp.server.stdiotrue, -Dspring.main.web-application-typenone, -Dspring.main.banner-modefalse, -Dlogging.pattern.console, D:/name-mcp-server.jar ] } } }这种写法下服务端 yml 里stdio、web-application-type这些可以省掉但name、version、type建议保留方便识别。两种方式选一种就行别混着配否则排查时不知道以哪个为准。5. 本篇常见错排查启动就退出没有任何输出。先看web-application-type是不是none。如果还是 servlet 类型Spring 会尝试起 TomcatSTDIO 进程生命周期就乱了。客户端报 JSON 解析失败。九成是 stdout 里混了非协议内容。检查banner-mode是否为off、logging.pattern.console是否清空。另外别在工具方法里用System.out.println它会直接污染协议流要打日志用log。工具死活不被调用。先确认ToolCallbackProviderBean 有没有被扫描到包路径对不对。再看Tool的 description 是不是太笼统模型选工具靠的就是这段文字写“起名”比写“处理”强得多。客户端连不上或超时。检查 jar 路径是否存在、java 是否在 PATH 里。如果工具执行超过 20 秒调大spring.ai.mcp.server.request-timeout。还有一种情况是客户端配置里command写成了完整路径但带空格记得用数组形式传参。改了 yml 不生效。STDIO 模式下客户端是拉起新进程改完要重新打包并重启客户端热更新在这里不适用。6. 接下来怎么走把验证过的通道接到真实业务上STDIO 通道验证通过之后你就可以把NameMcpServer换成真实工具了比如查订单、算库存、调内部接口。工具方法保持无状态、幂等返回值尽量结构化模型解析起来更稳。需要再确认模型侧行为时回到模型对话页面发几条带工具意图的指令https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite。要接更多客户端或者换 Key走 API Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite。参数细节以接入文档为准https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。如果你打算把这套 MCP 服务端挂到长期跑的编码 Agent 上Coding Plan 会更省事https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。最后留一个实用习惯每次新增工具后先本地用客户端调一次看日志里参数有没有正确传入。工具描述和参数描述这两段文字值得你多花五分钟打磨它直接决定模型会不会用你的工具。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。