Metadata-Version: 2.4
Name: semcode-mcp
Version: 0.1.1
Summary: 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-URL: Homepage, https://github.com/huawang1258/semantic-code-mcp
Project-URL: Repository, https://github.com/huawang1258/semantic-code-mcp
Project-URL: Issues, https://github.com/huawang1258/semantic-code-mcp/issues
Author: huawang1258
License-Expression: MIT
License-File: LICENSE
Keywords: code-search,embeddings,mcp,rag,semantic-search,tree-sitter
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Indexing
Requires-Python: >=3.10
Requires-Dist: cohere>=5.13.0
Requires-Dist: mcp>=1.2.0
Requires-Dist: numpy>=1.26.0
Requires-Dist: pathspec>=0.12.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: requests>=2.31.0
Requires-Dist: sqlite-vec>=0.1.6
Requires-Dist: tree-sitter-bash>=0.23.0
Requires-Dist: tree-sitter-c-sharp>=0.23.0
Requires-Dist: tree-sitter-c>=0.23.0
Requires-Dist: tree-sitter-cpp>=0.23.0
Requires-Dist: tree-sitter-go>=0.23.0
Requires-Dist: tree-sitter-java>=0.23.0
Requires-Dist: tree-sitter-javascript>=0.23.0
Requires-Dist: tree-sitter-php>=0.23.0
Requires-Dist: tree-sitter-python>=0.23.0
Requires-Dist: tree-sitter-ruby>=0.23.0
Requires-Dist: tree-sitter-rust>=0.23.0
Requires-Dist: tree-sitter-typescript>=0.23.0
Requires-Dist: tree-sitter>=0.23.0
Requires-Dist: voyageai>=0.3.0
Requires-Dist: watchdog>=4.0.0
Provides-Extra: local
Requires-Dist: sentence-transformers>=3.0.0; extra == 'local'
Description-Content-Type: text/markdown

# 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` 已被同名项目占用）：

```bash
# 方式一（推荐）：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 客户端注册

```json
{
  "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` 文件即可。

## 工作原理

1. **切分**：Tree-sitter 解析 AST，按函数/类边界切块，保留 `file_path / symbol / 行号` 元数据。
2. **向量化**：voyage-code-3 对代码块生成 1024 维向量（`input_type=document`）。
3. **存储**：向量入 sqlite-vec（vec0 虚拟表），同时入 FTS5 全文索引；`blob_hash = SHA256(path+code)` 实现内容寻址去重。
4. **检索**：查询同时走向量 KNN 与 BM25，用 RRF 融合排名，再用 rerank（默认 Voyage rerank-2.5）精排出 top_n。
5. **图扩展**：主结果沿 call graph 扩展 1 跳，把调用者/被调用者连带召回（附 `relation` 标记）。
6. **实时监控**：watchdog 监控文件变更（2s debounce），**后台主动增量同步**（O(变更数)），查询时零等待；后台失败不丢变更，下次查询前兜底。
7. **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 也会索引（有意设计，它们对检索架构问题价值极高）
- ⚠️ **硬编码在代码里的密钥会随代码块发往上表供应商**，敏感仓库索引前请先清理或用全本地模式

### 全本地模式（代码零出网）

```bash
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 | — |
