MCP、Agent、大模型应用架构解读

前言

随着大语言模型(LLM)的快速发展,如何让 AI 能够有效地与外部世界交互,已成为 AI 应用开发的核心课题。Anthropic 推出的 MCP(Model Context Protocol)、智能代理(Agent)和大模型应用三者的结合,形成了一套完整的 AI 系统架构。

接下来,我们深入解读这三个核心概念及其相互关系。


一、3个核心概念的定义

1.1 大模型应用(AI Application)

大模型应用是整个系统的最外层容器。它包括:

  • 应用程序框架和生命周期管理

  • 用户交互界面(CLI、Web、API等)

  • 系统配置和资源管理

  • 外部集成(数据库、监控等)

    大模型应用
    ├─ 启动应用
    ├─ 管理配置
    ├─ 处理用户输入
    ├─ 返回处理结果
    └─ 关闭应用

1.2 Agent(智能代理)

Agent 是大模型应用的大脑和执行引擎。它的职责是:

  • 理解用户意图(通过大模型)
  • 规划执行步骤
  • 决定调用什么工具
  • 处理工具执行结果
  • 持续优化和迭代

Agent 的核心价值在于将大模型的推理能力与外部工具执行能力结合。

1.3 MCP(Model Context Protocol)

MCP 是一个开放的通信协议规范。它定义了:

  • 工具的统一调用接口
  • 消息的标准格式(JSON-RPC 2.0)
  • 服务的发现和注册机制
  • 错误处理规范

MCP 的核心价值在于解耦工具调用的复杂性,实现工具即插即用。


二、三者的包含关系

复制代码
┌──────────────────────────────────────────────────┐
│                 大模型应用                        │
│                                                  │
│  ┌────────────────────────────────────────────┐ │
│  │              Agent                         │ │
│  │                                            │ │
│  │  ├─ 初始化 MCP (建立连接、获取工具)       │ │
│  │  ├─ 与大模型交互 (发送提示词、接收响应)  │ │
│  │  ├─ 解析大模型输出 (识别工具调用)        │ │
│  │  ├─ 通过 MCP 调用工具 (执行具体任务)     │ │
│  │  ├─ 处理工具结果 (反馈给大模型)          │ │
│  │  └─ 循环迭代 (直到任务完成)              │ │
│  │                                            │ │
│  │         ◄──────────────────────►          │ │
│  │            MCP (工具协议)                  │ │
│  │         ◄──────────────────────►          │ │
│  │                                            │ │
│  └────────────────────────────────────────────┘ │
│                                                  │
│  用户输入  ──►  应用处理  ──►  用户输出        │
│                                                  │
└──────────────────────────────────────────────────┘

三、工作流程详解

3.1 初始化阶段

复制代码
第一步:读取配置文件(mcp.json)
  ├─ 检查有哪些 MCP Server
  ├─ 验证配置的合法性
  └─ 记录工具来源信息

第二步:连接所有 MCP Server
  ├─ 为每个 Server 创建 MCP Client
  ├─ 建立传输连接(stdio/HTTP/WebSocket)
  ├─ 发送 initialize 信息握手
  └─ 获取 Server 能力信息

第三步:获取所有工具列表
  ├─ 从每个 Server 调用 listTools()
  ├─ 收集返回的工具定义
  ├─ 合并工具列表并检查冲突
  └─ 标记每个工具来自哪个 Server

第四步:准备就绪
  └─ Agent 获得完整的工具清单,可以开始工作

代码示例:

复制代码
class AIApplication {
  private agent: Agent
  
  async initialize() {
    // Agent 初始化
    this.agent = new Agent("mcp.json")
    await this.agent.initialize()
    
    console.log("✓ 应用初始化完成")
    console.log(`✓ 可用工具数: ${this.agent.toolCount}`)
  }
}

3.2 处理请求阶段

当用户输入一个请求时,完整的处理流程如下:

复制代码
用户输入: "帮我计算 (10 + 5) * 2 的结果"
  │
  ▼
┌─────────────────────────────────────────┐
│  Agent 第一步:准备提示词                 │
│  ├─ 获取当前的工具列表                   │
│  ├─ 组织成 Claude 能理解的格式          │
│  └─ 加入用户的原始请求                   │
└──────────────┬──────────────────────────┘
               │
  ┌────────────▼─────────────┐
  │  Claude API              │
  │  (处理用户请求)          │
  │  ├─ 理解用户意图         │
  │  ├─ 规划执行步骤         │
  │  └─ 决定调用哪些工具     │
  │                          │
  │  Claude 响应:            │
  │  "我需要先调用 add(10,5)"│
  └────────────┬─────────────┘
               │
  ┌────────────▼──────────────────────┐
  │  Agent 第二步:处理工具调用请求     │
  │  ├─ 解析 Claude 的响应             │
  │  ├─ 识别出要调用 "add" 工具        │
  │  ├─ 找到 "add" 来自哪个 Server    │
  │  └─ 获取该 Server 的 MCP Client    │
  └────────────┬──────────────────────┘
               │
  ┌────────────▼──────────────────────┐
  │  Agent 第三步:通过 MCP 调用工具    │
  │  ├─ 构建标准化的 RPC 请求          │
  │  ├─ 调用: client.callTool("add",   │
  │  │         {a: 10, b: 5})         │
  │  └─ 等待工具执行完毕               │
  └────────────┬──────────────────────┘
               │
  ┌────────────▼──────────────────────┐
  │  MCP Server (实际执行工具)         │
  │  ├─ 接收 RPC 请求                  │
  │  ├─ 执行: 10 + 5 = 15             │
  │  └─ 返回结果: {result: 15}        │
  └────────────┬──────────────────────┘
               │
  ┌────────────▼──────────────────────┐
  │  Agent 第四步:反馈给 Claude        │
  │  ├─ 把结果添加到对话历史           │
  │  ├─ "add(10, 5) 的结果是 15"      │
  │  └─ 重新调用 Claude               │
  └────────────┬──────────────────────┘
               │
  ┌────────────▼──────────────────────┐
  │  Claude 继续推理                  │
  │  ├─ 看到了第一步的结果             │
  │  ├─ 继续规划下一步                 │
  │  └─ "现在我需要调用 multiply(15,2)"│
  └────────────┬──────────────────────┘
               │
  (重复步骤 2-4 直到 Claude 说完成)
               │
  ┌────────────▼──────────────────────┐
  │  Claude 最终响应                   │
  │  ├─ stop_reason = "end_turn"      │
  │  ├─ content = "答案是 30"         │
  │  └─ Agent 停止循环                 │
  └────────────┬──────────────────────┘
               │
               ▼
        返回用户: "答案是 30"

3.3 循环机制的关键

Agent 的循环处理是理解整个架构的关键:

复制代码
async process(userInput: string): Promise<string> {
  let messages = [{ role: "user", content: userInput }]
  
  for (let iteration = 0; iteration < maxIterations; iteration++) {
    // 1. 调用 Claude
    const response = await claude.messages.create({
      messages,
      tools: this.tools  // 传递所有可用工具
    })
    
    // 2. 添加 Claude 的响应到历史
    messages.push({ role: "assistant", content: response.content })
    
    // 3. 检查 Claude 是否完成
    if (response.stop_reason === "end_turn") {
      // Claude 完成了,返回最终答案
      const textBlock = response.content.find(b => b.type === "text")
      return textBlock.text
    }
    
    // 4. Claude 要求调用工具
    if (response.stop_reason === "tool_use") {

      const toolResults = [ ]

      
      for (const block of response.content) {
        if (block.type === "tool_use") {
          // 通过 MCP 调用工具
          const result = await this.callToolViaMCP(
            block.name,
            block.input
          )
          
          toolResults.push({
            type: "tool_result",
            tool_use_id: block.id,
            content: JSON.stringify(result)
          })
        }
      }
      
      // 5. 把工具结果添加到历史(关键!Claude 需要看到结果)
      messages.push({
        role: "user",
        content: toolResults
      })
      
      // 循环回第 1 步,Claude 基于工具结果继续推理
    }
  }
}

关键点:

  • messages 数组是"记忆",不断积累
  • 每次调用 Claude 时,都传递完整的历史
  • Claude 基于之前的工具执行结果进行下一步决策

四、MCP 的泛化调用设计

4.1 为什么需要泛化?

不泛化的方式(混乱):

复制代码
// 需要为每个工具写特定代码
if (toolName === "add") {
  result = calculator.add(args.a, args.b)
} else if (toolName === "query") {
  result = database.query(args.sql)
} else if (toolName === "analyzeCode") {
  result = codeAnalyzer.analyze(args.code)
}
// ... 100+ 个 else if ...

// 问题:新增工具时要改应用代码

泛化的方式(MCP):

复制代码
// 一个函数搞定所有工具
const result = await this.callToolViaMCP(toolName, args)

// 问题解决:新增工具时只需改配置

4.2 泛化的实现原理

复制代码
┌──────────────────────────────────────────┐
│   统一的工具调用接口                      │
│   callTool(name: string, args: any)      │
└──────────────┬───────────────────────────┘
               │
      ┌────────┴────────┐
      │                 │
      ▼                 ▼
  ┌────────┐      ┌──────────┐
  │ Server │      │ Server   │
  │ A      │      │ B        │
  │        │      │          │
  │ add    │      │ query    │
  │ sub    │      │ insert   │
  └────────┘      └──────────┘

所有 Server 遵守相同的 MCP 规范:
  ├─ 都支持 listTools() 方法
  ├─ 都支持 callTool(name, args) 调用
  ├─ 都返回标准格式的结果
  └─ 应用无需关心 Server 差异

4.3 MCP 规范的约束

MCP 定义了统一的消息格式:

复制代码
// 工具列表请求
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "tools/list"
}

// 工具列表响应
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "tools": [
      {
        "name": "add",
        "description": "Add two numbers",
        "inputSchema": {
          "type": "object",
          "properties": {
            "a": {"type": "number"},
            "b": {"type": "number"}
          },
          "required": ["a", "b"]
        }
      }
    ]
  }
}

// 工具调用请求
{
  "jsonrpc": "2.0",
  "id": "2",
  "method": "tools/call",
  "params": {
    "name": "add",
    "arguments": {"a": 5, "b": 3}
  }
}

// 工具调用响应
{
  "jsonrpc": "2.0",
  "id": "2",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "5 + 3 = 8"
      }
    ]
  }
}

四、结尾

因此有了对这三者的核心概念的了解,其实对大模型应用开发也有了比较深入的认识了。

评论区欢迎讨论。

相关推荐
阿湯哥2 小时前
多智能体架构深度解析:企业落地如何选择Skills与SubAgents?
架构·wpf
敲敲了个代码2 小时前
React 官方纪录片观后:核心原理解析与来龙去脉
前端·javascript·react.js·面试·架构·前端框架
无心水2 小时前
1、Go语言工作区和GOPATH实战指南:从项目初始化到部署
开发语言·后端·架构·golang·go·gopath·go mod init
萤丰信息2 小时前
智慧园区新基建:“云-管-端”架构的破局之路与数智革命
大数据·人工智能·科技·安全·架构·智慧城市·智慧园区
王然-HUDDM2 小时前
HUDDM(全息普适需求动力学模型)详解
数学建模·架构·系统架构·agi·预编码算法
代码游侠2 小时前
ARM开放——阶段问题综述(一)
arm开发·笔记·嵌入式硬件·学习·架构
王卫东3 小时前
Vibe Coding:AI原生时代的编程范式革命与架构实践
架构·ai-native·vibe coding
vx-bot5556663 小时前
企业微信开放平台:生态化集成的架构演进与实践
架构·微信开放平台
min1811234563 小时前
急诊患者抢救流程流程图学术模板
架构·流程图·健康医疗