什么是 Model Context Protocol (MCP)?工程师简明指南
Source: Dev.to
什么是模型上下文协议(MCP)?给工程师的简明指南
在当今的生成式 AI 时代,大型语言模型(LLM) 已经成为构建智能应用的核心组件。尽管 LLM 本身功能强大,但在实际项目中,我们经常会遇到以下两个痛点:
- 提示(Prompt)管理混乱:不同的业务场景需要不同的提示模板,随着功能的迭代,这些模板会迅速膨胀、难以维护。
- 上下文信息共享不足:模型在一次调用中只能看到当前请求的上下文,无法自然地利用历史对话、用户偏好或外部知识库。
模型上下文协议(Model Context Protocol,简称 MCP) 正是为了解决上述问题而诞生的。它提供了一套统一的、可扩展的方式来描述、组织和传递模型所需的上下文信息,使得提示编写、上下文注入以及模型调用都可以标准化、模块化。
下面我们将从概念、核心组成、使用方式以及实际案例四个维度,系统地介绍 MCP。
目录
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."
}解释
- model:目标 LLM。
- schemaVersion:MCP 规范的版本号,便于向后兼容。
- contextBlocks:一个数组,每个元素都是一个 Context Block。
type决定了该块对应的 Schema 与 Resolver。id用于在日志或缓存中唯一标识。data是实际的上下文内容,必须符合对应 Schema。
- 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 的调用频率。
实战案例:构建一个多轮对话机器人
场景描述
- 业务需求:为电商平台提供积分查询与兑换的客服机器人。
- 挑战:
- 需要实时获取用户最新积分。
- 必须遵守平台的兑换规则(每次最多 500 积分,兑换比例 1%)。
- 对话历史必须保留,以便模型理解上下文。
解决方案(使用 MCP)
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 定义 Schema | 为 user_points、business_rules、conversation_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 校验,防止错误数据进入模型,降低“幻觉”风险。 |
| 可观测性 | id 与 type 为日志提供结构化标签,便于追踪问题根源。 |
| 灵活扩展 | 新增业务需求时,只需添加对应的 Schema 与 Resolver,无需重写 Prompt。 |
局限
| 局限 | 说明 |
|---|---|
| 初始成本 | 需要投入时间编写 Schema、实现 Resolver,适合中大型项目。 |
| 运行时开销 | 多个 Resolver 并行调用可能导致请求延迟,需要做好缓存与超时控制。 |
| 模板依赖 | Prompt 的最终质量仍然取决于模板编写的技巧,MCP 只能提供结构化数据,不能自动生成高质量自然语言。 |
结论
模型上下文协议(MCP)为 “结构化上下文 + 可编程 Prompt” 提供了一套统一的实现方式。通过 Schema + Resolver + Payload 的三层抽象,工程团队可以:
- 把上下文当作代码来管理,实现版本化
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 是一个 通信协议。它规定了:
工具的描述方式
MCP 服务器会公开一组带结构化定义的工具列表:name、description、input schema、output schema。大型语言模型读取这些定义,以了解有哪些工具可用以及如何使用它们。工具的调用方式
当代理想要使用某个工具时,会向 MCP 服务器发送结构化请求。服务器执行该工具并返回结构化响应。所有交互均基于 JSON‑RPC 2.0 的标准消息格式。发现机制
代理查询 MCP 服务器以获取其提供的工具。这意味着代理可以根据实际可用的工具进行适配,而不需要硬编码工具定义。
类比: MCP 对 AI 代理而言,就像 USB‑C 对设备的意义。USB‑C 出现之前,每种设备都有不同的接口——充电线、数据线、显示线——各不相同且不兼容。USB‑C 统一了接口,无论是哪种设备或哪根线,只要插上就能工作。
同理,MCP 统一了 AI 代理与工具之间的“接口”。会说 MCP 的代理可以连接任何会说 MCP 的工具,无论背后使用的是哪个 LLM,或工具连接的是哪个系统。
如何在三步中工作
工具所有者创建 MCP 服务器
一个轻量级服务,通过 MCP 接口公开一个或多个工具(例如,数据库查询功能、Slack 消息功能、代码执行环境)。服务器描述它提供的工具以及如何调用它们。代理发现可用工具
当代理初始化时,它会查询 MCP 服务器并收到包含可用工具及其模式的结构化列表。代理现在知道它可以做什么。代理调用工具
根据用户请求以及已知可用的工具,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。
快速推动采用的三大因素:
主要 LLM 提供商立即认可
Anthropic 构建了它,但 OpenAI、Google 和 Microsoft 在几个月内就采用了。跨供应商的支持意味着开发者只需一次构建 MCP 集成,即可在任何 LLM 上使用。工具所有者的集成成本降至几乎为零
将现有 API 暴露为 MCP 服务器只需少量包装代码。Slack、Datadog、Sentry 等公司能够快速添加 MCP 支持,因为额外工作量极小。开发者对这种需求迫切
替代方案——为每个代理、每个团队、每个 LLM 构建和维护自定义工具集成——显得非常痛苦。MCP 提供的解脱感立刻被感受到。
MCP 不包括的内容
MCP 定义 连接,但 不定义 与连接相关的规则。
- 该协议 没有内置机制 来指定哪些代理可以调用哪些工具。
- 它 没有审计日志。
- 它 没有办法检测 工具响应中是否包含注入的指令或恶意内容。
这些治理和安全问题必须由外围基础设施或基于核心 MCP 规范构建的扩展来处理。
为什么需要 MCP 网关
MCP 旨在操控 LLM。它没有团队级访问策略的概念。
注意: 这并不是缺陷——而是有意的范围决定。协议保持最小化,治理层则构建在其之上。
本地开发 / 小规模实验:
缺乏内置治理是可以接受的。面向多个团队、涉及敏感数据且有合规要求的生产部署:
MCP 开箱即用的功能与企业部署所需之间的差距会变得显著。
正是这段差距需要 MCP 网关 来填补:它在你的 MCP 服务器前提供治理和安全层,并处理:
- 身份验证
- 访问控制(RBAC)
- 审计日志
- 工具范围
所有这些都 对每个通过网关的代理一致执行。
TrueFoundry的 MCP 网关
TrueFoundry’s MCP Gateway 专为该层构建。它:
- 连接到您现有的身份提供者
- 在工具层面强制执行 RBAC
- 记录每一次工具调用的完整上下文
- 完全部署在您自己的基础设施中,确保您的数据永不离开您的环境
已经管理大量 AI 工作负载的团队使用它,将 MCP 从演示阶段转变为可靠的生产解决方案——跨团队、企业规模。