很多 Java 团队第一次做 AI 工具调用时,容易把问题简化成一句话:把内部接口注册成工具,让大模型自己决定什么时候调用。Demo 阶段这没问题,但一进入企业系统,很快会遇到三个现实问题:哪些工具能被调用、调用前后怎么审计、模型误调用时怎么兜底。
MCP 的价值不只是“让模型能调用工具”。它更像一层工具协议,把文件、数据库、内部 API、业务系统能力包装成 AI 应用可发现、可调用的上下文能力。而 Spring AI 的价值,是把这些能力纳入 Spring Boot 熟悉的配置、Bean、Advisor、Observability 和权限治理体系里。
本文只讲一个核心问题:在 Spring AI 里接入 MCP 时,不要把 MCP 工具裸塞给 ChatClient,应该把工具调用放进可治理的调用链。
1. MCP 解决的不是接口调用,而是工具协议统一
如果只是让大模型调用一个 Java 方法,Spring AI 自身的 Tool Calling 已经够用。比如把一个 @Tool 方法暴露给模型,模型根据上下文选择是否调用。
但企业系统里,工具来源往往不止一种:
- 本地 Java 方法
- 远程订单系统 API
- CRM、工单、知识库、数据库查询
- 文件系统、浏览器、DevOps 平台
- 不同团队维护的工具服务
如果每个工具都按模型厂商的 function calling 格式单独接入,最终会变成一堆适配器。MCP 的思路是把这些能力抽象成标准协议,由 MCP Server 暴露工具、资源、提示词等能力,MCP Client 负责连接和调用。
在 Spring AI 中,应用可以作为 MCP Client 连接一个或多个 MCP Server,并把服务端暴露出来的工具转换成 Spring AI 的 Tool Callback,交给 ChatClient 使用。
一个典型链路如下:
这条链路里最容易被忽略的是 Advisor。很多示例会直接把工具挂到 ChatClient 上,但真实项目中,Advisor 往往才是工具治理的关键位置。
2. 为什么不能直接裸用 MCP 工具
假设我们接入了一个订单 MCP Server,里面有这些工具:
- queryOrder
- refundOrder
- updateShippingAddress
- queryUserProfile
如果直接把全部工具交给模型,风险很明显:模型可能在用户只是咨询时触发写操作,也可能在没有权限校验的情况下查询敏感信息。
更稳妥的做法是把工具分层:
- 只读工具:允许模型在问答中自动调用,比如订单查询、库存查询。
- 高风险工具:需要业务确认,比如退款、改地址、创建工单。
- 敏感工具:需要额外鉴权,比如用户画像、合同、财务数据。
- 禁用工具:当前业务场景不暴露给模型。
MCP 负责统一工具协议,Spring AI 负责把这些工具放进工程治理体系。二者结合时,不应该让模型成为最终权限决策者。
3. Spring Boot 中的接入方式
Spring AI 官方文档提供了 MCP Client Boot Starter。具体依赖名称和配置项可能随 Spring AI 版本变化,实际项目应以当前官方文档为准。下面代码展示的是接入思路,而不是完整脚手架。
Maven 依赖可以类似这样组织:
<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>一个常见配置是通过 stdio 或 SSE 连接 MCP Server。例如本地 stdio 方式通常会引用一个 MCP Server 配置文件:
spring: ai: openai: api-key: ${OPENAI_API_KEY} mcp: client: stdio: servers-configuration: classpath:/mcp-servers.jsonmcp-servers.json 可以描述要启动或连接的 MCP Server。不同 MCP Server 的启动命令不同,比如 Node、Python 或独立二进制程序:
{ "mcpServers": { "order-tools": { "command": "java", "args": [ "-jar", "order-mcp-server.jar" ] } } }在 Spring AI 中,MCP Client 可以把远端工具转换为 ToolCallbackProvider,再交给 ChatClient:
@Configuration class AiConfig { @Bean ChatClient chatClient( ChatClient.Builder builder, ToolCallbackProvider toolCallbackProvider ) { return builder .defaultSystem(""" 你是订单客服助手。 查询类问题可以使用工具。 涉及退款、改地址、取消订单时,必须先向用户确认。 """) .defaultToolCallbacks(toolCallbackProvider) .build(); } }这段代码的重点不是 API 本身,而是边界:系统提示词声明业务规则,工具回调提供可调用能力,但这还不够。因为提示词不是权限系统,不能只靠它防止误调用。
4. 用 Advisor 给工具调用加一道工程边界
Spring AI 的 Advisor 机制可以参与 ChatClient 调用链,适合放置记忆、RAG、日志、策略控制等逻辑。对于 MCP 工具调用,Advisor 可以承担三类职责:
- 请求前:根据用户、租户、场景决定允许哪些工具。
- 调用中:记录模型选择工具的原因、参数、耗时。
- 响应后:检查是否出现敏感字段、危险操作或异常结果。
示意代码如下:
@Component class ToolGovernanceService { Set<String> allowedTools(String userRole, String scene) { if ("customer_service".equals(userRole)) { return Set.of("queryOrder", "queryLogistics"); } if ("manager".equals(userRole)) { return Set.of("queryOrder", "queryLogistics", "createRefundRequest"); } return Set.of(); } void audit(String userId, String toolName, Map<String, Object> args) { // 写入审计日志:用户、工具名、参数摘要、traceId、时间 } }真实项目中,工具过滤最好不要写死在 Prompt 里,而应该落在服务端策略中。原因很简单:Prompt 可以被用户输入干扰,而服务端权限判断必须稳定、可测试、可追踪。
如果当前版本的 Spring AI 暂时不能满足你对“动态过滤工具”的细粒度要求,也可以在 MCP Server 层做隔离:不同业务场景连接不同 MCP Server,或者同一个 Server 根据调用方身份只暴露部分工具。
5. MCP Server 侧也要控制工具粒度
很多团队设计 MCP Server 时,会直接把内部 API 一比一暴露成工具。这通常不是好设计。
比如内部订单系统可能有一个接口:
POST /internal/order/update它可以更新地址、备注、状态、金额等多个字段。如果直接包装成一个 MCP 工具,模型就拥有了一个过宽的操作面。
更合理的做法是面向 AI 场景重新设计工具:
public class OrderTools { @Tool(description = "根据订单号查询订单基础信息,只返回客服问答需要的字段") public OrderView queryOrder(String orderNo) { // 调用内部订单服务,并裁剪敏感字段 } @Tool(description = "创建退款申请,不直接执行退款,需要人工或规则系统审核") public RefundTicket createRefundRequest(String orderNo, String reason) { // 只创建申请,不直接退款 } }工具不是内部接口的透传层,而是 AI 应用的业务能力边界。它应该具备三个特征:
- 参数少且语义明确。
- 返回值经过裁剪,不泄露无关字段。
- 高风险操作改成“提交申请”或“生成草稿”,不要直接执行最终动作。
这也是 Java 后端经验能发挥价值的地方。AI 应用不是绕过工程体系,而是更依赖工程体系。
6. 实际落地时的几个坑
第一个坑是把 MCP 当成 API 网关。MCP 不是替代 REST、RPC 或消息队列的通用网关,它面向的是 AI Client 与工具之间的上下文协议。业务系统仍然应该保留原有 API 边界、鉴权、限流和审计。
第二个坑是只记录最终回答,不记录工具调用。AI 应用排查问题时,只看模型回复基本没用。至少要记录用户问题、模型选择的工具、工具参数摘要、工具响应摘要、耗时、异常和 traceId。
第三个坑是把写操作交给模型自动执行。即使模型能力再强,也不应该让它在没有确认机制的情况下完成退款、删除、发券、改配置等动作。更稳的方案是“模型生成操作意图,业务系统执行规则判断”。
第四个坑是工具描述写得太像接口文档。工具描述是给模型看的,不是给后端开发看的。它应该说明“什么时候用、不能用来做什么、参数怎么填”,而不是只写“查询订单接口”。
7. 一个更稳的企业架构
企业项目里,可以把 Spring AI + MCP 工具调用拆成四层:
- Chat 层:负责会话、流式响应、用户体验。
- Governance 层:负责 Advisor、权限、审计、工具策略。
- MCP 层:负责连接不同 MCP Server。
- Business Tool 层:负责真正访问订单、CRM、知识库等系统。
这样做的好处是职责清楚。模型负责理解意图和组织回答,MCP 负责工具协议,Spring Boot 负责治理和集成,业务系统负责最终规则。
MCP 让 AI 应用接入工具变得统一,但统一不等于放开。对 Java 后端团队来说,真正值得投入的不是把更多接口暴露给模型,而是把工具设计成可控、可审计、可回滚的业务能力。只有这样,Spring AI 接入 MCP 才不会停留在 Demo,而是能进入真实系统的生产链路。