MCP实战手记系列(二):跑通第一个 MCP Server(文末附github源码链接)
MCP 实战手记系列二· 实操入门系列一把 MCP 的现状和几个拐点铺开了但光看不练没体感。这篇动手把第一个 MCP Server 跑起来能启动、能调用、有真实返回。面向一线开发者重实操每篇都有我亲手跑过的东西。引子先别管协议细节把灯点亮系列一里我说过一句大白话MCP 干的事就是把工具的调用标准化让大模型能直接使唤你写的函数。但落到代码上很多人第一步就卡住觉得得先啃完那份几百页的协议规范。不用。Spring AI 把 MCP Server 封装到了加个注解就能用的程度你完全可以先跑起来再回头看协议。这篇只做一件事用 Spring AI 把第一个 MCP Server 跑通让它真的能回答机房现在多少度“某台设备开着没”。代码都在仓库里全 mock 数据clone 下来就能跑。一、这次要跑什么场景还是系列三用过的机房环境监控不过这次是从零搭的版本get_room_environment返回机房温度、湿度get_device_status传入设备名如ac-01返回它的运行状态数据全是内存 mock不连数据库、不连真实设备。这么设计是想让你把精力放在MCP Server 怎么搭上而不是被业务依赖绊住。二、最小骨架三样东西一个能用的 MCP Server骨架就三样。少一样跑不起来多一样是冗余。① 依赖dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-mcp-server-webmvc/artifactIdversion1.0.0-M7/version/dependency注意1.0.0-M7是里程碑版本不是正式版。里程碑版要额外加 Spring 的里程碑仓库而且别上生产它只是用来演示旧写法的。正式版是2.x系列三会用到。② 配置application.ymlserver:port:8080spring:ai:mcp:server:name:room-monitor-mcp-serversse-message-endpoint:/mcp/messagesse-message-endpoint是旧规范SSE 传输的标志性配置。先记住它系列三改无状态时这行会被删掉。③ 工具普通Service里的方法加Tool/ToolParam注解就变成 MCP 工具不用实现任何接口Tool(nameget_room_environment,description获取机房环境数据温度、湿度)publicRoomEnvironmentgetRoomEnvironment(){returnnewRoomEnvironment(23.5,48.2);// 真实项目里查数据库 / 时序库}再把服务注册成工具源BeanpublicToolCallbackProviderroomMonitorToolCallbackProvider(RoomMonitorServicesvc){returnMethodToolCallbackProvider.builder().toolObjects(svc).build();}这套声明式写法是 Spring AI 我最喜欢的地方。协议演进不该动你的业务代码系列三会验证这一点迁移时业务方法几乎一行不用改。三、跑起来cd 02-first-server mvn spring-boot:run端口 8080。启动日志里这几行是重点c.ethanliang.mcp.config.McpToolConfig : Registered Tool: get_device_status c.ethanliang.mcp.config.McpToolConfig : Registered Tool: get_room_environment o.s.a.m.s.a.McpServerAutoConfiguration : Registered tools: 2, notification: true o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path / c.ethanliang.mcp.FirstServerApplication : Started FirstServerApplication ...两个工具都注册上了服务在 8080 监听灯就亮了。顺带说个你可能会担心的点这个项目java.version设的是 17但我本地是JDK 21直接跑通的。17 只是编译目标字节码版本JDK 21 既能编译也能运行Spring Boot 3.3 要求 Java 1721 满足。所以你不用为了它去装 JDK 17。四、怎么调它不装任何客户端MCP 走 JSON-RPC。SSE 传输下不能直接 POST 工具调用得先握手GET /sse打开事件流服务端回一个endpoint事件里面带sessionId的 POST 地址类似/mcp/message?sessionIdxxx拿到地址后再POST你的 JSON-RPC 消息过去响应从刚才那条 SSE 流里回来我写了个几十行的 Python 脚本纯标准库走完这套流程下面都是实跑返回没改过。先initialize握手服务端亮明身份{protocolVersion:2024-11-05,capabilities:{logging:{},tools:{listChanged:true}},serverInfo:{name:room-monitor-mcp-server,version:1.0.0}}tools/list看有哪些工具中文描述是我在代码里写的Tool说明{tools:[{name:get_device_status,description:获取指定设备的运行状态,inputSchema:{type:object,properties:{deviceName:{type:string,description:设备名称如 ac-01、fan-02、light-03}},required:[deviceName],additionalProperties:false}},{name:get_room_environment,description:获取机房环境数据温度、湿度,inputSchema:{type:object,properties:{},required:[],additionalProperties:false}}]}真正调用get_room_environment返回{content:[{type:text,text:{\temperature\:23.5,\humidity\:48.2}}],isError:false}get_device_status传ac-01返回{content:[{type:text,text:\ac-01 运行中\}],isError:false}到这步一个 MCP Server 从代码到调用就完整闭环了。大模型侧只要是个支持 MCP 的客户端把这套端点接上去就能用这两个工具。五、踩坑记录实跑下来几个坑按搜索价值排① 编码坑中文 Windows 上 JVM 默认是 GBK我本地是中文 WindowsJDK 文件编码默认 GBK。一开始工具描述里的中文在客户端按 UTF-8 解析出来是一堆黑块和问号原因是 MCP 把中文按 GBK 序列化了。解法启动加-Dfile.encodingUTF-8java-Dfile.encodingUTF-8-jartarget/first-server-1.0.0-SNAPSHOT.jar如果你本地本来就是 UTF-8 环境多数 Linux / macOS或设了环境变量的 Windows不会撞这个坑可以忽略。② 握手坑不能直接 POST/mcp/messageSSE 传输下/mcp/message是要带sessionId的而sessionId得先GET /sse拿。直接 POST 会拿到Invalid message format (-32600)之类的错不是协议问题是顺序错了。先开流、再拿地址、最后发消息三步不能省。③ 依赖坑里程碑版要配仓库且别上生产1.0.0-M7不在 Maven 中央仓的正式路径里pom 得加spring-milestones仓库。另外它是里程碑版API 可能变、不建议生产用。系列三会切到正式版2.x正好对照。六、这个服务器下一篇就拆它现在跑起来的这个是有状态的。客户端建 SSE 长连接服务端分配session存状态。水平扩展时session 不共享就会出事。系列三《把 MCP Server 改成无状态》做的一件事就是把这样一个 SSE 有状态服务器改成无状态 Streamable HTTP。你会看到改动 90% 集中在配置和依赖业务工具代码基本不动。这篇文章的02-first-server就是那篇的改造前。小结跑通比想象简单依赖 配置 Tool三样凑齐就能用声明式工具定义是甜点业务方法加个注解变成 MCP 工具协议演进不绑架你的代码它现在是有状态的下篇拆掉 session看改动到底落在哪仓库已经就位git checkout v02就能把这一篇的代码原样跑起来。先把这个最小骨架吃熟后面几篇的改造才有落脚点。本文完整可运行代码 github.com/ethanliang2016/mcp-in-action对应目录02-first-server标签v02。git checkout v02即可还原这一篇的状态。MCP 实战手记系列路线图#篇目状态1总纲篇MCP 到哪一步了✅2跑通第一个 MCP Server本篇✅3把 MCP Server 改成无状态✅4-7CIMD 授权 / MCP Apps / 自建网关 / 安全篇规划后面几篇逐步放出关注我更新第一时间能看到。你跑第一个 MCP Server 时卡在哪一步评论区说有价值的我整理进后续篇目。参考MCP 2026-07-28 规范更新Spring AI MCP Server 文档