Agent如何传递不同类型的ID给MCP Server

1 概述

在Agent中,ID可以分两大类:一类是大模型推理出的业务ID(例如聊天记录中的ordier_id),另一类是Agent自身决定注入的上下文ID(例如user_id、tenant_id)。上下文ID 往往和系统的认证、权限相关,不能由大模型推理决定,必须由Agent完全把关。

Agent作为mcp client,发送的数据包如下:

复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "cancelOrder",
    "arguments": {  
      // 1. 这里放的是【大模型推理】出的业务ID
      "orderId": "20260811-ABC"
    },
    "_meta": {      
      // 2. 这里放的是【Agent自定决策】的上下文ID(Spring AI 自动放这里)
      "userId": "U-999",
      "tenantId": "TENANT-BJ",
      "traceId": "a1b2c3d4"
    }
  }
}

arguments字段:只包含大模型从用户聊天记录中提取的 orderId。

_meta字段:包含 Agent(例如你写的 Java 代码)决策后强行注入的 userId、tenantId 等。

2 Mcp Client 端(Agent应用)如何把 ID 塞进 _meta

在 Spring AI 中,你通过配置 AsyncMcpToolCallback 的 toolContextToMcpMetaConverter,告诉框架:"请把 Java 上下文里的 ID 自动转为 _meta 字段"。

复制代码
import org.springframework.ai.mcp.AsyncMcpToolCallback;
import org.springframework.ai.tool.ToolContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.Map;
import java.util.UUID;
import java.util.function.Function;

@Configuration
public class AgentClientConfig {

    @Bean
    public ChatClient chatClient(ChatClient.Builder builder) {
        return builder
            // 关键配置:定义如何将 ToolContext 转为 MCP 的 _meta
            .mcpToolCallbacks(List.of(AsyncMcpToolCallback.builder()
                .toolContextToMcpMetaConverter((Function<ToolContext, Map<String, Object>>) context -> {
                    // Agent 决策:从安全上下文或本地生成 ID
                    String userId = SecurityContextHolder.getContext().getAuthentication().getName(); // U-999
                    String tenantId = TenantContextHolder.getCurrentTenant(); // TENANT-BJ
                    String traceId = UUID.randomUUID().toString(); // a1b2c3d4
                    
                    // 返回的 Map 将自动成为 JSON 中的 _meta 对象
                    return Map.of(
                        "userId", userId,
                        "tenantId", tenantId,
                        "traceId", traceId
                    );
                })
                .build()))
            .build();
    }
}

业务调用代码(Service 层):

复制代码
@Service
public class OrderAgentService {
    private final ChatClient chatClient;

    public String handleUserRequest(String userInput) {
        // 用户输入:"帮我把订单 20260811-ABC 取消掉"
        // LLM推理出的ID会自动注入arguments字段
        // 上下文类型ID由上面的Converter自动注入_meta字段
        return chatClient.prompt(userInput)
            .call()
            .content();
    }
}

3 Mcp Server端如何拿到 _meta 里的 ID

在 MCP Server 端,Spring AI 会自动将收到的 JSON 解析并注入到 @Tool 方法的参数中。你需要让工具方法接收一个 ToolContext 参数,这个参数里就包含了 _meta 的所有内容。

Server 端工具定义代码:

复制代码
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.ToolContext;
import org.springframework.stereotype.Component;

@Component
public class OrderTools {

    @Tool(description = "根据订单ID取消订单")
    public String cancelOrder(
            // 1. 这里的 orderId 从 JSON 的 arguments 中获取(大模型推理)
            String orderId,
            
            // 2. 这里的 ToolContext 由框架自动注入,包含 _meta 的所有键值对
            ToolContext toolContext) {
        
        // 从 ToolContext 中提取 Agent 决策的 ID
        // 注意:这里拿到的 key 必须和 Client 端 Converter 里写的 key 一致
        String realUserId = (String) toolContext.getContext().get("userId");   // U-999
        String tenantId = (String) toolContext.getContext().get("tenantId");   // TENANT-BJ
        String traceId = (String) toolContext.getContext().get("traceId");     // a1b2c3d4

        // 安全校验:打印日志,确认 userId 绝对不是来自大模型
        System.out.println("安全校验:真实用户ID = " + realUserId);
        System.out.println("大模型提供的订单号 = " + orderId);

        // 执行业务,使用 realUserId 操作数据库,杜绝越权
        return orderService.cancel(realUserId, tenantId, orderId);
    }
}

4 总结:ID的流转路径

环节 动作 数据变化
用户输入 说了一句话 "取消 20260811-ABC"
大模型推理 提取业务参数 输出 arguments: {orderId: "20260811-ABC"}
Client Converter Agent 决策,注入上下文 自动生成 _meta: {userId: "U-999", ...}
网络传输 (JSON) 组装完整请求 params 里同时包含 arguments 和 _meta
Mcp Server 接收 框架解析 JSON 将 arguments 映射给 orderId 参数,将 _meta 映射给 ToolContext 参数
工具方法执行 获取并验证 业务代码从 ToolContext 拿 userId,抛弃大模型可能给出的任何用户标识
相关推荐
vx_Biye_Design4 分钟前
springboot旅游管理系统18006-计算机课程设计、毕业设计
java·spring boot·后端·python·elasticsearch·django·课程设计
半亩码田11 分钟前
C#转Python第4.7篇:logging:Python 的标准日志库
开发语言·python·c#
程序员老陆11 分钟前
从汇编层面理解 C++ 多线程
开发语言·c++·程序设计
谢亮_vipxieliang20 分钟前
深入理解 JavaScript 数据类型与类型转换
开发语言·javascript·ecmascript
IOT-Power28 分钟前
模板方法 + 策略模式
开发语言·c++
EatFan33 分钟前
2026 Rust 后端技术栈选型:Axum 0.8 + Tokio + SQLx 全链路怎么搭
开发语言·后端·rust·tokio·serde·axum·sqlx
外收内放33 分钟前
Python基础语法练习题(59-原始版本与优化版本)
开发语言·python
ASS-ASH36 分钟前
从力学与机械原理角度深度剖析:尊界V800刹车踏板支架断裂事件的技术逻辑
人工智能·python·数据可视化·机械工程·汽车安全·物理仿真·制动系统
xhy_070737 分钟前
AI 读了 .env,密钥会原样发给大模型吗?WES Code 的密钥打码(附实测)
人工智能·python·数据挖掘·flask·ai编程·wes code
2401_8888597138 分钟前
STM32H733 MPU、AXI、FMC学习
java·开发语言·stm32·spring