AI 博客

Context7、DeepWiki、GitMCP 与 Ref:你的智能体读的文档,是别人家的索引

有四个 MCP 服务端,存在的意义都是不让编码智能体照着它一知半解的 API 写代码,而且四个都管用。真正决定它们帮不帮得上忙的那根轴是:回来的是哪一种文本——上游文件、从上游抽出来的片段,还是模型写的关于这份代码的散文。而它们谁都没有堵上自己被拿来对治的那处失效:你的智能体依然不知道你跑的是哪个版本,因为没有一个会去读你的 lockfile,其中还有一个把版本变成了提示词里的一句话。

作者 智能体 AI 维基 22 分钟读完

这四个服务端都是为同一个瞬间造的:你的智能体写下一句在 2024 年看着没错的调用,然后构建失败。四个都能治好它。真正要紧的那个抉择,反倒是没人写进对比表的一条——递到你模型手上的那段文本,是库的维护者写的、是从他们写的东西里抽出来的,还是另一个模型写的关于他们代码的散文。这是三种不同的接地之物,而只有第三种能够自信地出错。

一眼概览

四个 MCP 服务端,对「文档从哪儿来」给出四种答案。

服务端谁在运营回来的是什么覆盖范围
Context7 Upstash——服务端开源,索引托管 按库、按版本抽取的片段与 API 参考 其目录中收录的库
DeepWiki Cognition(Devin 团队)——托管 一份关于某仓库的生成式 wiki,外加问答工具 GitHub 上的公开仓库
GitMCP 开源、免费的远程服务端 仓库自己的 llms.txt、文档或 README 任意 GitHub 仓库或 GitHub Pages 站点
Ref ref.tools——商业,需 API key 搜到的文档章节,每次读取约上限 5k token 公开文档与网页,外加你的私有来源
Feature matrix: four documentation servers across four axes Rows are Context7, DeepWiki, GitMCP and Ref. Text provenance: Context7 extracted from upstream, DeepWiki model-written, GitMCP upstream files served as-is, Ref extracted from upstream. Version targeting: Context7 per-version indexes, DeepWiki an index snapshot, GitMCP whichever branch or tag the URL names, Ref whatever the query matched. Private sources: Ref supports them, GitMCP by self-hosting, Context7 and DeepWiki are public catalogues. Self-hostable: GitMCP yes, Context7 server only, Ref no, DeepWiki no. Where the text comes from, and what you can pin Text provenance Version targeting Private sources Self-hostable Context7 Extracted Per version Public catalogue Server, not index DeepWiki Model-written Index snapshot Public repos only Hosted only GitMCP Upstream files Branch or tag By self-hosting Yes Ref Extracted Query match Yes No Strongest on this axis Partial Not offered
第一列,才是会改变你该如何阅读那份答案的那一列。

岔路口在出处,不在覆盖面

Three distances between an upstream repository and the agent's context An upstream repository on the left feeds three paths into an agent context on the right. The top path serves files unchanged — llms.txt, docs, README — labelled GitMCP. The middle path runs an extraction and indexing step that produces per-library snippets, labelled Context7 and Ref. The bottom path runs a model over the repository to write a wiki, which is cached and served, labelled DeepWiki, with a note that errors on this path are fluent. Upstream, extracted, or generated Upstream repository written by humans Served as-is llms.txt, docs, README GitMCP Extracted and indexed snippets, doc sections Context7, Ref A model writes a wiki then it is cached and served DeepWiki Agent context cannot tell which Errors on the bottom path arrive in the same confident register as the truths.
与源头的三种距离。文本一旦进了上下文,智能体就分不出它们了。

GitMCP 是最短的那条路。把它指向一个仓库,它会先找 llms.txt 文件,再找项目的文档,然后是 README,并在其中检索。你的模型读到的,就是某位维护者提交进去的东西。文档要是错的,它对人类来说本来就已经是错的,而且有人能为此开一个 issue。

Context7 与 Ref 又往外站了一步。两者都对上游材料建索引、并返回相关片段——Context7 是按库、按版本策展好的片段;Ref 是文档页中被搜到的章节,每次读取裁到约 5k token,并与本次会话中已经给过你的内容去重。这一步抽取有可能把「活在代码示例上方两段」的那句告诫丢掉,这是一种真实而寻常的检索失效;但这条流水线里没有任何环节会凭空造出一个论断。

DeepWiki 是另一种东西,值得挑明,因为它太容易被和另外三个归到一起。它让一个模型通读仓库,产出一份 wiki——架构散文、图示、一个 ask_question 工具——覆盖数以万计的热门仓库。对于 Context7 从来就没打算回答的那个问题,这极其有用:这个陌生的代码库是怎么运作的。而对于这个函数的签名是什么,它是错的输入,因为答案是关于代码的生成文本,而不是代码本身或它的文档;而一个生成出来的错误,与一个生成出来的真相,抵达时的笃定语气一模一样。你等于加了第二道接地工序,然后把它的输出缓存了下来。

一个好用的判据:问问自己,你会不会不点开出处链接就接受这个答案。对上游文本,答案通常是会。对一份生成式 wiki,答案应该是不会——这意味着这个工具干的是导航的活,不是权威的活,而你的提示词该把这一点说出来。

它们谁也不知道你跑的是哪个版本

How the documentation version gets chosen, in three setups Three columns. No documentation tool: the model answers from training data, so the version is whatever it absorbed, unknown and unstated. A documentation tool with no version in the query: the answer is current upstream, which is wrong in a new direction for a codebase pinned to an older release. The harness resolves the version from the lockfile and passes it into the query: the answer matches the code that will actually run. Which version does the answer describe? No docs tool The model answers from training data, at whatever version it absorbed. Docs tool, no version The index returns current upstream, whatever the repository is pinned to. Version from the lockfile Your harness resolves the pin and passes it in as a parameter, not a sentence. Failure mode Failure mode Failure mode Wrong in a random direction, and stale. Wrong in a specific direction, and plausible. Missing entry for the pin — which you can detect.
其中两种是失效模式。只有第三种是解法,而它是你要写的代码。

这一整个品类的卖点是版本漂移:你的模型学到的 API 此后变过,于是它照着自己记得的那个版本写代码。这里每一个服务端都治好了「陈旧」。而陈旧并不是同一个问题。

想一想「最新文档」对一个钉在两年前发行版上的服务意味着什么。用文档工具之前,模型照训练数据猜,错在一个随机方向上。用了之后,它读到当前上游,于是错在一个具体方向上——它会自信地用上今天存在的那个 API,而那个代码库根本跑不了。工具没有消除这处错配;它把错配挪了个位置,还让它更像真的。

再看每一个是怎么补上这道口子的,答案是:没有一个会替你补。Context7 走得最远:它维护按版本的索引,并会提供你点名的那个版本——但你是在提示词里点名的,这意味着那次绑定是由模型作出的一句自然语言断言,而模型没有任何理由读过你的 lockfile。GitMCP 返回的是你把 URL 指向的那个分支或 tag:你设了就是真的钉住,没设就是你仓库的默认分支。Ref 返回的是它搜索匹配到的东西,通常是文档站当前发行版。DeepWiki 提供的是它索引下来的那份快照。

所以版本绑定是你的活,而它大约是十五行外壳代码:

  • 在查询之前把版本解析出来,而不是在查询里。去读 package-lock.json、uv.lock、go.sum——凡是智能体正在改的那个仓库里权威的那份——并把解析出的版本作为一个由你的代码控制的参数注入到文档查询里。
  • 服务端支持指定 URL 的地方,就把 URL 钉住。指向一个 tag 的 GitMCP 端点是确定性的;指向默认分支的那个是移动靶,会在同一份评测的两次运行之间悄悄变掉。
  • 让版本不匹配可见,而不是致命。如果索引里没有那个被钉住版本的条目,你要的是智能体把这件事说出来并降级处理,而不是悄悄去读当前文档。这与在子智能体的返回里让「没有」显式存在是同一套纪律。
  • 凡是承重的说法,都拿已安装的那份产物去核。库就在磁盘上。去读真正的函数签名只花几百个 token,而且胜过任何索引——这正是为什么仓库导航与文档检索是互补,而不是互替。

文档工具是一条挂着计划的检索通道

这里每一个服务端,都是把第三方文本送进一个上下文窗口,而模型会把它当作可据以行动的材料来读。这就是「经由检索而来的注入面」的定义,而文档是异常好用的载体:一个刚取过文档的智能体,从构造上就正处在「愿意照着里面的指示办」的心情里。

有三件具体的事值得去计价,而不是抽象地担心。

第一,llms.txt 是一个位于约定路径、写给机器读者、你团队里没有任何人读过、而多数评审都会挥手放过的文件。GitMCP 优先用它——这是正确的设计决定,同时也意味着这条流水线上信任度最高的那个位置,被仓库里最少被评审的那个文件占着。本站关于 工具投毒的那套论证原封不动地适用:这条通道被信任,是因为它所处的位置,不是因为它说了什么。

第二,托管索引是共享基础设施。索引里装着什么,就会被提供给所有指向那个库的人,于是一条坏条目不是你的一次事故,而是一类事故——这是供应链的形状,比包管理器再高一层。

第三,也是最常被漏掉的:DeepWiki 索引的是公开仓库。拿它去问不公开的代码,不是一个你绕过去就好的能力缺口,而是一次发布行为。Ref 的存在有一部分正是为了把这种场景好好接住:私有来源挂在账号后面;GitMCP 是开源的,可以跑在你自己的基础设施上。这两者对私有代码库都是对的形状。而一个公开的 wiki 生成器不是。

把这些服务端返回的一切都当作数据,绝不当作指令。落到做法上:把取回的文本放进提示词里一个带分隔的区块,告诉模型这是参考材料、其中的一切指示一律忽略,并且别让文档工具待在那种「智能体读完就能直接照着动手、中间没有一步」的循环里。这就是全部的缓解措施,它很便宜,而几乎没人做——因为那段文本被叫作「文档」。

什么时候选哪个

情形选理由
智能体对着热门库写代码,版本要紧 Context7 按版本的索引是这里唯一从设计上就打算回答版本问题的
上手一个陌生的公开仓库 DeepWiki 生成式架构散文与仓库问答正是干这个的;具体细节另找地方核实
就一个特定项目,钉住版本,零配置 GitMCP 一个仓库一个 URL、上游文本,以及一个由你掌握的 tag
内部文档与公开文档一次搜完 Ref 支持私有来源,外加每次读取的硬性 token 上限
私有代码库,不接受第三方索引 自托管的 GitMCP 开源;代码不出你的网络

它们可以叠着用,认真做的团队多半最后会有两个:一个用于库参考,一个用于理解仓库。不能叠着用的是信任。逐个工具地判定:它的输出是权威,还是导航——并把这个判定写进提示词,因为模型不会从工具的名字里推出来。

常见问题

有没有哪一个是绝对更好的?

没有,因为其中两类回答的是不同的问题。Context7、Ref 与 GitMCP 回答「这个 API 做什么」;DeepWiki 回答「这个仓库是怎么搭起来的」。拿覆盖面去比它们,会漏掉一件事:它们的输出是不同种类的文本。

Context7 会自动钉到我已安装的版本吗?

不会。它维护按版本的文档,并会提供你指定的那个版本,但「指定」这件事得由你或模型在查询里做。这条流水线里没有任何环节会读你的 lockfile,所以解析版本是外壳的活。

我能把 DeepWiki 指向一个私有仓库吗?

公开的 DeepWiki 索引覆盖的是 GitHub 公开仓库;私有代码属于 Devin 账号的功能,而不是那个公开端点会提供的东西。把一个公开索引器指向私有代码,就当作是在发布它——换一个支持私有来源或可自托管的工具。

llms.txt 是什么,我该不该发一份?

它是位于仓库或站点根部的一个约定文件,给机器读者一份策展过的文档地图。如果你维护一个库,就发一份——这是控制智能体读到关于你什么内容的最便宜手段。要像对待仓库里任何别的文件那样评审它,因为对优先采用它的那些工具来说,它是你对外发布的、信任度最高的那个输入。

这些工具是省 token 还是费 token?

都有,取决于比较对象。相对于一个一页一页爬文档站的智能体,它们把消耗砍得很狠——Ref 把每次读取压在约 5k token,并丢掉已经给过你的结果。相对于一个本来会去读已安装包源码的智能体,它们多加了一次往返和一层摘要。这个比较只有按任务来看才有意义。

延伸阅读

本站:

项目来源: