代码搜索系统

opencodesearch是一个异步的Rust代码搜索系统,支持通过MCP协议进行代码检索,适用于大型代码库的搜索和管理。

  • by BrosnanYuen
  • Rust
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 BrosnanYuen/opencodesearch

使用说明

开放式代码搜索

opencodesearch 是一个具有模型上下文协议(MCP)服务器的异步Rust代码搜索系统。 它将大型存储库索引到矢量+关键字后端,并通过MCP工具提供搜索结果。

特性

  • 完全异步运行时(tokio)
  • 4个独立过程:
    • 编排器(状态机+监督)
    • 背景故事
    • MCP服务器进程
    • git监视器进程
  • 运行时代码中集成和使用的所需板条箱:
    • opencodesearchparser
    • qdrant-client
    • ollama-rs
    • rmcp
  • 混合检索:
    • 语义搜索(Qdrant向量)
    • 关键字搜索(Quickwit HTTP+本地影子回退)
  • MCP服务器与使用流式HTTP和stdio传输的MCP客户端兼容

建筑

编排器中的状态机:

  • SPINUP:负载 config.json
  • NORMAL:run ingestor + mcp + watchdog
  • UPDATE:保持 watchdog,停止 ingestor + mcp 在更新窗口期间
  • CLOSING:优雅地阻止所有孩子

更新流程:

  • 看门狗跟踪自上次同步以来的git提交
  • 当阈值(commit_threshold)已达到:
    • 发送 UPDATE_START 到编排器
    • pull+计算更改/删除的文件
    • 删除过时的文档
    • 重新索引更改的文件
    • 发送 UPDATE_END

需求

  • 防锈工具链
  • Docker+Docker组合
  • 本地网络访问:
    • 奥拉马(11434)
    • Qdrant(6333 HTTP, 6334 gRPC)
    • 机智(7280)

配置

config.json 架构:

{
  "codebase": {
    "directory_path": "/path/to/massive/repo",
    "git_branch": "main",
    "commit_threshold": 50,
    "mcp_server_name": "My cool codebase",
    "mcp_server_url": "http://localhost:9443",
    "background_indexing_threads": 2
  },
  "ollama": {
    "server_url": "http://localhost:11434",
    "embedding_model": "qwen3-embedding:0.6b",
    "context_size": 2000
  },
  "qdrant": {
    "server_url": "http://localhost:6334",
    "collection_name": "opencodesearch-code-chunks",
    "api_key": null
  },
  "quickwit": {
    "quickwit_url": "http://localhost:7280",
    "quickwit_index_id": "opencodesearch-code-chunks"
  }
}

重要提示:

  • qdrant.server_url 应以gRPC终结点端口为目标(6334)for qdrant-client.
  • quickwit.quickwit_url 应该以HTTP为目标(7280).

启动后端服务

运行所有本地依赖项:

docker compose up -d

检查容器:

docker ps

运行系统

1) 编排器模式(推荐)

启动并监督所有子进程。

cargo run -- orchestrator --config config.json

2) 单个流程模式

您可以直接运行每个进程进行调试。

英格斯托:

cargo run -- ingestor --config config.json

MCP服务器:

cargo run -- mcp --config config.json

通过stdio的MCP服务器(用于本地MCP客户端):

cargo run -- mcp-stdio --config config.json

看门狗(需要编排器IPC环境):

OPENCODESEARCH_IPC_SOCKET=/tmp/opencodesearch.sock cargo run -- watchdog --config config.json

MCP服务器使用情况

MCP服务器支持:

  • 通过流式传输HTTP cargo run -- mcp --config config.json
  • stdio通过 cargo run -- mcp-stdio --config config.json

已实施的MCP工具:

  • search_code
    • 输入:
      • query: string
      • limit?: number (默认值8,最大值50)
    • 输出(结构化JSON):对象数组
      • snippet
      • path
      • start_line
      • end_line
      • score
      • source

工具输入示例

{
  "query": "which function changes obj variable",
  "limit": 5
}

结果形状

{
  "hits": [
    {
      "path": "/repo/module.py",
      "snippet": "def mutate(obj): ...",
      "start_line": 10,
      "end_line": 22,
      "score": 0.92,
      "source": "qdrant"
    }
  ]
}

与MCP客户端一起使用

此服务器支持以下两种功能:

  • 可流式传输HTTP(cargo run -- mcp --config config.json)
  • 本地stdio(cargo run -- mcp-stdio --config config.json)

OpenAI 代码专家

Codex支持stdio和可流式传输的HTTP MCP服务器。

标准(CLI):

codex mcp add opencodesearch -- \
  cargo run --quiet --manifest-path /home/brosnan/opencodesearch/Cargo.toml -- \
  mcp-stdio --config /home/brosnan/opencodesearch/config.json

远程HTTP(~/.codex/config.toml 或 .codex/config.toml):

[mcp_servers.opencodesearch]
url = "http://localhost:9443/"

然后验证:

codex mcp list

开源代码

OpenCode配置使用 mcp 部分在 opencode.json (或 opencode.jsonc).

远程HTTP:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "opencodesearch": {
      "type": "remote",
      "url": "http://localhost:9443/",
      "enabled": true
    }
  }
}

本地标准:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "opencodesearch": {
      "type": "local",
      "command": [
        "cargo",
        "run",
        "--quiet",
        "--manifest-path",
        "/home/brosnan/opencodesearch/Cargo.toml",
        "--",
        "mcp-stdio",
        "--config",
        "/home/brosnan/opencodesearch/config.json"
      ],
      "enabled": true
    }
  }
}

克劳德代码

Claude Code支持HTTP、SSE和stdio MCP传输。

远程HTTP:

claude mcp add --transport http opencodesearch http://localhost:9443/

本地标准:

claude mcp add --transport stdio opencodesearch -- \
  cargo run --quiet --manifest-path /home/brosnan/opencodesearch/Cargo.toml -- \
  mcp-stdio --config /home/brosnan/opencodesearch/config.json

然后验证:

claude mcp list

TLS/HTTPS注释

  • 默认本地配置使用 http://localhost:9443.
  • 对于 https://...,提供您的MCP客户端信任的证书。
  • TLS证书和密钥默认值:
    • certs/localhost-cert.pem
    • certs/localhost-key.pem
  • 使用以下内容覆盖TLS文件路径:
    • OPENCODESEARCH_TLS_CERT_PATH
    • OPENCODESEARCH_TLS_KEY_PATH
  • 特别是对于Codex,您可以提供一个自定义CA包 CODEX_CA_CERTIFICATE.

参考文献

  • 食品法典委员会MCP文件:https://developers.openai.com/codex/mcp
  • OpenCode MCP文档:https://opencode.ai/docs/mcp-servers/
  • 克劳德代码MCP文档:https://code.claude.com/docs/en/mcp

快速卷曲测试

使用附带的脚本:

./test_mcp_curl.sh

可选:

  • MCP_URL=https://localhost:9443/ MCP_INSECURE=1 ./test_mcp_curl.sh

该脚本执行所需的MCP HTTP握手步骤:

  1. initialize
  2. 提取 mcp-session-id 从响应标头
  3. 发送 notifications/initialized 与相同 mcp-session-id
  4. 呼叫 tools/call 为了 search_code

手动卷曲顺序

初始化并捕获会话id:

curl -sS -D headers.txt http://localhost:9443/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl-test","version":"1.0"}}}'

发送初始化通知:

SESSION_ID="$(awk 'tolower($1)=="mcp-session-id:"{print $2}' headers.txt | tr -d '\r' | tail -n 1)"
curl -sS http://localhost:9443/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "mcp-session-id: ${SESSION_ID}" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

调用MCP工具:

curl -N http://localhost:9443/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "mcp-session-id: ${SESSION_ID}" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_code","arguments":{"query":"which function mutates obj","limit":5}}}'

Rust API文档

板条箱公开了可重用的模块,用于嵌入、索引、MCP服务和过程控制。

模块

  • config:解析类型化的应用程序配置(AppConfig)
  • chunking:将源文件解析/拆分为块(chunk_file)
  • indexing:索引运行时(IndexingRuntime)
  • qdrant_store:矢量存储+语义查询(QdrantStore)
  • quickwit:关键字存储/查询(QuickwitStore)
  • mcp:MCP服务器类型(OpenCodeSearchMcpServer)
  • watchdog:git更新监视器(WatchdogProcess)
  • orchestrator:多流程主管(Orchestrator)

最小Rust索引示例

use opencodesearch::config::AppConfig;
use opencodesearch::indexing::IndexingRuntime;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let config = AppConfig::from_path("config.json")?;
    let runtime = IndexingRuntime::from_config(config)?;

    runtime.index_entire_codebase().await?;
    Ok(())
}

最小Rust语义搜索示例

use opencodesearch::config::AppConfig;
use opencodesearch::indexing::IndexingRuntime;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let config = AppConfig::from_path("config.json")?;
    let runtime = IndexingRuntime::from_config(config)?;

    let query_vec = runtime.embed_query("where is object mutated") .await?;
    let hits = runtime.qdrant.semantic_search(query_vec, 5).await?;

    for hit in hits {
        println!("{}:{}-{}", hit.path, hit.start_line, hit.end_line);
    }

    Ok(())
}

最小化Rust MCP服务器嵌入

use opencodesearch::config::AppConfig;
use opencodesearch::indexing::IndexingRuntime;
use opencodesearch::mcp::OpenCodeSearchMcpServer;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let config = AppConfig::from_path("config.json")?;
    let runtime = IndexingRuntime::from_config(config)?;
    OpenCodeSearchMcpServer::new(runtime)
        .run_streamable_http("http://localhost:9443")
        .await
}

测试

标准测试

cargo test

活容器集成测试

需要运行Docker服务和本地git:

cargo test -- --ignored

当前忽略的集成测试验证:

  • Ollama连接
  • Quickwit+Qdrant连接
  • 生成的Python项目上的完整索引流
  • 通过非精确查询短语的MCP搜索路径进行检索
  • 看门狗阈值行为的100次提交重构场景

故障排除

  • Quickwit健康端点:使用 http://localhost:7280/health/livez
  • 如果嵌入失败,请确认Ollama型号的可用性:
    • qwen3-embedding:0.6b
  • Qdrant客户端需要gRPC端口(6334)在配置中
  • 如果集成测试在启动竞赛中失败,请在短暂的容器预热后重新运行