mcpField
D
Deadzone

Deadzone

本地服务
github.com开发工具425 周前更新

关于 Deadzone

Deadzone 是本地优先的文档语义搜索 MCP 服务,为使用 MCP 的开发者和 AI 工具检索程序库文档。它通过向量搜索返回片段,索引保存在本机 Turso 文件中。

主要功能

  1. 01按自然语言搜索程序库
  2. 02语义检索文档片段
  3. 03按库和版本筛选
  4. 04限制结果令牌预算
  5. 05本地保存索引

适用场景

  1. 01查找库中某项功能的实现说明
  2. 02按指定版本检索文档
  3. 03为编码 Agent 提供文档片段

MCP 相关

Deadzone 通过 stdio 提供 MCP 服务,向客户端开放 `search_libraries` 和 `search_docs` 两个工具。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"laradji-deadzone": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/laradji/deadzone:v0.7.4"
]
}
}
}
启动命令docker run -i --rm ghcr.io/laradji/deadzone:v0.7.4

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
ocighcr.io/laradji/deadzone:v0.7.4

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

         _                _
      __| | ___  __ _  __| |_______  _ __   ___
     / _` |/ _ \/ _` |/ _` |_  / _ \| '_ \ / _ \
    | (_| |  __/ (_| | (_| |/ / (_) | | | |  __/
     \__,_|\___|\__,_|\__,_/___\___/|_| |_|\___|

    > semantic doc search. local file. no cloud. no key.
    > you ask in english. it answers in snippets.

状态。 向量搜索已端到端接通。通过标准输入输出运行 MCP。单个二进制文件,支持 Linux 和 macOS,零遥测。最新标签请参阅发布版本,正在进行的工作请参阅路线图。 抓取器仍是混乱的那一部分——#64对此毫不避讳。


一段话介绍

你的 AI 客户端问:“如何注册一个工具?”文档里写的是 AddTool。基于 grep 的索引只能耸耸肩,向量索引却能找到答案。Deadzone 就是这个向量索引——使用 nomic-embed-text-v1.5,基于 Turso 原生余弦距离,由一个通过标准输入输出运行 MCP、并将每个字节都留在你笔记本电脑上的 Go 二进制文件封装而成。大致来说,它就是断网版的 Context7。


Deadzone 的规则

  1. 单个二进制文件。 deadzone。所有功能都通过子命令实现。不需要 pip install、npm i 或 docker compose up。
  2. 索引绝不离开本机。 本地 Turso 文件。无需账户,无需 API 密钥,关键路径不向外联网。
  3. 自然语言优先。 使用基于余弦距离的嵌入。不使用 FTS5。
  4. 二进制文件就是版本。 数据库与二进制文件绑定。升级二进制文件,数据库也会随之更新;不升级,数据库就不会变。
  5. 要么明确失败,要么不猜。 DEADZONE_DB_OFFLINE=1 会拒绝猜测。抓取器中的验证失败会丢弃文档,而不是中止整个任务。

安装(任选一种;最终都会使用同一个二进制文件)

# macOS Apple Silicon — the one-liner
brew install laradji/deadzone/deadzone

# Linux — resolve the latest tag once, then pick a flavor
VERSION=$(curl -fsSL https://api.github.com/repos/laradji/deadzone/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
ARCH=amd64    # or arm64

# self-mounting AppImage
curl -L -O "https://github.com/laradji/deadzone/releases/download/${VERSION}/deadzone_${VERSION}_linux_${ARCH}.AppImage"
chmod +x "deadzone_${VERSION}_linux_${ARCH}.AppImage"
mv "deadzone_${VERSION}_linux_${ARCH}.AppImage" deadzone

# or plain tarball (no FUSE needed)
curl -L "https://github.com/laradji/deadzone/releases/download/${VERSION}/deadzone_${VERSION}_linux_${ARCH}.tar.gz" \
  | tar xz --strip-components=1

这两种方式都会在当前目录中生成一个 deadzone 可执行文件,因此下面的 ./deadzone server 代码片段可以直接使用。

# Container — multi-arch (linux/amd64 + linux/arm64), ships with the DB baked, runs offline by default
docker pull ghcr.io/laradji/deadzone:latest
docker run --rm -i ghcr.io/laradji/deadzone:latest server

镜像内置了二进制文件、libonnxruntime、deadzone.db 和 nomic-embed-text-v1.5 ONNX 权重(总计约 230 MB),并以非 root 用户身份运行于 distroless 之上(没有 shell,也没有包管理器)。镜像中已设置 DEADZONE_DB_OFFLINE=1,因此首次启动即可立即运行——无需下载、无需挂载卷,也无需访问 --network。要刷新索引,只需拉取更新的标签。

Windows 目前受上游限制——缺少 libtokenizers.a。请使用 WSL。

校验校验和(可选,但成本很低):

curl -L -O "https://github.com/laradji/deadzone/releases/download/${VERSION}/deadzone_${VERSION}_checksums.txt"
sha256sum  --ignore-missing -c "deadzone_${VERSION}_checksums.txt"   # Linux
shasum -a 256 --ignore-missing -c "deadzone_${VERSION}_checksums.txt"   # macOS

AppImage 需要 FUSE v2。 大多数桌面系统都已安装;精简服务器则没有。如果出现 dlopen(): libfuse.so.2,请运行 apt-get install libfuse2(或 dnf install fuse-libs),也可以传入 --appimage-extract-and-run,完全绕过 FUSE。


运行

./deadzone server

这就是快速入门。首次启动时,它会获取与此二进制文件版本匹配的 deadzone.db,通过 SHA256 校验后,将其缓存到平台数据目录并启动服务。从第二次启动开始:完全不需要联网。升级二进制文件后,下次启动时会重新获取数据库;不升级,缓存就会一直使用。

MCP 客户端连接配置——原生二进制文件(Brew tap、tarball 或 AppImage):

{
  "mcpServers": {
    "deadzone": {
      "type": "stdio",
      "command": "/path/to/deadzone",
      "args": ["server"]
    }
  }
}

MCP 客户端连接配置——容器(ghcr.io 上的多架构镜像)。镜像已内置 deadzone.db,因此无需挂载卷,每次启动容器都能立即离线运行:

{
  "mcpServers": {
    "deadzone": {
      "type": "stdio",
      "command": "docker",
      "args": ["run", "--rm", "-i", "ghcr.io/laradji/deadzone:latest", "server"]
    }
  }
}

然后,在客户端中:

search_libraries("terraform aws")                 → ranked (lib_id, version) pairs
search_docs("creating an s3 bucket", lib_id=...)  → snippets, token-budgeted

两个工具

┌─────────────────────────────────────────────────────────────────────┐
│  search_libraries(name, limit?) → []LibraryHit                      │
│  ─────────────────────────────────────────────                      │
│  free text   ──►  vector match against the `libs` table             │
│                   ──► [{lib_id, version, doc_count, match_score}]   │
├─────────────────────────────────────────────────────────────────────┤
│  search_docs(query, lib_id?, version?, tokens?) → []Snippet         │
│  ──────────────────────────────────────────────────                 │
│  natural  ──► 768-dim embed ──► cosine over docs                    │
│  language                      ──► token-budgeted snippets back     │
└─────────────────────────────────────────────────────────────────────┘
参数形式说明
query字符串按语义匹配。不要写关键词,写出你想要的内容。
lib_id/org/project可选筛选条件。从 search_libraries 获取。
version"1.14" 或类似值可选版本固定;需要提供 lib_id。单独提供 version 会被拒绝。
tokens整数响应预算。默认值为 5000,最小值为 1000,约 4 个字符对应 1 个 token。
limit整数用于 search_libraries——最大结果数。默认值为 10,最大值为 50。
name字符串search_libraries 的自由文本。留空则返回索引最多的库。

实现原理

  deadzone server
       │
       ▼
  ┌──────────────┐   stdio JSON-RPC       ┌───────────────┐
  │  MCP client  │ ─────────────────────► │   handler     │
  └──────────────┘                        └──────┬────────┘
                                                 │
                              ┌──────────────────┴──────────────────┐
                              ▼                                     ▼
                     ┌────────────────┐                   ┌──────────────────┐
                     │   embedder     │                   │   Turso (local)  │
                     │  hugot + ORT   │                   │  F32_BLOB(768)   │
                     │  nomic v1.5    │                   │  vector_distance │
                     └────────┬───────┘                   └──────────────────┘
                              │  768-dim                             ▲
                              └──────────────  query vector  ────────┘
层级选择
语言Go 1.26.2,通过 mise 固定版本
存储Turso 本地文件 — 原生支持 F32_BLOB(N) + vector_distance_cos
驱动tursogo — 通过 purego 实现 无 CGO
嵌入模型hugot → nomic-ai/nomic-embed-text-v1.5,768 维,8192 token 上下文(int8 量化)
运行时ONNX Runtime — 构建时以 CGO 链接二进制;首次启动时自动获取并验证 libonnxruntime 的 SHA256
协议通过 stdio 使用 modelcontextprotocol/go-sdk

二进制本身通过 CGO 链接(hugot ORT 后端 + 静态 libtokenizers.a)。在运行时,唯一的原生依赖是 libonnxruntime,它会在 SHA256 验证通过的自动下载后通过 dlopen 加载。其他所有内容——Go 标准库、tursogo、模型权重——要么静态链接,要么首次启动时通过固定哈希获取。无需安装系统依赖,无需 sudo。如果下载内容与固定哈希不符,程序将中止运行;不会回退到未经验证的下载。

适用于气隙隔离设备的备用方式:

环境变量作用
DEADZONE_ORT_LIB_PATH手动指定 libonnxruntime 路径。跳过下载。
DEADZONE_ORT_CACHE覆盖 ORT 库缓存目录。
DEADZONE_HUGOT_CACHE覆盖模型权重缓存目录。
DEADZONE_DB_CACHE覆盖 deadzone.db 缓存目录。
DEADZONE_DB_OFFLINE=1拒绝任何网络调用。如果没有缓存内容则明确报错。容器镜像默认设置此项(镜像中已预置 deadzone.db)。
DEADZONE_DB_AUTOUPDATE=0禁用启动时的数据库新鲜度检查(默认会执行该检查;无论此标志为何值,fetch-db 都会始终执行检查)。

各平台的默认缓存路径:

平台deadzone.db 的位置
macOS~/Library/Application Support/deadzone/deadzone.db
Linux$XDG_DATA_HOME/deadzone/deadzone.db(否则为 ~/.local/share/...)
Windows%LOCALAPPDATA%\deadzone\deadzone.db

同目录下的 deadzone.db.release JSON 清单记录 {tag, sha256, fetched_at}。启动时会将缓存的标签与二进制中编译的版本进行比较:匹配 → 向对应 GitHub Release 中的 deadzone.db.sha256 发起 3 秒新鲜度检查,如果远程 sha 不同则原子替换(发生任何网络错误时软失败并继续使用缓存);不匹配 → 获取新标签对应的发布版本并原子替换;开发构建 → 回退到 /releases/latest,并记录 server.db_version_dev_fallback WARN。#197 之前的二进制会写入仅含标签的单行 sidecar;JSON 读取器仍接受此格式,并会在首次检查时将其重写为 v1 格式。


添加库

贡献者路径。最终用户无需处理此项——他们只需使用 deadzone.db 中提供的内容。

不打算自己编辑 YAML? 请通过新建问题页面提交 issue,并选择添加库或刷新库。模板会收集注册表条目所需的全部信息。

打算自己编辑 YAML? 请将条目追加到 libraries_sources.yaml:

libraries:
  # Single-version lib — no `versions` key, urls used as-is.
  - lib_id: /modelcontextprotocol/go-sdk
    kind: github-md
    urls:
      - https://raw.githubusercontent.com/modelcontextprotocol/go-sdk/main/README.md
      - https://raw.githubusercontent.com/modelcontextprotocol/go-sdk/main/docs/quick_start.md

  # Multi-version lib — `versions` expands into one effective lib_id
  # per version (/org/project/1.4, /org/project/1.5, …). {ref} is
  # substituted from each version's ref: field.
  - lib_id: /modelcontextprotocol/go-sdk
    kind: github-md
    versions:
      "1.4": { ref: v1.4.1 }
      "1.5": { ref: v1.5.0 }
    urls:
      - https://raw.githubusercontent.com/modelcontextprotocol/go-sdk/{ref}/README.md
      - https://raw.githubusercontent.com/modelcontextprotocol/go-sdk/{ref}/docs/getting-started.md
字段必填用途
lib_id是规范的 /org/project 标识符(与 db.docs.lib_id 一致)。
kind是github-md(原始 markdown)、github-rst(原始 reStructuredText)或 scrape-via-agent(通过 LLM 处理 HTML/文本)。
urls是文档 URL 列表,可选包含 {ref} 占位符。
versions否{"1.4": {ref: v1.4.1, urls: [...]}, "1.5": {ref: v1.5.0}, …} — 面向用户的标识符优先使用 major.minor。
ref否替换 {ref} 的 Git 标签或提交 SHA。每个版本的 ref: 会覆盖顶层设置。
versions[v].urls否每个版本的 URL 列表——会整体替换基准列表。适用于结构差异较大的版本。

1.0 之前:无需编辑 Go 代码,也无需重新编译。只需编辑 YAML 并重新抓取。


通过 Agent 抓取(实验性)

⚠️ 比较麻烦的部分。 目前适用于非 markdown 来源(Terraform 提供程序、mkdocs、GitBook 等),但 LLM→验证器循环容易受输入截断(上限为 48 KiB)、HTML→markdown 技能以及逐字代码匹配的影响。在内容密集的文档网站上,实际命中率约为每个 URL 50%——参见 #64。只要项目提供了已提交的 markdown,就优先使用 github-md。

使用你自己的 LLM 运行时——Ollama、llama.cpp、vLLM、LocalAI、LM Studio、Groq、OpenAI,或任何支持 POST /v1/chat/completions 的运行时:

export DEADZONE_AGENT_ENDPOINT=http://localhost:11434/v1
export DEADZONE_AGENT_ENDPOINT_MODEL=qwen2.5:7b
export DEADZONE_AGENT_ENDPOINT_API_KEY=sk-...   # optional

然后在 libraries_sources.yaml 中添加一个 kind: scrape-via-agent 条目,并列出页面 URL。下游流水线(解析 → 分块 → 嵌入 → 存储)与 github-md 完全相同;只有 markdown 来源不同。

防护措施。 LLM 输出中的每个围栏代码块都会与来源逐字验证——虚构示例会导致文档被丢弃(scraper.agent_verification_failed),而不会中止整个运行。端点缺失或无法访问时会在启动时中止;不会静默回退。


本地流水线(贡献者)

分两步引导:先准备工具链,再准备 CGO 原生依赖——两者分开处理,以便使用已供应 libtokenizers.a 的隔离网络 / CI 运行器通过覆盖 DEADZONE_TOKENIZERS_LIB 跳过第 2 步。

just bootstrap            # Go 1.26.2 + just toolchain (mise install)
just fetch-tokenizers     # libtokenizers.a — one-shot CGO setup
just build                # CGO + ORT, all packages
just scrape                       # all libs — one artifact folder per lib
just scrape /hashicorp/terraform  # one base lib, every version
just scrape /hashicorp/terraform/1.14   # one exact version
just consolidate                  # merge artifacts/*/artifact.db → deadzone.db
just serve                        # MCP server against deadzone.db

不带参数运行 just 会列出所有配方。每次抓取都会就地重写 artifacts/<slug>/artifact.db 和 state.yaml;consolidate 会将所有构件数据库原子性地合并到 deadzone.db。每个库的文件夹都被 gitignore 忽略;已提交的 artifacts/manifest.yaml 只记录发布历史。

通过 CI 获取完整注册表。 gh workflow run scrape-pack.yml -f tag=vX.Y.Z 会并行运行矩阵任务、合并结果,并将 deadzone.db 上传到带标签的发布版本。省略 -f tag=… 即会在生成合并数据库缓存后停止。


发布流程

自 #101 起采用两阶段流程——CI 发布二进制文件,操作者发布数据库。

# 1. Regenerate deadzone.db from the committed scraper config.
just scrape && just consolidate

# 2. Tag + push. CI's release.yml builds tarballs + AppImages, creates the release,
#    and auto-bumps the Homebrew tap on release.published.
git tag v0.X.0 && git push --tags

# 3. Ship deadzone.db + deadzone.db.sha256 to the same release.
just dbrelease v0.X.0

# 4. Commit artifacts/manifest.yaml so the release-history trace lands in git.
git add artifacts/manifest.yaml && git commit -m "release v0.X.0" && git push

推送稳定版标签后,CI 会完整执行整个流程:release.yml -> chain-release.yml 分派 scrape-pack.yml -> chain-image.yml 分派 docker-publish.yml(每个工作流各司其职,通过 workflow_run 串联)。

手动执行 Homebrew 回退流程。 tap 会在 release.published 时自动更新(#148)。如果 RELEASE_PUBLISH_TOKEN 过期导致流程中断,请手动运行:

gh workflow run update-package-channels.yml -f tag=v0.X.0

日志

通过 log/slog 将结构化 JSON 写入 stderr。deadzone server 的 stdout 专用于 MCP JSON-RPC。

子命令关键事件
scrapescraper.start、scraper.lib_start、scraper.fetch(每个 URL 一条)、scraper.indexed、scraper.lib_done、scraper.done。错误:scraper.fetch_failed、scraper.insert_failed。Agent 路径还会记录 scraper.agent_configured、scraper.agent_ping_ok、scraper.agent_verification_failed、agent.input_truncated。
consolidateconsolidate.start、consolidate.done,包含 artifacts、docs_merged、libs_merged、duration_ms。
dbreleasedbrelease.start、packs.dbrelease.uploaded(每个资源文件一条)、dbrelease.done,包含 sha256、size、lib_count、doc_count。
serverserver.start(包含 embedder 和 doc_count),每次调用记录一条 search_docs(包含 lib_id、tokens、results、latency_ms)。启动时可能会记录 server.db_upgraded、server.db_version_dev_fallback WARN、server.db_tag_sidecar_write_failed WARN。

任何子命令都可以使用 --verbose 添加调试级别的详细信息。用于 server 时会记录原始 query(默认关闭,因为查询可能包含用户数据)。用于 scrape 时会添加每篇文档的 scraper.doc_indexed。

MCP 客户端日志路径:macOS 上的 Claude Code 写入 ~/Library/Logs/Claude/mcp-server-deadzone.log;其他客户端的路径各不相同。


路线图与贡献

问题列表:laradji/deadzone/issues。通过 milestones 确定范围。使用 feature / research 标签标注类别;使用 P1 / P2 / P3 标注优先级。

新增或刷新库:前往 New issue 页面,选择对应表单。


为什么要使用向量

因为 "how to register a tool" 应该能找到写有 AddTool 的文档,而如果用户事先不知道答案,任何 FTS5 查询都无法找到它。以嵌入为先进行检索才是重点;其他一切都只是基础设施。

长篇分析:docs/research/context7-analysis.md。


许可证

Apache License, Version 2.0。第三方归属信息见 NOTICE。

有一点需要特别注意。 Apache 2.0 仅涵盖 Deadzone 源代码,不包括其他内容。它不涵盖抓取器索引的第三方文档——这些文档归原作者所有,并受其各自许可证约束。运行 deadzone scrape 须遵守每个来源的服务条款。预构建包受原始内容的许可证约束,而非 Apache 2.0。个人在本地建立索引:没问题。公开再分发:请先做好功课。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。