事实来源
事实来源是整个文档的结构化图谱——包括页面、标题、章节和交叉链接——由 Claude Code 等 AI 代理通过 markdown-lsp 在本地构建。代理在您的代码仓库上运行解析器,将图谱保存在内存中,并在处理文档时以命令或 LSP 请求的形式查询它。
注意。 服务端事实来源索引以及托管的 MCP 图谱工具(
get_doc_graph、read_doc_sections、reindex_doc_graph和doc_*LSP 风格工具)已在 v0.22.0 中移除。现在图谱完全驻留在代理的机器上:不存在托管索引,没有重新索引配额,也不会因此消耗项目余额。
如何向代理提供事实来源图?#
在你希望代理查询的仓库中运行 markdown-lsp,只要代理在该仓库中工作,就可以使用此图谱。无需在 Docsbook 中启用任何功能,也不需要 Docsbook 账户。
该图谱由 markdown-lsp 构建——这是我们的开源 Markdown 语言服务器,以 markdown-lsp 的形式发布在 npm 上,并且要求 Node 20 或更高版本。代理有两种方式可以访问它,这确实是两种不同的接口,而不是同一事物的两种称呼:
# 1. As commands the agent runs. Every subcommand prints JSON to stdout.
npx markdown-lsp workspace-outline ./docs
npx markdown-lsp links-to ./docs quick-start.md
# 2. As a language server, for an editor or a structural indexer.
npx markdown-lsp lsp --stdio对于 Claude Code,该软件包提供了一项技能,可在对话中设置第一种路径:
npx skills add Docsbook-io/markdown-lspmarkdown-lsp 内部没有 MCP 服务器。代理通过运行命令或使用 LSP 进行交互——因此这里不会消耗 MCP 令牌或 Docsbook 余额。完整的标志列表请参阅 markdown-lsp 自述文件。
图中包含的内容#
对于每个页面,图中存储:
- 规范引用(
path#section) - 标题和前置元数据
- 带有稳定锚点的标题树
- 章节正文(Markdown)
- 出站链接和入站链接
每条命令运行时都会读取工作树的当前状态,因此代理获取的内容始终与磁盘上的文件一致——包括尚未提交的编辑内容。在结构化路径上无需使缓存失效。
图是如何构建的#
该图由 markdown-lsp 解析——这是我们针对 Markdown 的开源语言服务器协议实现,在 npm 上发布为 markdown-lsp。它会解析为 unified + remark AST(支持 GitHub 风格的 Markdown),而不是在文本上匹配正则表达式,因此:
- 像
../guide.md#section这样的相对路径会解析为真实页面和真实锚点 - 内联、引用和自动链接样式都会被识别为链接,而不仅仅是内联形式
- 无法解析到任何内容的链接会被提前报告——图导出结果会携带一个
unresolvedCount,并且每条边都会标明其来源链接的类型
代理可以向图谱询问什么#
这些是 markdown-lsp 子命令。它们针对从磁盘构建的内存图谱运行,因此即时、免费,并且不会回调 Docsbook。每个命令都将文档目录作为第一个参数,并输出 JSON;--pretty 会为其添加缩进。
结构
| 子命令 | 返回内容 |
|---|---|
workspace-outline <dir> |
包含元数据的所有页面——最经济的概览方式 |
outline <dir> <page> |
单个页面的标题大纲,不包含正文 |
get-section <dir> <page> <anchor> |
按锚点 slug 获取某个区段的正文 |
搜索
| 子命令 | 返回内容 |
|---|---|
search-symbols <dir> <query> |
对标题进行模糊子序列搜索;oaf 匹配 OAuth flow |
search-text <dir> <query> |
全文搜索,支持 ranked 或 verbatim,并支持 --regex、--case-sensitive 和 --context n |
search-paths <dir> <glob> |
匹配 glob 的页面(ai/*.md、**/auth.md) |
链接图
| 子命令 | 返回内容 |
|---|---|
links-to <dir> <page> |
所有链接到当前页面的页面——LSP 的 references 问题 |
links-from <dir> <page> |
从当前页面发出的所有链接 |
resolve-link <dir> <from-page> <link-text> |
链接文本实际解析到的目标页面和锚点 |
graph <dir> --format json|dot|mermaid|html |
完整图谱:包含区段数量的节点、带有类型的边,以及 unresolvedCount——无法解析到任何内容的链接 |
另外三个子命令构成语义层,也是其中并非完全本地运行的命令:index 构建持久化嵌入索引,semantic-search 查询该索引,而 graph --semantic 添加相似度边。每个命令都需要环境中的嵌入提供商密钥,并会将页面文本发送给该提供商。index 是增量式的——未更改的单元会从 .markdown-lsp-cache/ 下的本地缓存中提供,因此在编辑一个页面后重新运行它时,只会重新嵌入一个页面。
为什么图谱是在本地而不是托管的?#
Docsbook 在代理的机器上构建事实来源图谱,因为代理需要它提供的三样东西——新鲜度、隐私性和无限次重新读取——恰恰是托管索引无法提供的。
- 没有配额,也没有费用。 根据代理的需要随时重新建立索引;所有内容都在磁盘上,并且不会按调用计费。
- 始终保持最新。 图谱会在代理保存未提交的编辑后立即反映这些更改,而由已推送提交构建的托管索引无法做到这一点。
- 私密。 使用结构化子命令时,未发布的草稿永远不会离开机器——不会配置密钥,也不会发出请求。
- 不受 Docsbook 绑定。
markdown-lsp可对任何 Markdown 仓库运行,包括未在此处发布的文档。
这种权衡确实存在,也值得明确说明:没有检出你的仓库的代理无法从此图谱中获得任何内容。该代理应改用托管的 search_docs 和 get_doc_outline 工具。
限制与未决问题#
- “不离开机器”仅适用于结构部分。
index、semantic-search和graph --semantic会将页面文本发送给嵌入提供商,因为嵌入本身就是如此生成的。如果你的文档属于机密内容,请使用完全不需要密钥的结构子命令,并单独决定是否使用语义子命令。 - LSP 服务器不是 CLI。这些子命令会在内存中构建图,无需数据库;运行完整的语言服务器为编辑器提供服务,则需要 Postgres 来维护增量索引。本页面中的命令走的是 CLI 路径。
- 新鲜度是运行的一项属性,而不是监视器的属性。每个命令都会读取其运行时工作树的状态,因此代理获取的图在当时是最新的;语义索引的新鲜程度取决于上一次
index。该软件包本身建议使用 git hook,而不是守护进程。 - 图了解链接结构,但不了解正确性。
unresolvedCount会告诉你某个链接无法解析到任何内容。这里没有任何信息能告诉你某个页面是否错误、过时或与产品相矛盾——这正是 MCP 服务器的分析和变更历史工具所负责的部分。 - 取决于版本。子命令名称和标志属于
markdown-lsp,其版本更新遵循自身的计划。软件包 README 是权威来源;本页面描述的是当前发布的接口。 - 尚待确认:wiki 风格的
[[note]]链接。本页面的早期版本曾表示支持此类链接。该软件包既未记录 wiki 链接,也未记录可添加此功能的插件,并且其解析器是remark,与 GitHub 风格 Markdown 配合使用时不会自行解析这些链接。在软件包另有说明之前,请将 wiki 链接视为不受支持;上述内容涵盖了三种样式中的普通 Markdown 链接。
相关#
- MCP 服务器 — 为工作区、内容、分析和 Webhook 提供托管服务的服务器。
- Docs 技能 — 构建于图谱之上的技能目录。
- llms.txt — 面向没有代码检出的代理,提供已发布站点的机器可读索引。
- MCP 服务器安全性 — 托管端存储哪些内容,以及令牌可以访问哪些内容。
- Webhooks — 在托管端订阅
content.indexed和content.outdated。