MCP 客户端怎样区分工具、资源和提示模板
MCP 客户端区分工具、资源和提示模板,关键不是看名称里有没有“tool”或“prompt”,而是按协议完成两次判断:先看 initialize 响应里的能力声明,再把协议方法映射到对应对象。tools 是可被模型请求执行的函数能力,resources 是由 URI 标识的上下文数据,prompts 是可由用户选择并带参数展开的消息模板。
官方规范地址:https://modelcontextprotocol.io/specification/2025-06-18
本文把客户端设计拆成“能力覆盖率、列表完整度、调用确认率”三个可记录指标。它们是工程上的观测口径,不是某个真实服务端的实测性能数据:客户端至少要知道自己发现了哪些能力、列表是否读完、哪些工具调用经过了用户确认。
先看初始化响应里的能力声明
MCP 的生命周期要求客户端先发起 initialize,与服务端协商协议版本和能力;服务端返回自己的 capabilities 后,客户端再发送 notifications/initialized 进入正常操作阶段。因此,客户端目录的第一条记录应来自初始化响应,而不是来自某个列表接口的偶然返回。

服务端可能只声明其中一类,也可能同时声明三类。客户端可以把能力覆盖率记成一个集合,而不是把缺失能力当成错误。例如:
{
"capabilities": {
"tools": { "listChanged": true },
"resources": { "subscribe": true, "listChanged": true },
"prompts": { "listChanged": false }
}
}
上面的 JSON 是协议字段示例,字段旁边的布尔值只表示服务端是否支持相应的变更通知或订阅能力。客户端拿到响应后可以得到三条不同的结论:
- 存在
tools,才去发现和调用工具; - 存在
resources,才去读取 URI 资源,并根据subscribe决定是否建立资源订阅; - 存在
prompts,才把提示模板暴露给用户选择。
这里最容易犯的错是“列表为空就认为能力不存在”。能力声明回答的是“服务端是否提供这一类接口”,列表响应回答的是“当前能列出哪些对象”,两者必须分别记录。建议至少保存 capabilityDeclared、listCompleted 和 lastChangedAt 三个指标字段。
用方法名判断对象类型
初始化能力只能决定客户端应该打开哪扇门,真正的对象类型由协议方法决定。可以用下面这张对照表作为客户端路由规则:
| 能力 | 发现方法 | 取单项或执行方法 | 核心数据 | 主要驱动方 |
|---|---|---|---|---|
| tools | tools/list | tools/call | inputSchema、调用结果 | 模型 |
| resources | resources/list、resources/templates/list | resources/read | uri、MIME 类型、内容 | 应用 |
| prompts | prompts/list | prompts/get | 参数、消息列表 | 用户 |

这张表也解释了为什么不能把三类对象塞进同一个“可执行项”数组:工具的关键是输入 JSON Schema 和调用结果,资源的关键是 URI 与内容,提示模板的关键是参数展开后的消息。它们都能有 name 和 description,但同名字段不等于同一种语义。
列表接口支持分页,客户端不能只读取第一页就把“列表完整度”记为 100%。当响应带有 nextCursor 时,应继续请求下一页;没有游标时才可以把本轮列表标记为完成。这个指标尤其适合排查“客户端明明支持工具,但模型看不到某个工具”的问题。
区分模型驱动、应用驱动和用户驱动
MCP 规范对三类能力的交互模型有明确区分。工具通常是模型根据上下文发现并请求调用的函数;资源是应用决定如何让用户或模型选择、搜索或自动纳入上下文的数据;提示模板则面向用户显式选择,常见呈现方式是命令或可选模板列表。
因此,客户端 UI 或代理层可以按下面的决策方式组织:
- 遇到
tools:展示名称、描述、输入参数和风险提示;调用前保留用户拒绝入口。 - 遇到
resources:展示资源 URI、名称、描述和 MIME 类型;读取结果后由应用决定放入哪个上下文槽位。 - 遇到
prompts:展示可选模板及其参数;用户确认后调用prompts/get,再把返回的消息交给后续模型流程。
注意“驱动方”是交互模型,不是安全豁免。工具描述和工具注解仍然可能来自不可信服务端,客户端应把它们当作待审查元数据;资源内容也不能在没有用户同意时被转发到其他服务。
统一保存元数据但分开执行入口
如果客户端需要做搜索、排序或权限展示,可以建立统一目录,但必须保留一个不可变的 kind 字段。下面的 TypeScript 只是客户端内部类型草图,不绑定任何 SDK;注释说明了分类判断和入口分离的目的。
type McpEntry =
| { kind: "tool"; name: string; description?: string; inputSchema: unknown }
| { kind: "resource"; uri: string; name?: string; mimeType?: string }
| { kind: "prompt"; name: string; description?: string; arguments?: unknown[] };
function routeEntry(entry: McpEntry): string {
// kind 是协议语义边界,不能只靠 name 或 description 猜测。
switch (entry.kind) {
case "tool":
// 工具进入模型可调用目录,真正调用时还要经过授权确认。
return "tools/call";
case "resource":
// 资源要按 URI 读取,不能被当成可执行函数。
return "resources/read";
case "prompt":
// 提示模板先由用户选择,再按名称和参数获取消息。
return "prompts/get";
}
}
工程上可以把三类对象放在同一个搜索界面,但点击动作应该不同:工具按钮打开参数和确认面板,资源打开上下文预览,提示模板打开参数填写面板。这样既方便统一检索,也不会让用户误以为“看到的每一项都能直接执行”。
对于工具,inputSchema 是客户端生成参数表单或做请求前校验的重要依据;对于资源,URI 是唯一定位键,资源模板还可能需要先补全 URI 参数;对于提示模板,参数最终进入 messages,不能把模板名字直接当成用户消息文本。
处理分页、变更通知和安全边界
把分类逻辑写对之后,仍要处理三个动态问题。第一,列表可能分页;第二,服务端可能声明 listChanged,随后通过通知告诉客户端列表有变化;第三,资源和工具都可能触及敏感数据或外部副作用。
可以把一次同步的结果记录为下面四个状态,而不把它们混成一个“加载成功”:
| 状态 | 含义 | 排查重点 |
|---|---|---|
| 能力已声明 | 初始化响应包含对应 capability | 是否真的注册了该类能力 |
| 列表已完成 | 所有分页都已消费 | 是否遗漏 nextCursor |
| 变更已同步 | 收到 list_changed 后重新拉取 | 通知处理器是否按 kind 路由 |
| 调用已确认 | 工具调用前完成用户确认 | 是否把不可信描述当成授权依据 |
工具调用至少要在 UI 上说明工具名称、参数和可能的副作用,并给用户拒绝机会。资源读取要尊重用户的数据边界,不因为“资源是只读的”就自动把内容发送给任意模型或远端服务。提示模板虽然由用户选择,模板展开后的消息仍应在进入模型前展示关键参数。
如果服务端没有声明某个 capability,客户端不要凭空调用对应方法;如果能力已声明但列表请求失败,应保留“声明存在、列表未完成”的状态,让重试和诊断有依据。这个拆分比单纯显示“连接成功”更能解释客户端为何看不到对象。
一个可落地的分类核对清单
在接入新的 MCP 服务端时,可以用以下顺序核对:
- 是否完成
initialize和notifications/initialized,并保存服务端返回的协议版本与 capabilities? - 是否按能力分别调用
tools/list、resources/list、prompts/list,并处理nextCursor? - 是否用
kind固定三类内部模型,而不是靠名称、图标或描述猜测? - 是否将工具调用、资源读取、提示模板展开设计成三种不同交互?
- 是否在服务端列表变化后重新同步,并在工具调用前保留用户确认?
记住一个最短判断:能被模型请求执行的是工具;由 URI 表示、供上下文使用的是资源;由用户选择、返回消息模板的是提示。客户端只要把“能力声明—发现方法—执行入口—安全交互”四层分开,三类对象就不会在同一个目录里互相误用。
常见问题
MCP 的 resources 能不能像 tools 一样直接调用?
不能按同一语义处理。资源通过 URI 定位,通常使用 resources/read 获取内容;它可能被应用放进模型上下文,但不是带参数执行的函数。
prompts/list 返回的对象为什么不能直接交给模型?
列表通常只提供模板的名称、描述和参数定义。客户端还需要调用 prompts/get,提供所需参数,拿到消息列表后再按应用流程展示或提交。
服务端同时声明 tools 和 resources 时要合并吗?
可以合并到一个可搜索目录,但不要合并执行语义。保留 kind,让搜索结果点击后分别进入工具确认、资源预览或提示参数面板。
LangChain 怎样把工具调用结果映射到消息历史
- 上一篇
- LangChain 怎样把工具调用结果映射到消息历史
- 下一篇
- PHP PDO 怎样设置 ATTR_EMULATE_PREPARES 避免类型误判
-
- 科技周边 · 人工智能 | 1小时前 | token · ai ·
- AI 应用怎样记录 token 用量和请求追踪信息
- 323浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | python · 工具调用 · LangChain Command AIMessage ToolMessage tool_call_id 消息历史
- LangChain 怎样把工具调用结果映射到消息历史
- 250浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- Safetensors 怎么只读取指定权重并查看文件元数据
- 256浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- ONNX Runtime 怎样为不同硬件选择执行提供者
- 371浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 性能排查 · PyTorch 性能排查 torch.compile TorchDynamo 图断裂 fullgraph
- PyTorch torch.compile 怎样定位图断裂原因
- 475浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 内存优化 · PyTorch DataLoader IterableDataset num_workers prefetch_factor pin_memory persistent_workers
- PyTorch DataLoader 怎样控制多进程预取内存
- 319浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 人工智能 · websocket WebRTC 断线重连 会话恢复 OpenAI Realtime API conversation.item.create
- OpenAI Realtime API 怎样处理断线后的会话恢复
- 356浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- Transformers DataCollatorForLanguageModeling 的 mlm 与 labels 构造方法
- 336浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- OpenAI API 怎样配置提示词缓存降低重复输入成本
- 317浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- PyTorch torch.utils.checkpoint 怎样用重计算换显存
- 370浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 异步任务 · 人工智能 · openai · 批处理文件 OpenAI Batch API output_file_id error_file_id output_expires_after
- OpenAI Batch API 怎样设置 output_expires_after 管理输出文件
- 460浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 |
- PyTorch autograd anomaly detection 怎样定位 NaN 梯度
- 248浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 842次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 842次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 921次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 897次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 725次使用
-
- Golang 实现Redis 协议解析器的解决方案
- 2022-12-23 109浏览
-
- Go Redis客户端使用的两种对比
- 2022-12-30 195浏览
-
- Go语言实现UDP协议及TCP通讯
- 2023-01-01 398浏览
-
- etcd通信接口之客户端API核心方法实战
- 2023-01-07 433浏览
-
- Go gRPC服务客户端流式RPC教程
- 2023-01-08 260浏览

