Alex Cheng
本文目录01 · 定义02 · 为什么需要03 · 职责与机制04 · 一次查询的推导05 · 三类能力怎样选06 · 完整应用方案07 · 验收与扩展08 · 换场景应用
← Agent、Skill 与 MCP

一篇讲透 MCP:角色、消息流、Tools、Resources 与 Prompts

沿一次完整请求,读懂客户端、服务端与模型如何配合。

Alex Cheng · 2026-09-09

假设你想做一个需求评审助手:它能找到指定项目的文档,按你的标准检查问题,最后把评审意见保存成草稿。真正需要弄清的,不是“要接几个 MCP”,而是模型缺少哪种能力、谁来提供这项能力,以及怎样确认它真的做对了。

这篇文章围绕这个任务展开。先定义 MCP,再推导为什么需要它、一次调用怎样发生,最后把需求拆成可以交给开发者或 AI 实现的方案。目标是让你能设计并验收一个小型接入,而不只是认得术语。

MCP 解决的是应用与外部能力之间的沟通约定。业务目标、访问权限和结果验收,仍然需要我们设计。
如果已经接触过 MCP,先用三个问题定位阅读起点

① 能否解释 MCP 和 Server 的区别?说不清,从第 1 节读。② 能否解释“工具可见却没取得资料”?说不清,重点读第 3—4 节。③ 能否为一个新助手写出能力、权限与验收结果?还不能,完成第 6—8 节的设计任务。先口头作答再继续,不把看懂答案当作会用。

01 / 定义:MCP 到底是什么

可以把 MCP 想成一套通用的“服务目录+办事规则”:接入方先问有哪些服务、需要填写哪些信息,再按约定提交请求、接收结果。这里的关键不是目录长什么样,而是不同接入方能用同一种方式和服务沟通。

更准确地说,MCP(Model Context Protocol,模型上下文协议)是一套让 AI 应用与外部服务交换能力描述、资料和调用结果的协议。协议是双方遵守的消息规则;实现这些规则的程序,才是你真正安装、配置或开发的东西。

例如,文档系统可以通过一个 MCP Server 提供“搜索文档”。AI 应用先得到这个工具的名称、用途和参数要求,再发起查询。Server 收到请求后调用文档系统的接口,取得真实资料。MCP 并没有替文档系统建立数据库,也没有替用户开通账号。

这个类比哪里会失效?

办事窗口可能靠常识理解模糊要求,程序不能依赖这种默契。参数、访问范围和错误返回需要明确实现;“统一规则”也不等于“所有接入都自动兼容”。

先停一下:MCP、MCP Server、文档系统有什么不同?

MCP 是沟通规则;MCP Server 是实现规则、对外提供能力的程序;文档系统保存实际资料。若把三者都叫“连接工具”,会看不清适配和维护由谁负责。回看本节,再用“天气查询”各举一个对应对象。

02 / 推导:什么情况下值得用 MCP

有了定义,才能判断是否需要它。先从一个更直接的方案出发:应用调用文档 API,把返回内容交给模型。这条路完全成立,MCP 不是使用 AI 的前提。

  1. 前提一:模型只有本次提供给它的信息。如果需求文档没有送入上下文,它不会因为知道文档名称就读到正文。
  2. 所以,需要一个取资料的执行环节。可以由应用直接调用 API,也可以让应用通过 MCP 接入提供查询能力的 Server。
  3. 前提二:同一能力可能被多个 AI 应用使用。如果每个应用都维护各自的能力描述、参数转换和返回约定,重复适配会增多。
  4. 因此,统一交互规则才产生复用价值。Server 集中封装外部系统,支持 MCP 的应用按照共同约定使用它。

注意最后一步的条件:只有出现复用或统一接入需求时,这份收益才更明显。已有的 Server、可用客户端和维护成本,都要算进决策。

标准化的是接口,不是外部业务。

Server 里面仍然有人要调用真实 API、处理账号和错误。MCP 不会让适配工作消失;成熟的 Server 让你复用已有工作,自建 Server 则意味着你承担这部分维护。

评审助手的选择:如果只是这一次检查一份文件,直接上传即可。如果文档不断更新,而且桌面助手、内部网页和自动化流程都要访问同一资料能力,就值得评估 MCP。固定后端只访问一个 API 时,则比较直接集成与 MCP 的实际维护成本。

判断:AI 总是误解评审标准,接入 MCP 能直接解决吗?

不能。这里首先缺的是明确的任务要求和验收标准,连接更多数据不等于判断更准确。只有确认所需信息根本无法取得时,才回到连接问题。变式:一份文档已经完整上传,但答案仍跑题,应该优先检查任务还是接口?

03 / 机制:谁负责理解,谁负责执行

决定采用 MCP 后,先别急着配置。我们需要把“评审助手”拆成几层职责,否则容易以为模型自己连接了数据库、自己获得了保存权限。

Host 是承接任务的 AI 应用;Model 是生成回答或提出调用的模型;Client 是应用内负责 MCP 通信的组件;Server 提供外部能力;外部系统保存资料并执行业务。它们描述的是职责,不是必须购买五个独立产品。

图 1 · 应用组织任务,模型提出建议,Client 与 Server 负责连接。点击图解可放大。

读图时先看包含关系:Client 在 Host 内。再看两条通信路径:应用和模型交换任务、工具说明与结果;Client 和 Server 交换 MCP 消息。模型可以建议调用工具,但仍由应用组织执行。Server 又通过文档 API 等具体实现访问真实数据。

这也解释了权限为什么不能交给模型“自觉遵守”:模型能说出工具名,并不证明用户可以访问那个项目。应用与服务端必须落实各自的检查。Server 可以在本机,也可以在远端,“服务端”不是必须上云的意思。

补一步:模型返回“请保存草稿”后,能直接宣布保存成功吗?

还不能。缺少应用检查、Client 发起调用、Server 执行业务以及返回结果。第一个断点在“建议”被误当成“执行”。即使调用成功,还应检查草稿是否确实保存到正确位置。

04 / 推导:一次查询为什么要分两步

现在只做评审流程的第一件事:“列出项目 P-01 的文档。”应用已连接到一个文档 Server。此时,模型面对的第一个问题不是文档有哪些,而是有哪些能力可用。

第一步,发现能力。Client 请求工具列表,Server 返回名称、用途与参数结构。应用筛选后交给模型。这份结果相当于说明书,还不是文档清单。

第二步,执行操作。模型根据任务提出工具名与参数;应用检查后,通过 Client 请求 Server 执行。文档系统返回数据,应用再把工具结果交给模型,模型才有依据回答用户。

图 2 · 先获取能力说明,再执行具体操作。授权检查发生在应用中,工具执行发生在服务端。
这一刻拿到什么本例中的内容能据此得出什么
工具说明list_documents,需要 project_id知道怎样查询,不知道查询结果。
调用建议list_documents,project_id=P-01知道模型打算做什么,尚未证明执行。
执行结果返回 D-01、D-02 的标识与标题取得清单;若没有正文,还不能评审内容。

这三个中间结果就是排错依据。没有工具说明,查能力暴露;建议参数不对,查描述与上下文;执行失败,查权限、业务对象和接口;有清单却没有正文,继续读取,而不是让模型凭标题写评审。

改变条件:工具列表只有“搜索标题”,还能直接完成正文评审吗?

不能。列表只证明能搜索标题,需要再找到读取正文的能力,或由用户提供正文。若省略这一步,就把“找到资料”误当成“拥有评审依据”。回到图中发现阶段检查能力是否覆盖目标。

05 / 辨别:Tool、Resource、Prompt 怎样选

查询流程走通后,评审还需要材料和标准。MCP 可以提供三类能力,我们按“当前要解决什么问题”来选,不按术语听起来是否高级来选。

能力典型控制方式评审助手中的例子最易误判的边界
Tool
可调用函数
模型根据任务选择调用;应用仍可约束或拒绝。搜索同类需求、保存评审意见。只读搜索同样可以是 Tool。分类依据不是有无写入。
Resource
可获取的数据
应用决定何时读取、怎样展示或放入上下文。用户选定的需求文档、固定评审准则。暴露 URI 不会自动把资料传给模型。
Prompt
可复用消息模板
通常由用户在界面中选择,应用获取模板消息。“检查需求完整性”入口。模板描述步骤不等于步骤已经发生;仍需模型与工具执行。

从一个最小方案开始:让模型自己找资料,可以先提供搜索和读取两个 Tools;用户已经明确选中资料,则可以由应用读取 Resource 并放入上下文。评审要求先写在应用中也可以;只有希望把模板作为可发现、可复用的服务能力提供时,才需要 MCP Prompt。三种能力不必一次凑齐。

图 3 · 读取资源只是拿到材料;筛选并加入上下文,才让模型在本次回答中用到它。

图里最容易漏掉的是最后一步:读取 Resource 后,应用还要决定哪些内容送给模型。同样,取得 Prompt 只是取得模板消息,填写文档 ID 不会自动把正文读进来。三类能力都需要应用组织,协议不会自动生成完整工作流。

为什么“读取文档”有时是 Tool,有时是 Resource?

判别线索是交互中由谁决定取什么,而不是有没有写操作。模型根据任务主动选择读取,可以用 Tool;应用根据用户选中的资料主动附上内容,可以用 Resource。回看比较表后再判断:一个只读天气查询函数,是否也能是 Tool?可以。

06 / 应用:跟着做一个需求评审助手

下面用一个具体的 CSV 导出需求走完整个流程。第一版只读资料、生成评审草稿;第二版才增加保存。练习使用虚构数据,方便你对照每一步的输入和结果。

操作路线

① 准备资料 → ② 定义工具 → ③ 独立调试 → ④ 接入助手 → ⑤ 执行评审 → ⑥ 核对结果

① 准备:先把一份可检查的材料放进去

在本地新建一个练习文件夹,建立 documents.json。先不用接公司的文档系统,避免账号、网络和资料质量同时干扰判断。

{
  "D-01": {
    "project_id": "P-01",
    "version": 3,
    "title": "订单 CSV 导出",
    "text": "运营人员可按日期导出订单 CSV。一次最多导出1000条。超过1000条提示缩小日期范围。验收:导出文件包含订单号、日期、金额三列。"
  },
  "D-99": {
    "project_id": "P-02",
    "version": 1,
    "title": "其他项目资料",
    "text": "本次练习无权读取。"
  }
}
  • 你决定:练习只允许访问 P-01;“导出失败怎么办”在材料中没有写,助手应指出缺项。
  • 完成标志:你能打开文件确认 D-01 的全文、版本与项目。不要把这一步交给模型猜。
  • 为什么保留 D-99:它是权限反例,用于检查系统是否真的拒绝越界。

② 实现:把读取能力做成两个工具

将下面的任务和数据文件一起交给编码助手,让它在练习目录中实现 Server。这里选择 Python SDK 的 MCPServer 接口;环境需要 Python 3.10 及以上。先用 python3 --version 检查,不满足时先准备合适的 Python 环境。

基于 documents.json 实现需求评审 MCP Server。
使用官方 Python MCP SDK 2.x 的 MCPServer,不使用同名第三方包。
提供两个工具:
1. list_documents(project_id):仅允许 P-01,返回 id/title/version,不返回正文。
2. read_document(document_id):返回 id/project_id/version/title/text。
   每次读取都检查项目范围;不能假设经过列表筛选就安全。
文档不存在与无权访问分别返回可识别的错误,不泄露越权正文。
使用 stdio 供本机 MCP 客户端启动,不向 stdout 输出调试日志。
工具描述明确用途与参数;读取函数从文件实时取数据。
不要提供保存、删除或发送工具。
交付 server.py、依赖文件、独立业务测试和启动步骤。
先展示实际版本和测试输出,不要仅回答“已经完成”。

在练习目录中打开终端,建立隔离环境。下面命令适用于 macOS 或 Linux;Windows 的环境激活路径不同。

python3 -m venv .venv
source .venv/bin/activate
python -m pip install "mcp[cli]>=2,<3"
python -m pip freeze > requirements.lock.txt

检查交付:打开代码,至少能找到两个明确的工具注册、服务端项目检查和文件读取逻辑。让编码助手先跑业务测试;“存在一个 Python 函数”还不等于“工具已通过 MCP 暴露”。

③ 独立调试:先不让模型参与

在同一个已激活环境的终端执行 mcp dev server.py,按终端输出打开 MCP Inspector。该调试工具需要 Node.js 的 npx;如果提示找不到命令,先补齐环境,再继续。Inspector 是直接查看和调用 Server 的调试界面,这一步用来排除模型选错工具的干扰。

  1. 进入 Tools,列出工具。应能找到 list_documents 和 read_document。
  2. 调用 list_documents,参数为 {"project_id":"P-01"}。结果应只有 D-01,不包含 D-99。
  3. 调用 read_document,参数为 {"document_id":"D-01"}。对照文件,检查第 3 版全文是否完整返回。
  4. 再调用 D-99 和不存在的 D-404。前者应拒绝访问,后者应明确不存在;两者都不能返回伪造正文。
没有通过这一步,不继续调 Prompt。

工具不可见,检查注册、启动和连接;参数报错,检查名称与输入结构;数据不对,检查文件读取与权限。这些问题在模型参与之前就应该可以复现。

④ 接入:把同一个 Server 交给 AI 应用启动

选择支持本地 stdio MCP 的客户端,在其 MCP 连接配置中填写启动命令与参数。不同客户端入口不同,但需要表达的内容一致:

  • command:练习目录内虚拟环境 Python 的绝对路径,例如 /你的练习目录/.venv/bin/python。
  • args:Server 文件的绝对路径,例如 /你的练习目录/server.py。Server 的直接运行入口需要启动 stdio 服务。
  • 数据定位:用脚本所在目录定位 documents.json,避免客户端工作目录不同导致找不到文件。
  • 连接检查:重新连接后,确认客户端发现上述两个工具;如果发现的是旧工具列表,先检查它启动的是不是同一个文件。

这里填写的是字段含义,不是一份可通用于所有客户端的配置文件。让编码助手根据你实际使用的客户端生成对应配置;不要把 Inspector 的网页地址当成 stdio Server 的远程地址。

⑤ 执行:给助手一个可核对的评审任务

请列出 P-01 的文档,再读取 D-01 的完整正文。
先告诉我文档标题、版本和实际读取到的内容。
然后检查目标、范围、异常处理和验收条件。
按“问题 / 原文依据 / 影响 / 建议”输出评审草稿。
原文没有写的规则标为“未说明”,建议不要冒充原文要求。
不要保存、发送,也不要访问其他项目。

观察调用记录,应该先看到列表查询,再看到 D-01 读取。回答中出现“第 3 版”还不够:还要核对返回的正文确实来自工具结果。

问题依据影响建议
导出失败后的处理未说明材料规定了超量提示,但未规定网络或生成失败时的行为。开发和验收可能采用不同处理方式。补充失败提示、重试入口及重复导出的处理要求。

这是一条合理的评审示例。若助手把“自动重试三次”写成既有要求,就是把建议变成事实;若说“没有规定超过 1000 条怎么办”,则是漏读了原文。两种错误都应该退回,而不是因为表格整齐就通过。

⑥ 留证:保留这次成功的完整链路

  • 保存当次数据文件和依赖版本。
  • 保存两个工具的输入与返回结果。
  • 保存实际评审任务及输出,标注每条建议是否有依据。
  • 按下一节的反例再跑一轮,确认不是只对正常输入有效。

07 / 扩展与验收:从只读助手到可控保存

只读链路跑通后,先做反例测试,再增加写入。验收时把“工具能调用”“取到正确数据”“评审有依据”“草稿被正确保存”作为四件不同的事。

第一轮:按顺序执行五个检查

操作通过条件失败后检查
用 Inspector 列出工具,再查询 P-01两个只读工具可见,列表只有 D-01。工具注册、输入结构和项目过滤。
绕过列表,直接读取 D-99读取端拒绝,返回中无正文。是否仅在列表端做了权限检查。
请求 D-404明确不存在;助手不继续编造评审。业务错误与模型上下文的处理。
评审 D-01识别失败处理缺项,同时认可已有超量规则。完整正文是否送入、任务标准是否清楚。
把 D-01 的版本改为 4,并补充失败提示后重读返回第 4 版,评审不再说失败提示未说明。旧文件路径、缓存、旧对话上下文。

每个检查记录输入、实际输出、是否通过和错误位置。实际结果与预期不一致时,先保留失败记录,再修复重试;不要用一次正常结果覆盖失败证据。

第二轮:增加保存草稿,先定义边界

  • 保存位置:练习目录的 drafts 文件夹,不覆盖需求原文,不对外发送。
  • 保存对象:文档 ID、评审依据版本、评审正文。
  • 重复请求:为一次确认生成稳定的 request_id;同一请求重试返回原记录,不重复创建。
  • 确认规则:应用展示目标、版本与草稿,用户确认后才发起写入。Prompt 中的“请确认”不能替代应用侧控制。
扩展现有练习,增加 save_review_draft:
输入 document_id、expected_version、review_text、request_id。
写入前检查项目权限与真实文档版本。
版本不一致时返回 VERSION_CONFLICT,不创建草稿。
相同 request_id 且相同内容重试返回同一 draft_id;
相同 request_id 但内容不同,返回冲突,不覆盖。
返回 draft_id、document_id、version 和持久化结果。
提供 read_review_draft(draft_id),用于保存后的回读。
测试使用本地文件,增加重启后回读与重复请求测试。
说明本地文件方案的并发限制,不宣称适用于生产高并发。

第三轮:实际执行一次保存

  1. 重新读取材料。确认当前版本,把评审结果与该版本绑定。
  2. 展示待保存内容。检查文档 ID、版本、完整草稿与保存位置;你修改了草稿,就以最终确认内容为准。
  3. 确认后调用保存。应用传入同一组已确认参数和 request_id。服务端再次检查范围与版本。
  4. 记录返回值。成功时取得 draft_id;失败时展示原因,不生成“已保存”的自然语言假确认。
  5. 回读校验。用 draft_id 读取草稿,比较目标文档、依据版本和正文是否完全一致。
为什么成功之后还要回读?

“收到请求”和“持久化完成”是不同状态。回读能发现写错目录、内容截断或只存入内存等问题;重启 Server 后再读一次,还能检验保存是否依赖进程内存。

第四轮:制造冲突与重试

  1. 先读取第 3 版并生成草稿,再把数据文件改成第 4 版。仍用 expected_version=3 保存,应返回版本冲突,drafts 中不新增记录。
  2. 重新读取第 4 版,核对变化并重新评审,确认后以新请求保存。
  3. 使用完全相同的 request_id 和内容再调用一次,应返回同一 draft_id;然后改变正文但沿用 request_id,应拒绝冲突。
  4. 重启 Server,回读已保存草稿;结果应仍然存在且内容一致。

练习中的固定项目限制只能说明这个本地场景的范围检查。换成真实团队使用,还需要从可信身份取得用户权限,并处理并发、审计和恢复;不能把用户传入的 project_id 当作授权凭据。

交付清单
  • 只读正常与异常路径均有测试记录。
  • 用户未确认时不发起保存;版本冲突不落盘。
  • 重试不重复保存;成功记录可回读、重启后仍存在。
  • 原始需求未被改写,评审建议与材料事实明确区分。

08 / 迁移:换一个场景,自己设计一次

现在把需求评审换成会议助手:用户希望读取指定会议纪要、生成待办,确认后发给同事。先不要看下面的参考过程,写下你的方案:需要取得什么资料、提供哪些能力、哪里必须由人决定、用什么结果验收。

展开参考过程与常见错因

最小版先读取纪要、生成待办草稿。若用户已选定纪要,可由应用读取并提供上下文;若模型需要查找会议,则提供查询与读取 Tools。提取要求可以先写在应用内,不必立即做成 MCP Prompt。人核对负责人、截止时间与收件人后,再允许独立的发送 Tool 执行。验收应包含纪要缺失、无权读取、负责人未明确、拒绝发送和重复请求。若把“提取待办”直接当作“允许发送”,错在任务目标与操作授权混淆,回看第 7 节;若只列工具名而没有材料来源,回看第 5 节。

再增加一个条件:发送失败后用户点了重试。方案需要避免重复通知,而不是原样调用直到出现成功提示。这是业务一致性问题,MCP 的连接约定不会替你自动处理。

对我来说,能用 MCP 的标志,是能从任务推出能力,从能力找到负责的程序,再为每一步写出可观察的结果。你不需要先背完全部协议字段,但需要能回答:为什么接、接什么、谁执行、怎样证明做对了。

交流产品判断与 AI 实践 →
MCP 图解放大视图