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,抛弃大模型可能给出的任何用户标识
相关推荐
染指111013 分钟前
162.Agent-LangGraph-检查点的作用
人工智能·python·langchain·agents
飞浪纪元[FWC–FE]16 分钟前
从零到一键绿:Qt 5.14.2 + VS2019 开发环境搭建、Kit 套件配置与构建错误修复完全手册
开发语言·qt
Wang's Blog27 分钟前
Java 项目实战:交友项目 - 联系人列表
java·开发语言·交友
我命由我1234531 分钟前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
架构师伯子明33 分钟前
FFmpeg C++学习(一):编译和demo
开发语言·c++·学习
海域云SeaArea_36 分钟前
Windows Server 2008 R2 从零安装 IIS7.5(二):php.ini 配置
开发语言·windows·php
叼烟扛炮1 小时前
[LangChain] 学习笔记(02):LCEL 链式调用与动态模型配置实战
服务器·开发语言·网络·笔记·学习·langchain
xixingzhe21 小时前
图表中同比与环比的区别:看趋势还是看变化?
开发语言·python
andyweike1 小时前
Swift
开发语言·ios·swift
纪念 2291 小时前
C++算法(六)
开发语言·c++·算法