spring-ai 学习系列(5)-MCP(webflux sse)
前面学习了stdio模式的MCP使用,可以看到这种方式局限性比较大,mcp host/mcp client/mcp server通常要在同1台机器上,使用进程间通讯。更常见的做法是,大家各自部署自己的mcp server,就象常规后端http api一样,想部署在哪都行,只要http能访问即可。
一、调整pom依赖

1 <dependency>
2 <groupId>org.springframework.ai</groupId>
3 <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
4 <version>1.0.0</version>
5 </dependency>
MCP Server的代码相对stdio模式而言,完全不用改!
二、调整yaml
spring:
ai:
mcp:
server:
type: async
启动MCP Server,如果访问http://localhost:8080/sse看到类似以下界面,说明启动成功

三、MCP Client
public static void main(String[] args) {
WebFluxSseClientTransport webFluxSseTransport = new WebFluxSseClientTransport(WebClient.builder().baseUrl("http://localhost:8080"));
McpSyncClient mcpClient = McpClient.sync(webFluxSseTransport).build();
McpSchema.InitializeResult initialize = mcpClient.initialize();
System.out.println("initialize=>" + initialize);
Object ping = mcpClient.ping();
System.out.println("ping=>" + ping);
McpSchema.ListToolsResult toolsList = mcpClient.listTools();
System.out.println(toolsList);
McpSchema.CallToolResult orderStatus = mcpClient.callTool(
new McpSchema.CallToolRequest("queryOrderStatus",
Map.of("orderNo", "25070601")));
System.out.println(orderStatus);
mcpClient.closeGracefully();
}
Client运行后,会看到类似输出:
20:50:03.897 [reactor-http-nio-2] INFO io.modelcontextprotocol.client.McpAsyncClient -- Server response with Protocol: 2024-11-05, Capabilities: ServerCapabilities[completions=CompletionCapabilities[], experimental=null, logging=LoggingCapabilities[], prompts=PromptCapabilities[listChanged=true], resources=ResourceCapabilities[subscribe=false, listChanged=true], tools=ToolCapabilities[listChanged=true]], Info: Implementation[name=mcp-server, version=1.0.0] and Instructions null
initialize=>InitializeResult[protocolVersion=2024-11-05, capabilities=ServerCapabilities[completions=CompletionCapabilities[], experimental=null, logging=LoggingCapabilities[], prompts=PromptCapabilities[listChanged=true], resources=ResourceCapabilities[subscribe=false, listChanged=true], tools=ToolCapabilities[listChanged=true]], serverInfo=Implementation[name=mcp-server, version=1.0.0], instructions=null]
ping=>{}
ListToolsResult[tools=[Tool[name=queryOrderStatus, description=根据订单号查询订单状态, inputSchema=JsonSchema[type=object, properties={orderNo={type=string, description=订单号,格式为8位数字,比如:25070601}}, required=[orderNo], additionalProperties=false, defs=null, definitions=null]]], nextCursor=null]
CallToolResult[content=[TextContent[audience=null, priority=null, text="订单号:25070601,订单状态:已发货"]], isError=false] Process finished with exit code 0
四、在MCP Host中使用MCP Server

仍然以Cherry Studio为例,添加MCP server后,点保存(前提:MCP Server应对的url http://localhost:8080/sse 必须能正常访问)
注:点保存时,cherry studio会向 http://localhost:8080/sse,发送几次请求(参考上一节的分析),可用wireshark之类的抓包工具验证
- 第1次是get 请求

/sse会返回1个sessionId值99e64481-8190-4e17-ba64-05404b9131 (相当于与mcp server建立了长连接,后面的所有post请求,都会用到这个sessionId)
- 第2次post请求 initialize

json请求如下:

1 {
2 "method": "initialize",
3 "params": {
4 "protocolVersion": "2025-03-26",
5 "capabilities": {},
6 "clientInfo": {
7 "name": "Cherry Studio",
8 "version": "1.4.8"
9 }
10 },
11 "jsonrpc": "2.0",
12 "id": 0
13 }
initialize
- 第3次post请求 notifications/initialized
{
"method": "notifications/initialized",
"jsonrpc": "2.0"
}
- 第4/5/6次post请求 ping(即:连ping 3次, 这里可能是我本机网络不好,cherry studio重试了几次,每次请求后,id值返回会+1,下一次请求时,入参里的id,必须是上次返回的id值)
{
"method": "ping",
"jsonrpc": "2.0",
"id": 1
}
- 第7次post请求 resources/list
{
"method": "resources/list",
"jsonrpc": "2.0",
"id": 6
}
- 第8次post请求 tools/list
{
"method": "tools/list",
"jsonrpc": "2.0",
"id": 4
}
- 第9次post请求 prompts/list
{
"method": "prompts/list",
"jsonrpc": "2.0",
"id": 5
}
大家有兴趣的话,可以自行用postman或apipost之类的工具,一步步手动发送post请求,模拟这个过程,观察/sse的页面输出

互此,cherry studio已知道了mcp sever的所有信息,后面的会话中,就能使用该工具了。

文中代码:https://github.com/yjmyzz/spring-ai-sample/tree/day04
spring-ai 学习系列(5)-MCP(webflux sse)的更多相关文章
- Spring Boot 学习系列(10)—SpringBoot+JSP的使
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 解决问题 随着spring boot 框架的逐步使用,我们期望对于一些已有的系统进行改造,做成通用的脚手架, ...
- Spring Boot 学习系列(03)—jar or war,做出你的选择
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 两种打包方式 采用Spring Boot框架来构建项目,我们对项目的打包有两种方式可供选择,一种仍保持原有的 ...
- Spring Boot 学习系列(序)—Spring Boot
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Spring Boot? Spring Boot 是由pivotal团队提供的一个基于Spring的全新框架 ...
- Spring Boot 学习系列(06)—采用log4j2记录日志
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 为什么选择log4j2 log4j2相比于log4j1.x和logback来说,具有更快的执行速度.同时也支 ...
- Spring Boot 学习系列(05)—自定义视图解析规则
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 自定义视图解析 在默认情况下Spring Boot 的MVC框架使用的视图解析ViewResolver类是C ...
- Spring Boot 学习系列(09)—自定义Bean的顺序加载
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Bean 的顺序加载 有些场景中,我们希望编写的Bean能够按照指定的顺序进行加载.比如,有UserServ ...
- Spring Boot 学习系列(08)—自定义servlet、filter及listener
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的filter及listener配置 在传统的Java web项目中,servlet.filter和li ...
- Spring Boot 学习系列(07)—properties文件读取
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的properties读取方式 一般的,我们都可以自定义一个xxx.properties文件,然后在工程 ...
- Spring Boot 学习系列(04)—分而治之,多module打包
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 明确功能,各司其职 在一个结构清晰的项目中,一个没有module划分的结构显然不是最佳实践.有人会说可以在同 ...
- Spring Boot 学习系列(01)—从0到1,只需两分钟
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 快速构建 如果我们想基于spring mvc 提供一个简单的API查询服务,传统的方式,首先需要我们引入sp ...
随机推荐
- Kreuzberg:本地OCR+多格式解析!Kreuzberg如何用Python暴力提取30+文档格式?程序员看完直呼内行!
嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 我们经常需要从各种不同类型的文档中提取文本内容,无论是办公文档.图像还是PDF文件.而Kre ...
- 代码随想录第二十一天 | Leecode 669. 修剪二叉搜索树、108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树
Leecode 669. 修剪二叉搜索树 题目描述 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high.通过修剪二叉搜索树,使得所有节点的值在[low, high]中.修 ...
- 【记录】gnuplot|gnuplot怎么把多个图画成一个?
版本:gnuplot 5.2 patchlevel 2 解决了无数次了还是反复忘,气,遂记. 下列程序的功能: 读取文件夹下的所有dat文件,并把所有dat的结果画在一张图里并标好图例: set te ...
- spring boot迁移计划 第Ⅰ章 --chapter 1. rust hyper 结合rust nacos-client开发nacos网关 part ④ nacos-client
1. toml依赖 nacos_rust_client = "0.3" local_ipaddress = "0.1" ahash = "0.8&qu ...
- 鸿蒙Next开发实战教程—电影app
最近忙忙活活写了不少教程,但是总感觉千篇一律,没什么意思,大家如果有感兴趣的项目可以私信给幽蓝君写一写. 今天分享一个电影App. 这个项目也比较简单,主要是一些简单页面的开发和本地视频的播放以及 ...
- Number of Atoms——LeetCode进阶路
原题链接https://leetcode.com/problems/number-of-atoms/ 题目描述 Given a chemical formula (given as a string) ...
- 5 MyBatis动态sql中foreach标签的使用
1 MyBatis动态SQL之if 语句 2 MyBatis动态sql之where标签|转 3 MyBatis动态SQL之set标签|转 4 MyBatis动态SQL之trim元素|转 5 MyBat ...
- 把PDF转换成指定后缀名的图片
生活中难免遇到各种文件类型转换的问题,尤其是在办理一些证件的时候.例如,申请居住证积分的时候,把PDF版本的毕业证扫描件转换成jpg或者png等.下面提供一个工具,用于把PDF转换成指定后缀名的图 ...
- IIS设置发布公告页面
IIS原有站点停用 IIS新增里新增一个站点,端口及域名和原有站点一致 新增公告提示页面,如:index.html 新增web.config文件,并设置web.config 1 <system. ...
- 关于家庭宽带IPv6的开启、绑定域名、使用教程等
前言 好几年前网上就很多讨论家庭宽带支持IPv6,能怎么怎么改变生活.带来多少便利,奈何之前租的房子是房东办好的宽带,我没有权限接触到光猫,自己也一直懒得研究这个新鲜事物,前阵子自己捣鼓了一下,还是得 ...