什么是 Model Context Protocol (MCP)?工程师简明指南

发布: (2026年4月6日 GMT+8 16:59)
20 分钟阅读
原文: Dev.to

Source: Dev.to

什么是模型上下文协议(MCP)?给工程师的简明指南

在当今的生成式 AI 时代,大型语言模型(LLM) 已经成为构建智能应用的核心组件。尽管 LLM 本身功能强大,但在实际项目中,我们经常会遇到以下两个痛点:

  1. 提示(Prompt)管理混乱:不同的业务场景需要不同的提示模板,随着功能的迭代,这些模板会迅速膨胀、难以维护。
  2. 上下文信息共享不足:模型在一次调用中只能看到当前请求的上下文,无法自然地利用历史对话、用户偏好或外部知识库。

模型上下文协议(Model Context Protocol,简称 MCP) 正是为了解决上述问题而诞生的。它提供了一套统一的、可扩展的方式来描述、组织和传递模型所需的上下文信息,使得提示编写、上下文注入以及模型调用都可以标准化、模块化。

下面我们将从概念、核心组成、使用方式以及实际案例四个维度,系统地介绍 MCP。


目录

  1. MCP 的核心概念
  2. MCP 的结构化模型
  3. 如何在代码中使用 MCP
  4. 实战案例:构建一个多轮对话机器人
  5. MCP 的优势与局限
  6. 结论

MCP 的核心概念

术语含义
Context Block描述模型需要的某类信息的独立块,例如用户资料、对话历史、业务规则等。
Schema对 Context Block 的结构进行约束的 JSON Schema,确保上下文数据的完整性和类型安全。
Resolver用于在运行时获取或生成 Context Block 内容的函数或服务。
MCP Payload包含所有 Context Block 实例的完整请求体,最终会被序列化为模型的 Prompt。

关键点:MCP 并不替代 Prompt,而是为 Prompt 提供结构化的、可复用的上下文。最终的 Prompt 仍然是自由文本,只是它的生成过程由 MCP 自动化。


MCP 的结构化模型

{
  "model": "gpt-4o-mini",
  "schemaVersion": "1.0",
  "contextBlocks": [
    {
      "type": "user_profile",
      "id": "profile_123",
      "data": {
        "name": "张三",
        "age": 28,
        "membershipLevel": "Gold"
      }
    },
    {
      "type": "conversation_history",
      "id": "conv_456",
      "data": [
        {"role": "user", "content": "我想了解我的积分情况"},
        {"role": "assistant", "content": "您目前拥有 1200 积分"}
      ]
    },
    {
      "type": "business_rules",
      "id": "rules_001",
      "data": {
        "maxPointsRedeemable": 500,
        "redeemRate": 0.01
      }
    }
  ],
  "promptTemplate": "You are a helpful customer service assistant. Use the provided context blocks to answer the user query."
}

解释

  1. model:目标 LLM。
  2. schemaVersion:MCP 规范的版本号,便于向后兼容。
  3. contextBlocks:一个数组,每个元素都是一个 Context Block
    • type 决定了该块对应的 Schema 与 Resolver。
    • id 用于在日志或缓存中唯一标识。
    • data 是实际的上下文内容,必须符合对应 Schema。
  4. promptTemplate:模板字符串,MCP 会在渲染时把 contextBlocks 中的数据注入到模板里,生成最终的 Prompt。

如何在代码中使用 MCP

下面的示例基于 Node.js(使用 axios 发送请求),展示了从 Resolver 获取数据、组装 MCP Payload 并调用 OpenAI API 的完整流程。

// 1️⃣ 定义每种 Context Block 的 Schema(这里使用 ajv 进行校验)
const userProfileSchema = {
  type: "object",
  properties: {
    name: { type: "string" },
    age: { type: "integer" },
    membershipLevel: { type: "string" }
  },
  required: ["name", "age", "membershipLevel"]
};

const conversationHistorySchema = {
  type: "array",
  items: {
    type: "object",
    properties: {
      role: { enum: ["user", "assistant", "system"] },
      content: { type: "string" }
    },
    required: ["role", "content"]
  }
};

// 2️⃣ Resolver:从外部服务获取上下文
async function resolveUserProfile(userId) {
  const resp = await axios.get(`https://api.example.com/users/${userId}`);
  return resp.data; // 必须符合 userProfileSchema
}

async function resolveConversationHistory(sessionId) {
  const resp = await axios.get(`https://api.example.com/sessions/${sessionId}/history`);
  return resp.data; // 必须符合 conversationHistorySchema
}

// 3️⃣ 组装 MCP Payload
async function buildMcpPayload(userId, sessionId) {
  const [profile, history] = await Promise.all([
    resolveUserProfile(userId),
    resolveConversationHistory(sessionId)
  ]);

  return {
    model: "gpt-4o-mini",
    schemaVersion: "1.0",
    contextBlocks: [
      { type: "user_profile", id: `profile_${userId}`, data: profile },
      { type: "conversation_history", id: `conv_${sessionId}`, data: history }
    ],
    promptTemplate: `
      You are a friendly assistant. Use the following context to answer the user:

      {{#each contextBlocks}}
      ## {{type}}
      {{json this.data}}
      {{/each}}

      User query: {{userQuery}}
    `
  };
}

// 4️⃣ 调用模型(这里使用 OpenAI 官方 SDK)
async function callModel(mcpPayload, userQuery) {
  const renderedPrompt = renderTemplate(mcpPayload.promptTemplate, {
    contextBlocks: mcpPayload.contextBlocks,
    userQuery
  });

  const response = await openai.chat.completions.create({
    model: mcpPayload.model,
    messages: [{ role: "user", content: renderedPrompt }]
  });

  return response.choices[0].message.content;
}

注意

  • Schema 校验:在将 data 写入 contextBlocks 前务必进行校验,防止不符合预期的结构导致 Prompt 失效。
  • 模板渲染:示例中使用了 Handlebars({{#each}})进行渲染,你可以根据团队偏好选择 Jinja、Mustache 等。
  • 缓存:对于不经常变化的块(如业务规则),建议在内存或分布式缓存中保存,以降低 Resolver 的调用频率。

实战案例:构建一个多轮对话机器人

场景描述

  • 业务需求:为电商平台提供积分查询与兑换的客服机器人。
  • 挑战
    1. 需要实时获取用户最新积分。
    2. 必须遵守平台的兑换规则(每次最多 500 积分,兑换比例 1%)。
    3. 对话历史必须保留,以便模型理解上下文。

解决方案(使用 MCP)

步骤操作说明
1定义 Schemauser_pointsbusiness_rulesconversation_history 分别编写 JSON Schema。
2实现 Resolver- resolveUserPoints(userId) 调用积分系统 API。
- resolveBusinessRules() 读取配置文件或数据库。
- resolveConversationHistory(sessionId) 从对话存储读取。
3构建 MCP Payload将三个块组合,并使用统一的 Prompt Template。
4渲染 Prompt在模板中插入:
① 用户基本信息(姓名、会员等级)
② 当前积分
③ 业务规则
④ 最近 5 条对话记录
5调用模型将渲染后的 Prompt 发送给 LLM,获取答案。
6后处理若答案涉及积分兑换,调用业务系统执行实际扣减,并将结果写回 conversation_history

示例 Prompt(渲染后)

You are a helpful customer service assistant. Use the following context to answer the user:

## user_profile
{
  "name": "张三",
  "age": 28,
  "membershipLevel": "Gold"
}

## user_points
{
  "totalPoints": 1200
}

## business_rules
{
  "maxPointsRedeemable": 500,
  "redeemRate": 0.01
}

## conversation_history
[
  {"role":"user","content":"我想兑换积分"},
  {"role":"assistant","content":"每次最多可以兑换 500 积分,兑换比例为 1%"},
  {"role":"user","content":"那我现在有多少积分?"}
]

User query: 我想兑换 300 积分,怎么操作?

模型输出示例

您好,张三!您当前拥有 1200 积分。按照平台规则,您可以一次兑换最多 500 积分,兑换比例为 1%。如果您想兑换 300 积分,请确认,我将为您完成兑换并扣除相应积分(300 × 0.01 = 3 元)。


MCP 的优势与局限

优势

维度具体收益
可维护性所有上下文统一声明,修改一次即可在所有 Prompt 中生效。
可复用性同一 Context Block 可以在不同业务线、不同模型之间共享。
安全性通过 Schema 校验,防止错误数据进入模型,降低“幻觉”风险。
可观测性idtype 为日志提供结构化标签,便于追踪问题根源。
灵活扩展新增业务需求时,只需添加对应的 Schema 与 Resolver,无需重写 Prompt。

局限

局限说明
初始成本需要投入时间编写 Schema、实现 Resolver,适合中大型项目。
运行时开销多个 Resolver 并行调用可能导致请求延迟,需要做好缓存与超时控制。
模板依赖Prompt 的最终质量仍然取决于模板编写的技巧,MCP 只能提供结构化数据,不能自动生成高质量自然语言。

结论

模型上下文协议(MCP)为 “结构化上下文 + 可编程 Prompt” 提供了一套统一的实现方式。通过 Schema + Resolver + Payload 的三层抽象,工程团队可以:

  1. 把上下文当作代码来管理,实现版本化

MCP 解决的问题

AI 模型擅长推理,但它们本身是完全孤立的。

  • 一个在文本上训练的语言模型知道很多东西,但它 不知道 你的数据库里有什么,Slack 频道里有什么,或者 Jira 中当前有哪些未完成的任务。
  • 它无法发送邮件、查询你的 CRM,或触发一次部署。

要让 AI 代理完成有价值的工作——不仅仅是回答问题,而是真正采取行动——它们需要连接到外部工具和数据源。

在 MCP 之前,这些连接都是 定制构建 的:

团队集成
工程工作流助理自定义 GitHub 集成
同一团队单独的 Jira 集成
同一团队内部部署系统集成

这些集成都没有转移到其他团队,也无法在不同的大语言模型之间复用。

如果一个团队想从 OpenAI 切换到 Claude,他们必须重写这些集成。如果另一个团队需要类似的功能,他们只能从头开始构建。

BCG 给这个问题量化了一个数字:没有标准协议,随着组织中 AI 代理的增多,集成复杂度呈二次方增长。每个新代理都需要与每个工具建立自己的连接。复杂度快速叠加。

MCP 通过标准化连接来解决此问题。 与其让每个团队自行构建定制集成,工具只需以 MCP 服务器的形式暴露自己,使用统一的接口。任何兼容 MCP 的代理都可以无须自定义代码地连接到任何 MCP 服务器。一次构建的集成即可在所有场景中使用。

What MCP Actually Is

Model Context Protocol 是一个 开放标准 —— 最初由 Anthropic 于 2024 年 11 月发布,2025 年 12 月捐赠给 Linux 基金会,成为新成立的 Agentic AI Foundation 的一部分 —— 用于定义 AI 代理如何发现并调用外部工具。

从本质上讲,MCP 是一个 通信协议。它规定了:

  1. 工具的描述方式
    MCP 服务器会公开一组带结构化定义的工具列表:namedescriptioninput schemaoutput schema。大型语言模型读取这些定义,以了解有哪些工具可用以及如何使用它们。

  2. 工具的调用方式
    当代理想要使用某个工具时,会向 MCP 服务器发送结构化请求。服务器执行该工具并返回结构化响应。所有交互均基于 JSON‑RPC 2.0 的标准消息格式。

  3. 发现机制
    代理查询 MCP 服务器以获取其提供的工具。这意味着代理可以根据实际可用的工具进行适配,而不需要硬编码工具定义。

类比: MCP 对 AI 代理而言,就像 USB‑C 对设备的意义。USB‑C 出现之前,每种设备都有不同的接口——充电线、数据线、显示线——各不相同且不兼容。USB‑C 统一了接口,无论是哪种设备或哪根线,只要插上就能工作。
同理,MCP 统一了 AI 代理与工具之间的“接口”。会说 MCP 的代理可以连接任何会说 MCP 的工具,无论背后使用的是哪个 LLM,或工具连接的是哪个系统。

如何在三步中工作

  1. 工具所有者创建 MCP 服务器
    一个轻量级服务,通过 MCP 接口公开一个或多个工具(例如,数据库查询功能、Slack 消息功能、代码执行环境)。服务器描述它提供的工具以及如何调用它们。

  2. 代理发现可用工具
    当代理初始化时,它会查询 MCP 服务器并收到包含可用工具及其模式的结构化列表。代理现在知道它可以做什么。

  3. 代理调用工具
    根据用户请求以及已知可用的工具,LLM 向 MCP 服务器发送结构化的工具调用。服务器执行该工具并返回结果。LLM 将结果纳入推理并继续。

这就是完整的循环。LLM 不需要了解工具的实现细节。工具也不需要了解 LLM 的任何信息。协议处理它们之间的对话。

为什么生态系统增长如此之快

MCP 于 2024 年 11 月推出。到 2025 年 4 月,MCP 服务器下载量从大约 100 k 增长到每月超过 8 M。到 2025 年底,公开可用的 MCP 服务器超过 5,800 台,涵盖 Slack、Confluence、Sentry 等以及数据库、代码执行环境和内部企业系统。SDK 下载量突破每月 97 M

快速推动采用的三大因素:

  1. 主要 LLM 提供商立即认可
    Anthropic 构建了它,但 OpenAI、Google 和 Microsoft 在几个月内就采用了。跨供应商的支持意味着开发者只需一次构建 MCP 集成,即可在任何 LLM 上使用。

  2. 工具所有者的集成成本降至几乎为零
    将现有 API 暴露为 MCP 服务器只需少量包装代码。Slack、Datadog、Sentry 等公司能够快速添加 MCP 支持,因为额外工作量极小。

  3. 开发者对这种需求迫切
    替代方案——为每个代理、每个团队、每个 LLM 构建和维护自定义工具集成——显得非常痛苦。MCP 提供的解脱感立刻被感受到。

MCP 不包括的内容

MCP 定义 连接,但 不定义 与连接相关的规则。

  • 该协议 没有内置机制 来指定哪些代理可以调用哪些工具。
  • 没有审计日志
  • 没有办法检测 工具响应中是否包含注入的指令或恶意内容。

这些治理和安全问题必须由外围基础设施或基于核心 MCP 规范构建的扩展来处理。

为什么需要 MCP 网关

MCP 旨在操控 LLM。它没有团队级访问策略的概念。

注意: 这并不是缺陷——而是有意的范围决定。协议保持最小化,治理层则构建在其之上。

  • 本地开发 / 小规模实验:
    缺乏内置治理是可以接受的。

  • 面向多个团队、涉及敏感数据且有合规要求的生产部署:
    MCP 开箱即用的功能与企业部署所需之间的差距会变得显著。

正是这段差距需要 MCP 网关 来填补:它在你的 MCP 服务器前提供治理和安全层,并处理:

  • 身份验证
  • 访问控制(RBAC)
  • 审计日志
  • 工具范围

所有这些都 对每个通过网关的代理一致执行

TrueFoundry的 MCP 网关

TrueFoundry’s MCP Gateway 专为该层构建。它:

  • 连接到您现有的身份提供者
  • 在工具层面强制执行 RBAC
  • 记录每一次工具调用的完整上下文
  • 完全部署在您自己的基础设施中,确保您的数据永不离开您的环境

已经管理大量 AI 工作负载的团队使用它,将 MCP 从演示阶段转变为可靠的生产解决方案——跨团队、企业规模。

探索 TrueFoundry 的 MCP 网关 →

0 浏览
Back to Blog

相关文章

阅读更多 »

让 OpenClaw 在压缩后记住它的操作

为什么会这样?虽然 AI 看起来像魔法,运作也像魔法,但在底层它仍然有其局限性,在这种情况下,就是它的上下文窗口 https://pla...