news 2026/10/8 7:46:07

mcp-for-beginners Java 客户端实战:用 Spring AI + WebFlux SSE 构建 MCP Calculator 客户端

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
mcp-for-beginners Java 客户端实战:用 Spring AI + WebFlux SSE 构建 MCP Calculator 客户端
  • 教程
  • 文档
  • 人工智能

【免费下载链接】mcp-for-beginners

This open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.

项目地址:https://gitcode.com/GitHub_Trending/mc/mcp-for-beginners
点击查看免费下载

本篇指南围绕 mcp-for-beginners 开源课程中「02-client」章节的 Java 实现展开,讲解如何编写一个基于 Spring AI MCP 框架的 Java 客户端,通过 Server-Sent Events(SSE)传输协议连接第一章构建的 Calculator MCP 服务器,完成工具发现(listTools)、远程调用(callTool)与结果展示的完整闭环。读完本文,你将掌握WebFluxSseClientTransport与McpClient.sync的使用方式、各计算工具的调用参数约定,以及一套可复用的「服务器 + 客户端」联调排障流程。

前置条件:先把 Calculator Server 跑起来

在启动客户端之前,必须先保证第一章的 Calculator MCP 服务器处于运行状态。按照课程约定,服务器位于03-GettingStarted/01-first-server/solution/java/目录,使用 Maven Wrapper 构建并以 JAR 形式运行:

cd ..\01-first-server\solution\java .\mvnw clean install -DskipTests java -jar target\calculator-server-0.0.1-SNAPSHOT.jar

服务器启动后应监听http://localhost:8080,其 SSE 端点默认为http://localhost:8080/sse。客户端运行还需要满足:

  1. Java 21 或更高版本——项目的pom.xml中通过maven-compiler-plugin的<release>21</release>以及<java.version>21</java.version>明确了编译目标;
  2. Maven——无需单独安装,项目已内置 Maven Wrapper(mvnw/mvnw.cmd)。

说明:根据 服务器端 README 的提示,该 Java 解决方案使用的是较早期的 HTTP + SSE 传输,面向 MCP2025-11-25协议版本;新编写的远程服务器建议改用2026-07-28的 Streamable HTTP。本文的 Java 客户端与这套课程代码保持一致的 SSE 传输方式。

SDKClient 是什么

SDKClient是本节提供的 Java 客户端示例,它演示了四件 MCP 客户端最核心的事情:

  • 使用SSE(Server-Sent Events)传输与 MCP 服务器建立连接;
  • 从服务器列出可用的工具列表;
  • 远程调用各种计算器函数;
  • 处理响应并把计算结果打印展示出来。

客户端本身是一个不带 Web 容器的普通 Java 应用:main方法创建传输层、实例化客户端,然后在run()方法中依次执行工具发现与调用逻辑,完整源码见 SDKClient.java。

工作原理:客户端到服务器的五步调用链

客户端基于 Spring AI MCP 框架工作,整个流程可以拆解为五个阶段:

  1. 建立连接:创建WebFluxSseClientTransport,指向 Calculator 服务器的http://localhost:8080;
  2. 初始化客户端:通过McpClient.sync(transport).build()构建同步客户端并调用initialize()完成握手;
  3. 工具发现:调用listTools()列出服务器上全部可用操作;
  4. 执行操作:用样本数据逐一调用加、减、乘、除、幂、开方、绝对值等数学函数;
  5. 展示结果:把每次CallToolResult的返回内容打印到控制台。

值得补充的是,客户端在initialize()之后还会调用client.ping()主动探测一次连接健康状态,并在全部工具调用结束后调用client.closeGracefully()优雅释放连接资源——这两步在课程文档中未单独展开,却是实战客户端中值得保留的健壮性细节。

项目结构

SDKClient位于标准的 Maven 单模块布局中,唯一的源码文件路径如下:

src/ └── main/ └── java/ └── com/ └── microsoft/ └── mcp/ └── sample/ └── client/ └── SDKClient.java # 主客户端实现

完整的可运行工程位于 03-GettingStarted/02-client/solution/java/,除源码外还包含pom.xml、mvnw(Unix 包装脚本)、mvnw.cmd(Windows 包装脚本)与LICENSE。

核心依赖与构建配置

项目的 Maven 配置见 pom.xml,其中最关键的一个依赖是:

<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-server-webflux</artifactId> </dependency>

该依赖主要提供三部分能力:

  • McpClient——主要的客户端接口,提供initialize()、listTools()、callTool()、ping()、closeGracefully()等操作;
  • WebFluxSseClientTransport——基于 WebFlux 的 SSE 传输实现,用于 HTTP 通信;
  • MCP 协议 schema 与请求/响应类型(如CallToolRequest、CallToolResult、ListToolsResult)。

pom.xml中还值得注意的细节有:

  • 通过spring-ai-bom(版本1.0.0-SNAPSHOT)进行依赖版本统一管理,父工程为spring-boot-starter-parent3.4.4;
  • 项目坐标com.example:calculator-client:0.0.1-SNAPSHOT,说明这是一个 Spring Boot 构建的独立客户端 JAR;
  • 额外引入spring-boot-starter-actuator与测试相关的spring-boot-starter-test、junit-jupiter;
  • 配置了exec-maven-plugin(3.1.0),主类指向com.microsoft.mcp.sample.client.SDKClient,便于用mvnw exec:java直接运行;
  • 仓库(repository)配置包含 Sonatype Central 快照仓库与 Spring Milestones / Snapshots 仓库,用于解析spring-ai的快照构件。

构建与运行

使用 Maven Wrapper 构建项目:

.\mvnw clean install

构建成功后运行客户端:

java -jar .\target\calculator-client-0.0.1-SNAPSHOT.jar

注意:执行上述命令前,务必确保 Calculator 服务器已运行在http://localhost:8080。除打包运行外,课程主教程(03-GettingStarted/02-client/README.md)还提供了另一种更适合开发期的运行方式:

# 编译 ./mvnw clean compile # 直接以主类运行,无需打包 ./mvnw exec:java -Dexec.mainClass="com.microsoft.mcp.sample.client.SDKClient"

客户端执行的计算与预期输出

客户端启动后会依次完成下列操作:

  1. 连接http://localhost:8080上的 Calculator 服务器;
  2. 列出全部可用工具;
  3. 执行一组预置的计算样本(见下表):
工具参数期望结果
adda=5, b=38
subtracta=10, b=46
multiplya=6, b=742
dividea=20, b=45
powerbase=2, exponent=8256
squareRootnumber=164
absolutenumber=-5.55.5
help无列出可用操作

对应的控制台输出大致如下:

Available Tools = ListToolsResult[tools=[Tool[name=add, description=Add two numbers together, ...], ...]] Add Result = CallToolResult[content=[TextContent[text="5,00 + 3,00 = 8,00"]], isError=false] Subtract Result = CallToolResult[content=[TextContent[text="10,00 - 4,00 = 6,00"]], isError=false] Multiply Result = CallToolResult[content=[TextContent[text="6,00 * 7,00 = 42,00"]], isError=false] Divide Result = CallToolResult[content=[TextContent[text="20,00 / 4,00 = 5,00"]], isError=false] Power Result = CallToolResult[content=[TextContent[text="2,00 ^ 8,00 = 256,00"]], isError=false] Square Root Result = CallToolResult[content=[TextContent[text="√16,00 = 4,00"]], isError=false] Absolute Result = CallToolResult[content=[TextContent[text="|-5,50| = 5,50"]], isError=false] Help = CallToolResult[content=[TextContent[text="Basic Calculator MCP Service\n\nAvailable operations:\n1. add(a, b) - Adds two numbers\n2. subtract(a, b) - Subtracts the second number from the first\n..."]], isError=false]

两个值得注意的细节:

  • 数字格式与本地化有关:结果中的5,00 + 3,00 = 8,00使用逗号作为小数点分隔符,这是因为服务器端 CalculatorService.java 用String.format("%.2f %s %.2f = %.2f", ...)格式化输出,格式符受运行环境默认 Locale 影响;在中文等以点号分隔的环境下会显示为5.00 + 3.00 = 8.00,属正常现象而非错误;
  • 线程警告是正常现象:程序结束阶段可能看到 Maven 关于残留线程的警告,这是响应式(reactive)应用运行后的常见表现,并不表示出错。

代码逐段解析

1. 传输层设置

var transport = new WebFluxSseClientTransport(WebClient.builder().baseUrl("http://localhost:8080"));

这行代码创建了一个基于 SSE 的传输实例,指向 Calculator 服务器地址。SSE 适合 MCP 服务器基于 HTTP 的「服务端推送 + 请求/响应」交互模型,客户端通过WebClient与服务器的/sse端点建立长连接、接收服务端事件。

2. 客户端创建与初始化

var client = McpClient.sync(this.transport).build(); client.initialize();

McpClient.sync(...)返回一个同步调用的客户端构建器,build()产出客户端实例,initialize()完成 MCP 协议握手(交换协议版本与能力信息)。源码中还紧跟着client.ping()用于验证连接可用性。

3. 列出工具

ListToolsResult toolsList = client.listTools(); System.out.println("Available Tools = " + toolsList);

listTools()返回ListToolsResult,其中包含服务器注册的全部工具,包括名称、描述与输入 schema——这些信息正是后续callTool参数约定的来源。

4. 调用工具

CallToolResult resultAdd = client.callTool(new CallToolRequest("add", Map.of("a", 5.0, "b", 3.0))); System.out.println("Add Result = " + resultAdd);

CallToolRequest需要两个要素:工具名与参数 Map。参数键名必须与服务器端工具方法的形参名严格一致。对照服务器实现 CalculatorService.java,可以总结出如下参数约定:

  • add(a, b)、subtract(a, b)、multiply(a, b)、divide(a, b):两个参数均命名为a和b;
  • power(base, exponent):参数名为base、exponent;
  • squareRoot(number)、absolute(number):参数名为number;
  • help():无参数,传入空 Map(Map.of())。

每个工具的返回结果封装在CallToolResult中,其中isError=false表示调用成功,content列表里的TextContent携带服务器返回的文本结果。课程主教程(03-GettingStarted/02-client/README.md)中的 Java 示例还演示了help工具的调用,其参数同样为空的Map.of()。

5. 优雅关闭

client.closeGracefully();

所有工具调用完成后,通过closeGracefully()主动关闭连接,避免资源泄漏。

服务器端工具清单对照

为便于理解客户端各调用参数的含义,这里汇总服务器侧通过@Tool注解暴露的全部操作(源码见 CalculatorService.java):

工具名参数描述边界处理
adda, b两数相加—
subtracta, b第一数减第二数—
multiplya, b两数相乘—
dividea, b第一数除以第二数b 为 0 时返回错误信息
powerbase, exponent求幂—
squareRootnumber开平方负数返回错误信息
modulusa, b求余数b 为 0 时返回错误信息
absolutenumber求绝对值—
help无列出全部操作与示例—

客户端示例调用了除modulus之外的全部工具,你可以在此基础上自行扩展一次callTool(new CallToolRequest("modulus", Map.of("a", 17.0, "b", 5.0)))来验证求余操作。

故障排查

服务器未启动

若出现连接错误,先确认第一章的 Calculator 服务器是否已运行:

Error: Connection refused

解决方法:先启动 Calculator 服务器,再运行客户端。

端口被占用

如果 8080 端口已被其他程序占用:

Error: Address already in use

解决方法:关闭占用 8080 端口的其他应用,或把服务器改到其他端口后同步修改客户端baseUrl。

构建错误

如果构建过程中遇到依赖解析或编译错误,可跳过测试重新构建以定位问题:

.\mvnw clean install -DskipTests

注意,spring-ai的1.0.0-SNAPSHOT构件依赖 Sonatype Central 快照仓库与 Spring 里程碑仓库,若构建时无法联网访问这些仓库,也会导致依赖下载失败。

小结与下一步

从本示例可以提炼出 MCP 客户端的三个关键认知:客户端既能发现服务器的能力(工具列表),也能调用这些能力(远程执行计算);客户端既可以拉起服务器进程(如 stdio 场景),也可以连接已在运行的服务器(如本示例的 SSE 场景);写一个自己的客户端是验证服务器能力、替代 Inspector 图形化调试的极佳途径。

本节的 Java 客户端还只是「无脑调用」的演示。课程的下一章 03-llm-client 将在此基础上为客户端接入大语言模型,让 LLM 根据用户意图自主决定调用哪些 MCP 工具,这才是 MCP 在 Agent 工作流中的真正威力所在。

  • 教程
  • 文档
  • 人工智能

【免费下载链接】mcp-for-beginners

This open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.

项目地址:https://gitcode.com/GitHub_Trending/mc/mcp-for-beginners
点击查看免费下载
上一篇:3分钟掌握StPageFlip:打造专业级Web翻页效果的终极指南
下一篇:OpenModScan完全指南:如何用这款免费Modbus主站工具提升你的工业自动化效率

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 7:45:34

题解:洛谷 P1075 [NOIP 2012 普及组] 质因数分解

本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。 欢迎大家订阅我的专栏:算法…

作者头像 李华
网站建设 2026/10/8 7:45:28

题解:洛谷 P1116 车厢重组

本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。 欢迎大家订阅我的专栏:算法…

作者头像 李华
网站建设 2026/10/8 7:45:07

三国杀更新版本

#include<iostream> #include<cstdlib> #include<stdio.h> #include<time.h> using namespace std; int main(){srand(time(NULL));string b[8]{"杀","杀","杀","杀","杀","闪","闪…

作者头像 李华
网站建设 2026/10/8 7:43:20

IEC 104测试工具深度解析:协议栈调试与报文级故障定位

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/8 7:43:18

TPS259483与STM32F746ZG实现智能电源路径保护与热插拔控制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华