内容
# zoekt-mcp
[](https://github.com/radiovisual/zoekt-mcp/actions/workflows/ci.yml)
[](https://pypi.org/project/zoekt-mcp/)
[](https://github.com/radiovisual/zoekt-mcp/pkgs/container/zoekt-mcp)
[](https://registry.modelcontextprotocol.io/v0.1/servers?search=zoekt-mcp)
[](LICENSE)
MCP 服务器,暴露 Sourcegraph Zoekt 代码搜索功能给任何支持 MCP 的 AI 代理(如 Claude Code、Claude Desktop、Cursor、MCP Inspector 等),使代理能够在您的代码仓库中执行快速、索引、正则表达式/符号感知的代码搜索,而不受编程语言限制。
- **MCP 服务器:** Python 编写,基于 FastMCP,运行在标准输入/输出上,客户端可以将其作为子进程启动。已发布到 PyPI、ghcr.io,并被列入官方 MCP 注册中心,因此 **无需克隆即可使用**。
- **后端:** `zoekt-webserver`,您可以通过附带的 Docker Compose 文件自行运行 - 或将 MCP 服务器指向您已有的 zoekt-webserver。
- **暴露的工具:** `search_code`、`list_repos`、`get_file`。
## 架构
```mermaid
flowchart LR
subgraph Client["MCP 客户端"]
CC["Claude Code<br/>Claude Desktop<br/>Cursor 等"]
end
subgraph Server["zoekt-mcp (Python)"]
Tools["search_code<br/>list_repos<br/>get_file"]
end
subgraph Backend["Docker: zoekt 后端"]
Web["zoekt-webserver"]
Idx[("zoekt 索引<br/>命名卷")]
Indexer["zoekt-indexer<br/>(一次性)"]
end
Code[("您的代码<br/>绑定挂载")]
CC <-->|"标准输入/输出<br/>MCP 协议"| Tools
Tools <-->|"HTTP JSON<br/>/api/search<br/>/api/list<br/>/print"| Web
Web --> Idx
Code --> Indexer
Indexer --> Idx
```
### 单次搜索流程
```mermaid
sequenceDiagram
actor You
participant Claude as Claude Code
participant MCP as zoekt-mcp
participant Web as zoekt-webserver
participant Idx as zoekt 索引
You->>Claude: "getVideoId 定义在哪里?"
Claude->>MCP: search_code("sym:getVideoId")
MCP->>Web: POST /api/search
Web->>Idx: 扫描分片
Idx-->>Web: 匹配 + ctags 符号
Web-->>MCP: 原始 JSON 结果
Note over MCP: 修剪为 {repo, file,<br/>line, text, symbols}
MCP-->>Claude: 格式化结果
Claude-->>You: "src/index.js:17 (function)"
```
## 快速入门
从“无任何安装”到“Claude 可以搜索我的代码”共有三个步骤:安装 MCP 服务器、运行后端,将其连接到您的客户端。在任何步骤中都不需要克隆。
### 前提条件
您需要以下条件之一来运行 MCP 服务器,以及用于后端的 Docker:
- **uv 在您的 PATH 中** — 用于 `uvx zoekt-mcp` 安装路径。MCP 客户端通过 `uvx` 启动服务器,因此 `which uv` 必须在您的客户端启动进程的 shell 中解析。每个机器只需安装一次:
```bash
# 官方安装程序(macOS / Linux)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Homebrew
brew install uv
# pipx
pipx install uv
```
安装程序将 `uv` 和 `uvx` 放入 `~/.local/bin/`(Linux/macOS)或 `%USERPROFILE%\.local\bin\`(Windows)。通过 `uv --version` 验证。
- **... 或 Docker** — 用于 `docker run ghcr.io/radiovisual/zoekt-mcp` 安装路径。任何最近的 Docker Desktop 或引擎都可以使用。您还需要 Docker 来运行后端,因此此路径可以为您节省安装 `uv` 的步骤。
以及用于后端:
- **带有 Compose v2 的 Docker** — 运行 `zoekt-webserver` 和一次性索引器,详见每个版本的附件。
### 1. 启动后端(每台机器一次)
zoekt 后端是一个普通的 Docker Compose 堆栈,您需要自行运行 - zoekt-mcp **不** 进行生命周期管理。获取最新 GitHub 版本附带的 compose 文件和辅助脚本,并将它们与包含代码的目录一起启动:
```bash
# 从最新版本中获取您需要的两个文件。
mkdir -p ~/.zoekt-mcp && cd ~/.zoekt-mcp
curl -LO https://github.com/radiovisual/zoekt-mcp/releases/latest/download/docker-compose.yml
curl -LO https://github.com/radiovisual/zoekt-mcp/releases/latest/download/index.sh
chmod +x index.sh
# 将索引器指向机器上的任何父目录。
# 每个顶级子目录都成为一个可搜索的仓库。
echo "ZOEKT_REPOS_DIR=/home/you/code" > .env
# 启动 zoekt-webserver + 一次性索引器。
docker compose up -d
```
如果 `/home/you/code` 看起来如下:
```text
~/code/
├── project-a/ → 索引为 zoekt 仓库 "project-a"
├── project-b/ → 索引为 zoekt 仓库 "project-b"
└── scratch-notes/ → 索引为 zoekt 仓库 "scratch-notes"
```
...zoekt 索引 **所有三个仓库**,并且您可以按 `repo:project-a` 限定查询 - 或省略 `repo:` 以一次性搜索所有内容。详见下面的 [索引多个代码库](#索引多个代码库)。
健康检查:
```bash
curl -s -XPOST -d '{"Q":"repo:."}' http://localhost:6070/api/list \
| python3 -m json.tool | head -20
```
您应该会看到每个 `ZOEKT_REPOS_DIR` 的子目录都列为一个 zoekt 仓库。
> 在 macOS / Windows Docker Desktop 上,您选择的文件路径必须位于允许的文件共享根目录下(请参阅 Docker Desktop → 设置 → 资源 → 文件共享)。在 Linux 上没有此类限制。
>
> **仅需在不触及您实际代码目录的情况下试用?** 克隆存储库并使用树内测试夹具:`./tests/fixtures/up.sh` - 详见 [开发](#开发) 在本文件的底部。
### 2. 将 MCP 服务器连接到您的客户端
根据您的现有工具,选择适合您的安装路径。两者最终都会运行相同版本的服务器二进制;区别在于启动方式。
#### 路径 A — `uvx`(推荐,如果您已经有 uv)
`uvx` 在首次调用时下载最新的 `zoekt-mcp`,缓存它,然后启动它。无需永久安装,无需管理虚拟环境。
**Claude Code (`~/.claude.json`):**
```json
{
"mcpServers": {
"zoekt": {
"type": "stdio",
"command": "uvx",
"args": ["zoekt-mcp"],
"env": { "ZOEKT_URL": "http://localhost:6070" }
}
}
}
```
或通过 `claude` CLI:
```bash
claude mcp add zoekt \
--env ZOEKT_URL=http://localhost:6070 \
-- uvx zoekt-mcp
```
**Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_config.json` 在 macOS 上):**
```json
{
"mcpServers": {
"zoekt": {
"command": "uvx",
"args": ["zoekt-mcp"],
"env": { "ZOEKT_URL": "http://localhost:6070" }
}
}
}
```
**Cursor (`~/.cursor/mcp.json` 或 `.cursor/mcp.json` 在项目中):**
```json
{
"mcpServers": {
"zoekt": {
"command": "uvx",
"args": ["zoekt-mcp"],
"env": { "ZOEKT_URL": "http://localhost:6070" }
}
}
}
```
要固定特定版本而不是始终使用最新版本:
```json
"args": ["zoekt-mcp==0.1.0"]
```
#### 路径 B — Docker 镜像(无需 Python 工具)
如果您已经为后端运行 Docker 而不是安装 `uv`,请改用容器镜像。MCP 客户端通过标准输入/输出启动它,与 `uvx` 路径相同。
**Claude Code / Claude Desktop / Cursor:**
```json
{
"mcpServers": {
"zoekt": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"--network=host",
"-e", "ZOEKT_URL=http://localhost:6070",
"ghcr.io/radiovisual/zoekt-mcp:latest"
]
}
}
}
```
在 Docker Desktop(macOS/Windows)上,主机无法通过 `localhost` 从容器内部访问。删除 `--network=host` 并改用 `host.docker.internal`:
```json
"args": [
"run", "-i", "--rm",
"-e", "ZOEKT_URL=http://host.docker.internal:6070",
"ghcr.io/radiovisual/zoekt-mcp:latest"
]
```
要固定特定版本,请将 `:latest` 替换为 semver 标签(例如 `:0.1.0`)。镜像是多架构的(`linux/amd64` + `linux/arm64`),因此它在 Apple Silicon 和 ARM Linux 主机上运行,无需额外标志。
### 3. 重启客户端
重启 Claude Code / Claude Desktop / Cursor,三个工具(`search_code`、`list_repos`、`get_file`)应该会出现。尝试类似“`getVideoId` 定义在哪里?”并观察它调用 `search_code("sym:getVideoId")`。
## 索引多个代码库
**一个 zoekt-mcp 服务器可以处理任意数量的仓库** - 默认情况下。每个 `ZOEKT_REPOS_DIR` 的顶级子目录都成为一个单独的可搜索仓库,共享一个索引。`search_code` 工具可以通过 `repo:NAME` (与仓库名称匹配的正则表达式)限定范围,或省略 `repo:` 以跨所有仓库搜索。
如果您的项目位于不同的父目录下(例如 `~/work/` 和 `~/personal/`),最简单的解决方法是创建一个带有符号链接的“索引根”目录,并将 `ZOEKT_REPOS_DIR` 设置为该索引根。一个服务器,一个配置,所有仓库都可搜索。
```bash
mkdir -p ~/.zoekt-root
ln -s ~/work/project-a ~/.zoekt-root/project-a
ln -s ~/personal/side-thing ~/.zoekt-root/side-thing
cd ~/.zoekt-mcp
echo "ZOEKT_REPOS_DIR=$HOME/.zoekt-root" > .env
docker compose up -d
```
> Docker 必须在解析绑定挂载时跟随符号链接,这在 Linux 上有效,但在 Docker Desktop 上存在问题。如果链接目录在容器内不可见,请改用将真实目录(或克隆)放在 `~/.zoekt-root` 下。
### 何时真正需要两个服务器
第二个 zoekt-mcp 实例仅在您需要 **完全隔离的索引池** 时才值得设置成本 - 例如,将工作代码和个人代码放在完全独立的搜索命名空间中,或同时运行两个不同的后端(例如不同的 zoekt 版本)。如果您只是想索引更多代码,则不需要;一个服务器和多个子目录是正确的工具。
如果您确实需要两个实例:
1. 复制 `~/.zoekt-mcp/docker-compose.yml` 到第二个文件,例如 `~/.zoekt-mcp/docker-compose.personal.yml`。
2. 在副本中更改:
- 编排项目名称(例如 `zoekt-mcp-personal`)
- 主机端口映射(例如 `6071:6070`)
- 命名卷(例如 `zoekt-mcp-personal-index`)
- 容器名称(例如 `zoekt-mcp-personal-webserver`)
3. 为第二个堆栈提供自己的环境文件,例如 `~/.zoekt-mcp/.env.personal`,将 `ZOEKT_REPOS_DIR` 指向不同的目录。
4. 使用各自的编排文件和环境文件启动每个堆栈:
```bash
cd ~/.zoekt-mcp
docker compose up -d
docker compose -f docker-compose.personal.yml \
--env-file .env.personal up -d
```
5. 将两者作为不同的服务器连接到您的 MCP 客户端 - 相同的 `zoekt-mcp` 二进制文件,不同的 `ZOEKT_URL` 值:
```json
{
"mcpServers": {
"zoekt-work": {
"command": "uvx",
"args": ["zoekt-mcp"],
"env": { "ZOEKT_URL": "http://localhost:6070" }
},
"zoekt-personal": {
"command": "uvx",
"args": ["zoekt-mcp"],
"env": { "ZOEKT_URL": "http://localhost:6071" }
}
}
}
```
Claude Code 看到了两个独立的工具集(`search_code` / `list_repos` / `get_file` 来自每个命名空间),并根据问题决定调用哪一个。
对于大多数用户来说,**一个服务器和一个配置良好的 `ZOEKT_REPOS_DIR` 就是您所需要的**。除非您有具体原因需要隔离,否则不要使用多服务器。
### 高级:在专用仓库目录下暂存代码
作为替代将 `ZOEKT_REPOS_DIR` 指向您的实际代码目录,您可以创建一个专用暂存目录,并在其中放置克隆或目录副本。当您无法将实际代码目录公开给 Docker 时会很有用(例如,由于 Docker Desktop 的企业文件共享限制),或用于您没有本地存储库的一次性实验:
```bash
mkdir -p ~/.zoekt-mcp/repos
git clone https://github.com/myorg/myrepo ~/.zoekt-mcp/repos/myrepo
cd ~/.zoekt-mcp
echo "ZOEKT_REPOS_DIR=$HOME/.zoekt-mcp/repos" > .env
docker compose up -d
```
权衡是 **新鲜陷阱**:您现在拥有每个项目副本的两个副本 - 您实际编辑的副本和暂存的副本。在每次重新索引时,索引器会重新读取暂存的副本,因此您需要在每次重新索引之前在 `~/.zoekt-mcp/repos/myrepo/` 中执行 `git pull`(或 `cp -r` 编辑)。优先将 `ZOEKT_REPOS_DIR` 指向您的实时代码目录,除非您有具体原因不这样做。
## 工具表面
| 工具 | 参数 | 返回值 |
|------|--------|---------|
| `search_code` | `query: str`, `max_results: int = 50`, `context_lines: int = 3` | `{query, file_count, match_count, duration_ns, files: [{repo, file, language, branches, matches: [{line, text, ranges, symbols}]}]}` |
| `list_repos` | `filter: str = ""` (可选 `repo:` 原子) | `{count, repos: [{name, url, branches, index_time}]}` |
| `get_file` | `repo: str`, `path: str`, `branch: str = "HEAD"` | `{repo, path, branch, content}` |
### 查询语言
Zoekt 的查询 DSL([完整参考](https://github.com/sourcegraph/zoekt/blob/main/doc/query_syntax.md)):
| 原子 | 示例 | 含义 |
|------|---------|---------|
| `repo:` | `repo:flask-app` | 限制在名称与(正则表达式)匹配的仓库中 |
| `file:` | `file:app.py` | 限制在匹配的文件路径中 |
| `lang:` | `lang:python` | 限制在某种语言中 |
| `sym:` | `sym:list_users` | 匹配符号定义 |
| `case:yes` | `case:yes Foo` | 区分大小写的文本匹配 |
| `/regex/` | `/users?/` | 正则表达式文本匹配 |
| (空格) | `lang:go func main` | 布尔 AND |
| `or` | `def hello or function hello` | 布尔 OR |
## 保持索引新鲜
Zoekt 搜索的是 **预先构建的索引**,而不是直接搜索您的文件。当您编辑代码时,索引不会自动更新 - 您的下一次搜索可能会返回过时的行号,错过新添加的符号,或者将 Claude 指向已移动或更名的函数。过时的搜索是 Claude 消耗令牌的主要原因,因为当 `search_code` 返回的结果没有用时,Claude 会使用 `get_file` 回退到读取整个文件。
以下是每次运行索引器时发生的情况:
```mermaid
flowchart LR
Src["您的代码<br/>(实时文件)"]
Mount["/src<br/>(只读<br/>绑定挂载)"]
Scratch["/tmp/{repo}<br/>(临时<br/>副本)"]
Git["临时<br/>git 仓库<br/>+ 快照提交"]
Shard[("索引分片<br/>/data/*.zoekt")]
Src -->|绑定挂载| Mount
Mount -->|cp -r| Scratch
Scratch -->|"git init; git add -A;<br/>git commit"| Git
Git -->|zoekt-git-index| Shard
```
复制到 `/tmp/` 是暂时的 - 它在每次索引器运行时都会刷新,从不触及您的实际文件。每次刷新总是读取当前安装目录中存在的内容。
幸运的是,重新索引速度很快(几秒钟内完成,即使对于大型仓库),并且完全在 Docker 中运行,不涉及任何 LLM 调用,费用为零令牌。您只需要决定 **如何** 触发它。
因为主要的快速入门已经将 `ZOEKT_REPOS_DIR` 指向您的实时代码目录,所以每次重新索引都会自动反映您的最新编辑 - 无需复制步骤以保持同步。(如果您使用的是 [高级暂存工作流](#高级暂存代码目录下暂存代码),请在触发重新索引之前更新 `~/.zoekt-mcp/repos/` 下的克隆,否则 zoekt 只会读取过时的副本。)
### 触发重新索引的配方
所有四个配方都在后台运行 - 无需 Claude、无需令牌、无需上下文窗口参与。选择与您工作方式相符的配方。
#### 1. 手动重新索引
在您认为自己进行了重大更改时运行 `~/.zoekt-mcp/index.sh`。该脚本仅在当前 `ZOEKT_REPOS_DIR` 上运行索引器容器,而不会重启 web 服务器,因此在搜索过程中保持搜索可用。
```bash
~/.zoekt-mcp/index.sh
```
*适用情况:* 您仅将 Claude 用于偶尔的会话,并且不介意在开始前输入一个命令。后台成本为零。
#### 2. cron(定时重新索引)
在计划上进行后台重新索引。没有手动步骤,之间可能会过时。
```cron
# 每 15 分钟重新索引
*/15 * * * * cd ~/.zoekt-mcp && ./index.sh >/dev/null 2>&1
```
*适用情况:* 您大多数天都在编写代码,希望 Claude 打开时有相对较新的搜索。每小时一次对大多数用户来说已经足够。
#### 3. 文件系统监视器
通过 `inotifywait`(Linux)或 `fswatch`(macOS)实时响应文件更改。捕获每个编辑,空闲时除外。
```bash
# Linux:一行命令,运行在 tmux 窗格或 systemd --user 服务中
while inotifywait -r -e modify,create,delete,move \
--exclude '\.git/|node_modules/|__pycache__/' \
/path/to/your/code 2>/dev/null; do
~/.zoekt-mcp/index.sh
done
```
```bash
# macOS 等效,使用 fswatch(brew install fswatch)
fswatch -o /Users/you/code | xargs -n1 -I{} ~/.zoekt-mcp/index.sh
```
*适用情况:* 您希望“搜索始终是最新的,无论我何时提问”。警告:如果项目中使用嘈杂的工具(编译器将文件写入构建目录,IDE 文件锁定时),则重要性列表至关重要 - 如果没有它们,您将不断重新索引。
## 结论
4. Claude启动钩子
每次启动新的 Claude Code 会话时,以便保证每次会话的首次搜索都是最新的。这样做可能对来说是最好的选择:进程,无需 cron 条鲜度与您实际感受到过时的时间完全吻合。
```json
// ~/.claude.json
{
"hooks": {
"SessionStart": [
{
"command": "$HOME/.zoekt-mcp/index.sh"
}
]
}
}
适合场景:* 您希望在实际使用 Claude 时保证搜索结果的最新鲜,并且不需要任何后台进程。会话启动时可能会被索引阻塞,但这通常只需要几秒钟。
### 我应该种方式?
| 如果您… | 使用 |
|---------|| …偶尔启动 Claude 且不介意手动操作方法 1** (手动) |
| …希望“设置后忘记”但能容忍 N 分钟的过时 | 2** (cron) |
| …希望搜索结果始终最新并且可以调整排除列表 | **3** (监视器) |
| …主要 Code 会话与代码交互方法 4** (会话启动钩子) |
这些互相排斥 - 例如希望同时拥有环境新鲜度和保证,可以同时运行 cron启动钩子。
## 检测器进行手动```bash
npxcontextprotocol/inspector uvx --from . zoekt-mcp
```
检测器会在 `http://localhost:6274` 打开一个浏览器 UI。在 **工具** → **搜索代码** 中,尝试:
- `lang:python def hello` — 预期在 `flask-app/app.py` 中找到匹配项
- `lang:javascript USERS` — 预期在 `express-app/index.js` 中找到
- `sym` — 预期在**两个**示例中找到
在 **工具 → 列出仓库** 中,空应返回 `flask 和 `express-app` 开发
本节适用于对 zoekt-mcp 本身进行开发。如果您只需要**使用**它,上面的[快速入门](#) 部分已经涵盖了所有内容 - 不需要克隆当您想要更改、运行完整的测试套件发布版本时,才需要。
### 设置
克并让 `uv` 为您管理虚拟环境:
git clone https:///radiovisual/zoekt-mcp
cd zocp
uv sync
uv sync` 会创建/`,解析所有内容并安装所有运行时 + 开发依赖项。开发组(`pytest`、`pytest-asyncio`、`respx`、`ruff`、`pre-commit`、`pymarkdownlnt`)默认安装;如果您只想要运行时安装,可以使用 `uv sync --no-dev`。
常用开发命令:
```bash
uv run pytest # 运行完整的测试套件 zoekt-mcp --help # 从源代码运行 CLI
uv add <package> # 添加新的运行时依赖项 add --dev <package # 添加新的开发依赖uv lock --upgrade 刷新 uv.lock
```
要从本地克隆的仓库运行 zoekt-mcp 以对抗的后端(例如,在服务器代码迭代时):
``` zoekt-mcp --zoekt-url http://localhost:6070
```
###发布版本是完全自动 标签推送会触发发布PI 和 ghcr.io 的管道,并附上 compose 文件的 GitHub 发布。请参阅LEASING.md`](RELEASING.md) 以流程(帮助脚本 +路径)和首次标签前PI/GHCR 设置。
### 提交常规
通过 [](https://pre-commit钩子,代码 linting 和测试已集成到流中,这样您就无需手动运行它们。在 `uv sync` 之后,每个克隆仓库只需安装一次两种类型的钩子:
```bash
uv run pre-commit install --hook-type pre-commit --hook-type pre-push
```
之后,每次 `git commit` 都会运行:
- **ruff** (`ruff check` + format --check`),针对暂存的 Python 文件位于 [`pyprojectpyproject.toml)tool.ruff]` 下。
- **pymarkt** (`pym scan`),针对暂 Markdown 文件 - 配置位于project.toml`](pyproject.toml) 中的 `[tool.pym]` 下。我们禁用 ``(行长度)和046`(代码块因为它们会影响可读的文章和宽表格,以及 `MD033`,以便允许故障排除 `<details>` 块。
每次 `git push` 都会运行离线 pytest 套件(`tests/test_client_unit.py` 和 `tests/test_server_shaping.py`),然后再推送到远程服务器,因此可以在测试失败时阻止推送。测试范围限定为 `pre-push` 而不是 `pre-commit`保持本地提交的快速;集成套件被排除,因为它需要一个正在运行的 zoserver。
钩子 `uv run`,本地和 CI 中运行版本由 `uv.lock` 中固定的版本决定 - 环境差异。相同的 linting**和**单元测试github/workflows/ci.yml](.github/workflows/ci.yml) 在每次推送到 `main` 和每次拉取请求时运行。
要手动运行所有内容(例如,在打开拉取请求之前):
```bash
uv run pre-commit run --all-files
```
要修复 Python 格式而不是仅仅检查它:
```bash
uv run ruff format
uv run ruff check --fix
```
## 自动测试
```bash
# 单元测试(不需要 Docker)
uv run pytest tests/test_client_unit.py tests/test_server_shaping.py -v
# 集成堆栈与示例库一起启动,然后运行言。
./tests/fixtures/up.sh
uv run pytest tests/test_integration.py -v
./tests/fixtures/down.sh
```
`tests/fixtures/up.sh` 设置 `ZOEPOS_DIR=../examples调用相同的 `deploy.yml`,因此测试泄漏到生产部署路径中。集成测试在 `ZOEKT_URL` 不可达时会自动跳过,因此在没有 Docker 的全新检出中,简单的 `uv run pytest` 仍然通过。
## 配置
| 设置 | 环境变量 | 标志 | 默认值 |
|---------|---------|------|---------|
| Zoekt 后端 URL | `ZOEKT_URL` | `--zoekt-url` | `http://localhost:6070` |
| HTTP 超时(秒) | `ZOEKT_TIMEOUT `--timeout` | `30` |
环境变量和标志是等效的 - 选择一个适合您的 MCP 客户端配置变量。大多数客户端通过 JSON 配置文件中的 `"env"` 块设置环境变量,这就是为什么上面的 `uvx` 和 Docker 代码段使用 `ZOEKT_URL` 而不是 `--zoekt-url`。
## 仓库布局
```text
zoekt-mcp/
├── src/zoekt_mcp/ # Python MCP 服务器 tests/
│ ├── test_client_unit.py # 离线单元测试
│ ├── test_integration.py # 实时测试(后端关闭时跳过)
│ / # 测试专用(up.sh / down.sh)
├── deploy/
│ ├── docker-compose.yml # 通用 zoekt 后端(环境变量驱动)
│ └── repos/ # 用户填充的源挂载(git└── examples/
├── flask-app/ # Flask 验证语料库
└── express-app/ # Express 验证语料库
```
## 故障排除
常见索引问题,以问答形式呈现。点击任何问题以展开答案。
<details>
<summary><b>问:<code>search_code</code> 返回 0 个命中,因为我知道字符串在项目中。哪里出了问题?</b></summary>
十分之九的情况下,索引包含您的代码 - zo正在搜索不同的(或过时的)语料库。MCP 服务器本身不过滤或重写查询;您发送的内容直接发送到 `/api/search`,因此 0 个命中意味着索引中**没有**命中。
通过三个步骤诊断:
1. 要求代理调用 `list_repos`(或 `curl -s -XPOST -d '{"Q."}' http:6070/api/list`)。这是 zoekt 可以看到的内容的真实来源。
2. 如果您的项目未在列表中,则索引器被指向其他地方。常见的罪魁祸首:
- `~/.zoekt-mcp/.env` 丢失或具有错误的 `ZOEKT_REPOS_DIR`,因此 `docker compose up` 索引了一个空或意外的目录。
- 某人从本地克隆运行了 `./tests/fixtures/up.sh`,它设置了 `ZOEKT_REPOS_DIR=../examples` 并且只索引了 `examples/express-app` 和 `examples/flask-app`。
- 索引器在每次运行时都会清空 `/data/*`,因此以前成功的运行**不会**在后续运行中持续存在 - 最近的索引器调用是 web 服务器唯一能看到的东西。
3. 重新运行索引器以指向正确的目录:
```bash
cd ~/.zoekt
echo "ZOEKT_REPOS_DIR=/absolute/path/to/parent-of-your-repo" > .env
docker compose up -d --force-recreate zoekt-indexer
```
`ZOEKT_REPOS_DIR` 必须是**父**目录;其下的每个顶级子成为一个仓库。在索引器退出后,重新list_repos` 以</details>
<detailssummary><b>问器退出时出现>WARNING: no repositories were indexed</code>。怎么办?</b>
`ZOEKT_DIR` 指向没有索引器可以变成顶级子目录。将 `ZOEKT_REPOS_DIR为已经包含您的项目子目录的父
```bash
cdekt-mcp
ZOEKT_REPOS_DIR=$HOME/code" >
docker compose up -d
```
`ZOEPOS_DIR` 松散文件被 编排文件中的循环目录。
</details>
<summary><b:<code>list</code> 显示 <code>express-app</ 和 <code>-app</code> 但不是我的代码。</b></这些是在开发克 `examples/` 下的仓库验证固定装置。它们器运行时出现在您的,通常是 `tests/up.sh` 从本地运行时,设置了OEKT_REPOS_DIR=../examples`。请实际项目目录重新参见上面的第一个问答),替换;索引运行时都会清空/`,因此无需单独</details>
<detailssummary><b>我编辑了一个文件结果仍然显示旧内容号。</b></索引是一个快照,而不是实时视图。zoekt 只ZOEKT_REPOS_DIR` 中上次运行时存在的内容。可以通过 `~/.zoekt-m` 触发刷新,或设置 [保持索引新鲜](#keeping-the-index-fresh) 中的四个自动化方法之一,以便自动刷新。重新索引速度很快(几秒钟内,甚至对于大型仓库),并且完全在 Docker 中运行 - 无需 LLM 调用,无需标记成本。
</details>
<details>
<b>问:<code>POST /</code> 返回 HTML 而不是 JSON。</b>
Web 服务器未使用 `-rpc` 启动,因此/*` 降级到 HTML 搜索处理程序捆绑的-compose.yml` 已经传递 `-rpc`(请参见 `zoekt-webserver` 下的 `command:` 块);如果您在其他地方运行自己的 zoekt-web 服务器,请将其添加到 argv 并重启。
</details>
## 许可证
MIT - 请参阅 [`LICENSE`](LICENSE)。
<!-- mcp-name: io.github.radiovisual/zoekt-mcp -->
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器