Semantic code search MCP server: Tree-sitter AST chunking + voyage-code-3 embeddings + hybrid retrieval (sqlite-vec + FTS5 + RRF) + Voyage rerank-2.5 + call graph expansion
Project description
semantic-code-mcp
自建代码语义检索 MCP Server —— 自然语言查询 → 相关代码片段。
「效果优先」技术栈:Tree-sitter AST 切分 + voyage-code-3 embedding(int8 量化)+ sqlite-vec 向量库 + BM25 全文 + RRF 融合 + Voyage rerank-2.5 重排 + Call Graph 图扩展。一个 VOYAGE_API_KEY 跑通 embedding + rerank 全链路。
工程特性:watchdog 文件实时监控 + 多工作区 LRU 管理 + MCP progress notification + cancel signal。
架构
codebase_search(query, dir)
│
▼
WorkspaceManager ── LRU(max 8) ── FileWatcher(watchdog + 2s debounce)
│
▼
Indexer ── 全量扫描/watcher增量(O(变更数)) ── Chunker(Tree-sitter AST) ── Embedder(voyage-code-3)
│ │
│ Store(sqlite-vec + FTS5 + 文件hash)
▼
Retriever ── 向量召回 + BM25召回 ── RRF融合 ── rerank(Voyage/Cohere)── Call Graph扩展 ── top_n 代码片段
│
▼
MCP Server ── async tools + progress notification + cancel signal
| 模块 | 职责 |
|---|---|
chunker.py |
Tree-sitter 按函数/类切分(16 语言 + md/yaml/json 等文档配置按行切),提取调用关系构建 call graph |
store.py |
sqlite-vec 向量(float/int8)+ FTS5 全文 + 文件指纹 + call graph 边表 |
embedder.py |
voyage-code-3,document/query 双模式,int8 量化,限流重试 |
retriever.py |
向量 + BM25 → RRF → rerank → 意图感知打分(测试/文档/调用链意图)→ 文件多样性截断 → 图扩展 |
indexer.py |
目录扫描 + 文件 hash 增量同步 + watcher dirty 增量同步 |
watcher.py |
watchdog 文件监控 + 2s debounce + 50 变更立即 flush |
workspace.py |
多工作区 LRU 管理器(创建/淘汰/状态追踪) |
server.py |
MCP 封装,async 工具 + progress + cancel + WorkspaceManager |
安装
发布包名为 semcode-mcp(PyPI 上 semantic-code-mcp 已被同名项目占用):
# 方式一(推荐):uv 环境零安装,MCP 客户端配置里直接 uvx 启动
uvx semcode-mcp
# 方式二:npx(要求已装 uv,该 npm 包是透传 uvx 的薄壳)
npx -y semcode-mcp
# 方式三:pip
pip install semcode-mcp
# 源码开发
pip install -e .
配置
复制 .env.example 为 .env 并填入 key:
| 变量 | 必需 | 说明 |
|---|---|---|
VOYAGE_API_KEY |
是 | Voyage embedding + rerank(同一个 key 双用),申请:https://dash.voyageai.com/ |
COHERE_API_KEY |
否 | 可选 rerank 后备后端;默认用 Voyage rerank-2.5,无需此 key |
高级配置
| 变量 | 默认值 | 说明 |
|---|---|---|
SCM_EMBED_MODEL |
voyage-code-3 |
Embedding 模型 |
SCM_EMBED_DTYPE |
float |
向量精度:float(最高精度)/ int8(省 71% 存储) |
SCM_EMBED_MAX_RETRIES |
4 |
API 限流/错误时自动重试次数 |
SCM_EMBED_MIN_INTERVAL |
0 |
请求最小间隔秒数(未绑卡 3 RPM 限制时设 21) |
SCM_EMBED_CONCURRENCY |
voyage 3 / local 1 |
索引时 embedding 并发请求数(实测 3 路≈提速 3 倍) |
SCM_EMBED_CHAR_BUDGET |
200000 |
单批最大字符数(未绑卡时可调小) |
SCM_RERANK_BACKEND |
auto |
rerank 后端:auto(有 VOYAGE key 用 Voyage,其次 Cohere)/ voyage / cohere / off |
SCM_RERANK_MODEL |
按后端 | voyage → rerank-2.5,cohere → rerank-v3.5 |
SCM_DB_DIR |
~/.semantic-code-mcp |
索引数据库存放目录 |
SCM_TOP_K |
50 |
向量召回候选数 |
SCM_TOP_N |
10 |
最终返回结果数 |
HTTPS_PROXY |
— | Cohere API 代理(国内需配) |
SCM_MAX_WORKSPACES |
8 |
最大同时管理的工作区数(LRU 淘汰) |
SCM_WATCH |
1 |
文件监控:1 启用(默认),0 禁用 |
在 MCP 客户端注册
{
"mcpServers": {
"semantic-code": {
"command": "uvx",
"args": ["semcode-mcp"],
"env": {
"VOYAGE_API_KEY": "your-voyage-key"
}
}
}
}
npx 用法把 command/args 换成 "npx", ["-y", "semcode-mcp"];
源码开发用 pip install -e . 后配 "semcode-mcp", [](包采用相对 import,
不支持 python server.py 直接跑,需用 console script 或 python -m semantic_code_mcp.server)。
工具
codebase_search
| 参数 | 类型 | 说明 |
|---|---|---|
information_request |
string | 自然语言查询,如"用户登录鉴权逻辑在哪里" |
directory_path |
string | 代码库绝对路径 |
唯一工具,首次调用自动全量索引,之后 watcher 驱动增量同步(O(变更数),极速)。支持 MCP progress notification 实时回报索引进度。需要强制重建索引时删除 ~/.semantic-code-mcp/ 下对应 .db 文件即可。
工作原理
- 切分:Tree-sitter 解析 AST,按函数/类边界切块,保留
file_path / symbol / 行号元数据。 - 向量化:voyage-code-3 对代码块生成 1024 维向量(
input_type=document)。 - 存储:向量入 sqlite-vec(vec0 虚拟表),同时入 FTS5 全文索引;
blob_hash = SHA256(path+code)实现内容寻址去重。 - 检索:查询同时走向量 KNN 与 BM25,用 RRF 融合排名,再用 rerank(默认 Voyage rerank-2.5)精排出 top_n。
- 图扩展:主结果沿 call graph 扩展 1 跳,把调用者/被调用者连带召回(附
relation标记)。 - 实时监控:watchdog 监控文件变更(2s debounce),后台主动增量同步(O(变更数)),查询时零等待;后台失败不丢变更,下次查询前兜底。
- LRU 管理:多工作区并发(最多 8 个),超限自动淘汰最久未用的 workspace。
索引存储
每个工作区按目录路径哈希存为 ~/.semantic-code-mcp/<hash>.db(可用 SCM_DB_DIR 改)。删除该目录即清空所有索引。
隐私与数据边界
本工具的完整数据流向,用于评估能否用于敏感/闭源仓库:
会出网的数据(默认配置)
| 接收方 | 发送内容 | 时机 |
|---|---|---|
| Voyage AI | 代码块全文(embedding + rerank 候选)+ 查询文本 | 索引时 + 每次检索 |
| Cohere(可选后端) | 查询文本 + top-50 候选代码块全文 | 仅 SCM_RERANK_BACKEND=cohere 时;默认零发送 |
| 自配 LLM 端点(可选,默认关) | 仅查询文本(不含代码) | SCM_QUERY_EXPANSION=on 时 |
供应商对 API 数据的保留/训练策略请以其当前条款为准自行评估(Voyage/Cohere 均声明 API 数据默认不用于训练,本项目不替其背书)。
始终留在本地的
- 索引库全部落盘本机
~/.semantic-code-mcp/(向量 + 代码原文 + call graph),不上传任何服务 - 无遥测、无统计上报,除上表 API 外零网络请求
索引范围控制
- 全层级遵守
.gitignore(含否定模式):.env、构建产物等被忽略的文件不会进索引 - 例外:
AGENTS.md/.windsurfrules等 agent 指导文件即使被 gitignore 也会索引(有意设计,它们对检索架构问题价值极高) - ⚠️ 硬编码在代码里的密钥会随代码块发往上表供应商,敏感仓库索引前请先清理或用全本地模式
全本地模式(代码零出网)
pip install sentence-transformers
SCM_EMBED_BACKEND=local # 本地 embedding(默认 Qwen/Qwen3-Embedding-0.6B)
# 不配 COHERE_API_KEY # rerank 自动跳过,用 RRF 融合排序
检索质量会下降(参考公开评测中自托管 0.6B 方案的差距),但数据完全不离开本机。
路线
- 阶段 1 ✅:Tree-sitter + voyage-code-3 + hybrid + rerank —— 第一梯队 RAG
- 阶段 2 ✅:Call Graph 图扩展(caller/callee 连带召回)+ int8 量化向量(存储省 71%,一致率 95%)
- 阶段 3 ✅:工程化 —— watchdog 文件监控 + 多工作区 LRU + progress + cancel
- 阶段 4 ✅(部分):意图感知排序(调用链直查 edges / 测试意图 / 文档意图)+ 文档配置索引(AGENTS.md 豁免 gitignore)+ 50 条分类评测集
- 阶段 5 ✅:单工具化 + 后台主动增量同步 + 分阶段进度条日志 + Java 调用链(接收者边/构造类型名/泛型剥离)+ 配置意图(yaml 反转 boost)
- 并发 embedding 流水线(worker 只跑网络调用,sqlite 写回留在调用线程,顺序写回;CLIProxyAPI 9067 块全量 77s,≈串行 3 倍)
- HyDE 已评测,结论默认关:Top-1 86%→82%、延迟 2.9s→10.4s、Recall@5 98%→100%;架构类 +40 分但配置/SDK 类 -40(变体稀释精确标识符信号)。 改进线:选择性扩展——仅对不含精确标识符的模糊查询开 HyDE
- 后续候选:选择性 HyDE、本地后端对照评测、超大仓库 ANN 索引
评测(eval_golden.py,CLIProxyAPI 778 文件 / 9067 块)
50 条 query × 10 类(符号定位/调用链/架构职责/配置schema/同名干扰/SDK边界/协议契约/测试/中文/细节), 机械化打分可复现(期望文件 + must_contain 关键字):
| 指标 | Voyage rerank-2.5(默认) | Cohere v3.5 基线 | 参考(自托管 0.6B 方案公开数据) |
|---|---|---|---|
| Top-1 精确命中 | 88% | 84% | 32% |
| Recall@5 | 98% | 100% | 54% |
| 答案可用性 | 100% | 100% | 80% |
| MRR | 0.916 | 0.897 | — |
| 平均延迟 | 0.96s | 6.2s(试用 key 节流) | — |
附加 K 类私有业务仓库探针(不计入主总分):在真实业务仓库上验证复合意图拆分/
子查询分数混合/保底、trigram 中文召回、实现意图降权、expand_graph=True 全链路。
探针定义在 gitignore 的 eval_local_probes.py(PROBE_TARGET + PROBE_GOLDEN,
写法见 eval_golden.py 的 K 类加载段),不存在自动跳过(--skip-java 显式跳过)——
你可以对自己的仓库建一组同格式探针作为私有回归安全网。
复测:python eval_golden.py --json;回归测试:python test_fixes.py
模型选型说明
- embedding 为什么是 voyage-code-3 而非 Voyage 4 系列:4 系列(2026-01)是通用文本模型,
没有 voyage-code-4;官方文档代码检索场景仍推荐 code-3。想试通用旗舰可
SCM_EMBED_MODEL=voyage-4-large(需重建索引),与 code-3 的对比评测列入后续。 - rerank 为什么默认 Voyage:与 embedding 同一个 key 零额外配置;rerank-2.5 公开基准 优于 Cohere v3.5(官方数据 +7.94%,本项目评测 Top-1 +4);免费额度 200M token 且无 试用 key 10 次/分钟限速(评测提速 6.5×)。Cohere 保留为可选后端。
工程边界(已知成本)
- rerank 限速:未绑卡/试用 key 限速低(Cohere 试用 10 次/分钟)。密集调用设
SCM_RERANK_MIN_INTERVAL节流;429 自动退避重试兜底。 - 复合 query 额外延迟:中文双动作查询("生成…并清理…")每个子查询多发一次 rerank(+200~400ms/次,最多 2 次)。仅复合措辞触发,普通查询零开销。
- 阈值标定范围:子查询分数门槛 0.2、两段拆分等参数按 Cohere 分数分布在中文
Java 仓库 + Go 仓库双评测集上标定;切换 rerank 后端(分数分布不同)或其它语言/
仓库表现异常时,优先复核
_COMPOUND_SUB_MIN_SCORE。
性能数据(42 块 / 9 文件)
| 指标 | float32 | int8 |
|---|---|---|
| 索引耗时 | 2.9s | 2.4s |
| DB 大小 | 4328 KB | 1252 KB(节省 71%) |
| 检索延迟 | 0.3–0.8s | 0.3–0.8s |
| Top5 一致率 | — | 95%(19/20) |
| Rerank 排序 | score 0.1–0.7 | — |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file semcode_mcp-0.1.1.tar.gz.
File metadata
- Download URL: semcode_mcp-0.1.1.tar.gz
- Upload date:
- Size: 49.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec8f7ba104c1a270b9e92aa55fb8680b95bca3f860bcdff5a64cb6769bd245c3
|
|
| MD5 |
8fcb75f599012fdc38261cfc0c83aaf3
|
|
| BLAKE2b-256 |
ab75fcb39058bbf8122956b9bd8eca5c6aec9c10091f5e13472d2cce8bbc18cb
|
Provenance
The following attestation bundles were made for semcode_mcp-0.1.1.tar.gz:
Publisher:
release.yml on huawang1258/semantic-code-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
semcode_mcp-0.1.1.tar.gz -
Subject digest:
ec8f7ba104c1a270b9e92aa55fb8680b95bca3f860bcdff5a64cb6769bd245c3 - Sigstore transparency entry: 2205202325
- Sigstore integration time:
-
Permalink:
huawang1258/semantic-code-mcp@d9303e620a6f09cb5d14a6da54655c2b9eee3214 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/huawang1258
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d9303e620a6f09cb5d14a6da54655c2b9eee3214 -
Trigger Event:
push
-
Statement type:
File details
Details for the file semcode_mcp-0.1.1-py3-none-any.whl.
File metadata
- Download URL: semcode_mcp-0.1.1-py3-none-any.whl
- Upload date:
- Size: 54.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8dccd142101bca5ab2f3637cfdd16abd00b95d72e987a6129bb47cfe5cb65fa
|
|
| MD5 |
855b5fbf10eabfcfd8f2c5729acef247
|
|
| BLAKE2b-256 |
555ef02d12910ef56cb58050f6258ffdaace9c5b880c90a87203755597927bdf
|
Provenance
The following attestation bundles were made for semcode_mcp-0.1.1-py3-none-any.whl:
Publisher:
release.yml on huawang1258/semantic-code-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
semcode_mcp-0.1.1-py3-none-any.whl -
Subject digest:
b8dccd142101bca5ab2f3637cfdd16abd00b95d72e987a6129bb47cfe5cb65fa - Sigstore transparency entry: 2205202360
- Sigstore integration time:
-
Permalink:
huawang1258/semantic-code-mcp@d9303e620a6f09cb5d14a6da54655c2b9eee3214 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/huawang1258
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d9303e620a6f09cb5d14a6da54655c2b9eee3214 -
Trigger Event:
push
-
Statement type: