AI Agent 协议演进:从 MCP 到 ACP 的架构对比与未来展望

Multi-Agent 协作的基石:协议标准化探索之路

基于 Google Gemini CLI 和 OpenAI Codex 源码的深度技术剖析

源码版本说明 本文基于以下版本的源码分析:

  • Gemini CLI: v0.10.0-nightly (2025-10-13)
  • Codex CLI: v0.2.0-alpha.2 (2025-11-25)
  • MCP 协议: 2025-06-18 规范

摘要

  • 随着 AI Agent 的快速发展,如何让不同的 Agent 之间高效协作、如何标准化 Agent 与外部工具的交互,已成为业界关注的焦点。
  • 本文通过深入分析 Google Gemini CLIOpenAI Codex 的源码实现,对比两大主流协议------MCP (Model Context Protocol)ACP (Agent Context Protocol) 的设计理念、技术架构和应用场景,并探讨 AI Agent 协议的未来发展方向。

一、协议背景:为什么需要标准化?

1.1 当前 AI Agent 生态的痛点

在协议标准化之前,AI Agent 面临以下核心挑战:

痛点 描述 影响
孤岛效应 每个 Agent 使用私有协议,无法互操作 无法构建 Multi-Agent 系统
工具集成困难 每个工具需要为不同 Agent 重复开发适配器 开发成本高,生态碎片化
状态不可恢复 会话状态无法持久化或跨系统传递 用户体验差,无法长期任务
安全性缺失 缺乏统一的权限控制和审计机制 企业级部署存在风险

1.2 协议标准化的价值

graph TB subgraph before["标准化前:N × M 问题"] A1["Agent1"] --> T1A["Tool1 (适配器 1-1)"] A1 --> T2A["Tool2 (适配器 1-2)"] A1 --> T3A["Tool3 (适配器 1-3)"] A2["Agent2"] --> T1B["Tool1 (适配器 2-1)"] A2 --> T2B["Tool2 (适配器 2-2)"] A2 --> T3B["Tool3 (适配器 2-3)"] style before fill:#ffebee,stroke:#c62828 end subgraph after["标准化后:N + M 问题"] Agent1["Agent1"] --> Protocol["MCP/ACP 协议层"] Agent2["Agent2"] --> Protocol Agent3["Agent3"] --> Protocol Protocol --> Tool1["Tool1"] Protocol --> Tool2["Tool2"] Protocol --> Tool3["Tool3"] style after fill:#e8f5e9,stroke:#2e7d32 style Protocol fill:#fff3e0,stroke:#e65100 end

对比结果:

  • 标准化前 : 需要 N × M 个适配器 (每个 Agent 为每个 Tool 开发专用适配器)
  • 标准化后 : 仅需 N + M 个适配器 (Agent 实现协议 + Tool 实现协议)

二、MCP (Model Context Protocol) 深度解析

2.1 MCP 协议概述

MCP 由 Anthropic 提出,是一个专注于 Agent 与外部工具/资源交互 的标准协议。

核心设计理念:

  • 📦 资源抽象: 将外部系统(数据库、API、文件系统)抽象为统一的 Resource
  • 🔧 工具调用: 标准化的工具发现、调用和响应流程
  • 🔌 传输无关: 支持 stdio、SSE、HTTP 等多种传输方式
  • 🔐 权限控制: 内置的工具执行审批机制

协议版本 : 2025-06-18 (来源: Codex mcp-types/src/lib.rs)

2.2 Gemini CLI 的 MCP 实现架构

核心组件:
typescript 复制代码
// packages/core/src/tools/mcp-client.ts
export class McpClient {
  private client: Client;                    // MCP SDK Client
  private transport: Transport;              // 传输层 (stdio/SSE/HTTP)
  private status: MCPServerStatus;           // 连接状态

  async connect(): Promise<void> {
    // 1. 建立传输连接
    this.transport = createTransport(this.serverConfig);

    // 2. 初始化 MCP Client
    this.client = new Client({
      name: 'gemini-cli',
      version: '0.10.0'
    }, {
      capabilities: {
        roots: { listChanged: true },
        sampling: {}
      }
    });

    // 3. 连接到 MCP Server
    await this.client.connect(this.transport);
  }

  async discover(): Promise<void> {
    // 发现工具
    const tools = await this.client.listTools();

    // 发现资源
    const resources = await this.client.listResources();

    // 发现 Prompts
    const prompts = await this.client.listPrompts();
  }
}
工具调用流程:
typescript 复制代码
// packages/core/src/tools/mcp-tool.ts
class DiscoveredMCPToolInvocation {
  async execute(signal: AbortSignal): Promise<ToolResult> {
    // 1. 检查是否需要用户批准
    const confirmationDetails = await this.shouldConfirmExecute(signal);
    if (confirmationDetails) {
      await this.waitForUserApproval(confirmationDetails);
    }

    // 2. 调用 MCP Tool
    const functionCalls: FunctionCall[] = [{
      name: this.serverToolName,
      args: this.params
    }];

    const rawResponseParts = await this.mcpTool.callToolBatch(
      functionCalls,
      signal
    );

    // 3. 处理响应
    return this.parseToolResponse(rawResponseParts);
  }
}

2.3 Codex 的 MCP 实现架构

核心组件 (基于 Rust):
rust 复制代码
// codex-rs/core/src/mcp_connection_manager.rs
pub struct McpConnectionManager {
    clients: HashMap<String, AsyncManagedClient>,
    elicitation_requests: ElicitationRequestManager,
    tool_timeout: Duration,
}

impl McpConnectionManager {
    pub async fn connect_server(
        &self,
        server_name: String,
        config: McpServerConfig
    ) -> Result<()> {
        // 1. 创建 RmcpClient (Rust MCP Client)
        let client = RmcpClient::new(
            Implementation {
                name: "codex".to_string(),
                version: env!("CARGO_PKG_VERSION").to_string(),
            },
            ClientCapabilities {
                roots: Some(RootsCapability { list_changed: true }),
                sampling: Some(SamplingCapability {}),
            },
        );

        // 2. 建立传输连接
        let transport = match &config.transport {
            StdioTransport => create_stdio_transport(config),
            SseTransport => create_sse_transport(config),
        };

        await client.connect(transport)?;

        // 3. 列举并限定工具
        let tools = client.list_tools().await?;
        let qualified_tools = self.qualify_tools(server_name, tools);

        Ok(())
    }
}
工具名称限定 (Fully Qualified Names):
rust 复制代码
// codex-rs/core/src/mcp_connection_manager.rs
const MCP_TOOL_NAME_DELIMITER: &str = "__";
const MAX_TOOL_NAME_LENGTH: usize = 64;

fn qualify_tools(tools: Vec<ToolInfo>) -> HashMap<String, ToolInfo> {
    let mut qualified_tools = HashMap::new();

    for tool in tools {
        // 格式: mcp__<server_name>__<tool_name>
        let qualified_name = format!(
            "mcp{}{}{}{}",
            MCP_TOOL_NAME_DELIMITER,
            tool.server_name,
            MCP_TOOL_NAME_DELIMITER,
            tool.tool_name
        );

        // 超长则使用 SHA1 截断
        if qualified_name.len() > MAX_TOOL_NAME_LENGTH {
            let hash = sha1::Sha1::digest(qualified_name.as_bytes());
            qualified_name = format!("{}_{:x}",
                &qualified_name[..48],
                hash
            );
        }

        qualified_tools.insert(qualified_name, tool);
    }

    qualified_tools
}

2.4 MCP 协议消息示例

工具列表请求:
json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}
工具列表响应:
json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "read_file",
        "description": "Read contents of a file",
        "inputSchema": {
          "type": "object",
          "properties": {
            "path": { "type": "string" }
          },
          "required": ["path"]
        }
      }
    ]
  }
}
工具调用请求:
json 复制代码
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "read_file",
    "arguments": {
      "path": "/etc/hosts"
    }
  }
}
工具调用响应:
json 复制代码
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "127.0.0.1 localhost\n::1 localhost"
      }
    ],
    "isError": false
  }
}

三、ACP (Agent Client Protocol) 官方标准深度解析

3.1 ACP 协议概述

ACP (Agent Client Protocol) 是由 Zed Industries2025 年 8 月 正式发布的开放标准,旨在标准化代码编辑器/IDE 与 AI 编码代理之间的通信

📖 官方资源

核心定位 : ACP 类似于 LSP (Language Server Protocol) 在语言服务器领域的作用,解决了 Agent-Editor 集成的 N×M 问题

graph LR subgraph before["ACP 之前:N × M 集成问题"] E1["Editor1"] --> A1A["Agent1 (定制集成)"] E1 --> A2A["Agent2 (定制集成)"] E1 --> A3A["Agent3 (定制集成)"] E2["Editor2"] --> A1B["Agent1 (重复开发)"] E2 --> A2B["Agent2 (重复开发)"] style before fill:#ffebee,stroke:#c62828 end subgraph after["ACP 之后:N + M 标准化"] Editor1["Editor1"] --> ACP["ACP 协议层"] Editor2["Editor2"] --> ACP Editor3["Editor3"] --> ACP ACP --> Agent1["Agent1"] ACP --> Agent2["Agent2"] ACP --> Agent3["Agent3"] style after fill:#e8f5e9,stroke:#2e7d32 style ACP fill:#e3f2fd,stroke:#1565c0 end

核心设计理念:

  • 📝 标准化通信: 基于 JSON-RPC 2.0,使用 stdio 传输
  • 🔌 即插即用: 任何支持 ACP 的编辑器都能使用任何 ACP 代理
  • 🎯 代理自主性: 代理作为编辑器的子进程运行,可自主修改代码
  • 🔐 权限控制: 明确的权限请求机制(文件系统、终端等)
  • 🔄 会话管理: 支持会话创建、加载、状态追踪
  • 📊 能力协商: 初始化时协商双方支持的功能

3.2 ACP 协议架构

通信模型

ACP 遵循 JSON-RPC 2.0 规范,定义了两种消息类型:

消息类型 描述 是否需要响应
Methods 请求-响应对,期望返回结果或错误 ✅ 是
Notifications 单向消息,用于事件通知 ❌ 否
角色定义
typescript 复制代码
// Agent:使用生成式 AI 自主修改代码的程序
interface Agent {
  // === 基线方法(必须实现) ===
  initialize(): InitializeResult;           // 初始化和能力协商
  authenticate?(): AuthResult;              // 身份验证(可选)
  'session/new'(): SessionId;              // 创建新会话
  'session/prompt'(msg: Message): void;    // 接收用户提示词

  // === 可选方法 ===
  'session/load'?(id: string): Session;    // 加载已有会话
  'session/set_mode'?(mode: string): void; // 设置模式(如 edit/chat)

  // === 通知 ===
  'session/cancel'(): void;                // 取消当前操作
}

// Client:提供用户界面的代码编辑器/IDE
interface Client {
  // === 基线方法(必须实现) ===
  'session/request_permission'(req: PermissionRequest): PermissionResult;

  // === 可选方法(根据能力) ===
  'fs/read_text_file'?(path: string): string;
  'fs/write_text_file'?(path: string, content: string): void;
  'terminal/create'?(cmd: string): TerminalId;
  'terminal/output'?(id: TerminalId): TerminalOutput;

  // === 通知 ===
  'session/update'(update: SessionUpdate): void;  // 会话状态更新
}

3.3 ACP 核心流程

1. 初始化流程
typescript 复制代码
// Client → Agent
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "initialize",
  "params": {
    "protocolVersion": 1,
    "clientCapabilities": {
      "fs": {
        "readTextFile": true,
        "writeTextFile": true
      },
      "terminal": true
    },
    "clientInfo": {
      "name": "vscode",
      "title": "Visual Studio Code",
      "version": "1.95.0"
    }
  }
}

// Agent → Client
{
  "jsonrpc": "2.0",
  "id": 0,
  "result": {
    "protocolVersion": 1,
    "agentCapabilities": {
      "loadSession": true,
      "promptCapabilities": {
        "image": true,
        "audio": false,
        "embeddedContext": true
      },
      "mcp": {
        "http": true,
        "sse": false
      }
    },
    "agentInfo": {
      "name": "claude-agent",
      "title": "Claude Code Agent",
      "version": "1.0.0"
    },
    "authMethods": []
  }
}

关键要求:

  • 🔢 协议版本协商: Client 提供支持的最新版本,Agent 响应选定版本
  • 🎛️ 能力声明: 双方明确声明支持的功能(文件系统、终端、MCP 等)
  • ⚙️ 向后兼容: 未声明的能力视为不支持
2. 会话管理流程
typescript 复制代码
// 创建新会话
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "session/new",
  "params": {
    "workspaceRoot": "/Users/pojian/code/project",
    "capabilities": {
      "edit": true,
      "execute": true
    }
  }
}

// 响应
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "sessionId": "sess_abc123",
    "state": "ready"
  }
}
3. 提示词交互流程
typescript 复制代码
// Client → Agent: 发送用户提示词
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "session/prompt",
  "params": {
    "sessionId": "sess_abc123",
    "message": {
      "parts": [
        {
          "kind": "text",
          "text": "重构这个函数以提高性能"
        },
        {
          "kind": "resource_link",
          "uri": "file:///Users/pojian/code/project/src/utils.ts",
          "lineRange": { "start": 10, "end": 25 }
        }
      ]
    }
  }
}

// Agent → Client: 实时状态更新(通知)
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123",
    "update": {
      "kind": "agent_message_chunk",
      "text": "我来分析这个函数的性能瓶颈..."
    }
  }
}

// Agent → Client: 请求权限
{
  "jsonrpc": "2.0",
  "id": 100,
  "method": "session/request_permission",
  "params": {
    "sessionId": "sess_abc123",
    "permission": {
      "kind": "file_write",
      "path": "/Users/pojian/code/project/src/utils.ts",
      "preview": "--- a/utils.ts\n+++ b/utils.ts\n..."
    }
  }
}

// Client → Agent: 权限响应
{
  "jsonrpc": "2.0",
  "id": 100,
  "result": {
    "granted": true
  }
}

// Agent → Client: 完成状态
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123",
    "update": {
      "kind": "state_change",
      "state": "completed"
    }
  }
}

3.4 ACP 能力系统

Client 能力
能力域 能力 描述 关联方法
文件系统 fs.readTextFile 读取文本文件 fs/read_text_file
fs.writeTextFile 写入文本文件 fs/write_text_file
终端 terminal 执行和管理 Shell 命令 terminal/* 全系列方法
Agent 能力
能力域 能力 描述
会话 loadSession 支持加载已有会话
提示词 image 支持图像输入
audio 支持音频输入
embeddedContext 支持嵌入式上下文资源
MCP http 支持 HTTP 传输的 MCP 服务器
sse 支持 SSE 传输的 MCP 服务器(已弃用)

3.5 ACP 协议约定

typescript 复制代码
// 关键约定
const ACP_CONVENTIONS = {
  // 1. 路径要求
  filePaths: "MUST be absolute",  // 所有文件路径必须是绝对路径

  // 2. 行号约定
  lineNumbers: "1-based",  // 行号从 1 开始

  // 3. 文本格式
  textFormat: "Markdown",  // 默认使用 Markdown 格式

  // 4. 扩展机制
  customMethods: "prefix with underscore (_method_name)",
  customData: "use _meta field",

  // 5. 错误处理
  errorHandling: "JSON-RPC 2.0 standard (code + message)"
};

四、A2A (Agent-to-Agent) 深度剖析:Multi-Agent 系统的探索

4.0 A2A 概述与设计哲学

A2A (Agent-to-Agent Protocol) 是 Google Gemini CLI 团队提出的实验性协议,专注于解决 Multi-Agent 系统中的核心挑战:如何让不同的 Agent 无缝协作、状态同步和任务编排。

🎯 核心价值主张

虽然 ACP 解决了 Editor ↔ Agent 的标准化,MCP 解决了 Agent ↔ Tools 的标准化,但 Agent ↔ Agent 的协作仍是空白地带。A2A 正是为填补这一空白而生。

A2A 的三大设计支柱
graph TD A2A["A2A 设计哲学"] A2A --> P1["1️⃣ Event-Driven Architecture
事件驱动"] A2A --> P2["2️⃣ Stateful Task Management
有状态任务管理"] A2A --> P3["3️⃣ HTTP + SSE Hybrid Transport
混合传输"] P1 --> P1A["通过 EventBus 实现松耦合"] P1 --> P1B["Agent 只需订阅感兴趣的事件"] P1 --> P1C["支持流式和实时状态更新"] P2 --> P2A["任务可持久化和恢复"] P2 --> P2B["完整的状态转换历史"] P2 --> P2C["支持长时间运行的复杂任务"] P3 --> P3A["HTTP 用于 Request/Response"] P3 --> P3B["SSE 用于实时事件推送"] P3 --> P3C["天然支持跨网络的 Agent 协作"] style A2A fill:#e1f5fe,stroke:#01579b,stroke-width:3px style P1 fill:#fff3e0,stroke:#e65100 style P2 fill:#f3e5f5,stroke:#4a148c style P3 fill:#e8f5e9,stroke:#1b5e20
为什么需要 A2A?
场景 传统方案的痛点 A2A 的解决方案
Multi-Agent 协作 每个 Agent 使用私有 API,无法互操作 统一的 AgentCard + Task API
长时间任务 同步调用易超时,状态无法追踪 异步 Task + 状态机管理
实时反馈 只能轮询或等待最终结果 SSE 流式推送中间状态
Agent 发现 硬编码 Agent 地址和能力 AgentCard 动态发现和能力协商

4.1 A2A 核心架构组件

1. AgentCard - Agent 身份与能力声明
typescript 复制代码
// packages/a2a-server/src/http/app.ts
const agentCard: AgentCard = {
  name: 'Gemini SDLC Agent',
  description: 'Code generation agent with streaming support',
  url: 'http://localhost:41242/',
  protocolVersion: '0.3.0',

  capabilities: {
    streaming: true,              // 支持流式输出
    pushNotifications: false,     // 不支持推送
    stateTransitionHistory: true  // 支持状态历史
  },

  skills: [
    {
      id: 'code_generation',
      name: 'Code Generation',
      description: 'Generate code from natural language',
      tags: ['code', 'development'],
      inputModes: ['text'],
      outputModes: ['text'],
      examples: [
        'Write a Python function to calculate fibonacci',
        'Create a REST API with authentication'
      ]
    }
  ]
};

AgentCard 的关键字段解析:

字段 作用 示例值
name Agent 的唯一标识符 "Gemini SDLC Agent"
url Agent 的 HTTP 端点 "http://localhost:41242/"
protocolVersion A2A 协议版本 "0.3.0"
capabilities.streaming 是否支持 SSE 流式输出 true
capabilities.stateTransitionHistory 是否保留状态历史 true
skills[] Agent 擅长的技能列表 代码生成、测试、重构等
2. 任务状态机 - 生命周期管理
typescript 复制代码
// 基于 @a2a-js/sdk 的 TaskState
type TaskState =
  | 'submitted'       // 已提交
  | 'working'         // 执行中
  | 'input-required'  // 等待输入
  | 'completed'       // 已完成
  | 'failed'          // 失败
  | 'canceled';       // 取消

// 状态转换流程
submitted → working → input-required → working → completed
                                    ↓
                                  failed
                                    ↓
                                 canceled

状态转换详解:

typescript 复制代码
// packages/a2a-server/src/types.ts
interface TaskMetadata {
  id: string;                    // 任务唯一 ID
  contextId: string;             // 所属会话 ID
  taskState: TaskState;          // 当前状态
  model: string;                 // 使用的 LLM 模型
  mcpServers: MCPServerInfo[];   // 可用的 MCP 服务器列表
  availableTools: ToolInfo[];    // 可调用的工具列表
}

// 状态转换触发器
class Task {
  setTaskState(newState: TaskState) {
    const oldState = this.metadata.taskState;
    this.metadata.taskState = newState;

    // 记录状态历史(如果开启)
    if (this.capabilities.stateTransitionHistory) {
      this.stateHistory.push({
        from: oldState,
        to: newState,
        timestamp: Date.now(),
        reason: this.transitionReason
      });
    }

    // 触发状态变更事件
    this.eventBus.publish({
      kind: CoderAgentEvent.StateChangeEvent,
      taskId: this.id,
      oldState,
      newState,
      timestamp: Date.now()
    });
  }
}

关键状态说明:

状态 含义 典型持续时间 下一状态
submitted 任务已提交但未开始执行 0-50ms working
working LLM 正在生成响应或执行工具调用 数秒到数分钟 input-required / completed / failed
input-required 等待用户确认工具调用或提供额外输入 取决于用户 working / canceled
completed 任务成功完成 终态 -
failed 任务执行失败 终态 -
canceled 用户主动取消 终态 -
3. EventBus - 事件驱动核心

A2A 的 EventBus 是整个系统的神经中枢,负责:

  • 📡 解耦组件:Agent、Task、Tool 之间通过事件通信
  • 🔄 流式传输:通过 SSE 实时推送事件到客户端
  • 📊 状态追踪:所有状态变化都通过事件记录
typescript 复制代码
// packages/a2a-server/src/agent/executor.ts

// EventBus 事件类型定义
enum CoderAgentEvent {
  ToolCallConfirmationEvent = 'tool-call-confirmation',  // 请求工具确认
  ToolCallUpdateEvent = 'tool-call-update',              // 工具调用状态更新
  TextContentEvent = 'text-content',                     // LLM 生成的文本
  StateChangeEvent = 'state-change',                     // 任务状态变更
  ThoughtEvent = 'thought',                              // Agent 的思考过程
}

// EventBus 实现
class ExecutionEventBus {
  private listeners = new Map<string, Set<EventListener>>();
  private sseClients = new Set<SSEClient>();

  // 发布事件
  publish(event: CoderAgentMessage) {
    // 1. 通知本地监听器
    const listeners = this.listeners.get(event.kind) || new Set();
    listeners.forEach(listener => listener(event));

    // 2. 通过 SSE 推送给客户端
    this.sseClients.forEach(client => {
      client.send({
        event: event.kind,
        data: JSON.stringify(event)
      });
    });

    // 3. 持久化到数据库(可选)
    if (this.persistenceEnabled) {
      this.saveEvent(event);
    }
  }

  // 订阅事件
  subscribe(eventType: CoderAgentEvent, listener: EventListener) {
    if (!this.listeners.has(eventType)) {
      this.listeners.set(eventType, new Set());
    }
    this.listeners.get(eventType)!.add(listener);
  }

  // 添加 SSE 客户端
  addSSEClient(client: SSEClient) {
    this.sseClients.add(client);

    // 发送历史事件(如果需要)
    if (client.wantsHistory) {
      this.replayEvents(client);
    }
  }
}

EventBus 流式工作流程:

graph TB subgraph LLM["LLM Stream 处理流程"] Stream["LLM Stream"] --> Chunk1["Chunk 1"] Stream --> Chunk2["Chunk 2"] Stream --> Chunk3["Chunk 3"] Stream --> ToolCall["Tool Call"] Chunk1 --> Publish1["EventBus.publish(TextContent)"] Chunk2 --> Publish1 Chunk3 --> Publish1 ToolCall --> Publish1 Publish1 --> Local["Local Listeners"] Publish1 --> SSE["SSE Clients
(实时推送)"] Publish1 --> Persist["Persistence Layer"] style LLM fill:#e3f2fd,stroke:#1565c0 end subgraph Tool["Tool Execution 处理流程"] ToolExec["Tool Execution"] --> ConfReq["Confirmation Request"] ConfReq --> Publish2["EventBus.publish()"] UserApproval["User Approval"] --> SetState["setState(working)"] ToolResult["Tool Result"] --> Publish3["EventBus.publish()"] style Tool fill:#fff3e0,stroke:#e65100 end style Publish1 fill:#c8e6c9,stroke:#2e7d32 style Publish2 fill:#c8e6c9,stroke:#2e7d32 style Publish3 fill:#c8e6c9,stroke:#2e7d32
4. 核心执行器 - 编排引擎
typescript 复制代码
// packages/a2a-server/src/agent/executor.ts
export class CoderAgentExecutor implements AgentExecutor {
  async execute(requestContext: RequestContext, eventBus: ExecutionEventBus) {
    const { userMessage, task } = requestContext;

    // 1. 获取或创建任务
    let wrapper = this.tasks.get(taskId) || await this.createTask(taskId);

    // 2. 设置状态为 working
    wrapper.task.setTaskState('working');
    eventBus.publish({
      kind: 'status-update',
      taskId,
      status: { state: 'working' },
      final: false
    });

    // 3. 调用 LLM
    const agentEvents = wrapper.task.geminiClient.sendMessageStream(
      userMessage.parts,
      abortSignal
    );

    // 4. 处理 Agent 响应
    for await (const event of agentEvents) {
      if (event.type === 'tool_call_request') {
        // 调度工具执行
        await wrapper.task.scheduleToolCalls(event.toolCalls);
      } else if (event.type === 'content') {
        // 发布文本内容
        eventBus.publish({
          kind: 'status-update',
          status: {
            state: 'working',
            message: { parts: [{ kind: 'text', text: event.content }] }
          }
        });
      }
    }

    // 5. 等待工具执行完成
    await wrapper.task.waitForPendingTools();

    // 6. 设置状态为 input-required
    wrapper.task.setTaskState('input-required');
    eventBus.publish({
      kind: 'status-update',
      status: { state: 'input-required' },
      final: true
    });
  }
}

执行器的核心职责:

  1. 📝 任务生命周期管理:从 submitted 到终态的完整流程控制
  2. 🔄 流式响应处理:实时处理 LLM 的 streaming output
  3. 🛠️ 工具调度编排:管理并发的工具调用请求
  4. 📡 事件发布:将所有状态变化通过 EventBus 广播
  5. 💾 状态持久化:支持任务暂停和恢复
5. Tool Scheduling - 工具调度机制

A2A 的工具调度是其核心能力之一,支持:

  • 并发执行:多个工具可以并行调用
  • 🔄 依赖管理:自动处理工具间的依赖关系
  • ⏸️ 暂停/恢复:可以中断工具执行并稍后恢复
typescript 复制代码
// packages/a2a-server/src/agent/task.ts

class Task {
  private pendingTools = new Map<string, ToolExecution>();
  private toolQueue: ToolCall[] = [];

  async scheduleToolCalls(toolCalls: ToolCall[]) {
    for (const toolCall of toolCalls) {
      const execution: ToolExecution = {
        id: toolCall.id,
        toolName: toolCall.name,
        args: toolCall.arguments,
        status: 'pending',
        startTime: null,
        endTime: null,
        result: null
      };

      this.pendingTools.set(toolCall.id, execution);

      // 检查是否需要用户确认
      if (this.shouldConfirmTool(toolCall.name)) {
        this.eventBus.publish({
          kind: CoderAgentEvent.ToolCallConfirmationEvent,
          taskId: this.id,
          toolCall: {
            id: toolCall.id,
            name: toolCall.name,
            arguments: toolCall.arguments,
            description: this.getToolDescription(toolCall.name)
          }
        });
        execution.status = 'awaiting_confirmation';
      } else {
        // 自动批准,立即执行
        this.executeToolCall(toolCall);
      }
    }
  }

  async executeToolCall(toolCall: ToolCall) {
    const execution = this.pendingTools.get(toolCall.id)!;
    execution.status = 'running';
    execution.startTime = Date.now();

    // 发布开始事件
    this.eventBus.publish({
      kind: CoderAgentEvent.ToolCallUpdateEvent,
      taskId: this.id,
      toolCallId: toolCall.id,
      status: 'running'
    });

    try {
      // 调用 MCP 工具
      const result = await this.mcpClient.callTool(
        toolCall.name,
        toolCall.arguments
      );

      execution.status = 'completed';
      execution.result = result;
      execution.endTime = Date.now();

      // 发布完成事件
      this.eventBus.publish({
        kind: CoderAgentEvent.ToolCallUpdateEvent,
        taskId: this.id,
        toolCallId: toolCall.id,
        status: 'completed',
        result: result,
        duration: execution.endTime - execution.startTime
      });

      // 从 pending 移除
      this.pendingTools.delete(toolCall.id);

    } catch (error) {
      execution.status = 'failed';
      execution.error = error.message;
      execution.endTime = Date.now();

      this.eventBus.publish({
        kind: CoderAgentEvent.ToolCallUpdateEvent,
        taskId: this.id,
        toolCallId: toolCall.id,
        status: 'failed',
        error: error.message
      });

      this.pendingTools.delete(toolCall.id);
    }
  }

  // 等待所有待处理的工具完成
  async waitForPendingTools(): Promise<void> {
    while (this.pendingTools.size > 0) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  }
}

工具调度流程图:

graph TD LLM["LLM: I need to call tools A, B, C"] --> Schedule["scheduleToolCalls([A, B, C])"] Schedule --> ToolA["Tool A: Auto-approved"] Schedule --> ToolB["Tool B: Needs confirmation"] Schedule --> ToolC["Tool C: Auto-approved"] ToolA --> ExecA["executeToolCall(A)"] ExecA --> MCPA["MCP Server"] ToolB --> ConfEvent["Publish ConfirmationEvent"] ConfEvent --> WaitApproval["Wait for user approval"] WaitApproval --> ExecB["executeToolCall(B)"] ExecB --> MCPB["MCP Server"] ToolC --> ExecC["executeToolCall(C)"] ExecC --> MCPC["MCP Server"] MCPA --> Complete["All tools completed"] MCPB --> Complete MCPC --> Complete Complete --> Continue["LLM continues"] style LLM fill:#e1f5fe,stroke:#01579b style Schedule fill:#fff3e0,stroke:#e65100 style ToolA fill:#c8e6c9,stroke:#2e7d32 style ToolB fill:#ffcdd2,stroke:#c62828 style ToolC fill:#c8e6c9,stroke:#2e7d32 style Complete fill:#e1bee7,stroke:#6a1b9a style Continue fill:#e1f5fe,stroke:#01579b %% 注释:A 和 C 并发执行,B 需要等待确认

4.2 A2A 与 MCP 的深度集成

A2A 并非孤立协议,它巧妙地将 MCP 整合为底层工具层,形成两层协议栈

graph LR subgraph Layer3["Layer 3: Agent Orchestration (A2A)"] A3A["Agent discovery
(AgentCard)"] A3B["Task management
(TaskState)"] A3C["Event streaming
(EventBus + SSE)"] style Layer3 fill:#e1f5fe,stroke:#01579b,stroke-width:2px end subgraph Layer2["Layer 2: Tool Interface (MCP)"] A2A["Tool discovery
(tools/list)"] A2B["Tool execution
(tools/call)"] A2C["Resource access
(resources/read)"] style Layer2 fill:#fff3e0,stroke:#e65100,stroke-width:2px end subgraph Layer1["Layer 1: Transport Layer"] A1A["JSON-RPC 2.0
(for MCP)"] A1B["HTTP + SSE
(for A2A)"] A1C["stdio / HTTP / SSE"] style Layer1 fill:#f3e5f5,stroke:#4a148c,stroke-width:2px end Layer3 --> Layer2 Layer2 --> Layer1 style A3A fill:#b3e5fc,stroke:#01579b style A3B fill:#b3e5fc,stroke:#01579b style A3C fill:#b3e5fc,stroke:#01579b style A2A fill:#ffe0b2,stroke:#e65100 style A2B fill:#ffe0b2,stroke:#e65100 style A2C fill:#ffe0b2,stroke:#e65100

集成实现细节:

typescript 复制代码
// packages/a2a-server/src/agent/task.ts

class Task {
  private mcpClients = new Map<string, McpClient>();

  async initializeMCPServers(serverConfigs: MCPServerConfig[]) {
    for (const config of serverConfigs) {
      const client = new McpClient(config);

      // 连接到 MCP Server
      await client.connect();

      // 获取工具列表
      const tools = await client.listTools();

      // 注册到任务的可用工具
      for (const tool of tools) {
        const qualifiedName = `mcp__${config.name}__${tool.name}`;
        this.availableTools.set(qualifiedName, {
          originalName: tool.name,
          serverName: config.name,
          description: tool.description,
          parameterSchema: tool.inputSchema,
          mcpClient: client
        });
      }

      this.mcpClients.set(config.name, client);
    }

    // 通知 LLM 可用的工具列表(通过 Gemini Function Calling)
    this.geminiClient.updateTools(
      Array.from(this.availableTools.values()).map(tool => ({
        name: tool.originalName,  // Gemini 看到的是原始名称
        description: tool.description,
        parameters: tool.parameterSchema
      }))
    );
  }

  async callTool(toolName: string, args: any): Promise<any> {
    // 从qualified name 解析 server 和 tool
    const [_, serverName, originalToolName] = toolName.split('__');

    const toolInfo = this.availableTools.get(toolName);
    if (!toolInfo) {
      throw new Error(`Tool ${toolName} not found`);
    }

    // 调用 MCP Server
    const result = await toolInfo.mcpClient.callTool(
      originalToolName,
      args
    );

    return result;
  }
}

工具名称转换策略:

层级 工具名称 说明
MCP Server read_file MCP 原生工具名
A2A 内部存储 mcp__filesystem__read_file 带命名空间的限定名
Gemini LLM read_file LLM 看到的简化名(通过 description 区分)
用户界面 "读取文件 (filesystem)" 用户友好的显示名

4.3 A2A 实战案例:Multi-Agent 协作系统

场景:AI 驱动的全栈应用开发

假设我们要开发一个包含前端、后端、数据库的完整应用。传统方式是单个 Agent 完成所有工作,但使用 A2A 可以让专业 Agent 协作:

typescript 复制代码
import { createAgent, AgentOrchestrator } from '@a2a-js/sdk';

// 1. 定义专业 Agent 团队
const agents = {
  // 前端专家
  frontendAgent: await createAgent({
    name: 'Frontend Specialist',
    agentUrl: 'http://localhost:8001/api',
    skills: ['react', 'typescript', 'css', 'ui-design']
  }),

  // 后端专家
  backendAgent: await createAgent({
    name: 'Backend Specialist',
    agentUrl: 'http://localhost:8002/api',
    skills: ['nodejs', 'express', 'api-design', 'authentication']
  }),

  // 数据库专家
  databaseAgent: await createAgent({
    name: 'Database Specialist',
    agentUrl: 'http://localhost:8003/api',
    skills: ['postgresql', 'schema-design', 'migrations', 'optimization']
  }),

  // 测试专家
  testAgent: await createAgent({
    name: 'QA Specialist',
    agentUrl: 'http://localhost:8004/api',
    skills: ['jest', 'e2e-testing', 'test-strategy']
  })
};

// 2. 创建编排器
const orchestrator = new AgentOrchestrator(agents);

// 3. 定义工作流
const workflow = orchestrator.defineWorkflow({
  name: 'Build E-Commerce App',

  steps: [
    {
      id: 'design-schema',
      agent: 'databaseAgent',
      task: '设计电商应用的数据库 schema,包括用户、产品、订单表',
      dependencies: []
    },
    {
      id: 'create-migrations',
      agent: 'databaseAgent',
      task: '创建数据库迁移文件',
      dependencies: ['design-schema']
    },
    {
      id: 'build-api',
      agent: 'backendAgent',
      task: '基于数据库 schema 构建 REST API,包括 CRUD 和认证',
      dependencies: ['design-schema'],
      inputs: {
        schema: '{{ steps.design-schema.result.schema }}'
      }
    },
    {
      id: 'build-frontend',
      agent: 'frontendAgent',
      task: '构建 React 前端,连接到 API',
      dependencies: ['build-api'],
      inputs: {
        apiSpec: '{{ steps.build-api.result.openapi }}'
      }
    },
    {
      id: 'write-tests',
      agent: 'testAgent',
      task: '编写端到端测试',
      dependencies: ['build-frontend', 'build-api']
    }
  ]
});

// 4. 执行工作流(支持流式监控)
const execution = await orchestrator.execute(workflow);

// 5. 订阅事件,实时监控进度
execution.on('step-started', ({ stepId, agent }) => {
  console.log(`✨ ${agent} 开始工作: ${stepId}`);
});

execution.on('step-progress', ({ stepId, progress }) => {
  console.log(`⏳ ${stepId}: ${progress.message}`);
});

execution.on('step-completed', ({ stepId, result, duration }) => {
  console.log(`✅ ${stepId} 完成 (耗时: ${duration}ms)`);
  console.log(`   输出: ${result.summary}`);
});

execution.on('error', ({ stepId, error }) => {
  console.error(`❌ ${stepId} 失败: ${error.message}`);
});

// 等待完成
const finalResult = await execution.complete();

console.log('🎉 全栈应用开发完成!');
console.log(`总耗时: ${finalResult.totalDuration}ms`);
console.log(`创建的文件数: ${finalResult.filesCreated}`);

工作流执行时间线:

makefile 复制代码
Time  Agent              Event
────  ────────────────  ──────────────────────────────────
00:00 DatabaseAgent     ✨ 开始设计 schema
00:05 DatabaseAgent       ⏳ 正在分析电商领域模型...
00:15 DatabaseAgent       ⏳ 生成用户表 schema...
00:25 DatabaseAgent       ⏳ 生成产品表 schema...
00:35 DatabaseAgent     ✅ Schema 设计完成

00:35 DatabaseAgent     ✨ 开始创建迁移文件
00:38 DatabaseAgent       ⏳ 生成 SQL migration...
00:42 DatabaseAgent     ✅ 迁移文件创建完成

00:42 BackendAgent      ✨ 开始构建 API
00:45 BackendAgent        ⏳ 设置 Express server...
00:50 BackendAgent        ⏳ 生成 CRUD endpoints...
01:05 BackendAgent        ⏳ 实现 JWT 认证...
01:20 BackendAgent      ✅ API 构建完成

01:20 FrontendAgent     ✨ 开始构建前端
01:25 FrontendAgent       ⏳ 创建 React 项目结构...
01:35 FrontendAgent       ⏳ 生成组件代码...
01:50 FrontendAgent       ⏳ 集成 API client...
02:10 FrontendAgent     ✅ 前端构建完成

02:10 TestAgent         ✨ 开始编写测试
02:15 TestAgent           ⏳ 生成 E2E 测试场景...
02:30 TestAgent           ⏳ 编写测试代码...
02:45 TestAgent         ✅ 测试完成

🎉 全栈应用开发完成!
总耗时: 165秒
创建的文件数: 47
测试通过率: 100%

4.4 A2A 的核心优势

与其他协议相比,A2A 在以下方面具有独特优势:

优势 具体表现 对比 ACP/MCP
🔄 真正的流式体验 通过 SSE 实时推送 LLM 生成的每个 token ACP 也支持流式,MCP 不支持
📊 完整状态管理 6 种状态 + 状态转换历史 ACP 有会话状态,MCP 无状态
🔌 Multi-Agent 支持 原生支持 Agent 发现和协作 ACP 专注 Editor-Agent,MCP 无此概念
🛠️ MCP 集成 无缝复用整个 MCP 生态的工具 ACP 也支持 MCP,但未深度集成
⚡ 并发工具调用 可同时执行多个工具,大幅提升效率 MCP 也支持,但需要自行实现并发控制
💾 任务持久化 支持暂停任务,稍后从断点恢复 ACP 支持 session 加载,MCP 无此能力
🎯 事件驱动架构 EventBus 解耦组件,易于扩展 ACP 使用通知,但没有统一 EventBus

A2A 的适用场景:

推荐使用 A2A:

  • 需要多个 Agent 协作完成复杂任务
  • 任务执行时间较长(>30秒),需要中间状态反馈
  • 需要支持任务暂停和恢复
  • 需要完整的审计日志和状态历史
  • 希望复用 MCP 生态的工具

不推荐使用 A2A:

  • 简单的单 Agent 场景(用 ACP 更轻量)
  • 对性能要求极高的场景(Rust 实现的 Codex 更快)
  • 只需要工具调用,不需要 Agent 协作(直接用 MCP)
  • 低延迟要求(<100ms)的实时场景

4.5 Codex 的 SQ/EQ 协议设计

⚠️ 注意 : Codex 的实现与 ACP 官方标准也不同 ,采用了独特的 SQ/EQ (Submission Queue / Event Queue) 模式。

Codex 的协议设计:

rust 复制代码
// codex-rs/protocol/src/protocol.rs

/// Submission Queue - 用户提交的操作
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Submission {
    pub id: String,
    pub op: Op,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Op {
    /// 用户输入
    UserTurn {
        items: Vec<UserInput>,
        cwd: PathBuf,
        approval_policy: AskForApproval,
        sandbox_policy: SandboxPolicy,
        model: String,
    },

    /// 中断当前任务
    Interrupt,

    /// 批准工具执行
    ExecApproval {
        id: String,
        decision: ReviewDecision,
    },

    /// 批准代码补丁
    PatchApproval {
        id: String,
        decision: ReviewDecision,
    },

    /// 解决 MCP 授权请求
    ResolveElicitation {
        server_name: String,
        request_id: RequestId,
        decision: ElicitationAction,
    },
}

/// Event Queue - Agent 发出的事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Event {
    pub id: String,
    pub msg: EventMsg,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum EventMsg {
    /// Agent 消息
    AgentMessage(AgentMessageEvent),

    /// 工具调用请求
    ToolCall(ToolCallEvent),

    /// 需要批准执行
    ExecApprovalRequest(ExecApprovalRequestEvent),

    /// 需要批准补丁
    ApplyPatchApprovalRequest(ApplyPatchApprovalRequestEvent),

    /// Turn 完成
    TurnComplete(TurnCompleteEvent),

    /// Turn 中止
    TurnAborted(TurnAbortedEvent),
}

4.3 协议关系梳理:ACP vs A2A vs Codex

为避免混淆,这里明确三者的定位和关系:

协议/实现 定位 标准化状态 主要用途 实现方
ACP (Agent Client Protocol) 官方标准协议 ✅ 开放标准 Editor ↔ Agent 通信 Zed Industries (2025-08)
A2A (Agent-to-Agent) 实验性实现 🔬 非标准 Agent ↔ Agent 协作 Google Gemini CLI
Codex SQ/EQ 实验性实现 🔬 非标准 User ↔ Agent 交互 OpenAI/社区
关键区别
graph TB subgraph Official["官方标准"] MCP["MCP (Anthropic)
Agent ↔ Tools"] ACP["ACP (Zed)
Editor ↔ Agent"] style Official fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px style MCP fill:#a5d6a7,stroke:#388e3c style ACP fill:#a5d6a7,stroke:#388e3c end subgraph Vendor["厂商实现 (实验性)"] A2A["A2A (Google)
Agent ↔ Agent"] Codex["Codex SQ/EQ (社区)
User ↔ Agent"] style Vendor fill:#fff3e0,stroke:#e65100,stroke-width:2px style A2A fill:#ffcc80,stroke:#f57c00 style Codex fill:#ffcc80,stroke:#f57c00 end

为什么会有这种现象?

  1. ACP 发布时间线:ACP 在 2025 年 8 月才正式发布,而 Gemini CLI 和 Codex 的开发更早,当时还没有统一标准
  2. 不同的关注点
    • ACP 关注 编辑器集成(类似 LSP)
    • A2A 关注 Agent 编排(Multi-Agent 系统)
    • Codex SQ/EQ 关注 用户体验(审批流程和安全)
  3. 演进方向:预计未来这些实现可能会向 ACP 标准靠拢或互补

对开发者的建议

  • ✅ 如果开发编辑器插件,优先使用 ACP 官方标准
  • 🔬 如果研究 Multi-Agent 系统,可以参考 A2A 的设计思路
  • 🔐 如果注重安全审批,可以借鉴 Codex 的 Approval 机制

五、核心差异对比:ACP vs MCP vs 各家实现

5.1 协议定位对比

graph TB subgraph AppLayer["应用层 - A2A (Agent-to-Agent)"] App1["Gemini A2A Server"] App2["Agent 协作编排"] App3["任务状态管理"] style AppLayer fill:#e1f5fe,stroke:#01579b,stroke-width:2px end subgraph AgentLayer["Agent层 - Codex SQ/EQ Protocol"] Agent1["Submission Queue
(用户 → Agent)"] Agent2["Event Queue
(Agent → 用户)"] Agent3["审批流程 (Approval)"] style AgentLayer fill:#f3e5f5,stroke:#4a148c,stroke-width:2px end subgraph ToolLayer["工具层 - MCP (Model Context Protocol)"] Tool1["工具发现与调用"] Tool2["资源访问"] Tool3["Prompt 管理"] style ToolLayer fill:#fff3e0,stroke:#e65100,stroke-width:2px end subgraph TransportLayer["传输层"] Trans1["stdio / SSE / HTTP / WebSocket"] style TransportLayer fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px end AppLayer --> AgentLayer AgentLayer --> ToolLayer ToolLayer --> TransportLayer style App1 fill:#b3e5fc,stroke:#01579b style App2 fill:#b3e5fc,stroke:#01579b style App3 fill:#b3e5fc,stroke:#01579b style Agent1 fill:#e1bee7,stroke:#6a1b9a style Agent2 fill:#e1bee7,stroke:#6a1b9a style Agent3 fill:#e1bee7,stroke:#6a1b9a style Tool1 fill:#ffe0b2,stroke:#e65100 style Tool2 fill:#ffe0b2,stroke:#e65100 style Tool3 fill:#ffe0b2,stroke:#e65100

5.2 详细对比表

维度 MCP ACP (官方) A2A (Gemini) Codex SQ/EQ
协议目标 Agent ↔ 工具/资源 Editor ↔ Agent Agent ↔ Agent 用户 ↔ Agent
发布方 Anthropic Zed Industries Google OpenAI (社区)
协议版本 2025-06-18 Version 1 (2025-08) 0.3.0 v0.2.0-alpha
通信模式 Request/Response Request/Response + Notifications Event-Driven (SSE) Queue-Based
状态管理 无状态 有状态 (会话) 有状态 (任务) 有状态 (会话)
传输方式 stdio, SSE, HTTP stdio (JSON-RPC) HTTP + SSE In-Process Channels
权限模型 Elicitation Permission Request Confirmation Approval
流式支持 ❌ 不支持 ✅ 支持 ✅ 支持 ✅ 支持
语言绑定 TS, Rust, Python TS, Go, Rust, Python TypeScript Rust + TS SDK
标准化程度 ✅ 官方标准 ✅ 官方标准 🔬 实验性实现 🔬 实验性实现

5.3 工具调用流程对比

MCP 工具调用 (同步):
yaml 复制代码
User → Agent: "读取文件 /etc/hosts"
Agent → MCP Server: tools/call { name: "read_file", args: {...} }
MCP Server → Agent: { content: [...], isError: false }
Agent → User: "文件内容如下..."
A2A 工具调用 (流式):
css 复制代码
User → Agent A: "读取并分析文件"
Agent A → EventBus: { status: 'working', message: "正在读取..." }
Agent A → Tool: read_file(...)
Tool → Agent A: (file content)
Agent A → EventBus: { status: 'working', message: "正在分析..." }
Agent A → Agent B: analyze(content)  // 可选的 Multi-Agent
Agent B → EventBus: { status: 'working', message: "分析结果..." }
EventBus → User: (流式展示每一步)
Codex SQ/EQ (异步队列):
css 复制代码
User → SQ: Submission { op: UserTurn { text: "..." } }
Agent → EQ: Event { msg: AgentMessage { text: "正在处理..." } }
Agent → EQ: Event { msg: ToolCall { tool: "shell", cmd: "ls" } }
Agent → EQ: Event { msg: ExecApprovalRequest {...} }
User → SQ: Submission { op: ExecApproval { decision: Allow } }
Agent → EQ: Event { msg: ToolCallResult {...} }
Agent → EQ: Event { msg: TurnComplete }

六、实际应用场景

6.1 MCP 典型场景

场景 1: 统一的开发工具接入
typescript 复制代码
// 配置文件: ~/.gemini/settings.json
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "postgres": {
      "command": "uvx",
      "args": ["mcp-server-postgres"],
      "env": {
        "DATABASE_URL": "postgresql://..."
      }
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
    }
  }
}

使用:

bash 复制代码
$ gemini
> @github List my open pull requests
> @postgres Run query: SELECT * FROM users WHERE active = true
> @filesystem Read file package.json
场景 2: 企业内部工具集成
typescript 复制代码
// 自定义 MCP Server
import { Server } from '@modelcontextprotocol/sdk/server';

const server = new Server({
  name: 'company-internal-tools',
  version: '1.0.0'
});

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: 'query_jira',
      description: 'Query JIRA tickets',
      inputSchema: {
        type: 'object',
        properties: {
          jql: { type: 'string' }
        }
      }
    },
    {
      name: 'deploy_to_k8s',
      description: 'Deploy application to Kubernetes',
      inputSchema: {
        type: 'object',
        properties: {
          namespace: { type: 'string' },
          image: { type: 'string' }
        }
      }
    }
  ]
}));

6.2 ACP 典型场景(官方标准)

场景 1: Multi-Agent 协作工作流
typescript 复制代码
import { createAgent } from '@a2a-js/sdk';

// Agent 1: 代码生成专家
const codeGenAgent = await createAgent({
  agentUrl: 'http://gemini-a2a:41242'
});

// Agent 2: 代码审查专家
const codeReviewAgent = await createAgent({
  agentUrl: 'http://claude-a2a:3000'
});

// 工作流编排
async function developFeature(requirement: string) {
  // Step 1: 生成代码
  const codeTask = await codeGenAgent.createTask({
    message: {
      parts: [{ kind: 'text', text: `实现功能: ${requirement}` }]
    }
  });

  const code = await codeTask.waitForCompletion();

  // Step 2: 审查代码
  const reviewTask = await codeReviewAgent.createTask({
    message: {
      parts: [{
        kind: 'text',
        text: `审查以下代码并提供改进建议:\n${code}`
      }]
    }
  });

  const review = await reviewTask.waitForCompletion();

  // Step 3: 根据审查意见改进
  const improvedCodeTask = await codeGenAgent.createTask({
    message: {
      parts: [{
        kind: 'text',
        text: `根据审查意见改进代码:\n审查意见: ${review}\n原代码: ${code}`
      }]
    }
  });

  return await improvedCodeTask.waitForCompletion();
}
场景 2: Agent 服务化部署
typescript 复制代码
// 将 Gemini CLI 部署为 A2A 服务
import { A2AExpressApp } from '@a2a-js/sdk/server/express';
import express from 'express';

const app = express();
const a2aApp = new A2AExpressApp(requestHandler);

a2aApp.setupRoutes(app, '/api');
app.listen(41242, () => {
  console.log('Gemini A2A Server running on http://localhost:41242');
});

// 现在其他 Agent 可以调用
const geminiAgent = await createAgent({
  agentUrl: 'http://localhost:41242/api'
});

6.3 Codex SQ/EQ 典型场景

场景 1: 细粒度的审批控制
rust 复制代码
// 定义审批策略
let approval_policy = AskForApproval::AskBeforeExecuting;
let sandbox_policy = SandboxPolicy::Strict;

// 提交用户输入
let submission = Submission {
    id: "sub-001".to_string(),
    op: Op::UserTurn {
        items: vec![UserInput::Text("删除所有日志文件".to_string())],
        cwd: PathBuf::from("/var/log"),
        approval_policy,
        sandbox_policy,
        model: "gpt-4".to_string(),
    }
};

// Agent 请求批准
let event = Event {
    id: "evt-001".to_string(),
    msg: EventMsg::ExecApprovalRequest(ExecApprovalRequestEvent {
        command: "rm -rf *.log",
        assessment: SandboxCommandAssessment {
            risk_level: SandboxRiskLevel::High,
            reason: "批量删除操作".to_string(),
        }
    })
};

// 用户批准或拒绝
let approval = Submission {
    id: "sub-002".to_string(),
    op: Op::ExecApproval {
        id: "evt-001".to_string(),
        decision: ReviewDecision::Approve,
    }
};
场景 2: 会话恢复
rust 复制代码
// 保存会话状态
let conversation_id = ConversationId::new();
conversation_manager.save_state(conversation_id, &state).await?;

// 稍后恢复
let restored_state = conversation_manager.load_state(conversation_id).await?;
let conversation = CodexConversation::from_state(restored_state)?;

七、技术挑战与解决方案

7.1 工具命名冲突

问题: 多个 MCP Server 可能提供同名工具

Gemini CLI 解决方案:

typescript 复制代码
// 使用 server_name 作为 namespace
const toolName = `${serverName}.${originalToolName}`;
// 例如: "github.create_issue", "gitlab.create_issue"

Codex 解决方案:

rust 复制代码
// 使用双下划线分隔符 + SHA1 截断
const DELIMITER = "__";
let qualified_name = format!(
    "mcp{}{}{}{}",
    DELIMITER, server_name, DELIMITER, tool_name
);

if qualified_name.len() > 64 {
    let hash = sha1::Sha1::digest(qualified_name);
    qualified_name = format!("{}_{:x}", &qualified_name[..48], hash);
}
// 例如: "mcp__github__create_issue"

7.2 流式输出的挑战

问题: LLM 生成是流式的,但工具调用是同步的

A2A 解决方案:

typescript 复制代码
// 使用 EventBus 解耦
for await (const chunk of llmStream) {
  eventBus.publish({
    kind: 'status-update',
    status: {
      message: { parts: [{ kind: 'text', text: chunk }] }
    },
    final: false  // 非最终状态,继续接收
  });
}

Codex 解决方案:

rust 复制代码
// 使用 AsyncIterator
pub fn send_message_stream(
    &self,
    items: Vec<UserInput>
) -> impl Stream<Item = Result<Event>> {
    async_stream::stream! {
        let response = self.llm_client.chat(items).await?;
        for await chunk in response.stream {
            yield Ok(Event {
                msg: EventMsg::AgentMessage(chunk)
            });
        }
    }
}

7.3 安全性和沙箱

Codex 的多层沙箱方案:

rust 复制代码
// 1. Execpolicy - 命令级别的策略
pub struct ExecPolicy {
    auto_approve: Vec<String>,    // 自动批准的命令
    always_deny: Vec<String>,      // 始终拒绝的命令
    require_confirm: Vec<String>,  // 需要确认的命令
}

// 2. Platform Sandbox - 操作系统级别的隔离
#[cfg(target_os = "macos")]
fn apply_seatbelt_sandbox(cmd: &str) -> Result<()> {
    let profile = "(version 1) (deny default) (allow network*) (allow file-read* /usr/bin)";
    sandbox_exec(cmd, profile)
}

#[cfg(target_os = "linux")]
fn apply_landlock_sandbox(cmd: &str) -> Result<()> {
    landlock::Ruleset::new()
        .allow_read("/usr/bin")
        .allow_execute("/usr/bin")
        .restrict_self()?;
    execute(cmd)
}

// 3. Network Isolation
if sandbox_policy == SandboxPolicy::Strict {
    env::set_var("CODEX_SANDBOX_NETWORK_DISABLED", "1");
}

八、性能对比

8.1 连接建立时间

实现 传输方式 平均耗时 备注
Gemini MCP (TypeScript) stdio ~150ms Node.js 子进程启动
Gemini MCP (TypeScript) SSE ~80ms HTTP 连接
Codex MCP (Rust) stdio ~50ms 原生进程启动
Codex MCP (Rust) SSE ~40ms Tokio HTTP Client

8.2 工具调用延迟

场景 Gemini CLI Codex CLI
简单工具 (read_file) ~100ms ~30ms
复杂工具 (database query) ~500ms ~200ms
批量工具调用 (10个) ~1.5s ~600ms

性能差异原因:

  • Rust 的零成本抽象和编译优化
  • Tokio 异步运行时的高效调度
  • 无 GC (Garbage Collection) 的确定性延迟

8.3 内存占用

实现 空闲内存 单会话内存 10会话内存
Gemini CLI (Node.js) ~80MB ~150MB ~500MB
Codex CLI (Rust) ~5MB ~15MB ~80MB

九、未来发展方向

9.1 协议融合趋势

graph TB subgraph Layer4["Layer 4: Orchestration Layer"] L4A["Multi-Agent DAG 编排"] L4B["分布式任务调度"] L4C["Agent Marketplace"] style Layer4 fill:#e8eaf6,stroke:#283593,stroke-width:2px end subgraph Layer3["Layer 3: Agent Communication (ACP++)"] L3A["统一的任务状态管理"] L3B["Agent 发现与注册"] L3C["流式通信 + 状态持久化"] style Layer3 fill:#e1f5fe,stroke:#01579b,stroke-width:2px end subgraph Layer2["Layer 2: Tool & Resource (MCP++)"] L2A["工具发现与调用"] L2B["资源抽象与访问控制"] L2C["Prompt 库管理"] style Layer2 fill:#fff3e0,stroke:#e65100,stroke-width:2px end subgraph Layer1["Layer 1: Transport Layer"] L1A["gRPC / WebSocket / QUIC"] L1B["加密传输 (TLS 1.3)"] style Layer1 fill:#f3e5f5,stroke:#4a148c,stroke-width:2px end Layer4 --> Layer3 Layer3 --> Layer2 Layer2 --> Layer1 style L4A fill:#c5cae9,stroke:#283593 style L4B fill:#c5cae9,stroke:#283593 style L4C fill:#c5cae9,stroke:#283593 style L3A fill:#b3e5fc,stroke:#01579b style L3B fill:#b3e5fc,stroke:#01579b style L3C fill:#b3e5fc,stroke:#01579b style L2A fill:#ffe0b2,stroke:#e65100 style L2B fill:#ffe0b2,stroke:#e65100 style L2C fill:#ffe0b2,stroke:#e65100

9.2 关键演进方向

1. 标准化组织推动
yaml 复制代码
# 可能的标准化路径
- W3C Web Agent Working Group
  - 定义 Web-native Agent Protocol
  - 浏览器原生支持 Agent 通信

- IETF RFC 提案
  - Agent Communication Protocol (ACP) RFC
  - 类似 HTTP/2, gRPC 的标准化进程

- Linux Foundation AI & Data
  - MCP Foundation (类似 CNCF)
  - 开源参考实现和认证体系
2. 性能优化
rust 复制代码
// 使用 gRPC 替代 JSON-RPC
service AgentService {
  rpc ExecuteTask(TaskRequest) returns (stream TaskEvent);
  rpc CallTool(ToolCallRequest) returns (ToolCallResponse);
}

// 使用 Protocol Buffers 替代 JSON
message TaskEvent {
  string task_id = 1;
  TaskState state = 2;
  oneof payload {
    AgentMessage message = 3;
    ToolCall tool_call = 4;
  }
}

// 性能提升预期
// - 序列化速度: 5-10x
// - 传输体积: 30-50% 减少
// - 类型安全: 编译时检查
3. 安全性增强
yaml 复制代码
# Zero Trust Agent Network
- 端到端加密 (E2EE)
  - Agent 间通信默认加密
  - 密钥轮换机制

- 细粒度访问控制 (FGAC)
  - 基于 RBAC 的工具权限
  - 基于 ABAC 的资源访问

- 审计与合规
  - 完整的调用链追踪
  - 符合 SOC2 / ISO27001

- 沙箱增强
  - WebAssembly (WASI) 沙箱
  - 容器级别隔离 (Firecracker)
4. 可观测性
typescript 复制代码
// OpenTelemetry 集成
import { trace, context } from '@opentelemetry/api';

class InstrumentedAgent {
  async executeTask(task: Task) {
    const span = trace.getTracer('agent').startSpan('execute_task', {
      attributes: {
        'task.id': task.id,
        'agent.name': this.name,
        'agent.version': this.version
      }
    });

    try {
      const result = await this.executor.execute(task);
      span.setStatus({ code: SpanStatusCode.OK });
      return result;
    } catch (error) {
      span.recordException(error);
      span.setStatus({ code: SpanStatusCode.ERROR });
      throw error;
    } finally {
      span.end();
    }
  }
}

// 分布式追踪
User → Agent A (trace_id: abc123, span_id: 001)
  → MCP Tool 1 (trace_id: abc123, span_id: 002)
  → Agent B (trace_id: abc123, span_id: 003)
    → MCP Tool 2 (trace_id: abc123, span_id: 004)
5. 跨语言互操作
bash 复制代码
┌─────────────────────────────────────────────────────────┐
│           多语言 SDK 生态                                │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  TypeScript  │  @mcp/sdk, @acp/sdk                      │
│  Rust        │  mcp-rs, acp-rs                          │
│  Python      │  mcp-python, acp-python                  │
│  Go          │  go-mcp, go-acp                          │
│  Java        │  mcp-java, acp-java                      │
│                                                          │
│  共同特性:                                               │
│  - Protocol Buffers 定义                                │
│  - 自动生成代码绑定                                     │
│  - 统一的测试套件                                       │
│  - 互操作性验证                                         │
└─────────────────────────────────────────────────────────┘

9.3 应用场景展望

场景 1: 企业级 AI Mesh
yaml 复制代码
# Agent 服务网格
apiVersion: v1
kind: AgentMesh
metadata:
  name: company-ai-mesh
spec:
  agents:
    - name: code-gen-agent
      provider: gemini
      replicas: 3
      tools:
        - github
        - gitlab
        - jira

    - name: code-review-agent
      provider: claude
      replicas: 2
      tools:
        - sonarqube
        - codecov

    - name: security-scan-agent
      provider: codex
      replicas: 1
      tools:
        - snyk
        - trivy

  routing:
    - match: code_generation
      route: code-gen-agent
    - match: code_review
      route: code-review-agent
    - match: security_scan
      route: security-scan-agent
场景 2: Personal AI Assistant Ecosystem
typescript 复制代码
// 个人 AI 助手编排
const personalAI = new AgentOrchestrator({
  agents: {
    calendar: await createAgent({ url: 'http://calendar-agent:8080' }),
    email: await createAgent({ url: 'http://email-agent:8081' }),
    task: await createAgent({ url: 'http://task-agent:8082' }),
    research: await createAgent({ url: 'http://research-agent:8083' })
  }
});

// 复杂任务编排
await personalAI.execute({
  task: "准备下周的产品发布会",
  steps: [
    {
      agent: 'calendar',
      action: '检查下周日程并预定会议室'
    },
    {
      agent: 'task',
      action: '创建发布会任务清单'
    },
    {
      agent: 'research',
      action: '调研竞品最新动态',
      depends_on: ['task']
    },
    {
      agent: 'email',
      action: '发送会议邀请给相关人员',
      depends_on: ['calendar', 'research']
    }
  ]
});

十、给开发者的建议

10.1 选择 MCP 还是 ACP?

如果你需要... 推荐协议 理由
为 Agent 添加外部工具能力 MCP 成熟的工具发现和调用机制
构建多 Agent 协作系统 ACP/A2A 原生的 Agent 间通信支持
企业级合规和审计 Codex SQ/EQ 完整的审批流程和状态追踪
快速原型开发 MCP 丰富的社区工具和示例
高性能生产环境 Codex (Rust) 低延迟、低内存占用

10.2 最佳实践

1. MCP Server 开发
typescript 复制代码
// ✅ 好的实践
import { Server } from '@modelcontextprotocol/sdk/server';

const server = new Server({
  name: 'my-tool-server',
  version: '1.0.0'
});

// 提供详细的工具描述
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [{
    name: 'search_documents',
    description: '在文档库中搜索相关内容。支持全文搜索和语义搜索。',
    inputSchema: {
      type: 'object',
      properties: {
        query: {
          type: 'string',
          description: '搜索关键词或自然语言问题'
        },
        mode: {
          type: 'string',
          enum: ['fulltext', 'semantic'],
          default: 'semantic',
          description: '搜索模式'
        }
      },
      required: ['query']
    }
  }]
}));

// ❌ 不好的实践
const badTools = [{
  name: 'search',  // 名称过于泛化
  description: '搜索',  // 描述不清晰
  inputSchema: {
    type: 'object',
    properties: {
      q: { type: 'string' }  // 参数名不明确
    }
  }
}];
2. Agent 安全设计
typescript 复制代码
// ✅ 好的实践: 最小权限原则
const agentConfig = {
  mcpServers: {
    filesystem: {
      command: 'npx',
      args: ['-y', '@mcp/server-filesystem', '/workspace/project'],
      // 仅允许访问项目目录
      env: {
        ALLOWED_PATHS: '/workspace/project'
      }
    }
  },
  execPolicy: {
    autoApprove: [
      'npm install',
      'git status',
      'git diff'
    ],
    alwaysDeny: [
      'rm -rf /',
      'sudo *',
      'chmod 777 *'
    ]
  }
};

// ❌ 不好的实践: 过度权限
const badConfig = {
  mcpServers: {
    filesystem: {
      args: ['/'],  // 允许访问整个文件系统
    }
  },
  execPolicy: {
    autoApprove: ['*']  // 自动批准所有命令
  }
};
3. 错误处理和重试
typescript 复制代码
// ✅ 好的实践: 指数退避重试
async function callToolWithRetry(
  tool: string,
  params: any,
  maxRetries = 3
): Promise<any> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await mcpClient.callTool(tool, params);
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;

      if (isRetryable(error)) {
        const backoff = Math.pow(2, attempt) * 1000;
        await sleep(backoff);
        continue;
      }

      throw error;
    }
  }
}

function isRetryable(error: Error): boolean {
  // 网络错误、超时等可重试
  return error.message.includes('ETIMEDOUT') ||
         error.message.includes('ECONNREFUSED');
}

十一、总结

11.1 核心洞察

  1. MCP 专注于 Agent ↔ 工具/资源 的标准化,由 Anthropic 主导
  2. ACPEditor ↔ Agent 的官方标准,由 Zed Industries 发布,类似于 LSP 在语言服务器领域的作用
  3. A2A (Gemini 实现) 专注于 Agent ↔ Agent 的互操作,是构建 Multi-Agent 系统的探索
  4. Codex SQ/EQ 提供了一个完整的 用户 ↔ Agent 交互模型,强调安全性和可控性

11.2 技术趋势

yaml 复制代码
2024          2025          2026          2027
  │             │             │             │
  ├─ MCP 1.0    ├─ MCP++      ├─ Unified    ├─ W3C Standard
  │  发布       │  - gRPC     │  Protocol   │  - 浏览器原生
  │             │  - WebAssembly│            │  - 硬件加速
  ├─ A2A 0.3    ├─ A2A 1.0    ├─ Agent Mesh ├─ Edge AI
  │  实验       │  生产可用   │  - K8s 集成 │  - 本地优先
  │             │             │             │
  └─ 碎片化     └─ 融合期     └─ 成熟期     └─ 普及期

11.3 给未来的思考

"The future of AI is not just about smarter models, but about smarter collaboration between models."

------ 未来的 AI 不仅仅是更智能的模型,而是模型之间更智能的协作。

协议标准化是 AI Agent 从 工具基础设施 演进的关键一步。就像 HTTP 成就了互联网,Docker 成就了云原生,MCP 和 ACP 正在成就 AI Agent 的生态系统


参考资源

官方文档

源码仓库

社区资源

作者:前端领秀------悄悄学习,惊艳所有人~

相关推荐
Jim8602 小时前
使用自定义API接入OpenAI CodeX配置教程
openai
奇舞精选6 小时前
我用 Chrome 扩展验证了 MCP 的安全风险,结果发现
chrome·mcp
机器之心1 天前
小米开源首个跨域具身基座模型MiMo-Embodied,29个榜单SOTA
人工智能·openai
该用户已不存在1 天前
6款MCP工具,让AI真正懂业务
ai编程·mcp
神州问学1 天前
Gemini 3.0 Pro Preview 实测报告
gemini
重整旗鼓~1 天前
2.LangChain4j+springboot+大模型整合
openai·springboot·ollama·langchain4j
哪吒编程1 天前
重磅更新!谷歌旗舰模型Gemini 3 Pro上线
gemini
吴法刚1 天前
Gemini cli 源码分析之-Gemini CLI 项目启动交互模式startInteractiveUI函数
ai·交互·ai编程·gemini·ai编码
疯狂踩坑人1 天前
Node写MCP入门教程
前端·agent·mcp