登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

MCP区分资源读取与工具调用的实现方法

来源:17golang原创

时间:2026-09-16 00:22:08 359浏览 收藏

在 MCP(Model Context Protocol)服务里,最容易混淆的是 Resource 和 Tool:前者负责把上下文交给客户端读取,后者负责让模型请求一次明确的动作。判断标准很简单:如果对象的核心价值是“这里有一份可定位的数据”,优先建成 Resource;如果需要传入参数并触碰查询、计算、写入或外部系统,就应该建成 Tool。两者都可以返回文本或结构化内容,但发现方式、权限模型和错误处理不能混为一谈。

要点速览
  • Resource 用唯一 URI 表示可读取的数据,典型调用是 resources/read
  • Tool 用名称和 JSON Schema 描述可执行能力,典型调用是 tools/call
  • 只读上下文、可变动作、协议错误和业务失败要分别建模,权限与审计也要分层。

先把 Resource 和 Tool 的职责边界摆正

Resource 更像“可被引用的上下文入口”。规范示例中的文件、数据库 Schema、应用资料都可以通过 URI 唯一定位,客户端用 resources/list 发现它们,再用 resources/read 读取内容。Resource 是否自动进入模型上下文,由 Host 应用决定,协议本身不强制某一种界面或选择方式。

Tool 则是“可请求执行的能力”。服务端通过 tools/list 公布名称、描述和 inputSchema,客户端在确认用户意图和权限后,用 tools/call 传入 arguments。查询天气、执行数据库查询、创建工单或调用内部 API,都属于 Tool 的典型边界。即便工具返回一段文档,也不能因为结果是文本就把它建模成 Resource。

判断点ResourceTool
核心语义读取一份有 URI 的上下文执行一次有名称的能力
发现方法resources/listtools/list
执行/读取方法resources/readtools/call
关键输入URI,可选模板参数arguments 与 JSON Schema
主要风险越权读取、URI 穿越、过期内容误操作、参数注入、数据外发
MCP Resource 与 Tool 的协议职责边界说明图,展示 URI 读取上下文和名称参数执行动作的区别
图1:MCP 对象职责结构说明图,展示 Resource 的 URI 读取边界与 Tool 的参数调用边界,不是运行截图。

资源读取用 URI 链路,工具调用用名称和参数

实现时先声明 capability,再按对象的协议消息设计路由。Resource 至少要让客户端知道可用 URI、名称、描述和 MIME 类型;动态数据可以用 Resource Template 表达参数化 URI,并按需支持订阅或列表变更通知。Tool 至少要给出稳定名称、可读描述和严格的输入 Schema;如果返回对象需要稳定解析,再补充 outputSchema

{
  "jsonrpc": "2.0",
  "id": 21,
  "method": "resources/read",
  "params": {"uri": "memo://project/alpha/architecture"}
}

{
  "jsonrpc": "2.0",
  "id": 22,
  "method": "tools/call",
  "params": {
    "name": "search_project",
    "arguments": {"project": "alpha", "query": "鉴权边界"}
  }
}

上面两条消息看起来都像“向服务端取信息”,但语义不同:第一条是按 URI 取已经定义好的资源;第二条是要求服务端执行一次搜索动作。伪代码中也应保留这个分支,避免把所有请求都塞进一个万能 Tool:

type Request =
  | { method: "resources/read"; params: { uri: string } }
  | { method: "tools/call"; params: { name: string; arguments: Record } };

function dispatch(request: Request) {
  if (request.method === "resources/read") {
    // 资源先校验 URI 和读取权限,再返回文本或二进制内容。
    return readResource(request.params.uri);
  }

  // 工具先校验参数、确认敏感动作,再进入业务执行和审计记录。
  return callTool(request.params.name, request.params.arguments);
}

这里的 readResourcecallTool 是服务端内部实现接口,不是 MCP 新增的方法名。真正对外暴露的仍是 JSON-RPC 消息。资源读取失败应返回资源不存在等协议错误;工具如果名称未知或参数不符合 Schema,属于协议层错误;外部服务超时、库存不足或业务拒绝,则应在工具结果中明确 isError: true,让客户端知道“调用到了,但执行没有成功”。

MCP Resource 和 Tool 的发现、读取、调用及错误边界结构说明图,展示 JSON-RPC 方法与结果分层
图2:MCP 消息与错误分层说明图,展示发现、读取、调用以及协议错误和执行错误的对应关系,不是运行截图。

生产环境按权限、审计和错误分层

Resource 的安全重点是“能否读到这份数据”。服务端要校验 URI,限制可访问的资源范围,并在资源包含敏感信息时绑定用户、租户或工作区权限。不要把文件路径直接拼接成 URI 后无条件读取,也不要把一次性授权信息写进可长期复用的资源描述。

Tool 的安全重点是“这次动作能造成什么影响”。输入要按 Schema 和业务规则双重校验;写入、删除、发送消息、付费或导出等动作应设置人工确认、超时、限流和审计日志。工具注解只能作为提示,客户端不应把不受信任服务端的注解当成安全证明。

  • Resource:校验 URI、访问主体、数据范围和内容新鲜度。
  • Tool:校验名称、参数、权限、幂等性、超时和副作用。
  • 两者共用:记录 request id、耗时、结果类型和脱敏后的失败原因。

最后做一次建模检查:没有副作用、需要被客户端选择或订阅、并且能用稳定 URI 表达的对象,通常适合 Resource;需要模型决定参数、触发查询或改变外部状态的对象,通常适合 Tool。若一个对象同时具备两种特征,可以让 Resource 提供只读上下文,再让 Tool 提供明确动作,避免用一个接口承担两套权限语义。

相关问题

Resource 能不能接收参数?

可以用 Resource Template 表达参数化 URI,并通过模板补全参数;但它仍然表示“按地址读取资源”,不要借此隐藏写入或执行动作。

Tool 返回文件时还算 Tool 吗?

算。判断依据是请求是否触发了一次能力调用,而不是结果是文本、图片还是文件。Tool 也可以返回 Resource Link 或嵌入式 Resource,供客户端继续读取。

工具失败应该返回 JSON-RPC error 吗?

未知工具、非法参数等协议问题用 JSON-RPC error;工具已经被正确调用但业务执行失败,应返回工具结果并设置 isError: true,两者不要混用。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>