使用 Weaviate MCP 構建編碼助手:對代碼與文檔進行 RAG 檢索
本文介紹如何利用 Weaviate 內置的 MCP 服務器為編碼助手(如 Claude Code、Cursor 和 VS Code)提供混合搜索能力,無需額外編寫膠水代碼。通過將代碼庫與文檔分塊並索引到 Weaviate,結合 BM25 精確匹配與向量語義檢索,LLM 智能代理可以高效獲取所需上下文,避免上下文過載與成本浪費。
上週,我讓 Claude Code 在我的代碼庫中實現一個相對簡單的功能。三輪對話後,上下文消耗超過 80K token,但 Claude 仍然缺少一些我忘記包含的關鍵信息。沒有檢索機制,你就會陷入這樣的循環:粘貼太少,代理靠猜測;粘貼太多,又要為代理未使用的上下文付費。
大多數團隊通過 RAG 對代碼庫進行檢索來解決這個問題。典型的方案是採用向量數據庫加上一個自定義的 MCP 服務器作為橋樑。Weaviate 簡化了這一過程:MCP 服務器內建於數據庫之中,位於與 REST API 同一端口的 /v1/mcp。僅需一個環境變量即可啓用。你可能已經在 Weaviate 中使用的混合檢索同樣適用於代碼檢索,其中 BM25 部分可以匹配像 connect_to_local 這樣的函數標識符,而向量部分則能發現語義意圖,例如“如何初始化客户端”。
本文將指導你基於這一內建 MCP 服務器構建編碼助手:包括如何攝取代碼庫、攝取文檔、連接 Claude Code、Cursor 和 VS Code,並運行真實的查詢。覆蓋以下主題:
- 為什麼你的編碼助手需要超越訓練數據
- 為什麼 Weaviate MCP 適合這項工作
- 第一步:運行帶 MCP 的 Weaviate
- 第二步:設計模式
- 第三步:代碼庫的分塊與攝取
- 第四步:文檔的分塊與攝取
- 第五步:連接 Claude Code、Cursor 和 VS Code
- 嘗試運行
- 代理運行手冊:自動設置
為什麼編碼助手需要超越訓練數據
LLM 具有固定的知識截止期,且對私有代碼一無所知。簡單的解決方法是直接把文件丟進提示詞中。但這帶來三個問題:
- 成本:上下文中的 token 按輪次計費。一個 200 個文件的 Python 項目無法完全放入提示詞,即使部分放入,在代理推理過程中也會持續計費。
- 過時的上下文:一旦文件進入提示詞,它就被凍結了。如果代理修改了一個函數後又需要重新讀取,它必須重新加載整個文件。模型所見的視圖與磁盤上的真實情況之間沒有實時鏈接。
- 不恰當的粒度:即使文件能放入提示詞,模型的注意力也會浪費在無關的部分——導入、模塊級樣板代碼等。代理正在編輯的函數與上百行
from x import y爭奪上下文。
檢索解決了這三個問題。只需一次索引代碼庫,將分塊存入向量數據庫,讓 LLM 客户端按需拉取所需內容。這就是 RAG。編碼助手此前缺乏一種乾淨的方式與這類數據庫通信,無需自定義適配層。這就是 MCP 發揮作用的地方。
為什麼 Weaviate MCP 適合這項工作
模型上下文協議(MCP)是 Claude Code、Cursor 和 VS Code 等 LLM 客户端調用外部工具的標準方式。Weaviate v1.37.1 將其核心操作作為 MCP 工具暴露在 Streamable HTTP 端點 /v1/mcp 上。共提供四個工具:
weaviate-collections-get-config:讓 LLM 檢查可用的集合及其屬性weaviate-tenants-list:在使用多租户時列出租户weaviate-query-hybrid:運行混合(BM25+向量)搜索weaviate-objects-upsert:僅在啓用寫權限時寫入對象
混合搜索是該方案對編碼助手最具體的好處。代碼是標識符與意圖的混合體。BM25 精確匹配標識符,向量捕獲意圖。像“我們在哪裏處理 429 重試?”這樣的查詢需要兩者同時作用:向量找到語義相關的重試代碼,BM25 將 429 作為精確詞條錨定。純向量檢索會丟失整數匹配,純 BM25 會遺漏用户未提及的措辭。混合搜索在這種混合意圖查詢中勝出。
操作簡便性是第二個原因。其他方案需要運行一個 MCP 服務器外加向量數據庫,相當於在生產中監視兩個服務。Weaviate 將 MCP 服務器放在數據庫內部,同端口、同認證體系,你只需要監控 Weaviate 本身。
第三個原因是多租户。一個 Weaviate 實例可以承載多個代碼庫,每個庫作為獨立的租户隔離。對於擁有多個倉庫的組織,一個集羣即可,無需為每個團隊單獨部署。
關於 Weaviate MCP 與函數調用(function calling)的區別:函數調用是針對具體 LLM API 的,而 MCP 是傳輸層協議——任何支持 MCP 的客户端都可以調用任何支持 MCP 的服務器,無需重寫。構建一次檢索,即可在 Claude Code、Cursor 和 VS Code 中使用,無需轉換。
第一步:運行帶 MCP 的 Weaviate
MCP 服務器默認禁用。兩個環境變量可啓用:
services:
weaviate:
image: cr.weaviate.io/semitechnologies/weaviate:1.37.1
ports:
- '8080:8080'
- '50051:50051'
environment:
MCP_SERVER_ENABLED: 'true'
MCP_SERVER_WRITE_ACCESS_ENABLED: 'true'
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true'
DEFAULT_VECTORIZER_MODULE: 'text2vec-openai'
ENABLE_MODULES: 'text2vec-openai'
OPENAI_APIKEY: ${OPENAI_APIKEY}MCP_SERVER_ENABLED 暴露只讀工具(集合查詢、租户列表、混合查詢)。MCP_SERVER_WRITE_ACCESS_ENABLED 添加 upsert 工具,允許代理寫回結果。如果只需要檢索,可以跳過寫權限。建議先只開啓只讀模式,因為大多數編碼代理的工作都只涉及檢索,而且可以避免代理向知識庫寫入無意義內容的風險。
生產環境認證
本例使用匿名訪問以保持聚焦於 MCP 配置。對於任何網絡部署,應啓用 API 密鑰並在客户端配置中添加 Authorization: Bearer——Weaviate 的 MCP 服務器支持標準認證和 RBAC。
啓動後,可通過 curl 發送 initialize 握手確認端點是否存活:
docker compose up -d
curl -sf -X POST http://localhost:8080/v1/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'如果 MCP 服務器存活,會返回一個包含服務器能力的 JSON-RPC 響應並設置 Mcp-Session-Id 頭。
第二步:設計模式
創建兩個集合:CodeChunks 和 DocChunks,共享同一個 Weaviate 實例。
client.collections.create(
name="CodeChunks",
properties=[
Property(name="content", data_type=DataType.TEXT, tokenization=Tokenization.WORD),
Property(name="symbol", data_type=DataType.TEXT, tokenization=Tokenization.LOWERCASE),
Property(name="file_path", data_type=DataType.TEXT, tokenization=Tokenization.FIELD),
Property(name="language", data_type=DataType.TEXT, tokenization=Tokenization.FIELD),
Property(name="repo", data_type=DataType.TEXT, tokenization=Tokenization.FIELD),
],
vector_config=Configure.Vectors.text2vec_openai(),
)symbol 使用小寫分詞,使 connect_to_local 作為一個 token 而非三個;file_path、language、repo 使用 FIELD 實現精確匹配;content 和 title 使用 WORD。
第三步:代碼庫的分塊與攝取
基於行的樸素分塊會破壞代碼結構。應採用語法邊界分塊:每個函數、每個類、每個頂級語句一個塊。Python 標準庫 ast 即可勝任 Python 代碼的分塊:
import ast
from pathlib import Path
def chunk_python_file(path: Path) -> list[dict]:
source = path.read_text()
tree = ast.parse(source)
lines = source.splitlines()
chunks = []
for node in ast.iter_child_nodes(tree):
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
start = node.lineno - 1
end = node.end_lineno
chunks.append({
"content": "\n".join(lines[start:end]),
"symbol": node.name,
"file_path": str(path),
"language": "python",
"repo": "my-service",
})
return chunks然後使用 Weaviate 的批量寫入模式:
with code_chunks.batch.dynamic() as batch:
for py_file in Path("./").rglob("*.py"):
for chunk in chunk_python_file(py_file):
batch.add_object(properties=chunk)每個分塊在插入時由 text2vec-openai 自動向量化。也可以替換為 text2vec-voyageai 或 text2vec-cohere。
第四步:文檔的分塊與攝取 文檔分塊應以標題為邊界。推薦按 H2 分割,若某節過長再按 H3 細分:
import re
def chunk_markdown(text: str, max_chars: int = 1500) -> list[str]:
sections = re.split(r"(?m)^## ", text)
chunks = []
for section in sections:
if len(section) < max_chars:
chunks.append(section.strip())
else:
subsections = re.split(r"(?m)^### ", section)
for sub in subsections:
if sub.strip():
chunks.append(sub.strip()[:max_chars])
return chunks每個塊同時保留 title 和 source_url 屬性。
第五步:連接 Claude Code、Cursor 和 VS Code
- Claude Code 原生支持 MCP:在
~/.claude/settings.json中添加配置指向 Weaviate 端點,混合搜索工具自動可用。 - Curs 通過
.cursor/mcp.json配置:原理類似,只需指定 URL 和工具列表。 - VS Code 需安裝 MCP 擴展後配置
mcp.json。
代理運行手冊:自動設置
提供一個 shell 腳本 setup.sh,包含以下步驟:檢查環境變量、拉取 Docker 鏡像、啓動 Weaviate、等待就緒、驗證 MCP 端點,然後運行 ingest.py 攝取數據。腳本具有冪等性,可重複執行。
總之,Weaviate MCP 為編碼助手提供了一條極簡的路徑來實現高效的混合檢索。通過將 MCP 服務器內建在數據庫內,該方案消除了額外的運維負擔,同時提供了強大的多租户支持和開箱即用的混合搜索能力。無論是個人項目還是團隊協作,都可以快速上手,讓 LLM 代理真正理解私有代碼庫。