前面学习了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,发送几次请求([参考上一节的分析](https://www.cnblogs.com/yjmyzz/p/18980212/spring-ai-learn-mcp-lifecycle)),可用wireshark之类的抓包工具验证
/sse会返回1个sessionId值99e64481-8190-4e17-ba64-05404b9131 (相当于与mcp server建立了长连接,后面的所有post请求,都会用到这个sessionId)
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 }
{
"method": "notifications/initialized",
"jsonrpc": "2.0"
}
{
"method": "ping",
"jsonrpc": "2.0",
"id": 1
}
{
"method": "resources/list",
"jsonrpc": "2.0",
"id": 6
}
{
"method": "tools/list",
"jsonrpc": "2.0",
"id": 4
}
{
"method": "prompts/list",
"jsonrpc": "2.0",
"id": 5
}
大家有兴趣的话,可以自行用postman或apipost之类的工具,一步步手动发送post请求,模拟这个过程,观察/sse的页面输出
互此,cherry studio已知道了mcp sever的所有信息,后面的会话中,就能使用该工具了。