Spring AI 接入 MCP:工具调用不是“能调就行”,关键是边界治理

很多 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 依赖可以类似这样组织:

XML 复制代码
<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 配置文件:

XML 复制代码
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
    mcp:
      client:
        stdio:
          servers-configuration: classpath:/mcp-servers.json

mcp-servers.json 可以描述要启动或连接的 MCP Server。不同 MCP Server 的启动命令不同,比如 Node、Python 或独立二进制程序:

javascript 复制代码
{
  "mcpServers": {
    "order-tools": {
      "command": "java",
      "args": [
        "-jar",
        "order-mcp-server.jar"
      ]
    }
  }
}

在 Spring AI 中,MCP Client 可以把远端工具转换为 ToolCallbackProvider,再交给 ChatClient:

java 复制代码
@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 可以承担三类职责:

  • 请求前:根据用户、租户、场景决定允许哪些工具。
  • 调用中:记录模型选择工具的原因、参数、耗时。
  • 响应后:检查是否出现敏感字段、危险操作或异常结果。

示意代码如下:

java 复制代码
@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 一比一暴露成工具。这通常不是好设计。

比如内部订单系统可能有一个接口:

java 复制代码
POST /internal/order/update

它可以更新地址、备注、状态、金额等多个字段。如果直接包装成一个 MCP 工具,模型就拥有了一个过宽的操作面。

更合理的做法是面向 AI 场景重新设计工具:

java 复制代码
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,而是能进入真实系统的生产链路。

相关推荐
JJJennie7776 分钟前
Anthropic 发布 Claude Academy,AI 教学开始告别提示词速成班
人工智能
一杯仙妖气20 分钟前
Grok 4.6 正式发布!性能直接飙升,xAI 这次真的开始冲击第一梯队! 可免费试用 2026年8月20日 admin AI xAI
人工智能
白露与泡影24 分钟前
解密 Pi 的 Harness 工程:Agent 会话如何实现持久化与恢复
java·人工智能·算法
DogDaoDao31 分钟前
Magma:微软如何用一个模型打通数字与物理世界的 AI Agent
人工智能·微软·机器人·大模型·机器人模型·智能体·magma
DS随心转插件40 分钟前
Grok生成的html怎么导出——AI导出鸭:大模型结构化输出的“最后一公里”工程化解构
前端·人工智能·ai·html·豆包·deepseek·ai导出鸭
世隆科技1 小时前
武汉世隆科技有限公司获评2026湖北省科创“新物种“瞪羚企业
人工智能
yinmaisoft1 小时前
当 AI“长”进低代码:从外挂点缀到原生融合,软件开发正在经历怎样的变革?
人工智能·低代码
2301_786756601 小时前
今日未放榜!国自然等待期,别被往年“周五经验”绑架
大数据·人工智能·科研·国自然·国家自然科学基金
进军的码农1 小时前
政府采购联想工作站:授权链合规验证+投标资质+代理商选择全指南
人工智能·技术支持·联想工作站·代理商推荐·cuda部署
松小鼠呀1 小时前
我不敢再生孩子:ChatGPT 曾花 $2m 让他闭嘴,AI 巨头到底隐藏了什么秘密?
人工智能·安全·chatgpt·ai编程·科技热点