模型上下文协议(MCP)

Model Context Protocol (MCP)

构建 AI 智能体(尤其是结合检索增强生成 RAG 的智能体)时,一大工程痛点是如何向语言模型持续提供丰富、一致的上下文,同时避免为每个新数据源或新工具重复编写专用的胶水代码。传统做法通常把检索文档、工具输出与对话记忆拼入提示词,每接入一个新数据源或工具就要单独写一套连接器,很容易演变为分散且难以维护的系统。

模型上下文协议(Model Context Protocol,MCP)正是为解决这一问题而提出的开放标准。它为 AI 模型连接外部数据与工具能力提供了统一接口,常被比作“AI 应用的 USB-C 接口”:任何遵循 MCP 的智能体,都可以使用同一种协议访问任何遵循 MCP 的数据源或工具服务。通过引入统一协议层,原本 N×MN \times MN×M 的网状定制集成被简化为 N+MN + MN+M——每个模型客户端与每个工具服务端只需各自实现一次 MCP,即可彼此互通。

在 Agentic RAG 与多步智能体系统中,MCP 支持模型与外部数据源之间的双向通信:不仅能让助手按需拉取最新事实、查询企业内部知识库或调用外部 API,还能在多轮交互与工具调用之间传递结构化上下文(包括记忆、工具定义与任务目标),维持复杂任务规划与执行的连续性。

MCP 也支持构建更完善、更自主的智能体。单轮问答机器人能力有限,智能体系统则需要多步骤推理、工具调用、历史交互记忆和复杂任务执行。通过在多次交互及工具使用中传递结构化上下文,系统可以保持规划和操作的连续性。协议面向智能体系统,帮助 AI 承担机械性工作,让人类集中处理创造性任务。它为 AI 应用提供统一的上下文连接基础,使应用能够以一致方式向模型提供记忆、工具和目标等信息。

MCP 架构

MCP 采用客户端—服务端(Client–Server)架构,将智能体的高层推理逻辑与底层数据源及工具实现解耦。典型部署包含三类核心角色:

  1. Host 进程(智能体运行环境):承载主 AI 应用的宿主程序(如 IDE 编程插件或购物助手聊天界面),负责处理用户交互、调用语言模型、编排整体工作流,并通过内部的 MCP Client 管理与外部资源的连接。
  2. MCP Client(协议客户端):由 Host 为每个外部数据源或工具服务创建的轻量级客户端。每个 Client 与单个 MCP Server 维持一对一的专用连接,负责遵循 MCP 协议收发消息并隔离不同服务之间的交互;一个 Host 可以同时运行多个 Client,并发连接多个 Server 获取上下文。
  3. MCP Server(协议服务端):实现 MCP 规范的本地或远程程序,向 Client 暴露资源(Resources)、工具(Tools)和提示词模板(Prompts)。在课程企业知识示例中,由自建 MCP Server 查询经过授权的飞书知识索引(也可按需对接本地文件或 PostgreSQL);数据源的认证、按类型解析与 ACL 权限校验均由各自的服务端适配器执行,而语言模型调用与对话状态则由 Host 统一管理。
图 1 · 只读知识 MCP 的连接边界
Host 与 MCP Client
单个演示用户的应用;stdio 连接课程服务
自建 MCP Server
search_knowledge(query);验证参数与调用身份
授权知识索引
Qdrant 查询 + ACL 复核;只返回获准片段
飞书 OpenAPI 读取器
独立摄取进程;docx / doc / bitable
资料同步
分页、更新、删除与撤权;失败状态阻止发布
模型与评估
聊天、结构化与 embedding;按实际能力分别配置
Host 通过 MCP Client 查询授权索引。独立 OpenAPI 摄取进程更新索引,获准片段由 Host 交给模型。

这些组件可以将智能体连接到以下来源。

  1. 通过上述三层角色,智能体既可连接本地数据源(MCP Server 获准访问的本机文件、数据库与本地服务),也可连接远程数据源(通过互联网访问的外部系统与 API)。
  2. 远程数据来源:通过互联网提供的外部系统,例如可由 MCP Server 访问的 API。

最小权限与上下文隔离:Host 掌控全局信息流并执行安全与隐私规则,而每个 MCP Server 仅接收完成自身职责所必需的参数,无需读取完整对话历史或其他数据源的内容。例如,当需要通过某 MCP Server 查询内部数据库时,Host 可先弹窗征得用户同意,再仅将该次查询参数发往目标 Server,避免将无关上下文暴露给外部服务。

JSON-RPC 2.0 通信与能力协商:Client 与 Server 之间通过有状态的 JSON-RPC 2.0 消息通信(本地进程间通信常采用 stdio 标准输入输出管道,远程服务则采用安全的 HTTP(S) 及 Server-Sent Events (SSE))。交互消息分为三类:请求执行操作的 Request(如读取文件或调用工具)、返回结果的 Response / Result,以及单向推送更新或事件的 Notification。在连接初始化握手阶段,双方还会进行能力协商(Capability Negotiation):Server 声明自身支持的 resources、tools 等功能,Client 则声明是否支持由服务端发起的反向请求(例如允许 Server 请求宿主模型生成内容的 sampling 能力)。

在实际工程中,团队可分别维护文档查询、任务状态与业务资料等多个独立的 MCP Server,每个 Server 聚焦明确的职责边界,并各自独立校验调用者身份、输入参数与资料权限(注意:资源变更通知的支持范围需按具体实现核验,底层的索引更新与资料删除仍需依赖完整的同步对账流程)。

通过 MCP 组织模型上下文

MCP 定义了一套标准结构来表达和交换模型所需的上下文材料,使上下文具备良好的机器可读性,便于跨不同智能体框架共享和复用:

  • Resources(资源):Server 向 Client 暴露的只读上下文数据(如文件、数据库记录、知识文档等),通过唯一的 URI 标识,支持通过 resources/list 枚举、通过 resources/read 读取。读取 Resource 仅用于观察和注入背景信息,不应产生修改外部环境的副作用。
  • Tools 与工具说明:Server 可以公布多个工具,并为每个工具提供元数据,例如功能说明、参数 schema,以及适用的其他信息。统一工具描述后,智能体可以一致地理解工具,并结合可获得的成本、速率限制或延迟信息决定何时使用。传统应用可能在提示中写入工具规则,或依赖特定厂商的 function calling;MCP 通过 tools/call 等 JSON-RPC 请求调用工具,使协议层不依赖某一家 LLM API。工具可以是计算器,也可以执行数据库查询或调用外部 API。连接提供工具的 Server 后,应用即可通过统一接口使用;使用说明可以放在结构化工具描述和相关提示材料中。
  • Prompts(系统消息与提示词模板):Server 可提供针对特定领域任务预设的消息模板或工作流提示词。应用可按需从服务端获取合适的角色设定、语气要求与操作指令模板,将提示词作为服务端受版本控制的数据进行集中维护,无需把全部提示词硬编码在客户端代码中。
  • 上下文对象:在应用设计中,可以使用结构化对象保存当前任务的状态和知识,包括先前交互或知识库提供的记忆、当前目标、可用工具说明,以及以前操作的结果或环境反馈。这相当于把原本很长的提示材料分为明确字段。通常采用 JSON 等结构后,可以保存、版本化或在系统间传递。例如,分别保存相关文档、中间结论和工具用法,使上下文同时具备完整性和机器可解析性。
  • 任务与目标表达(Tasks & Goals):Host 可向 Server 传递当前请求的目标说明,Server 也可根据任务类型返回匹配的提示词模板或关联资源。
  • Observations(观察结果):智能体执行操作后从外部获得的反馈(如搜索结果或状态变更)。通过 MCP 返回的结构化资源或工具结果可直接记录到智能体状态中,形成清晰的执行轨迹,供后续推理引用、排障调试或沉淀训练数据。
  • 调用元数据(Invocation Metadata):应用还可统一维护模型或工具调用的运行元数据(如目标 API/模型标识、预期延迟与单价、时间/算力预算、输出格式要求,以及模型属于纯文本 LLM 还是多模态视觉模型),供 Host 在交互时限紧张或预算受限时动态路由至低成本模型或避开高耗时工具。

控制职责的划分

图 2 · MCP能力的控制主体
提示词:用户控制
MCP 提示词对应用户主导的控制方式。
资源:应用程序控制
MCP 资源对应应用程序主导的控制方式。
工具:模型控制
MCP 工具对应模型主导的控制方式。
MCP的提示、资源和工具分别对应用户、应用和模型主导的控制方式。
  • Prompts 由用户控制:Server 开发者可以提供适合处理其数据的提示,应用将这些提示呈现给用户,并用于与 LLM 交互。
  • Resources 由应用控制:资源可以是文本或二进制数据。应用开发者通常负责规定如何使用这些信息;具体选择通常由应用逻辑管理,LLM 无需参与。
  • Tools 由模型控制:需要赋予应用与环境交互的自主能力时,可以使用工具。Server 提供工具列表、说明和参数要求,应用将其传给 LLM,由模型判断任务需要哪些工具以及如何调用。

通过这种声明式结构,MCP 充当了分层 AI 架构中的“上下文连接层”——正如网络协议统一了数据包传输,MCP 统一了上下文的封装与交换,使上层智能体逻辑与下层模型及外部工具保持相对独立。

通过 MCP 集成 RAG、记忆与工具

在传统实现中,文档检索流水线、长期记忆向量库与外部业务 API 往往采用各自独立的接入代码;借助 MCP,这三类能力可以统一收敛到同一套接入机制下。

例如,构建一个同时支持“查询内部库存、修改购物车、记住用户长期偏好”的购物助手时,可分别部署三个独立的 MCP Server:Inventory MCP Server(提供库存检索)、Shopping Cart MCP Server(暴露 addItem 工具)和 Memory MCP Server(读写对话记忆与用户画像),由 Host 同时连接三者。当用户提问时,Host 从 Inventory Server 和 Memory Server 获取结构化的商品资料与用户偏好并注入模型上下文;当用户下达“请把第三款耳机加入购物车”的指令时,应用通过 tools/call 调用购物车 Server 的工具并拿到更新结果,全程无需让核心智能体代码耦合购物车底层 API 或记忆库的存储细节。

1. 通过 MCP 调用工具的标准流程

图 3 · 通过MCP完成工具调用
获取工具列表
智能体通过 MCP 客户端获取服务器提供的工具。
确定工具及参数
大语言模型根据查询和可用工具,确定工具及调用参数。
调用工具并返回数据
客户端向服务器提交调用请求,并接收工具执行结果。
查询与工具结果
智能体将查询和工具结果交给大语言模型,生成答案。
Agent通过MCP客户端获取并调用服务器能力,把工具结果交给模型生成回答。
  1. 将用户查询发送给智能体宿主应用(通常是一个 Python 应用)。
  2. 宿主应用通过内置的 MCP Client 向连接的 MCP Server 获取可用工具列表。
  3. 将工具列表与用户查询一同传给 LLM,由模型选择需调用的工具并生成参数。
  4. 宿主应用通过 MCP Client 向对应的 MCP Server 发送工具执行请求,并接收返回结果。
  5. 将原始用户查询与工具返回的数据一并再次提交给 LLM。
  6. LLM 生成最终回答,由智能体应用返回给用户。

MCP 还支持更具交互性的检索和工具使用。传统 RAG 可能在回答前只检索一次,有状态会话和通知机制则可以支持多轮交互。例如,Server 可以发送更新,具备相应能力时也可以请求澄清;智能体可以订阅资源,在任务期间资源变化时收到通知。这有助于智能体持续参与环境中的交互。

2. 通过 MCP 接入功能完整的 Agentic RAG

图 4 · 通过MCP接入Agentic RAG
分析查询
判断是否需要补充数据,需要时通过 MCP 服务器调用工具。
重排序检索结果
检索结果经过重排序,再用于生成答案。
分析答案
检查答案是否正确、是否与查询相关。
改写查询
答案需要改进时,改写查询并重新分析。
查询分析、检索、重排序、回答生成和检查组成循环,Agent通过多个MCP服务器获取外部数据。
  1. 分析用户查询:基于 LLM 的智能体接收原始查询,按需进行一次或多次改写以生成后续子查询,并判断是否需要补充外部数据。
  2. 通过 MCP 触发多源检索:需要补充数据时,通过多个 MCP Server 获取实时用户数据、内部文档或网页信息。在此环节,MCP 发挥了五项关键作用:

MCP 在数据访问部分发挥以下作用。

  • 各数据领域团队可独立维护各自的 MCP Server,并定义专属的数据使用规则。
  • 各领域可在各自的 Server 层内聚实施安全与合规控制。
  • 新增数据源时只需按标准协议挂载新 Server,使数据服务与智能体逻辑独立演进。
  • 平台开发者可通过标准接口向外部消费方开放数据访问能力。
  • AI 工程师可专注于顶层智能体工作流编排,无需陷入各数据源的底层对接细节。
  1. 汇总与重排序:汇集各 MCP Server 返回的检索数据,使用能力强于普通 embedding 模型的重排序模型精排,收敛候选范围。
  2. 生成候选回答:在无需补充数据或已完成检索重排后,通过 LLM 生成一个或多个候选回答(或操作指令)。
  3. 答案评估与改写循环:评估回答的事实正确性与相关性;达标则返回给用户,若仍需改进则改写查询并重新进入循环。

MCP 也有助于集成记忆。Memory Server 可以连接向量数据库或其他存储,对智能体而言则是另一个信息提供者,类似与 Mem0 交互。长期记忆可以由 Server 保存,按需返回相关片段。记忆因此能够跨会话保留,并按需读取,避免全部受限于单次模型上下文窗口。多个智能体还可以使用同一记忆来源:Agent A 完成部分任务后,Agent B 从相同存储读取已完成内容并继续。MCP 提供共享记忆的统一接口,支持这种连续协作。智能体内部仍负责规划和决定何时使用工具;MCP 为其提供可访问的数据和操作。推理步骤使用已有上下文决定操作,操作通过 MCP 请求执行,观察结果以结构化响应返回,并加入下一次推理。统一结果格式也便于通过提示或微调训练模型识别错误及结果 schema,再据此调整计划。这种一致性有助于上下文工程和可靠性。记录请求与结果后,开发者可以查看执行轨迹,分析提示和失败位置。

本课程的 MCP 练习使用官方 Python SDK 封装 search_knowledge,共用飞书读取器和授权知识索引。新增来源时实现其实际 API、数据类型和权限判定,再提供标准工具;只读范围和允许参数由执行端检查。连接器名称不代表它已经具备目标租户权限。

通过 MCP 管理连接后,开发者能够集中处理智能体逻辑和策略。检索上下文、执行操作和访问状态均可通过标准接口组织。增加图像模型等新模态,或者新的知识来源时,可以新增对应端点和服务,减少对核心智能体的重构。开发者因而能够更多关注高层行为,以及模型是否有效使用所提供的上下文。

实际应用与生态示例

MCP 自 2024 年末由 Anthropic 开源以来,已在多个领域落地并形成了涵盖 Python、TypeScript、Java 等多语言 SDK 的开放生态:

  • 编程与开发工具:Sourcegraph 的编程助手 Cody 与协作代码编辑器 Zed 均已集成 MCP,支持按需通过 Server 拉取大型代码库文件或 Pull Request 差异(Diff)作为代码生成与审查的上下文。
  • 企业知识助手:以授权保修政策、业务数据库与飞书知识库作为数据源,底层通过对应文档类型的 OpenAPI 读取数据,上层由自建 MCP Server 暴露受限的只读查询接口;用户身份、有效继承权限与同步版本分别独立维护,一旦访问校验失败立即停止返回对应来源。
  • 网页与文档解析助手:解析经授权获取的网页、PDF 和 DOCX 并保留来源位置与更新记录(课程主线采用本地解析脚本与企业文档 API;若需接入实时网页工具,必须另行核验允许访问的域名白名单、调用身份、返回结构、限流策略与正文完整性)。
  • 学术与多智能体研究:如 MCPWorld 等评测基准利用 MCP 作为统一环境接口,使研究者能够在固定任务 Server 的前提下无缝替换底层推理模型,公平对比不同模型在 API 与 GUI 任务上的表现。

MCP 的开放生态包括 Python、TypeScript、Java 等 SDK。本课程把企业文档读取、Qdrant 查询和只读工具作为具体接入示例,Git、PostgreSQL 等开源服务可以按各自权限使用。日历、CRM 或写入能力需要另外实现业务接口与授权,协议本身不会赋予操作权限。

通过自建 MCP 提供只读知识查询

examples/mcp_server.pyPython
import json
import os
from pathlib import Path

from mcp.server.fastmcp import FastMCP
from qdrant_client import QdrantClient

from pipeline import DemoAcl, Embedding, KnowledgeIndex, Principal, configured_client

mcp = FastMCP('course-readonly-knowledge')
acl = DemoAcl(json.loads(Path('fixtures/acl.json').read_text()))
principal = Principal('demo-tenant', 'demo-user')
index = KnowledgeIndex(QdrantClient(url=os.environ['QDRANT_URL']), os.environ['QDRANT_COLLECTION'],
    Embedding(configured_client('EMBEDDING'), os.environ['EMBEDDING_MODEL'], int(os.environ['EMBEDDING_DIMENSIONS'])), acl)


@mcp.tool(description='只读查询当前演示用户获准访问的企业资料。',
          annotations={'readOnlyHint': True, 'destructiveHint': False, 'openWorldHint': False})
def search_knowledge(query: str) -> list[dict]:
    if not query.strip() or len(query) > 1000:
        raise ValueError('invalid_query')
    return index.retrieve(principal, query)


if __name__ == '__main__':
    # 此 stdio 示例绑定单个演示用户;远程多用户服务器需单独实现认证与会话身份。
    mcp.run(transport='stdio')

关于飞书官方远程 MCP 的能力边界,可查阅其支持工具列表(注意其中 fetch-doc 工具对内嵌表格等复杂结构存在读取限制),且官方个人 MCP Token 说明已提示该个人凭据方式将逐步下线。因此,课程中各类文档的读取、分页、权限与同步仍统一由后端的 OpenAPI 适配器承担。

此外,代码中的 readOnlyHint 等工具注解(Annotations)仅用于向客户端声明工具意图,服务端内部仍必须强制执行权限过滤与参数长度校验。本地 stdio 模式下密钥保存在本地进程环境变量中;若切换为远程 HTTP 连接,还需严格实现协议层认证与令牌受众(Audience)校验,严禁允许模型在工具调用参数中直接传入原始密钥或自行指定用户身份。

练习:通过 MCP 的 tools/list 接口检查工具定义,再用 tools/call 查询相同问题;随后撤回演示用户的资料访问权限并再次调用,确认接口返回空结果。

搜索课程

正在加载课程目录…