AI News HubLIVE
站內改寫4 分鐘閱讀

使用 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 具有固定的知識截止期,且對私有代碼一無所知。簡單的解決方法是直接把文件丟進提示詞中。但這帶來三個問題:

  1. 成本:上下文中的 token 按輪次計費。一個 200 個文件的 Python 項目無法完全放入提示詞,即使部分放入,在代理推理過程中也會持續計費。
  2. 過時的上下文:一旦文件進入提示詞,它就被凍結了。如果代理修改了一個函數後又需要重新讀取,它必須重新加載整個文件。模型所見的視圖與磁盤上的真實情況之間沒有實時鏈接。
  3. 不恰當的粒度:即使文件能放入提示詞,模型的注意力也會浪費在無關的部分——導入、模塊級樣板代碼等。代理正在編輯的函數與上百行 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 頭。

第二步:設計模式 創建兩個集合:CodeChunksDocChunks,共享同一個 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_pathlanguagerepo 使用 FIELD 實現精確匹配;contenttitle 使用 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-voyageaitext2vec-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

每個塊同時保留 titlesource_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 代理真正理解私有代碼庫。