claude-context Getting Started
整理日期:2026-04-23 仓库地址:https://github.com/zilliztech/claude-context
项目简介
claude-context 是 Zilliz(Milvus 背后的公司)开源的一个 MCP plugin,给 Claude Code、Cursor、Gemini CLI、Codex、Qwen Code 等 AI coding agent 补上「语义代码搜索」能力——把整个 codebase 向量化塞进 Milvus/Zilliz Cloud,agent 遇到问题时一次性捞出相关代码片段作为上下文。
解决的核心问题是 agent 读代码成本:不走 grep+多轮 discovery、也不把整个目录塞 prompt,而是用 embedding + vector search 直接命中相关 chunk。按官方定位:
Your entire codebase as Claude's context.
典型用法是跑在 npx @zilliz/claude-context-mcp@latest,通过 MCP 向 agent 暴露 4 个 tool:index_codebase、search_code、get_indexing_status、clear_index。
项目结构
monorepo(pnpm workspace),4 个 package + 1 个 python 桥接:
packages/
├── core/ # 核心库 @zilliz/claude-context-core
│ └── src/
│ ├── context.ts # Context 主类(编排 splitter + embedding + vectordb)
│ ├── embedding/ # OpenAI / Gemini / Ollama / VoyageAI 四家 provider
│ ├── vectordb/ # Milvus (gRPC + REST) + Zilliz 工具
│ ├── splitter/ # AST splitter(tree-sitter)+ LangChain fallback
│ └── sync/ # Merkle DAG 增量同步
├── mcp/ # @zilliz/claude-context-mcp(MCP server,stdio)
├── vscode-extension/ # semanticcodesearch VS Code 插件
└── chrome-extension/ # 浏览器插件
python/ # 纯桥接脚本(ts-node 执行),不是独立 SDK最关键的是 packages/core——mcp / vscode-extension / python 都是围绕它的壳。
核心架构
┌─────────────────────┐
│ AI coding agent │ Claude Code / Cursor / Codex / ...
│ (MCP client) │
└──────────┬──────────┘
│ stdio (MCP 协议)
┌──────────▼──────────┐
│ claude-context-mcp │ 4 个 tool:index / search / status / clear
│ server │
└──────────┬──────────┘
│ 调用 Context 类
┌──────────▼──────────────────────────────────────┐
│ @zilliz/claude-context-core │
│ │
│ ① Splitter (AST) — tree-sitter 按 function / │
│ class / interface 边界切 2500 字符 chunk │
│ 不支持的语言 → LangChain splitter fallback │
│ │
│ ② Embedding — OpenAI / Gemini / Ollama / │
│ VoyageAI 任选 │
│ │
│ ③ VectorDB — Milvus / Zilliz Cloud │
│ hybrid search(向量 + BM25) │
│ │
│ ④ FileSynchronizer — Merkle DAG 做增量 │
│ 基于每个文件 SHA256 的 hash 构建 DAG │
│ 只重新 embed 变动 chunk │
└──────────────────────────────────────────────────┘四条流水线互相解耦:你可以换 embedding provider(OpenAI → Ollama 本地模型)、换 vectordb(Milvus 自建 → Zilliz Cloud)、splitter 不支持的语言自动降级。
核心工作流程
1. 索引(index_codebase)
官方文档把它定位成「asynchronous indexing」:
- Agent 调
index_codebase(path),MCP server 立刻返回{status: "indexing", progress: 0} - 后台启动索引:
FileSynchronizer遍历目录,按DEFAULT_SUPPORTED_EXTENSIONS+.gitignore风格ignorePatterns筛文件- 每个文件算 SHA256 挂到
MerkleDAG上,snapshot 落盘到~/.context/merkle/<md5(absolute path)>.json - 每个文件过
AstCodeSplitter:tree-sitter 解析 AST,按SPLITTABLE_NODE_TYPES[lang](function / class / interface / method 等)切 chunk,默认chunkSize=2500、chunkOverlap=300 - 批量调 embedding provider 算向量
- 写入 Milvus collection(名字来自 absolute path 的规范化 hash)
- Agent 可以随时查
get_indexing_status拿进度;索引中也可search_code拿部分结果
进度是阶段性的:0% 准备 collection → 5% 扫文件 → 10-100% chunk + embed + 写库。大库会在 10% 停很久再快速推到 100%,这是正常的。
2. 搜索(search_code)
agent → search_code(path, query, limit=10)
→ Context 拿 query embedding
→ Milvus hybrid search(vector similarity + BM25 keyword)
→ 返回 top N chunk,每条带:
- 代码内容
- 文件路径 + 起止行号
- 相似度分数Hybrid search 里 BM25 分量是为了召回那些 embedding 模型容易丢掉的精确关键词(变量名、错误字符串、API 名)。
3. 增量同步(Merkle DAG)
这个是 claude-context 比「普通 RAG」讲究的地方:
- 每次索引/搜索前,
FileSynchronizer.checkForChanges()重新遍历目录生成新 DAG MerkleDAG.compare(oldDAG, newDAG)拿到{added, removed}集合- 只对差集做:
- 新增文件 → split + embed + insert
- 删除文件 → 按 filePath 从 collection 删
- 修改文件 → 先按 filePath 删旧 chunk,再 split + embed + insert 新 chunk
大仓库第一次索引慢,但之后每次都只处理变动文件,不会整库重算。
4. Codebase 身份识别
Collection 是按 resolved absolute path 区分的。同一仓库从不同路径(symlink / 不同 clone / mount)访问会被当成两个 codebase,各自独立索引。这个设计简单粗暴但可预测——dive-deep 文档专门强调:index_codebase / search_code / clear_index / get_indexing_status 都用同一个绝对路径,不然拿不到正确结果。
部署步骤
环境要求
- Node.js ≥ 20.0.0 且 < 24.0.0(README 明确写了,Node 24 不兼容)
- pnpm ≥ 10
- 一个 Milvus 实例:Zilliz Cloud free tier 最省事,或自建 Milvus
localhost:19530 - 一个 embedding provider 的 key:OpenAI / Gemini / VoyageAI 或本地 Ollama
最快的玩法(给 Claude Code 加能力)
claude mcp add claude-context \
-e OPENAI_API_KEY=sk-your-openai-api-key \
-e MILVUS_ADDRESS=your-zilliz-cloud-public-endpoint \
-e MILVUS_TOKEN=your-zilliz-cloud-api-key \
-- npx @zilliz/claude-context-mcp@latest然后在 Claude Code 里一句「index this codebase」,后台就开始跑了。
本地开发构建(我本次用的方式)
本次我只做了 core package 的本地构建 + 一个不需要外部依赖的 demo,没拉起完整 MCP server:
# dev-server 上
cd /data/projects/chaosreload/study/repo/public/claude-context
nvm use 22.22.0
pnpm install
pnpm approve-builds --all # tree-sitter-* 需要 native build
pnpm rebuild # 编译 tree-sitter 原生模块
pnpm build:core # 编译 @zilliz/claude-context-core踩坑 1:dev-server 默认是 Node 24.14.0,直接跑会在 tree-sitter native addon 加载时报错。nvm use 22.22.0 切过去就好。
踩坑 2:pnpm 10 默认不跑 postinstall 脚本(出于安全考虑),需要显式 pnpm approve-builds --all + pnpm rebuild,否则 tree-sitter 的 .node 二进制不会被构建,splitter 一调就崩。
踩坑 3:完整体验需要 Milvus 实例。Zilliz Cloud free tier 最省,但生产/评测时要注意 embedding 成本——OpenAI text-embedding-3-small 对中等 codebase(~10 万 chunk)一次全量索引也就几块钱量级,但大仓库(monorepo、million LoC)要小心 rate limit 和预算。
Demo 示例
跳过「要 OpenAI key + Milvus」的完整路径,我做了一个纯本地 demo,直接跑 core 里最独立的一个组件——AstCodeSplitter,展示「代码怎么被切块」这一步:
demo-splitter.mjs:喂 Python / TypeScript / Ruby 三段代码,看 splitter 产出什么。
关键代码:
import { AstCodeSplitter } from '@zilliz/claude-context-core';
const splitter = new AstCodeSplitter(2500, 300);
const pyChunks = await splitter.split(pythonSource, 'python', 'sample.py');
// chunkSize=2500 chars, chunkOverlap=300 chars实际运行结果
=== Python 示例 ===
🌳 Using AST splitter for python file: sample.py
分出 6 个 chunk
--- chunk[0] lines 5-20 (440 chars) --- # class TaskQueue 整体
--- chunk[1] lines 1-9 (409 chars) --- # __init__ + push
--- chunk[2] lines 8-15 (265 chars) --- # __init__ + push 片段(overlap)
--- chunk[3] lines 12-20 (269 chars) --- # push + pop
--- chunk[4] lines 18-25 (263 chars) --- # pop + async process_task
--- chunk[5] lines 23-35 (312 chars) --- # process_task + main
=== TypeScript 示例 ===
🌳 Using AST splitter for typescript file: sample.ts
分出 8 个 chunk (interface User / class UserRepo / fetchUser / type UserId)
=== 不支持的语言会 fallback 到 LangChainCodeSplitter ===
📝 Language ruby not supported by AST, using LangChain splitter for: sample.rb
Ruby fallback 分出 1 个 chunk有几个细节从输出里能看出来:
- Chunk 边界卡 AST 节点,不是简单按行切。Python 里一个
class TaskQueue { ... }作为独立 chunk(chunk[0]);TS 里interface User、class UserRepo、顶层fetchUser、type UserId都各自成块。 - chunkOverlap=300 真的有效。chunk[1] 末尾
self.tasks.append(task)和 chunk[2] 开头的__init__段是重叠的——这样搜索时跨边界的语义不会断裂。 - 不支持的语言 silently fallback,不是硬报错。AST splitter 识别 js/ts/py/java/cpp/go/rust/csharp/scala 共 9 种,剩下的(ruby/php/swift/kotlin/...)走 LangChain 的
RecursiveCharacterTextSplitter按字符递归切。
完整输出在 dev-server:/data/projects/chaosreload/study/demo/claude-context/demo-output.txt。
关键发现 / 学习心得
1. 把「代码 RAG」的工程细节都摊开写清楚了。 相比很多 vibe-based「给 agent 接个 vector search 就行了」的项目,claude-context 在几个具体问题上有明确的决策:
- 切块走 AST 而不是按行/字符,保证 chunk 是语义完整单元
- 增量用 Merkle DAG,不用 git diff(因为有些场景没 git,或者用户改了没提交)
- 召回用 hybrid search(向量 + BM25),关键词类 query 不会被 dense embedding 吃掉
- 路径按 absolute path 作为 codebase 身份,牺牲灵活性换可预测
2. Node 版本 < 24 是强约束,不是「建议」。 README 专门写了一行。原因是 tree-sitter 的 native binding 在 Node 24 上有兼容问题。任何人部署这类 native-module 密集型 MCP server,都该提前锁 Node 版本。
3. Snapshot 0/0 是坑。 我在 handlers.ts 里看到一段 Issue #295 相关的长注释:老版本 MCP 在 snapshot 里写过 { indexedFiles: 0, totalChunks: 0, status: 'completed' },客户端会把 0/0 当「没索引」,触发 force reindex,又把 0/0 写回去——无限循环。现在的版本有 validateLegacyZeroEntries() 启动时专门扫这种幽灵 entry,要么从 Milvus 实际行数里修复、要么删掉。
这个 issue 本身不算大 bug,但暴露了本地 snapshot ↔ 远端向量库的状态同步是这类产品最难做对的地方。可以单独写一篇 post-mortem。
4. Python SDK 其实是「TS 桥接器」。 python/README.md 写得很直白:"不是完整 SDK,只是一个简单的 bridge for testing purposes"。真要用 Python 原生调 Milvus 做 codebase RAG,claude-context 不是你要找的项目——这本质是一个 Node/TS 生态里的产品。
5. 和 GitNexus / aider 那种 AST 索引 + 调用图的路线不同。 claude-context 只做 embedding search,不建 call graph / symbol graph。好处是简单、语言无关、对 LLM 召回友好;坏处是回答「这个函数谁调用了」这种结构性问题没 GitNexus 那么直接。两个路线各有定位,可以互补。
参考资源
- 官方文档(dive-deep):
- DeepWiki AI 文档:https://deepwiki.com/zilliztech/claude-context
- npm 包:@zilliz/claude-context-core · @zilliz/claude-context-mcp
- VS Code 插件:semanticcodesearch
- Zilliz Cloud(最简部署的 Milvus):https://cloud.zilliz.com/
- 关键 issue:#295 — 0/0 snapshot 自我毁灭