Context7 docs-researcher 子代理:在 Cursor 中隔离式获取库文档的 MCP 工作流解析
本文围绕 Context7 的 Cursor 插件中内置的 docs-researcher 子代理展开:它是一个职责单一的“文档研究员”,通过 resolve-library-id 与 query-docs 两个 MCP 工具完成“定位库 → 拉取文档 → 返回精炼答案”的闭环,把大量原始文档内容隔离在子代理上下文中,避免污染主对话。读完本文,你将理解该代理的五步工作流程、两个工具的真实参数契约(来自 MCP 服务端子包源码),以及“一次查询只问一个概念”等检索质量准则背后的设计原因,并能据此在自己的 Cursor 工作流中正确调度文档检索。
一、docs-researcher 是什么:一个上下文隔离的文档检索代理
docs-researcher 是 Context7 Cursor 插件四件套(MCP Server、Rules、Skills、Agents)之一,定义在 docs-researcher.md 中。它的 YAML frontmatter 只有两个字段:
---
name: docs-researcher
description: Lightweight agent for fetching library documentation without cluttering your main conversation context.
---
description 一句话点明了它的存在意义:lightweight(轻量)+ without cluttering your main conversation context(不占用主对话上下文)。与直接在主对话里调用 Context7 MCP 工具相比,子代理的价值在于:query-docs 返回的文档片段往往很长,如果直接在主对话中拉取,这些内容会持续占据主对话的上下文窗口;而交给子代理执行后,主对话只回收一份“直接答案 + 代码示例 + 参考来源”的浓缩结果。
插件的 README 也明确给出了分工:自动场景(如直接问“How do I set up authentication in Next.js 15?”)走 rule/skill 驱动的主对话调用,而“当你想保持主上下文干净时,使用 docs-researcher 代理”。
代理的系统提示词定义了它的角色:
You are a documentation researcher specializing in fetching up-to-date library and framework documentation from Context7.
任务目标也很明确:拿到一个关于库/框架的问题后,抓取相关文档,并返回一个简洁、可执行的、带代码示例的答案。
二、五步工作流:从用户问题到浓缩答案
文档的核心是一张五步流程。下面逐步拆解,并把每一步与 MCP 服务端源码中的工具契约对应起来。
第 1 步:识别库名
从用户问题中提取库/框架名称(如 "react"、"next.js"、"prisma")。这一步是纯提示词层面的语义任务,没有工具调用。
第 2 步:调用 resolve-library-id 解析库 ID
两个参数:
| 参数 | 说明 | 来源依据 |
|---|---|---|
libraryName |
库名,建议使用官方规范写法 | 服务端 schema 描述要求"Use the official library name with proper punctuation — e.g., 'Next.js' instead of 'nextjs'" |
query |
描述要在文档里查什么,用于相关度排序 | 服务端注明该参数会随请求发送给 Context7 API,且不应包含 API 密钥等敏感信息 |
服务端实现位于 index.ts:工具 handler 接收 { query, libraryName } 后调用 searchLibraries,实际请求 GET {CONTEXT7_API_BASE_URL}/v2/libs/search?query=...&libraryName=...,60 秒超时,失败时把服务端 message 字段(或按状态码生成的兜底文案,如 429 限流、404 库不存在、401 密钥无效)返回给客户端。
一个值得注意的健壮性细节:由于 LLM 客户端经常“回显”工具描述里的措辞而不是字面 schema 键名,服务端在 index.ts 中实现了 aliasArgs 预处理——在 Zod 校验前把幻觉出的参数名改写为规范键名。全局映射为 query: ["userQuery", "question"];query-docs 额外映射 libraryId: ["context7CompatibleLibraryID", "libraryID", "libraryName"]。也就是说,即使子代理传错了参数名(比如把 libraryName 误用在 query-docs 上),服务端也会把它改写为 libraryId 再校验。
第 3 步:选择最佳匹配
子代理从返回的候选列表中挑选,文档给出的判据是三条:
- 名称精确或最接近匹配;
- 最高 benchmark score(基准评分,100 为最高,衡量文档质量);
- 若用户指定了版本(如 "React 19"),选择对应版本(如 v19.x)。
服务端返回给模型的并非原始 JSON,而是 formatSearchResult 格式化后的文本,每个候选包含:
Title/Context7-compatible library ID/Description(始终输出);Code Snippets:可用代码示例数量(值有效时才输出);Source Reputation:来源权威度,由 getSourceReputationLabel 把数值 trust score 映射为 High(≥7)/ Medium(≥4)/ Low / Unknown;Benchmark Score(>0 时输出);Versions:可用版本列表(非空时输出);Source:来源地址(如提供)。
多候选之间用 ---------- 分隔。因此文档里"prefer official/primary packages over community forks(多个匹配时优先官方主包而非社区 fork)"这条准则,实际上就是让模型在 Source Reputation 为 High 的条目中做选择。另外服务端工具描述明确约束:每个问题最多调用 resolve-library-id 3 次,3 次仍无结果就用现有最佳结果——这对子代理这类"单次任务"场景尤其重要,避免无谓的 API 消耗。
第 4 步:调用 query-docs 拉取文档
两个参数:
| 参数 | 说明 |
|---|---|
libraryId |
第 3 步选出的 Context7 库 ID,格式 /org/project,带版本时为 /org/project/version(如 /vercel/next.js/v14.3.0-canary.87) |
query |
要在文档中查什么,限定为单一概念,要具体但只谈一个主题 |
服务端 handler(index.ts)调用 fetchLibraryContext,请求 GET {CONTEXT7_API_BASE_URL}/v2/context?query=...&libraryId=...,并把响应文本直接作为工具输出返回。两个值得留意的行为:
- 同样受"每个问题最多调用 3 次"的约束(写在工具描述中);
- 若 API 返回空文本(如库 ID 无效),服务端会返回一条引导性提示,指出"文档未找到或未就绪,可能是 Context7 库 ID 无效,请用
resolve-library-id重新解析"——这正是流程要求"必须先解析后查询"的原因。
工具描述中还允许一条捷径:如果用户直接提供了 /org/project 或 /org/project/version 格式的库 ID,可以跳过 resolve-library-id。对应到 Cursor 客户端,docs/clients/cursor.mdx 给出的提示词写法就是:
use context7 with /supabase/supabase for authentication docs
use context7 with /vercel/next.js for app router setup
版本固定(Version Pinning)的完整形态在插件 README 中有示例:
/vercel/next.js/v15.1.8
/supabase/supabase/v2.45.0
resolve-library-id 的返回会附带 Versions 列表,供选择与项目匹配的版本。
第 5 步:返回聚焦答案
子代理的最终输出要求是"Summarize, don't dump",包含三要素:
- 对用户问题的直接回答;
- 来自文档的代码示例;
- 可用的链接或引用(如库版本)。
最后一条准则强调:目标是回答问题,不是倾倒整份文档。这与 frontmatter 里"不污染主上下文"的定位形成呼应——子代理的价值就在于压缩。
三、检索质量准则:为什么"一次查询只问一个概念"
文档 Guidelines 一节是整篇代理定义中含金量最高的部分,五条准则都值得展开:
-
query 描述"要查什么",且保持单一概念。
query-docs的服务端 schema 描述给出了正反例:好的 query 是 "How to set up authentication with JWT in Express.js" 或 "React useEffect cleanup function examples";坏的例子过于模糊("auth"、"hooks")或过于宽泛("routing and auth and caching in Next.js")。 -
多概念问题拆成多次调用。 如果问题横跨多个独立概念(如路由 + 鉴权 + 缓存),同一 libraryId 下按概念分别调用
query-docs;唯一例外是问题本身就在问"这些概念如何交互"。文档给出的原因是机制性的:"combined queries dilute ranking and return shallow results for each topic"(合并查询会稀释向量排序,导致每个主题都只返回浅层片段)。这与 Context7 后端对 query 做相关性重排序的实现方式一致——排序分数是围绕单一意图打分的,意图混杂时每个主题的得分都被摊薄。 -
版本感知。 用户提到 "Next.js 15"、"React 19" 时,使用版本特定的库 ID。
-
官方包优先。 多匹配时官方/主包优先于社区 fork(对应第 3 步中 Source Reputation 的判读)。
-
回答保持简洁。 呼应"研究后压缩"的代理定位。
这套准则与插件内 context7-mcp 技能 的 Step 1–4(Resolve → Select → Fetch → Use)和 use-context7 规则 高度同构——三者是同一套检索方法论在 Agent / Skill / Rule 三种载体上的投影:skill 教主对话"如何调",rule 规定"何时该调"(不确定 API、涉及特定版本、库有重大更新时调;语言基础特性或用户已给代码时不调),而 docs-researcher 则把这套方法论封装成一个可独立调度的轻量代理。
四、与 MCP 配置的关系:子代理依赖的传输层
子代理能调用的两个工具来自 Context7 MCP Server。Cursor 插件通过 mcp.json 声明远程端点:
{
"context7": {
"url": "https://mcp.context7.com/mcp/oauth"
}
}
指向的是 OAuth 保护端点。对照服务端源码(index.ts),HTTP 模式同时暴露 /mcp(匿名)与 /mcp/oauth(要求鉴权)两条路由;/mcp/oauth 会在缺失凭据时返回 JSON-RPC 401 错误,并对 JWT 形态的 key 做在线校验。对 Cursor 用户而言,安装方式在 docs/clients/cursor.mdx 中给出:
npx ctx7 setup --cursor
该命令通过 OAuth 认证、生成 API key 并安装相应 skill,可在 CLI 模式与 MCP 模式间二选一。理解这一层的关系有助于排障:如果子代理调用 query-docs 拿到的是"Authentication required"类错误,问题在 mcp.json 指向的鉴权端点与凭据,而不是代理提示词本身。
五、跨客户端一致性:同一代理在 Claude 插件中的对照
同一份 docs-researcher 定义在 Claude 插件中也存在(plugins/claude/context7/agents/docs-researcher.md),正文与 Cursor 版本逐字一致,唯一差异是 frontmatter 多了一个 model: sonnet 字段。这印证了两点:其一,代理的提示词是客户端无关的,真正的差异由宿主客户端的 agent 机制承担(Claude 需要显式指定模型,Cursor 版本则由客户端默认模型执行);其二,"轻量"定位在 Claude 侧体现为指定 sonnet 这类低开销模型——对"解析 + 检索 + 摘要"这种任务而言,小模型配合压缩指令已足够。
六、小结:把文档检索当作可编排的子任务
docs-researcher 的完整画像可以概括为三句话:
- 职责:输入一个库/框架问题,输出"直接答案 + 文档代码示例 + 引用"的浓缩结果;
- 机制:
resolve-library-id(最多 3 次/问题)→ 按名称匹配 / benchmark score / 版本三项判据选库 →query-docs(单概念 query,多概念拆调用,最多 3 次/问题)→ 摘要返回; - 价值:把冗长的文档原文留在子代理上下文中,主对话只保留可执行结论,同时借助服务端 alias 容错、版本固定与 3 次调用上限控制成本。
仓库中可继续深入的证据链:工具注册与参数校验见 packages/mcp/src/index.ts,结果格式化与来源权威度映射见 packages/mcp/src/lib/utils.ts,API 请求与错误处理见 packages/mcp/src/lib/api.ts,Cursor 客户端的安装与配置方式见 docs/clients/cursor.mdx。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00