热点解读:AI Agent 工具调用如何更可靠?Spring AI + MCP 实战:参数校验...

22 阅读1分钟

热点解读:AI Agent 工具调用如何更可靠?Spring AI + MCP 实战:参数校验、权限校验与人工确认

引言

AI Agent 不仅能生成文本,还可以调用查询、支付、发布、数据库操作等外部工具。工具调用能力越强,潜在风险也越高:模型可能生成错误参数,用户权限可能不足,高风险操作还可能被误执行。本文结合 Spring AI 与 MCP,介绍如何通过参数校验、权限校验、人工确认和审计机制,构建更可靠的 Agent 工具调用链路。

一、MCP 如何连接 AI Agent 与外部工具

MCP(Model Context Protocol)可以理解为 AI 模型访问外部工具和数据源的一套标准协议。通过 MCP Server,应用可以统一暴露工具、资源和提示词;Agent 则根据模型输出决定是否调用这些工具。

典型调用链路如下:

用户请求
   ↓
AI Agent
   ↓
模型生成工具调用请求
   ↓
MCP Client
   ↓
MCP Server
   ↓
参数校验、权限校验、业务执行
   ↓
返回工具结果

在 Spring AI 中,可以将 MCP 工具注册到 Agent 所使用的 ChatClient 中。以查询订单为例,工具定义应明确参数类型和约束:

@Tool(description = "根据订单号查询订单详情")
public OrderDetail getOrder(
        @ToolParam(description = "订单号,格式为 ORD-数字") String orderId) {
    return orderService.findById(orderId);
}

模型看到工具描述后,可能生成如下调用:

{
  "name": "getOrder",
  "arguments": {
    "orderId": "ORD-10001"
  }
}

需要注意的是,模型生成的参数只能作为“请求建议”,不能直接视为可信输入。工具描述可以帮助模型减少错误,但不能替代服务端校验。真正的安全边界必须位于 MCP Server 或业务服务端。

实际应用中,可以把低风险工具和高风险工具分开管理。例如订单查询、库存查询属于读操作,可以自动执行;退款、删除、发布、修改权限等操作,则必须进入更严格的控制流程。

二、参数校验:不要只依赖模型生成结果

AI Agent 的参数错误通常来自三类问题:

  1. 参数格式不符合要求;
  2. 参数之间存在业务冲突;
  3. 参数虽然格式正确,但超出业务范围。

例如,模型可能将“退款 100 元”生成负数、超出订单金额,或者传入一个不存在的订单号。因此,工具方法需要使用标准参数校验,并在业务层进行二次校验。

public record RefundRequest(
        @NotBlank String orderId,
        @Positive BigDecimal amount,
        @Size(max = 200) String reason) {
}

@Tool(description = "为订单申请退款,需要用户明确授权")
public RefundResult refund(@Valid RefundRequest request) {
    validator.validate(request);
    return refundService.apply(request);
}

在 Spring Boot 中,可以使用 Bean Validation 对字段进行基础校验:

if (request.amount().compareTo(order.amount()) > 0) {
    throw new BusinessException("退款金额不能超过订单金额");
}
if (!order.canRefund()) {
    throw new BusinessException("当前订单状态不允许退款");
}

参数校验建议分为三层:

  • 协议层校验:检查字段是否存在、类型是否正确;
  • 服务层校验:检查格式、长度、枚举值和数值范围;
  • 业务层校验:检查资源状态、金额关系和操作前置条件。

MCP 工具返回错误时,不建议返回堆栈信息或数据库细节,而应提供结构化、可理解的错误结果:

{
  "success": false,
  "code": "ORDER_NOT_REFUNDABLE",
  "message": "订单当前状态不支持退款"
}

这样模型可以根据错误信息向用户解释原因,或者要求用户补充信息,而不是不断重试同一个错误调用。

在实际应用中,参数校验尤其适用于数据库查询、工单创建、云资源操作和财务类工具。对于分页大小、时间范围、批量数量等参数,还需要设置上限,避免模型生成大范围查询导致系统压力。

三、权限校验:工具可见不等于用户可执行

Agent 能看到某个工具,并不意味着当前用户有权调用它。权限校验不能只放在提示词中,也不能只通过模型判断。

例如,提示词中写“只有管理员才能删除用户”,模型可能遵守,也可能因为上下文混乱而发起调用。因此,MCP Server 必须从认证上下文中获取当前用户身份,并在服务端完成授权判断。

@Tool(description = "删除指定用户,仅管理员可调用")
public DeleteResult deleteUser(String userId) {
    UserContext user = UserContext.current();

    if (!permissionService.hasRole(user, "ADMIN")) {
        throw new AccessDeniedException("无权执行删除操作");
    }
    return userService.delete(userId);
}

实际系统中建议采用 RBAC 或 ABAC 模型:

  • RBAC:根据用户角色控制工具权限,例如管理员、运维人员、普通用户;
  • ABAC:结合用户、资源、环境和操作条件判断,例如只能操作本人所属项目的资源;
  • 租户隔离:多租户系统中必须校验租户 ID,不能只依赖模型传入的租户参数。

一个重要原则是:租户、用户 ID、调用来源等安全字段,不应完全信任模型传参。系统应从登录态、Token 或服务间调用上下文中获取:

String tenantId = SecurityContext.currentTenant();
String operatorId = SecurityContext.currentUser();

resourceService.update(tenantId, operatorId, request);

对于 MCP Server,还应在连接层完成身份认证,例如使用 OAuth 2.0、JWT 或网关统一鉴权。工具层则负责细粒度授权和资源归属校验。

实际应用中,权限校验适用于云资源删除、生产环境发布、数据库写入、工单审批等场景。即使模型被提示注入攻击影响,服务端权限边界仍然可以阻止越权操作。

四、人工确认:为高风险操作增加“刹车”

参数正确、权限通过,并不代表操作一定应该自动执行。对具有不可逆性、资金影响或生产影响的工具,应增加人工确认环节。

例如,Agent 识别到用户想要退款时,可以先生成待确认请求,而不是直接调用退款接口:

public Confirmation createConfirmation(RefundRequest request) {
    String token = confirmationService.create(
            "REFUND", request, Duration.ofMinutes(5));
    return new Confirmation(token, "确认退款 " + request.amount() + " 元?");
}

前端向用户展示操作摘要:

操作:申请退款
订单:ORD-10001
金额:100.00 元
原因:商品质量问题
有效期:5 分钟
[确认执行] [取消]

用户确认后,服务端根据一次性确认令牌执行操作:

public RefundResult execute(String token) {
    Confirmation confirmation =
            confirmationService.consume(token);

    permissionService.check(confirmation.userId());
    return refundService.apply(confirmation.request());
}

确认令牌应满足以下要求:

  • 与具体用户、租户和操作绑定;
  • 设置短时间有效期;
  • 只能消费一次;
  • 绑定原始参数摘要,防止参数被替换;
  • 记录确认时间、确认人和请求来源。

人工确认并不意味着所有工具都需要弹窗。可以按照风险等级分类:

  • 低风险:查询、统计、读取配置,可自动执行;
  • 中风险:创建工单、修改非生产配置,可在特定条件下自动执行;
  • 高风险:删除资源、退款、发布生产版本,必须人工确认;
  • 极高风险:批量删除、权限提升、跨租户操作,应要求双人审批或直接禁止 Agent 执行。

这一机制适合运维自动化、财务助手、客服退款、云资源管理等场景,可以有效降低“模型理解正确但操作不该自动执行”的风险。

最佳实践

  1. 工具设计遵循最小权限原则
    每个工具只完成一个明确动作,避免暴露“执行任意 SQL”“执行任意 Shell”这类高风险接口。

  2. 模型校验与服务端校验分离
    通过工具 Schema、注解和提示词帮助模型生成正确参数,但最终校验必须由 MCP Server 和业务服务完成。

  3. 按风险等级设计执行策略
    为工具增加风险级别、是否需要确认、是否允许批量执行等元数据,避免所有工具采用同一种调用方式。

  4. 建立完整审计链路
    记录用户、租户、会话、模型版本、工具名称、参数摘要、授权结果、确认结果和执行结果。敏感参数应脱敏或加密存储。

  5. 保证关键操作幂等
    退款、发布、创建资源等操作应使用幂等键,避免模型重试或网络超时造成重复执行。

总结

Spring AI 与 MCP 为 Agent 接入外部工具提供了标准化能力,但可靠性不能只依赖模型能力。实际系统应将模型输出视为不可信请求,通过服务端参数校验、身份与权限校验、风险分级、人工确认和审计机制构建多层防线。只有把 AI 的推理能力与传统系统的安全边界结合起来,才能让 Agent 在真实生产环境中做到可控、可追踪、可回滚。