Spring AI 中的 MCP 服务端与客户端:实现工具与 AI 主机的解耦
- 作者

- 姓名
- Nino
- 职业
- Senior Tech Editor
在 Spring Boot 中构建大语言模型 (LLM) 应用时,开发者通常会采用一种简单直接的方法:在 AI 主机应用中创建带有 @Tool 注解的 Bean,并将其直接注入到 ChatClient 中。虽然这种模式在原型开发阶段非常高效,但随着应用规模的扩大,工具与主机的深度耦合会逐渐演变成维护噩梦。
本文将详细介绍如何使用 模型上下文协议 (Model Context Protocol, MCP) 来打破这种耦合。通过将工具逻辑抽离到独立的 MCP 服务端,并结合 n1n.ai 提供的稳定、高速的 LLM API(如 DeepSeek-V3 或 OpenAI o3),您可以构建出一个灵活、可扩展且易于维护的企业级 AI 架构。
耦合问题的深度解析
在传统的单体 AI 应用架构中,工具注册在 AI 服务内部。这种做法会带来以下几个核心痛点:
- 部署联动性:即使只是修改了一个简单的查询逻辑(例如修改
OrderTool中的 SQL 语句),也必须重新部署整个 AI 服务。在大型企业中,这意味着需要经过漫长的 CI/CD 流程和回归测试。 - 代码重复与碎片化:如果公司内部有多个 AI 应用(如客服机器人、内部 HR 助手、财务分析专家)都需要访问“订单查询”功能,你不得不将代码复制到每个项目中,或者维护一个极其复杂的共享库。
- 安全风险与信任边界:工具通常需要访问敏感数据库或内部 API。如果工具运行在 AI 主机的进程内,一旦工具代码出现内存泄漏或安全漏洞,将直接威胁到核心 AI 服务的稳定性。
- 静态清单限制:工具在应用启动时就已固定。如果需要在运行时动态添加或下线某个工具,通常需要重启服务,这对于追求零停机时间的系统来说是不可接受的。
MCP 协议:AI 时代的“插件标准”
MCP 是一种开放标准,旨在规范 AI 模型与外部数据源及工具之间的交互。在 MCP 架构中,AI 主机充当 MCP 客户端,而业务逻辑则封装在 MCP 服务端 中。
配合 n1n.ai 的多模型聚合能力,您可以轻松地在不同的 LLM 之间切换,同时保持工具集的稳定。无论您使用的是 Claude 3.5 Sonnet 还是最新的 OpenAI o3,只要它们支持工具调用,都可以通过 MCP 协议无缝对接您的业务逻辑。
架构设计方案
我们的方案包含两个相互独立的 Spring Boot 服务:
- MCP 工具服务端 (端口 8080):负责执行具体的业务逻辑,通过
@McpTool注解暴露接口,支持 Streamable HTTP 协议。 - AI 聊天服务 (端口 8081):作为面向用户的网关,使用 Spring AI 的
ChatClient,并作为 MCP 客户端动态发现远程工具。
第一步:构建独立 MCP 工具服务端
首先,在 pom.xml 中引入 Spring AI 专门为 MCP 服务端提供的 Starter:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
接下来,定义一个工具类。通过 @Tool 注解,Spring AI 会自动为该方法生成符合 OpenAI 或 Anthropic 规范的 JSON Schema。
@Service
public class OrderTool {
@Tool(description = "根据订单 ID 获取订单的当前状态和详细信息")
public Map<String, Object> getOrderStatus(
@ToolParam(description = "唯一的订单标识符,例如 ORD-12345")
String orderId) {
// 模拟业务逻辑:实际应用中这里会调用数据库或微服务接口
return Map.of(
"orderId", orderId,
"status", "已发货",
"estimatedDelivery", "2023-12-01",
"items", 3
);
}
}
在 application.properties 中配置服务端信息。我们选择 STREAMABLE 协议以支持长连接和会话管理:
spring.ai.mcp.server.name=business-tool-server
spring.ai.mcp.server.version=1.1.0
spring.ai.mcp.server.protocol=STREAMABLE
server.port=8080
第二步:实现 AI 聊天服务 (MCP 客户端)
客户端需要连接到上述工具服务器,并通过 n1n.ai 调用底层的 LLM。使用 n1n.ai 的优势在于其极高的可用性和对多种主流模型的统一封装。
引入客户端依赖:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
配置客户端连接参数,指向我们的工具服务端,并配置 n1n.ai 的 API Key:
spring.ai.mcp.client.toolcallback.enabled=true
spring.ai.mcp.client.connections.tool-server.url=http://localhost:8080/mcp
spring.ai.mcp.client.connections.tool-server.transport=STREAMABLE_HTTP
# 配置 n1n.ai 作为模型供应商
spring.ai.openai.base-url=https://api.n1n.ai/v1
spring.ai.openai.api-key=$\{N1N_API_KEY\}
spring.ai.openai.chat.options.model=gpt-4o
在配置类中,将 SyncMcpToolCallbackProvider 注入到 ChatClient。这一步非常关键,它使得 ChatClient 具备了动态从远程服务器获取工具清单的能力:
@Configuration
public class ChatConfig {
@Bean
public ChatClient chatClient(ChatModel chatModel,
SyncMcpToolCallbackProvider toolCallbackProvider) {
return ChatClient.builder(chatModel)
.defaultTools(toolCallbackProvider) // 自动注入远程工具注册表
.build();
}
}
核心优势:动态发现与热更新
MCP 架构最令人兴奋的特性是 动态发现 (Dynamic Discovery)。由于 SyncMcpToolCallbackProvider 在每次调用或根据刷新策略会重新获取工具列表,您可以在不重启 AI 聊天服务的情况下,直接上线新的工具。
对比分析表:
| 维度 | 内置工具 (耦合模式) | MCP 工具 (解耦模式) |
|---|---|---|
| 部署频率 | 随 AI 服务一同部署 | 独立部署,互不干扰 |
| 复用性 | 难以跨应用复用 | 一次部署,全公司 AI 应用共享 |
| 开发语言 | 必须是 Java/Spring | 可以是 Python, Go, Node.js 等 |
| 故障隔离 | 工具崩溃会导致 AI 服务宕机 | 工具服务端故障仅影响特定功能 |
生产环境建议:无状态模式
在容器化部署(如 Kubernetes)中,为了实现更好的水平扩展,建议将 MCP 服务端配置为 无状态 (STATELESS) 模式:
spring.ai.mcp.server.protocol=STATELESS
在无状态模式下,每个请求都包含完整的上下文信息,负载均衡器可以将请求分发到任何一个工具服务端实例,从而极大提升了系统的并发处理能力和容错性。
总结
通过将 Spring AI 与 MCP 协议相结合,我们成功地将业务工具从 AI 核心逻辑中解耦出来。这种架构不仅提升了代码的可维护性,还为未来的 Agent 编排和多模型协作打下了坚实的基础。配合 n1n.ai 提供的强大模型底座,您可以更专注于业务价值的实现,而非基础设施的维护。
立即在 n1n.ai 获取免费 API Key,开启您的解耦式 AI 开发之旅。
Get a free API key at n1n.ai。