用 Java 手动构建 Streamable HTTP 连接方式的 MCP 客户端

1,202 阅读3分钟

一、版本简述

截至 2025 年 7 月 23 日,Spring AI 早在 5 月 20 日推出了 1.0 正式版,而 java-sdk 的版本却仍然停留在 5 月 13 日的 v0.10.0,不支持 Streamable HTTP 连接。查看 MCP 官方文档,SSE 连接已被废弃,目前只定义了两种标准传输机制:Standard Input/Output (stdio) 和 Streamable HTTP。为了用 Java 构建 Streamable HTTP 连接方式的 MCP 客户端,我在这里使用的是 v0.11.0 快照版本。

传送门:MCP 官方文档Java SDK 仓库

二、MCP 简述

MCP(Model Context Protocol,模型上下文协议)是由 Anthropic 于 2024 年 11 月推出并开源的一种开放标准,旨在统一大型语言模型(LLM)与外部数据源、工具之间的通信方式。你可以把 MCP 看作是 AI 世界的 “USB-C 接口” —— 它让不同的 AI 模型能即插即用地接入各种外部系统(文件、数据库、API、工具等)。

这里有一个方便访问的 MCP 云服务端市场:阿里云百炼

三、手动构建

1、引入依赖

repositories {
	maven {
		name = 'Central Portal Snapshots'
		url = 'https://central.sonatype.com/repository/maven-snapshots/'
	}
}

dependencies {
	implementation 'io.modelcontextprotocol.sdk:mcp:0.11.0-SNAPSHOT'
	implementation 'io.modelcontextprotocol.sdk:mcp-spring-webflux:0.11.0-SNAPSHOT'
}

2、构建和使用

本文以阿里云百炼中的 Amap Maps,即高德地图 MCP 服务作为服务端。代码示例如下:

@Operation(summary = "访问高德mcp服务", description = "访问高德mcp服务", method = "POST")
@ApiOperationSupport(order = 15)
@PostMapping("test")
public McpSchema.CallToolResult test() {
    // 传输层
    McpClientTransport transport = HttpClientStreamableHttpTransport
            .builder("https://mcp.amap.com")
            .endpoint("/mcp?key=你的密钥")
            .objectMapper(new ObjectMapper())
            .build();

    // 客户端配置
    McpClient.AsyncSpec capabilities = McpClient
            .async(transport)
            .initializationTimeout(Duration.ofSeconds(10))
            .requestTimeout(Duration.ofSeconds(10))
            .roots(new ArrayList<>());

    // 初始化客户端
    McpAsyncClient client = capabilities.build();

    // 查询工具列表,调用工具
    try {
        return client.listTools()
                     .flatMap(tools -> {
                         log.info("工具列表: {}", tools);
                         return client.callTool(
                                 new McpSchema.CallToolRequest("maps_weather", Map.of("city", "成都"))
                         );
                     })
                     .block(Duration.ofSeconds(10));
    } finally {
        client.close();
    }
}

响应内容:

{
  "code": 200,
  "mdc": "8F697972-C38B-4813-8CA0-7FC6B987CE35",
  "message": "请求成功",
  "data": {
    "content": [
      {
        "type": "text",
        "text": "{\"city\":\"成都市\",\"forecasts\":[{\"date\":\"2025-07-24\",\"week\":\"4\",\"dayweather\":\"阵雨\",\"nightweather\":\"阵雨\",\"daytemp\":\"32\",\"nighttemp\":\"24\",\"daywind\":\"北\",\"nightwind\":\"北\",\"daypower\":\"1-3\",\"nightpower\":\"1-3\",\"daytemp_float\":\"32.0\",\"nighttemp_float\":\"24.0\"},{\"date\":\"2025-07-25\",\"week\":\"5\",\"dayweather\":\"阵雨\",\"nightweather\":\"中雨\",\"daytemp\":\"33\",\"nighttemp\":\"24\",\"daywind\":\"北\",\"nightwind\":\"北\",\"daypower\":\"1-3\",\"nightpower\":\"1-3\",\"daytemp_float\":\"33.0\",\"nighttemp_float\":\"24.0\"},{\"date\":\"2025-07-26\",\"week\":\"6\",\"dayweather\":\"阵雨\",\"nightweather\":\"多云\",\"daytemp\":\"33\",\"nighttemp\":\"24\",\"daywind\":\"北\",\"nightwind\":\"北\",\"daypower\":\"1-3\",\"nightpower\":\"1-3\",\"daytemp_float\":\"33.0\",\"nighttemp_float\":\"24.0\"},{\"date\":\"2025-07-27\",\"week\":\"7\",\"dayweather\":\"多云\",\"nightweather\":\"阵雨\",\"daytemp\":\"34\",\"nighttemp\":\"24\",\"daywind\":\"北\",\"nightwind\":\"北\",\"daypower\":\"1-3\",\"nightpower\":\"1-3\",\"daytemp_float\":\"34.0\",\"nighttemp_float\":\"24.0\"}]}"
      }
    ],
    "isError": false
  },
  "exceptionStack": null
}

四、自动构建

高德开放平台文档的 “快速接入 - Spring AI SSE 方式接入 MCP 服务” 为例,文档中的示例代码通过自动配置类,静态构建了 SSE 连接方式的 MCP 客户端,同样能成功访问服务。

五、碎碎念

1、公司组件

在实际项目中,公司的凭证组件完成了对客户端的封装,我只需要简单的 createMcpAsyncClient(pzbh)returnMcpAsyncClient(mcpClient) 就能方便的拿到客户端。而客户端的配置则在凭证页面进行管理,通过凭证编号来调用不同的客户端。

2、学习背景

我在最近项目中负责了 MCP 模块的设计与开发,也是第一次接触这个概念。时间紧张,难免浮于表层,到现在也只是一个使用者。也许后面会重新看一遍 MCP 的相关文档,深入梳理一下相关概念。没想到 Java 也逐渐和 AI 走到了一起,感觉很奇妙。