【随笔】MCP Resources如何按URI提供上下文:让Agent读取资料时保留来源
上一篇随笔介绍了Agent Skills如何按需加载操作说明。流程材料解决“怎样做”任务过程中还会遇到另一类输入配置、文档、数据库结构、知识条目应该怎样被发现和读取Model Context ProtocolMCPResources用URI标识可读取的数据。客户端可以先列出资源元数据再按URI读取内容返回结果继续携带原URI和媒体类型便于应用记录资料来自哪里。本文依据截至2026-10-01核对的MCP TypeScript SDK v2文档结合一个教学模拟器说明这条读取链路。一、Resource描述数据Tool执行动作在MCP中Resource用于提供可读取的上下文数据例如文件内容、接口说明、数据库模式和应用状态Tool通常表示可以调用的动作例如执行查询、创建记录或运行计算。这种职责划分有助于客户端表达意图读取docs://java/atomic是在取得资料调用search是在发起动作。实际权限、用户确认和可见范围仍由客户端与服务端共同落实URI本身不会绕过访问控制。一个资源通常包含以下信息字段作用uri唯一定位资源如docs://guide/atomicname或title给人看的名称mimeType说明内容格式如text/markdowntext或blob文本内容或Base64编码的二进制内容MCP TypeScript SDK v2文档将Resources列为服务端核心能力之一v2稳定分支实现2026-07-28协议规范。版本与安装方式应以官方TypeScript SDK v2文档为准。二、先列目录再按URI读取正文客户端不必一开始就把所有正文放进上下文。它可以先调用listResources()取得可发现条目再选择一个URI调用readResource({ uri })。图中导师猫维护资源目录学习猫拿着URI索引卡读取选中的文档。目录阶段适合展示名称、URI和媒体类型正文只有在任务需要时才进入后续处理。服务端也可以使用ResourceTemplate描述参数化URI例如repo://{owner}/{name}/readme。模板帮助客户端发现URI形状真正读取时仍要提供具体地址并由服务端校验参数和权限。三、URI保留了回查线索但不自动生成引用readResource返回的contents条目继续带有URI。应用可以把URI与本次回答、摘要或缓存记录关联起来之后重新读取或展示来源入口。这条链路可以概括为发现元数据→选择URI→读取内容→记录来源→生成回答。URI提供稳定的定位线索mimeType帮助客户端选择文本解析或二进制处理方式。需要注意携带URI并不等于已经完成引用。客户端还要决定怎样展示来源、是否允许用户打开、内容何时过期以及一段结论究竟由哪些资源支持。资源内容也可能变化要求可复现时应额外记录版本、时间戳、摘要哈希或仓库提交号。四、服务端注册与客户端读取下面是根据官方v2 API整理的结构示意。它展示静态资源的注册和读取回调省略了传输层、启动代码与错误处理server.registerResource(atomic-note,docs://java/atomic,{title:Java原子类笔记,mimeType:text/markdown},async(uri)({contents:[{uri:uri.href,mimeType:text/markdown,text:# AtomicInteger\n用于单变量原子更新。}]}));客户端的核心读取过程很短constlistedawaitclient.listResources();constselectedlisted.resources.find(itemitem.uridocs://java/atomic);if(selected){constresultawaitclient.readResource({uri:selected.uri});console.log(result.contents);}具体方法、返回类型和导入路径可能随SDK版本变化应对照官方客户端调用文档与服务端McpServer API。示意代码没有连接真实MCP服务因此不把它写成已执行示例。五、可运行模拟器观察目录与读取结果为了单独验证“列目录、按URI读取、保留来源”这三个概念下面用Python标准库写一个教学模拟器。它没有实现MCP传输、协议握手或SDK类型只模拟与本文相关的数据形状。fromdataclassesimportdataclassdataclass(frozenTrue)classResource:uri:strname:strmime_type:strtext:strCATALOG{docs://java/longadder:Resource(uridocs://java/longadder,nameLongAdder笔记,mime_typetext/markdown,text# LongAdder\n适合高竞争下的统计型累加。,),config://service/limits:Resource(uriconfig://service/limits,name服务限额,mime_typeapplication/json,text{requestsPerMinute: 120},),}deflist_resources():return[{uri:item.uri,name:item.name,mimeType:item.mime_type}foriteminCATALOG.values()]defread_resource(uri):itemCATALOG.get(uri)ifitemisNone:raiseValueError(funknown resource:{uri})return{contents:[{uri:item.uri,mimeType:item.mime_type,text:item.text}]}itemslist_resources()print(listed:,[item[uri]foriteminitems])resultread_resource(docs://java/longadder)contentresult[contents][0]print(read uri:,content[uri])print(mime:,content[mimeType])print(first line:,content[text].splitlines()[0])try:read_resource(docs://missing)exceptValueErroraserror:print(missing:,error)else:raiseAssertionError(missing resource must fail)运行输出listed: [docs://java/longadder, config://service/limits] read uri: docs://java/longadder mime: text/markdown first line: # LongAdder missing: unknown resource: docs://missing示例已在本机Python 3.12运行。目录结果只有元数据读取结果包含正文同时保留docs://java/longadder和text/markdown。不存在的URI明确失败没有悄悄返回空内容。六、生产接入需要补齐哪些边界首先是访问控制。同一个服务端可以暴露不同敏感度的资源列目录与读取正文都应根据连接身份、租户和具体URI判断权限。错误信息要足够定位问题也应避免泄露用户无权知道的资源名称。其次是内容时效。配置和状态可能快速变化缓存策略需要结合业务决定文档型资源可以提供版本或最后更新时间动态资源则应说明快照时刻。客户端不能把一次读取结果永久当作最新事实。再次是输入边界。参数化URI要防止路径穿越、越权枚举和未限制查询。服务端应解析结构化参数并做白名单校验避免直接把URI片段拼进本地路径或数据库语句。最后是来源呈现。若应用要让用户核对答案可以保存资源URI、读取时间与支持该结论的片段范围。二进制资源还要明确大小限制、媒体类型和解码失败处理。MCP负责交换结构应用仍需完成权限、可信度和用户界面的设计。七、 思维导图MCP Resources资源描述URI与名称mimeType与内容读取流程先列目录按URI读取来源回查结果保留URI版本与时间戳生产边界权限与参数校验缓存与引用呈现八、总结总结要点Resource与URI给上下文数据一个可发现、可读取的结构。客户端先看元数据再按任务需要取得具体内容。来源链路依靠读取结果中的URI、媒体类型以及应用额外保存的版本信息建立。它为回查提供入口引用展示仍需客户端完成。生产边界包括权限、时效、参数校验、缓存和错误处理。协议结构清楚之后仍要把数据访问与用户可核对性落实到应用设计中。下一篇随笔继续讨论MCP Resources的订阅与更新通知看看动态资料变化后客户端怎样避免一直使用旧快照。如果你觉得这篇文章对你有所帮助欢迎点赞、收藏、分享
上一篇/下一篇内容由系统自动关联
返回资讯列表 →