摘要:本文深入解析MCP协议及Streamable HTTP传输方式,结合Spring AI实战案例,手把手教你构建高效的AI工具调用系统。从协议原理到代码实现,从避坑指南到进阶技巧,一文掌握MCP核心技术。
引言
在AI应用开发中,如何让大模型安全、高效地调用外部工具,一直是开发者面临的挑战。传统的Function Call方式虽然简单,但在跨服务、跨语言场景下显得力不从心。
MCP(Model Context Protocol) 的出现,为这个问题提供了标准化的解决方案。本文将聚焦MCP的最新传输方式------Streamable HTTP,通过Spring AI框架的实战案例,带你快速掌握这一技术。
灵铠交互深耕AI交互领域,专注智能客服、音视频AI应用定制开发,助力企业快速落地轻量化、高可用的智能AI交互系统。

一、MCP协议:AI工具调用的"USB接口"
1.1 什么是MCP?
MCP(Model Context Protocol)是由Anthropic提出的开放协议,旨在标准化AI模型与外部工具的交互方式。
通俗理解:如果把AI模型比作电脑,那么MCP就是USB接口------无论什么工具(天气查询、数据库访问、文件操作),只要遵循MCP协议,AI都能即插即用。
1.2 MCP的三大传输方式
| 传输方式 | 底层协议 | 适用场景 | 特点 |
|---|---|---|---|
| STDIO | 标准输入输出 | 本地进程通信 | 简单,仅限同机 |
| SSE | HTTP + 服务端推送 | 服务端推送流式数据 | 单向流,兼容性好 |
| Streamable HTTP | HTTP/1.1 + 分块传输 | 双向流式通信 | 双向流、高性能、无状态 |
重点:Streamable HTTP是MCP协议在2025年引入的新传输方式,也是本文的核心内容。
二、Streamable HTTP:为什么它是最佳选择?
2.1 核心优势
Streamable HTTP的设计目标很明确:让MCP调用像普通HTTP请求一样简单,同时保持流式通信的高性能。
四大核心优势:
-
无状态通信:每个请求独立,Server不需维护会话状态,易于水平扩展
-
双向流式:支持请求和响应均为流式传输,实时性更强
-
标准兼容:基于HTTP/1.1,无需特殊协议支持,兼容现有基础设施
-
高性能:复用TCP连接,减少握手开销
2.2 工作原理
Streamable HTTP的核心是HTTP/1.1的分块传输编码(Chunked Transfer Encoding):
plain
客户端请求:
POST /api/mcp HTTP/1.1
Content-Type: application/json
Transfer-Encoding: chunked
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"getWeather"}}
服务端响应:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
{"type":"stream","content":"北京天气"}
{"type":"done","content":"北京:晴,26°C"}
关键点:
-
使用
Transfer-Encoding: chunked实现流式传输 -
每个JSON帧独立完整,可实时解析
-
通过TCP Keep-Alive复用连接,减少开销

三、实战:用Spring AI构建MCP Server
3.1 依赖配置
MCP Server的依赖配置取决于项目选择的Web框架。Spring AI提供了两种方案:
方案一:WebFlux(推荐用于流式场景)
xml
<dependencies>
<!-- WebFlux 响应式框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- MCP Server WebFlux 实现 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
方案二:WebMVC(传统同步场景)
xml
<dependencies>
<!-- 传统WebMVC框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MCP Server 核心实现 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
选择建议:
-
新项目 → WebMVC(学习成本低,生态成熟)
-
已有WebMVC项目 → WebMVC(保持一致)
-
追求高并发流式 → WebFlux(性能优势明显)
注意 :不要同时引入spring-boot-starter-web和spring-boot-starter-webflux!混用会导致依赖冲突。
3.2 定义MCP工具
使用@Tool注解定义工具,Spring AI会自动将其暴露为MCP服务:
java
@Component
public class WeatherTool {
@Tool(description = "根据城市名称查询当前实时天气信息")
public String getWeather(
@ToolParam(description = "城市名称,如:北京、上海") String city) {
// 调用外部天气API
String weatherData = callWeatherApi(city);
return String.format("""
{
"city": "%s",
"temperature": "26°C",
"weather": "晴",
"humidity": "45%%"
}""", city);
}
}
关键点:
-
@Tool注解的description属性至关重要,LLM会根据描述判断何时调用该工具 -
@ToolParam用于描述参数,帮助LLM理解如何传参
3.3 注册工具
在启动类中注册ToolCallbackProvider,将工具暴露为MCP服务:
java
@SpringBootApplication
public class McpServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpServerApplication.class, args);
}
@Bean
public ToolCallbackProvider weatherTools(WeatherTool weatherTool) {
return MethodToolCallbackProvider.builder()
.toolObjects(weatherTool)
.build();
}
}
原理解析:
-
MethodToolCallbackProvider扫描@Tool注解方法 -
解析方法签名和参数,生成JSON Schema
-
注册到MCP Server的工具列表
-
客户端连接后自动发现这些工具

四、实战:用Spring AI构建MCP Client
4.1 配置文件自动注入
Spring AI提供了强大的自动配置能力,只需在application.yaml中配置MCP Server地址,即可自动创建客户端:
yaml
spring:
ai:
mcp:
client:
enabled: true
type: SYNC
streamable-http:
connections:
my-mcp-server:
url: http://localhost:18083/mcpserver
endpoint: /api/mcp # 必须以/开头!
关键配置说明:
-
url:Server基础地址(不含端点路径) -
endpoint:MCP端点路径(**/**必须以开头,否则工具发现失败)
4.2 使用ChatClient调用工具
ChatClient是Spring AI的高级API,能够自动结合LLM和MCP工具,实现智能工具调用:
java
@RestController
public class SmartChatController {
@Autowired
private ChatClient.Builder chatClientBuilder;
@Autowired
private ToolCallbackProvider toolCallbackProvider;
@GetMapping("/smart-chat")
public String smartChat(@RequestParam String message) {
return chatClientBuilder
.defaultTools("my-mcp-server")
.build()
.prompt()
.user(message)
.toolCallbacks(toolCallbackProvider)
.call()
.content();
}
}
工作原理:
用户输入:"北京天气怎么样?"
↓
ChatClient将用户消息和工具列表发送给LLM
↓
LLM分析:"需要调用getWeather工具"
↓
Spring AI自动调用MCP Server的getWeather工具
↓
获取工具结果:{"city":"北京","temperature":"26°C"}
↓
LLM将工具结果总结为自然语言:"北京今天晴朗,气温26°C,适合出游。"
↓
返回给用户

五、避坑指南:context-path的陷阱
5.1 问题现象
在企业级应用中,context-path非常常见。但配置不当时,会导致MCP客户端无法连接服务端:
错误日志:
HttpClientStreamableHttpTransport - Connection refused
实际请求地址:http://localhost:18083/api/mcp(404)
正确地址应该是:http://localhost:18083/mcpserver/api/mcp
5.2 根本原因
HttpClientStreamableHttpTransport底层使用Java的URI.resolve()方法拼接URL。这个方法的行为取决于endpoint是否以/开头:
| 配置 | 结果 | 说明 |
|---|---|---|
baseUrl=/mcpserver/ + endpoint=api/mcp |
✅ /mcpserver/api/mcp |
正确:相对路径附加到baseUrl |
baseUrl=/mcpserver + endpoint=api/mcp |
❌ /api/mcp |
错误:替换了baseUrl最后一段 |
baseUrl=/mcpserver/ + endpoint=/api/mcp |
❌ /api/mcp |
错误:绝对路径覆盖了baseUrl |
5.3 正确配置方式
方式一:Spring AI自动配置(推荐)
yaml
spring:
ai:
mcp:
client:
streamable-http:
connections:
mcp-server:
url: http://localhost:18083/mcpserver
endpoint: /api/mcp # 必须以/开头
Spring AI会自动处理路径拼接,无需关注尾斜杠问题。
方式二:手动构建Transport
java
// ✅ 正确写法:baseUrl以/结尾 + endpoint不以/开头
HttpClientStreamableHttpTransport transport = HttpClientStreamableHttpTransport
.builder("http://127.0.0.1:18083/mcpserver/") // 注意尾斜杠
.endpoint("api/mcp") // 注意:没有前导/
.build();
六、进阶技巧
6.1 工具过滤:只让LLM看到需要的工具
当MCP Server包含大量工具时,可以使用McpToolFilter过滤工具,减少LLM的上下文压力:
java
// 只保留名称以"weather"开头的工具
SyncMcpToolCallbackProvider provider = SyncMcpToolCallbackProvider.builder()
.mcpClients(clients)
.toolFilter((conn, tool) -> tool.name().startsWith("weather"))
.build();
过滤策略示例:
java
// 按工具名称白名单过滤
Set<String> allowedTools = Set.of("getWeather", "getCurrentTime");
.toolFilter((conn, tool) -> allowedTools.contains(tool.name()))
// 按Server连接名称过滤(多MCP Server场景)
.toolFilter((conn, tool) -> conn.serverInfo().name().equals("weather-server"))
// 黑名单过滤(排除危险工具)
Set<String> blockedTools = Set.of("deleteUser", "dropDatabase");
.toolFilter((conn, tool) -> !blockedTools.contains(tool.name()))
6.2 跳过LLM总结:直接返回工具结果
在某些场景下,工具返回的结构化数据就是最终答案,不需要LLM二次总结:
问题 :默认的returnDirect参数对MCP工具不生效!
原因 :SyncMcpToolCallback未实现getToolMetadata()方法,returnDirect参数无法透传。
解决方案 :自定义ToolCallback继承SyncMcpToolCallback,重写元数据获取逻辑:
java
public class ReturnDirectSyncMcpToolCallback extends SyncMcpToolCallback {
private final boolean returnDirect;
@Override
public ToolMetadata getToolMetadata() {
return ToolMetadata.builder()
.returnDirect(returnDirect)
.build();
}
}
适用场景:
-
多智能体协作(减少延迟和Token消耗)
-
工具输出即最终答案(天气查询、订单查询)
-
AI工具已内置推理(LightRAG等)

七、总结
7.1 核心要点回顾
-
MCP协议:AI工具调用的标准化协议,实现"即插即用"
-
Streamable HTTP:基于HTTP/1.1的流式传输方式,兼顾性能与兼容性
-
Spring AI集成 :通过
@Tool注解和自动配置,快速构建MCP Server/Client -
避坑要点 :
endpoint必须以/开头,注意context-path的路径拼接 -
进阶技巧 :工具过滤减少上下文压力,
returnDirect跳过LLM总结
7.2 技术选型建议
| 场景 | 推荐方案 |
|---|---|
| 简单工具调用 | WebMVC + 自动配置 |
| 高并发流式场景 | WebFlux + Streamable HTTP |
| 多MCP Server | 配置文件定义多个连接 |
| 需要智能判断 | ChatClient + ToolCallbackProvider |
| 直接调用工具 | McpSyncClient |
7.3 下一步学习
-
阅读MCP协议规范
-
实践:搭建自己的MCP Server,集成更多工具
灵铠交互专注AI交互场景落地,深耕智能客服、音视频AI应用开发,为企业打造低延迟、高可用的智能化交互解决方案,助力业务AI数字化升级。

参考资源
标签 :#MCP#SpringAI#AI工具调用#StreamableHTTP#大模型应用
作者:灵铠互动技术团队
发布日期:2026年7月
