Code Search MCP
The Code Search MCP server enables AI clients to search and retrieve source code from large, indexed repositories (powered by Zoekt) via two core tools:
search_code: Search across indexed repositories for source code text or regex patterns. Find class/function names, error messages, configuration keys, API calls, etc. Supports:Filtering by repository name (regex), programming language (e.g.,
java,go,python), and file path (regex)Literal search (
literal=true) for strings with spaces, hyphens, or special charactersConfigurable result limit (1–100, default 20)
Returns repository name, file path, line number, and matched snippet
get_file_context: Retrieve surrounding source code for a specific file and line number (from search results). Features:Configurable lines before/after the target (0–100, default 20 each)
Target line highlighted with
>, includes real line numbers, start/end lines, total file lines, and truncation indicator
Safe file access is enforced — only repository-relative paths are accepted; absolute paths and directory traversal (..) are rejected.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Code Search MCPsearch for @RestController in Java files across all repos"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Code Search MCP
基于 Zoekt 和 Model Context Protocol(MCP)的代码搜索服务,让 AI 客户端能够快速检索大型代码库中的真实代码。
为什么做这个项目
大模型拥有通用编程知识,但默认不了解企业内部代码,也无法知道一个服务当前的目录结构、接口实现、配置依赖和跨仓库调用关系。当研发人员排查问题或理解陌生业务时,仍然需要在多个仓库之间反复切换、搜索和整理上下文。
这个项目尝试解决这一问题:
MCP 连接 AI 与代码库:把代码搜索能力暴露成标准化工具,让支持 MCP 的 AI 客户端可以按需调用,而不是依赖人工复制代码。
Zoekt 提供高性能索引:利用面向源码设计的索引和搜索能力,在大型、多仓库环境中快速定位关键词、符号和代码片段。
为代码理解提供可靠上下文:先检索真实代码,再让模型分析结果,降低仅凭模型已有知识猜测实现的风险。
降低跨团队搜索成本:研发人员不必预先熟悉所有仓库,也可以通过服务名、类名、接口、配置项或错误信息定位相关代码。
沉淀可复用的研发工具:代码检索能力可以继续用于故障排查、代码问答、影响面分析和研发 Agent,而不局限于单一聊天界面。
本项目当前的目标不是让模型一次性“读懂整个代码库”,而是为模型提供一个快速、可控、可追溯的代码检索入口。代码理解、调用链分析和故障定位将在此基础上逐步实现。
Related MCP server: zoekt-mcp
工作方式
用户提出代码问题
│
▼
支持 MCP 的 AI 客户端
│ 调用 search_code
▼
Code Search MCP Server
│ 构造查询并转换结果
▼
Zoekt Web Server
│ 查询预先生成的代码索引
▼
仓库、文件、行号和代码片段职责划分:
src/server.py:声明 MCP 工具,接收工具参数并格式化返回内容。src/services/zoekt_client.py:构造 Zoekt 查询、调用 Zoekt API 并解析响应。src/services/file_reader.py:安全解析仓库内路径并读取目标行上下文。src/models/:定义与 MCP 和 Zoekt 实现解耦的结构化结果模型。
当前能力
项目目前提供 search_code 和 get_file_context 两个工具,支持:
跨已索引仓库搜索代码;
按仓库、语言和文件路径过滤;
普通查询与正则查询;
对包含连字符、空格等特殊字符的内容进行字面量搜索;
返回仓库名、文件路径、行号和匹配代码片段;
限制返回结果数量,避免向模型传入过多上下文;
根据搜索命中的仓库、相对路径和行号读取源码上下文;
拒绝绝对路径和目录穿越,限制文件访问范围。
示例问题:
搜索所有 Java 仓库中使用 @RestController 的代码。
sample-service-v2 在哪些仓库中被引用?
哪个文件读取了指定的配置项?公开 Click 端到端演示
可用公开仓库 pallets/click 8.4.1(固定 commit) 复核一次真实的 MCP 调用闭环。演示以错误文本
The given command does not have a callback that can be invoked. 为查询条件,按
search_code → get_file_context → 仅基于返回源码回答 执行。
重跑的真实返回表明:当 callback 是 Command 且
other_cmd.callback is None 时,Click 在该位置抛出 TypeError。返回范围为第
836~860 行,并带有 truncated=true;因此该证据不把未出现在上下文中的类名或方法名
当作已验证结论。
本地运行
前置条件
Python 3.10 或更高版本;
已运行的 Zoekt Web Server;
已由 Zoekt 建立索引的代码仓库。
安装依赖
项目运行依赖和开发依赖定义在 pyproject.toml 中。创建并激活虚拟环境:
python -m venv .venv
source .venv/bin/activate仅安装运行依赖:
python -m pip install .本地开发或运行测试时,安装可编辑版本和开发依赖:
python -m pip install -e ".[dev]"可选:真实模型决策冒烟
evaluation/run_model_smoke.py 会通过 OpenAI Python SDK 请求一次模型决策,
但不会执行模型返回的检索工具。它要求调用方显式提供
OPENAI_API_KEY、OPENAI_BASE_URL 和 OPENAI_MODEL。建议将本地配置放在已被
Git 忽略的 .secrets/openai-smoke.env,然后执行:
set -a
source .secrets/openai-smoke.env
set +a
PYTHONPATH=. .venv/bin/python evaluation/run_model_smoke.py \
--no-proxy-base-url \
--out .artifacts/model-smoke.jsonOPENAI_BASE_URL 是传输配置:既可以指向 OpenAI API,也可以指向受信任的
OpenAI-compatible API 网关。OpenAIModel 本身只是应用内适配器,并不实现网络代理;
网关需要兼容 Chat Completions 的 strict function tools、tool_choice 和
parallel_tool_calls。远程环境应使用 TLS;仅在隔离且可信的本地/内网链路中接受明文
HTTP,并由部署方承担该链路的安全控制。
若机器设置了通用 HTTP、HTTPS 或 SOCKS 代理,而私有网关必须直连,可显式传入
--no-proxy-base-url。脚本只在当前进程中把 OPENAI_BASE_URL 的主机追加到
NO_PROXY 和 no_proxy,不会输出主机、修改系统代理或影响其他进程。
模型 Trace 只保留模型名、不含传输元数据的 ModelInput、稳定决策/错误分类、关联 ID 和
elapsed_ms。API Key、Base URL、请求头、原始异常和原始 Provider 响应均不进入
Trace。冒烟脚本会在写报告前验证已配置的 Key/Base URL 不在序列化结果中,并输出
redaction_evidence;任一检查失败都会终止执行,报告默认写入被 Git 忽略的
.artifacts/。
该 Click 冒烟会把规范索引名 click 及
Click、pallets/click、github.com/pallets/click 三个精确别名作为
repository_hints 提供给模型,并断言模型最终输出 repo="click"。Agent 执行层还会
通过 RepositoryAliasResolver 做第二次精确解析:原始别名保留在 ModelResult,真正
执行的规范名记录在 ToolCall;未知或冲突别名分别返回 unknown_repository 或
ambiguous_repository,不会再表现为成功的空搜索。
这里的脱敏边界只覆盖 Provider/传输元数据。ModelInput、业务证据和已校验决策会按
设计保留,脚本不是通用源码或 PII 脱敏器;调用方仍需在构造上下文前执行自己的仓库权限
与数据分级策略。
Replay a persisted model decision
无需再次请求模型,即可用公开脱敏 fixture
和单步重放 runner复现一次真实决策的
ToolCall → ToolResult → 下一份 ModelInput。准备好固定 Click 8.4.1 checkout 与 Zoekt
索引后,按真实 Tool 证据中的命令
运行;该入口不读取模型凭据,也不重新生成原始模型 Trace。
Replay one grounded Incident search task
incident-click-search-public.json
冻结一条公开、来源可核验的错误文本及 Click 8.4.1 精确 gold;对应 SHA-256
由同目录 sidecar 和 Runner 常量双重校验。先做不调用模型、Tool 或网络的契约校验:
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=. .venv/bin/python \
-m evaluation.replay_incident_search \
--fixture evaluation/fixtures/incident-click-search-public.json \
--validate-only真实入口还要求显式配置 ZOEKT_URL、REPOSITORY_ROOT 和
ZOEKT_INDEX_REVISION,并先核对 checkout、zoekt.name、声明 revision 与本地
gold。通过后只把 mapper 产生的唯一 error_text 任务经现有 Tool 执行边界发送给
src.server.search_code 一次;不调用模型、Agent Loop 或 get_file_context,也不重试。
该证据只覆盖直接 Tool backend 路径,不代表 MCP Client 闭环或 Incident 根因判断。
2026-08-29 的首次真实尝试保存在
incident-search-replay-real-2026-08-29.json
及其独立说明。同一冻结
fixture 在零 Tool 预检全部通过后只执行一次,结果稳定分类为
tool_execution_error;预算仍为 1 → 0,其他 Tool、模型和 Agent Loop 调用均为
0,且没有重试。该失败不计为真实检索闭环通过。
2026-08-30 在先确认本地 listener 与固定索引服务已恢复后,新的明确授权允许同一
fixture 再执行一次。零 Tool 预检保持全绿,唯一一次真实 search_code 将冻结 gold
命中 Top-1;预算、Trace、来源和 next State/Input 门禁均通过,仍未调用
get_file_context、模型或 Agent Loop。白名单 artifact 与边界说明见
incident-search-replay-real-2026-08-30.json
和成功复核记录。08-29 的
失败记录未被覆盖,也未通过改 query、fixture、gold 或 best-of 制造成功。
冻结的 Agent Eval
独立 Agent 评测集位于
evaluation/agent_cases.jsonl,固定为 Click 8.4.1
revision 6eeb50e948ea136db145280f6f5dd52eca3fa7e5 上人工复核的 10 条自然语言任务:
8 条可回答、2 条应以信息不足收口。冻结 SHA-256 为
09b3e346686d550c09c3b361ec16d00e51cac8fd257850593901ab212c2da129。
真实运行前先做不调用模型或 Zoekt 的契约校验:
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=. .venv/bin/python \
evaluation/run_agent_eval.py --validate-only真实入口要求调用方提供 OPENAI_API_KEY、OPENAI_BASE_URL、OPENAI_MODEL,以及由
索引创建方确认的 ZOEKT_INDEX_REVISION;同时要求 ZOEKT_URL、
REPOSITORY_ROOT/click、checkout revision 和 git config zoekt.name 一致。Runner 会在
任何模型调用前执行固定的正向/负向索引探针,并拒绝非默认文件或 SHA-256 不匹配的真实
评测。完整 10 条按文件顺序各运行一次,不提供 --max-cases、重试或 best-of 选项:
set -a
source .secrets/openai-smoke.env
set +a
export ZOEKT_INDEX_REVISION=6eeb50e948ea136db145280f6f5dd52eca3fa7e5
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=. .venv/bin/python \
evaluation/run_agent_eval.py \
--no-proxy-base-url \
--out evaluation/reports/agent-eval-YYYY-MM-DD.json \
--summary-out evaluation/reports/agent-eval-YYYY-MM-DD.md逐题 JSON 保留终态、Tool 尝试与名称序列、模型提交的引用、当前任务成功 Tool 来源校验、 金标范围匹配、Trace 不变量、模型/Tool/任务耗时和稳定失败分类;汇总指标只从这些明细 重算。写盘前会断言 API Key、Base URL、本机仓库路径和传输/Provider 原始字段均不存在。
2026-08-16 的首轮真实执行保存在
agent-eval-2026-08-16.json 和
agent-eval-2026-08-16.md。该轮 10/10
均在首次模型调用处以 model_execution_error 终止,任务成功率为 0/10,Tool 尝试为
0,引用分母为 0,Trace 完整性为 10/10。
模型服务恢复后,用户明确授权使用相同冻结数据、Prompt、检索和金标执行一次独立恢复
重试;结果保存在
agent-eval-2026-08-16-retry-01.json
和
agent-eval-2026-08-16-retry-01.md。
重试轮任务成功率为 3/10,引用有效率 6/20(30%),Trace 完整性 10/10,每题 Tool
上限全部满足。6 个正向答案因模型提交范围格式引用而 fail closed,另 1 条为 Tool 错误;
没有根据结果修改机制或执行第三轮,M3 退出门槛仍未达到。
这 6 条范围引用失败已按原始报告哈希冻结在
agent-eval-range-citation-failures-2026-08-16.json,
逐条保留模型输出、人工复核的结构化单行参考引用和稳定失败分类。下一项预注册的可证伪
假设见
agent-eval-range-citation-freeze-2026-08-16.md:
仅把最终决策中的自由文本引用改为严格的 repo / path / 正整数 line 字段,当前任务
成功 Tool 事实的精确运行时校验保持不变,不增加范围兼容或自动修复。
独立冻结的 Agent Holdout
未参与上述 Prompt 调试、失败分析或结构化引用实现的新 Click 8.4.1 holdout 位于
evaluation/agent_holdout_cases_2026-08-19.jsonl。
它独立保持 8 条可回答与 2 条应信息不足任务,冻结 SHA-256 为
e08cd744a44b3fb99ac98d0f5bf77ef6489f324c8109aba980687f459a0df396。
agent-holdout-exclusion-set-2026-08-19.json
逐条保留原 10 条 Agent case、18 条检索 case 和 6 条范围引用失败的 ID、问题或查询、目标位置及源文件哈希。完整人工源码复核、两条全仓无命中命令和诚实边界记录在
agent-holdout-freeze-2026-08-19.md。
以下入口只校验 8/2 分布、ID 和问题唯一性、Click revision、数据与排除集哈希、排除集
10/18/6 覆盖,以及正向 gold 与旧目标位置不相交;它不读取模型凭据,不调用模型或
Zoekt:
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=. .venv/bin/python \
evaluation/run_agent_holdout.py --validate-only后续独立工作日的真实运行也使用 evaluation/run_agent_holdout.py,且只接受默认冻结文件。
默认报告名为 agent-holdout-eval-YYYY-MM-DD.json 和
agent-holdout-eval-YYYY-MM-DD.md,不会覆盖 08-16 的原评测报告。冻结当天没有运行真实
holdout,也没有预填任何新质量指标。
配置 Zoekt 地址
默认连接 http://localhost:6070。如果 Zoekt 运行在其他地址,可以设置:
export ZOEKT_URL=http://localhost:6070
export REPOSITORY_ROOT=/path/to/indexed/repositoriesREPOSITORY_ROOT 下的一级目录名需要与 Zoekt 返回的仓库名一致。例如:
/path/to/indexed/repositories/
├── code-search-mcp/
└── demo-service/此时 Zoekt 命中中的 repo 应分别为 code-search-mcp 或 demo-service,
get_file_context 才能找到对应的本地源码。不要把 API Key、公司内网地址或
本地私有路径提交到仓库。
索引前固定 Zoekt 仓库名
本项目使用 REPOSITORY_ROOT/<repo> 将搜索结果映射到本地源码。对每个待索引的
Git 仓库,必须在生成或重建 Zoekt 索引前进入该仓库并执行:
git config zoekt.name <本地目录名>例如,本地目录为 REPOSITORY_ROOT/click 时:
cd /path/to/indexed/repositories/click
git config zoekt.name click随后再运行 Zoekt 的索引命令。若仓库已经索引过,修改配置后还必须重建该仓库的 索引;已有索引中的仓库名不会自动更新。
启动 MCP Server
PYTHONPATH=. .venv/bin/python -m src.server该服务使用 stdio 与 MCP 客户端通信,因此直接启动后没有普通 HTTP 页面属于正常现象。
配置 MCP 客户端
不同客户端的配置入口不同,核心配置如下。请把 cwd 和环境变量替换为你
自己的绝对路径:
{
"mcpServers": {
"code-search": {
"command": "/absolute/path/to/mcp-server/.venv/bin/python",
"args": ["-m", "src.server"],
"cwd": "/absolute/path/to/mcp-server",
"env": {
"PYTHONPATH": ".",
"ZOEKT_URL": "http://localhost:6070",
"REPOSITORY_ROOT": "/absolute/path/to/repositories"
}
}
}
}使用 MCP Inspector 调试
PYTHONPATH=. .venv/bin/mcp dev src/server.py:mcp该命令会通过 MCP Inspector 加载 FastMCP 服务,可以查看工具 schema 并手动调用
search_code 和 get_file_context。
工具说明
search_code
在 Zoekt 索引中定位精确的源码文本或正则模式。适合查找类名、函数名、错误 信息、配置键和调用表达式;它是文本/正则搜索,不等同于语义级符号分析。
参数 | 类型 | 默认值 | 说明 |
|
| 必填 | 源码文本或 Zoekt 正则表达式 |
|
|
| 仓库名正则过滤 |
|
|
| 语言过滤,如 |
|
|
| 仓库内文件路径正则过滤 |
|
|
| 返回命中数,范围 1~100 |
|
|
| 是否把 |
返回值示例:
{
"query": "UserNotFound",
"duration_ms": 3,
"matches": [
{
"repo": "demo-service",
"path": "src/service/user_service.py",
"line": 128,
"snippet": "raise UserNotFound(user_id)"
}
]
}以下情况建议设置 literal=true:
sample-service-v2
connection refused: upstream unavailable
com.example.user-serviceget_file_context
读取一次搜索命中周围的源码。通常先调用 search_code,再将某条命中的
repo、path 和 line 分别传给 repository、file_path 和
line_number。
参数 | 类型 | 默认值 | 说明 |
|
| 必填 |
|
|
| 必填 |
|
|
| 必填 |
|
|
|
| 目标行之前的行数,范围 0~100 |
|
|
| 目标行之后的行数,范围 0~100 |
返回的 content 带真实行号,并以 > 标出目标行:
126 | user = repository.find(user_id)
127 | if user is None:
> 128 | raise UserNotFound(user_id)
129 | return user为避免任意文件读取,file_path 只接受仓库内相对路径,绝对路径和逃出仓库
根目录的 .. 路径都会被拒绝。
完整调用流程
向 MCP 客户端提问:
在 demo-service 中查找 UserNotFound,读取最相关命中前后各 10 行,
然后说明这段代码在什么情况下抛出异常。若信息不足,请明确说明。理想工具调用链:
search_code(query="UserNotFound", repo="demo-service", limit=10)
↓
选择相关的 repo + path + line
↓
get_file_context(
repository="demo-service",
file_path="src/service/user_service.py",
line_number=128,
lines_before=10,
lines_after=10
)
↓
客户端基于真实源码回答,并引用文件与行号手动验证搜索
确保 Zoekt 已启动并已加载索引,然后执行:
PYTHONPATH=. .venv/bin/python test/test_search.py运行测试
单元测试默认不要求启动真实 Zoekt:
PYTHONPATH=. .venv/bin/pytest -v若环境中没有 pytest,先安装:
pip install pytest真实 Zoekt 验证(公开)
公开版使用 Click 8.4.1 作为真实 MCP Client 验证样例。完整的
search_code → get_file_context 调用轨迹、原始可见返回结果和限制说明见
上方“公开 Click 端到端演示”中的两份证据。
Click 检索评测基线
公开评测集位于 evaluation/cases.jsonl,当前共 18 条,固定使用
pallets/click 8.4.1 commit 6eeb50e948ea136db145280f6f5dd52eca3fa7e5。
先确认本地 checkout 与索引都使用该 revision,且 Zoekt 返回的仓库名为 click:
git -C "$REPOSITORY_ROOT/click" rev-parse HEAD
PYTHONPATH=. .venv/bin/python evaluation/run_eval.py --validate-only
PYTHONPATH=. .venv/bin/python evaluation/run_eval.py \
--out evaluation/reports/baseline-YYYY-MM-DD.json评测集包含正向命中、无命中、上下文边界,以及重复命中、无关结果、未限定
路径、符号候选、错误文本、语言/路径组合和长文件上下文等样例。每个正向样例声明金标
repo、path 与精确行号或可接受行号范围;无命中样例则明确声明受检
repo、path、line: null 和 failure_reason。无命中正确时不会调用
get_file_context,也不会被算入 Hit@1、Hit@5 或 search_code → get_file_context
闭环的分母,而是在 no_match_success 中单独统计。
固定 revision 上的逐条人工 git grep 复核记录见
evaluation/click-8.4.1-manual-grep.md。该清单记录每条样例的类别、目标仓库、路径和可接受行号范围。重复候选、无关结果和未限定路径的样例会保留 Zoekt 原始返回顺序;即使金标未排在 Top-1 或 Top-5,也不会为了提高指标收窄查询或调整排序。
2026-07-23 真实 Zoekt 重跑结果
baseline-2026-07-23.json 与 2026-07-22 的基线对比如下。新集新增的 8 条故意覆盖了候选重复、文档/注释噪声和未限定路径的情况,因此质量指标的分母扩大,不能把百分比降低解读为对原 10 条已覆盖场景的回归。
指标 | 2026-07-22(10 条 / 8 类) | 2026-07-23(18 条 / 15 类) |
正向 / 无命中样例 | 8 / 2 | 16 / 2 |
Hit@1 | 8/8(100%) | 12/16(75%) |
Hit@5 | 8/8(100%) | 13/16(81.25%) |
| 8/8(100%) | 12/16(75%) |
无命中正确率 | 2/2(100%) | 2/2(100%) |
平均 search wall latency | 28.551 ms | 19.231 ms |
平均 closed-loop wall latency | 29.840 ms | 20.320 ms |
重跑没有搜索或上下文读取错误。4 条如实保留为 top1_miss:两个 duplicate_hits、irrelevant_results,以及 unscoped_path;其中 unscoped_path 的金标仍在 Top-5。延迟反映此次本地服务状态,适合作为同一环境内的对照而非跨机器 SLA。
两个 context_boundary_* 样例分别命中 src/click/globals.py 的第 1 行和第
64 行,并断言 get_file_context 返回的实际 start_line、end_line、
total_lines、truncated 以及目标行标记。这会覆盖文件开头和结尾的截断行为。
报告会记录每条样例的原始 wall-clock 时间、聚合的 latency_ms.search_wall 与
latency_ms.closed_loop_wall,以及本地 checkout revision。调用顺序、固定查询和
time.perf_counter 的计时定义也写入 JSON,因而质量指标可以精确复现;延迟会随
机器与 Zoekt 运行状态变化,应比较同一环境下的报告而非要求逐毫秒一致。
本地私有仓库的测试基线和输出只保存在被 Git 忽略的目录,不纳入公开仓库或发行物。
每次已启用的执行都会将可复现性信息写入
.artifacts/zoekt-integration.json(可通过 ZOEKT_INTEGRATION_REPORT 改写路径):
Zoekt 地址、Python/HTTP 客户端信息、Zoekt Server commit、索引仓库 commit、本地
checkout commit、起止时间、耗时和执行结果。当前演示环境的服务器 /about 未暴露
build commit,因此该字段会记录为不可获取;如部署方能确认该值,可额外设置
ZOEKT_SERVER_COMMIT,它会优先写入报告。
常见问题
客户端启动后看不到工具
确认客户端配置中的 Python、
cwd都是绝对路径;确认虚拟环境已经安装
requirements.txt;确认以项目根目录作为工作目录,并设置
PYTHONPATH=.;在 MCP Inspector 中先验证服务能否加载。
search_code 报连接失败
确认 Zoekt Web Server 正在运行;
确认
ZOEKT_URL可从 MCP Server 进程访问;确认 Zoekt 已加载目标仓库索引。
搜索有结果,但 get_file_context 提示仓库或文件不存在
确认
REPOSITORY_ROOT/<repo>是实际存在的目录;确认 Zoekt 返回的仓库名与本地一级目录名一致;
确认搜索结果中的路径是仓库内相对路径;
确认 Zoekt 索引对应的源码与本地源码版本一致。
Zoekt 返回的 repo 与本地目录不一致
公开 Click 演示的首次调用就是这一失败案例:search_code 返回
repo=github.com/pallets/click,而本地源码目录是
REPOSITORY_ROOT/click。get_file_context 按 Tool 返回值拼接本地目录后,会尝试
读取 REPOSITORY_ROOT/github.com/pallets/click,因而报 Repository 不存在。
根因是未显式设置 zoekt.name 时,Zoekt 可能根据 Git origin 推导出
github.com/<owner>/<repo> 形式的仓库名;该名字与本项目按本地一级目录寻址的契约不一致。
修复方式是在索引前进入本地 checkout,执行
git config zoekt.name <本地目录名>,然后重建索引。例如目录名为 click 时执行
git config zoekt.name click。修复后先确认 search_code 返回 repo=click,再将其
返回的 repo、path、line 原样传给 get_file_context。
搜索服务名或完整错误信息时没有结果
带空格、连字符或 Zoekt 查询运算符的完整文本应设置 literal=true。需要正则
能力时则保持 literal=false。
设计取舍
为什么使用 Zoekt,而不是向量数据库?
当前阶段主要解决精确代码检索问题,例如类名、方法名、错误信息、配置项和 API 调用位置。这些查询通常包含明确的文本或正则特征,Zoekt 更适合作为第一层检索基础设施。
向量检索更适合语义相似内容,但可能遗漏必须精确匹配的符号,也会引入代码切分、Embedding 更新和索引一致性等额外成本。后续可以采用“Zoekt 精确检索 + 语义检索”的混合方案,而不是让二者互相替代。
为什么通过 MCP 暴露能力?
MCP 将搜索能力与具体 AI 客户端解耦。同一个服务可以被不同的 Agent 或开发工具调用,也便于未来继续增加 find_symbol 和 find_references 等工具。
Roadmap
接入 Zoekt 搜索 API
提供
search_codeMCP 工具支持仓库、语言、路径和字面量过滤
补充 Zoekt 查询构造和响应解析单元测试
补充 MCP Server 基本测试
补充真实 Zoekt 集成测试(默认关闭)
增加
get_file_context增加
find_symbol和find_references控制上下文长度并改善结果排序
接入代码理解 Agent
结合错误日志实现故障代码定位
当前限制
当前演示环境的 Zoekt Server
/about未暴露 build commit,故 Server commit 不可获取; 不应根据猜测补写版本或 commit。部署方可通过ZOEKT_SERVER_COMMIT显式提供已确认的值。get_file_context只返回目标行前后请求的有限行数(每侧最多 100 行)。当返回truncated=true时,文件前部或后部没有包含在上下文中;未出现在返回内容中的类、方法或 调用关系不能视为已验证。搜索结果质量依赖 Zoekt 索引是否及时、完整;
当前主要提供文本和正则搜索,不等同于完整的语义代码理解;
当前不会自动判断搜索结果中的代码是否正确,也不会直接修改代码;
企业代码接入时还需要补充仓库权限、访问审计和敏感信息保护。
Available Tools
2 toolsget_file_contextA
读取一次代码搜索命中位置周围带行号的源码上下文。
应在 search_code 返回候选命中后调用,并原样传入该命中的 repo、path 和
line。适合确认命中属于定义、调用还是配置,以及在回答用户前理解附近
的控制流。返回内容以 > 标出目标行,并包含实际起止行、文件总行数
和是否截断。不要用它搜索未知文件,也不要传入绝对路径或 .. 路径。
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | search_code 命中结果中的 path 字段;必须是仓库内相对路径 | |
| repository | Yes | search_code 命中结果中的 repo 字段(仓库名称) | |
| line_number | Yes | search_code 命中结果中的 line 字段(从 1 开始) | |
| lines_after | No | 目标行之后返回的源码行数,默认 20 | |
| lines_before | No | 目标行之前返回的源码行数,默认 20 |
Output Schema
| Name | Required | Description |
|---|---|---|
| content | Yes | |
| end_line | Yes | |
| file_path | Yes | |
| truncated | No | |
| repository | Yes | |
| start_line | Yes | |
| target_line | Yes | |
| total_lines | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so the description carries the full burden. It discloses output format (target line marked with >, start/end lines, total lines, truncation flag) and constraints (relative paths only). It does not mention error handling or side effects, but the read-only nature is implied. Transparency is good but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with purpose. Every sentence adds value: purpose, usage context, what not to do, output format. No redundant or verbose language. Efficiently structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 5 parameters with 100% schema coverage, an output schema, and no annotations, the description covers the essential aspects: when to use, parameter source, prohibitions, and output details. It could mention error behavior, but overall it is sufficiently complete for effective tool invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by clarifying that parameters should come from search_code hits (file_path is relative, repository is repo name, line_number is from hit's line field) and provides defaults/max for lines_after/before. This connects the schema to the usage context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads source context with line numbers around a code search hit. It uses a specific verb and resource, and distinguishes itself from sibling tool search_code by indicating it should be called after search_code returns hits.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use ('after search_code returns candidate hits'), provides context for what it is suitable for (confirming hit type, understanding control flow), and gives prohibitions (don't search unknown files, don't use absolute paths). This provides complete guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_codeA
在 Zoekt 已索引的仓库中定位源码文本及其文件位置。
当用户询问符号定义或引用、错误信息来源、配置项用法、接口实现或精确 代码模式时使用。结果包含仓库、仓库内相对路径、从 1 开始的行号和命中 行片段;需要理解周围实现时,再用该结果调用 get_file_context。
query 默认按 Zoekt 查询语法解释。搜索包含空格、连字符或查询运算符的 完整错误信息、服务名或包名时设置 literal=true。已知仓库、语言或路径 范围时应使用对应过滤器,以减少无关结果。该工具只做文本/正则检索, 不执行语义分析,也不保证命中就是定义。
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | 可选的语言过滤,例如 java、go 或 python | |
| path | No | 可选的仓库内文件路径正则过滤,例如 src/.*\.py | |
| repo | No | 可选的仓库名正则过滤;已知目标仓库时应尽量设置 | |
| limit | No | 最多返回的代码命中数,默认 20,最大 100 | |
| query | Yes | 要查找的源码文本或 Zoekt 正则表达式,例如类名、函数名、错误信息、配置键或调用表达式 | |
| literal | No | true 表示将 query 作为完整字面量,而非 Zoekt 查询语法;搜索带空格、连字符或运算符的错误信息、服务名、包名时使用 |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | Yes | |
| matches | Yes | |
| duration_ms | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so the description bears full responsibility. It discloses that the tool performs only text/regex search, no semantic analysis, and hits are not guaranteed to be definitions. It does not mention rate limits or auth, but the behavioral limitations are well-covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently structured: starts with purpose, then usage guidance, then parameter tips. Every sentence adds value, and there is no redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 parameters, output schema present, sibling tool), the description covers all necessary aspects: purpose, usage context, parameter behavior, limitations, and post-search workflow. It is fully adequate without ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, baseline 3. Description adds value by explaining default query interpretation, when to use literal=true, and provides examples for lang, path, and repo filters. This goes beyond the schema's bare definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool locates source code text and file locations in Zoekt-indexed repositories. It distinguishes from sibling tool get_file_context by specifying that this tool searches for code patterns, while the sibling handles context after hits are obtained.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides when-to-use scenarios (symbol definitions, error messages, config usage, etc.), when-not-to-use (when understanding surrounding implementation, use get_file_context instead), and guidance on parameter usage (literal flag for special characters, filters for known scopes).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
2 tool updates
v0.1.0- First observed
get_file_context - First observed
search_code
TDQS
The two tools have clear, non-overlapping purposes: search_code finds code locations based on text queries, while get_file_context retrieves surrounding source context for a specific hit. No ambiguity exists.
Both tool names follow a consistent verb_noun pattern (search_code, get_file_context) using snake_case. The naming is predictable and clearly conveys the action and object.
With only 2 tools, the server is minimal but focused on a narrow domain: code search and context retrieval. While some might expect additional filtering or browsing tools, the count is appropriate for a targeted utility.
The server covers the core workflow of searching code and retrieving file context. Minor gaps exist (e.g., no direct language-specific filter, no batch operations), but the surface is sufficient for the stated purpose.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted code graph over MCP: exact callers, dependencies, and cross-repo blast radius for AI agents.
251Search GitHub, npm, PyPI, StackOverflow, ArXiv from one MCP — built for coding agents.
Agent-driven search: build, import, tune, search, and score result quality — all over MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that provides code search capabilities for AI tools and LLMs using Zoekt, allowing for searching across codebases with advanced query syntax and content fetching.22MIT
- AlicenseAqualityCmaintenanceExposes Sourcegraph Zoekt code search to MCP-capable AI agents, enabling fast, indexed regex/symbol-aware code search over repositories.32MIT
- AlicenseNot gradedqualityCmaintenanceProvides two-modal code search (lexical via Zoekt and semantic via ChromaDB embeddings) for AI coding agents through MCP tools, enabling fast regex and meaning-based code lookup.MIT
- AlicenseNot gradedqualityDmaintenanceMCP server exposing Sourcegraph's AI-enhanced code search capabilities to coding agents, enabling advanced code search, repository discovery, and content fetching.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/YamadaYoukai/CodeNavigator'
If you have feedback or need assistance with the MCP directory API, please join our Discord server