mcpField
S
Semcode

Semcode

远程服务
github.com/GoodbyePlanet版本控制8今天更新
代码仓库

关于 Semcode

Semcode 为需要检索多个 GitHub 仓库代码的开发者和 AI 客户端提供混合语义搜索。它用 Tree-sitter 解析代码符号,并结合向量与 BM25 检索,也可索引 Git 提交历史。

主要功能

  1. 01跨 GitHub 仓库搜索代码
  2. 02Tree-sitter 解析代码符号
  3. 03结合语义向量与 BM25
  4. 04增量索引并清理旧条目
  5. 05可选索引 Git 提交历史

适用场景

  1. 01用自然语言查找代码实现
  2. 02按函数或类名定位代码
  3. 03检索提交记录及变更文件

MCP 相关

该 MCP 服务通过搜索和索引工具向客户端开放代码检索,并提供小型 HTTP API。支持 HTTP、stdio 和旧版 SSE 连接。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址http://localhost:8090/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

详细介绍

MCP Server Python 3.12+ License MIT Release CI

semcode

一个 MCP(Model Context Protocol)服务,可对你在 config.yaml 中列出的多个 GitHub 仓库中的代码进行混合语义搜索。它使用 Tree-sitter 解析符号,并为代码和 git 提交历史建立索引,因此 AI 客户端可以通过自然语言或符号名称查询。

混合检索将稠密嵌入与 BM25 相结合,因此无论是自然语言查询(“我们在哪里发布订单事件?”)还是符号名称查找(PlaceOrderRequest)都能获得良好效果。

已提交至:

mcpservers.org

mcpmarket.com

mcp.so

工作原理

  1. 从配置的 GitHub 仓库获取源文件
  2. 使用 Tree-sitter 解析代码符号(函数、类、方法、组件)
  3. 为每个符号生成两种嵌入——稠密语义向量(可插拔的提供方:默认使用 Jina Code V2,也可使用 Voyage / OpenAI / Ollama)和 BM25 稀疏向量,后者以代码标识符词元为键(将 camelCase / snake_case 拆分为子词)
  4. 将两种向量存入 Qdrant,并使用混合搜索检索——对稠密和稀疏结果执行 Reciprocal Rank Fusion(RRF)——从而让自然语言查询和符号名称查找都能获得良好效果
  5. 可选地将提交历史索引到单独的 Qdrant 集合中(仅稠密向量)
  6. 通过 MCP 协议(以及一个小型 HTTP API)提供搜索和索引工具

索引采用增量式处理——当文件的 Git blob SHA 与上次索引的版本一致时,会跳过该文件。已不存在(或解析后不含任何符号)的文件会自动清理。传入 force: true 可重新嵌入所有内容。

想了解更多详情?查看博客!

文档

有关 RAG 系统内部机制的深入文档,请访问 goodbyeplanet.github.io/semcode:

支持的语言

语言会根据文件扩展名或文件名自动检测,无需配置。

Go、Java、Python、TypeScript / JavaScript(React)、Rust、C#、C、C++、Ruby、PHP、Kotlin、Scala、Swift、Dart、Bash、SQL、 Lua、R、Dockerfile、Docker Compose、Markdown、JSON、HTML、CSS、XML。

在适用场景下,大多数解析器都能识别框架特性——例如 Java/Kotlin 的 Spring stereotypes 和 HTTP 路由、Python 的 FastAPI/Pydantic、 C# 的 ASP.NET、Ruby 的 Rails、PHP 的 Laravel/Symfony、React/SwiftUI/Flutter 组件等。各语言提取细节请参阅 server/parser/。

设置

前置条件: Python 3.12+、Docker、GitHub token

# Install dependencies
uv sync

# Copy environment file, then edit .env to set GITHUB_TOKEN
# (a fine-grained PAT with Contents: read on the target repos is sufficient)
cp .env.example .env

# Optional — only if you want curated/static services (see below for the alternative):
# copy the services config, then list the repositories you want indexed
cp config.example.yaml config.yaml

在 config.yaml 中配置要编入索引的仓库:

services:
  - name: my-service
    github_repo: owner/repo
    github_ref: main              # optional, defaults to "main" — branch, tag, or commit SHA
    root: src/main/java           # optional — limit indexing to this subdirectory (useful for monorepos)
    exclude:                      # optional — skip matching paths
      - "**/vendor/**"
      - "**/node_modules/**"

索引器会自动发现并索引所有具有可识别扩展名的文件。使用 root 将服务限定在共享仓库中的某个子目录内,并使用 exclude 跳过不想编入索引的路径(测试、构建产物、生成的代码等)。

扩展到少数几个仓库以上: config.yaml 是一份经过筛选的静态列表——适合少量服务,但用这种方式为数百个仓库编制索引,意味着需要手动维护数百条配置。作为替代方案(或补充),POST /reindex 接受内联的仓库定义,并可即时注册仓库,无需在 config.yaml 中添加条目——参见 examples/github-actions/reindex-on-merge.yml,其中提供了一个即用型工作流,可自动注册仓库并在每次合并时重新编制索引。详情请见下文的 HTTP API 部分。如果两者的名称冲突,始终以 config.yaml 中的条目为准。

以这种方式运行时,完全不需要 config.yaml——缺少该文件会被视为配置了零个服务,而不是错误。docker-compose.yaml 也体现了这一点:默认情况下不会挂载 config.yaml,因此对于仅使用按需注册的设置,make docker-up / make docker-up-jina 开箱即用。如果还需要经过筛选的服务,请将 config.example.yaml 复制为 config.yaml(见上文),并改用 -with-config 目标;这些目标会叠加 docker-compose.config-yaml.yml 以添加挂载:make docker-up-with-config / make docker-up-jina-with-config(或直接运行 docker compose -f docker-compose.yaml -f docker-compose.config-yaml.yml up -d)。不要直接编辑 docker-compose.yaml 中的卷配置行——如果主机上不存在 config.yaml,绑定挂载会悄悄在该位置创建一个空目录,而不是让路径保持不存在,这会导致服务无法运行(如果发生这种情况,会显示清晰的错误:CONFIG_PATH (...) is a directory, not a file)。

一个 GITHUB_TOKEN 即可读取你以这种方式编入索引的所有仓库。 对于 config.yaml 中的少数几个条目,限定这些仓库范围的细粒度 PAT 已经足够;但对于组织范围的自助注册——任何仓库只需添加该工作流即可接入——每当有新仓库开始使用时,都需要在其他地方更新 PAT 的仓库访问列表。将 GitHub App 安装到整个组织(所有仓库,Contents: read)即可避免这一问题:新仓库会自动获得授权,无需在每次接入时维护 token。

运行

根据你希望嵌入来自本地容器还是托管服务提供商,有两种运行方式。请选择一种:

路径 A — 通过 TEI 使用本地 Jina(默认,无需 API 密钥):

make docker-up-jina
# or: docker-compose --profile jina up

路径 B — 使用托管服务提供商(Voyage / OpenAI)或本地 Ollama:

# 1. In .env, set EMBEDDINGS_PROVIDER=voyage|openai|ollama and the relevant API key.
# 2. Then start without the jina profile:
make docker-up
# or: docker-compose up

使用 config.yaml 配置精选服务?请使用上方适用目标对应的 -with-config 变体(make docker-up-with-config / make docker-up-jina-with-config)——参见设置部分。

⚠ 默认的 EMBEDDINGS_PROVIDER 为 jina。如果启动时未使用 --profile jina,但保留默认服务提供商,semcode 将会启动(Jina 在 compose 中设置为 required: false),但首次嵌入调用会因连接错误而失败——不会自动回退。

服务启动时会启用健康检查和持久化卷:

服务配置文件端口卷用途
Qdrant始终启用6333(HTTP),6334(gRPC)qdrant_data向量数据库
Jina Embeddings(TEI)jina8087embeddings_cache嵌入模型服务
semcode MCP始终启用8090使用 -with-config 时以只读方式挂载 ./config.yamlMCP + HTTP 服务

MCP 服务启动时集合为空——请调用 reindex MCP 工具或 POST /reindex 触发初始索引(见下文)。

连接 AI 客户端

服务运行后,将 AI 客户端指向 http://localhost:8090/mcp。

Claude Code(CLI)

claude mcp add --transport http semcode http://localhost:8090/mcp

其他 MCP 客户端(Claude Desktop、Cursor 等)——在客户端的 MCP 配置中添加一项:

{
  "mcpServers": {
    "semcode": {
      "transport": "http",
      "url": "http://localhost:8090/mcp"
    }
  }
}
通过 stdio 连接

客户端也可以自行启动服务进程,并通过 stdin/stdout 与其通信,而不是连接正在运行的 HTTP 服务。这仍然需要 Qdrant 可访问(例如,docker-compose up qdrant),并且本地 Python 环境已安装依赖项(uv sync)。

Claude Code(CLI)

claude mcp add semcode --transport stdio --env MCP_TRANSPORT=stdio -- uv run --directory /path/to/semcode python -m server.main

其他 MCP 客户端——在客户端的 MCP 配置中添加一项:

{
  "mcpServers": {
    "semcode": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/semcode", "python", "-m", "server.main"],
      "env": {
        "MCP_TRANSPORT": "stdio"
      }
    }
  }
}

GITHUB_TOKEN、QDRANT_URL 和嵌入服务提供商变量仍从项目目录中的 .env 读取——uv run 会自动加载这些变量。

通过 SSE 连接

SSE 是旧版 MCP HTTP 传输方式,现已由 streamable-http 取代。仅在客户端尚不支持 streamable-http 时使用——新配置 应使用上方的 streamable-http 设置。

在 .env(或环境变量)中设置 MCP_TRANSPORT=sse,然后以与 streamable-http 相同的方式启动服务(make docker-up / make docker-up-jina,或在本地运行 uv run python -m server.main)。服务会在 http://localhost:8090/sse 提供 SSE 端点。

Claude Code(CLI)

claude mcp add --transport sse semcode http://localhost:8090/sse

其他 MCP 客户端——在客户端的 MCP 配置中添加一项:

{
  "mcpServers": {
    "semcode": {
      "transport": "sse",
      "url": "http://localhost:8090/sse"
    }
  }
}

索引

索引流水线以符号为中心:每个函数、类、方法或组件都会成为独立的分块,并附带向量嵌入和丰富的负载数据。

  • 发现 — 列出 github_ref 中仓库的所有文件,并应用 root 和 exclude 过滤条件
  • 变更检测 — 将文件的 Git blob SHA 与上次索引的值进行比较;未变更的文件会被跳过
  • 解析 — Tree-sitter 遍历 AST,并针对每种语言生成 CodeSymbol 对象
  • 稠密嵌入文本 — 语言标签、符号类型、父类、包、框架扩展信息(Spring stereotype、HTTP 路由、Lombok、React memo)、文档字符串、签名和源代码(源代码会截断至 EMBEDDING_MAX_CHARS;这是一个根据提供方调整的默认值,详见 docs/configuration.md)
  • 稀疏(BM25)嵌入文本 — 签名、文档字符串和源代码。代码标识符会在分词前拆分为子词(camelCase、snake_case),因此 getUserById 除了完整词元外,还会按 get、user、by、id 建立索引
  • 批处理 — 稠密嵌入提供方的批次大小为 32(Jina/TEI、Ollama)或 128(Voyage、OpenAI);BM25 在进程内运行
  • 写入 — 两种向量均存储在 Qdrant 的同一个点中,并以确定性 UUID(按服务 / 文件 / 符号 / 行)为键
  • 清理 — 删除仓库中已不存在的文件(或当前解析结果为零个符号的文件)对应的条目

Git 历史索引是单独的可选流水线,会将提交消息和变更文件路径嵌入到 git_commits 集合中。完整的统一差异存储在负载数据中,并可通过 get_commit 工具检索。每个服务的提交数量上限由 GIT_HISTORY_MAX_COMMITS 限定(默认值为 500)。

测试

uv sync --group dev
uv run pytest

测试位于 tests/ 下:

  • tests/parser/test_*.py — 每种语言对应一个文件;通过 tests/fixtures/<language>/ 中的标准测试样例验证解析器行为
  • tests/test_pipeline.py、tests/test_store.py、tests/test_git_history.py — 索引流水线和 Qdrant 存储的集成测试
  • tests/test_reindex_route.py — HTTP 路由测试

MCP 工具

工具描述
search_code根据查询进行混合搜索(密集向量 + BM25),可选按语言、服务和符号类型筛选
find_symbol按名称查找符号——精确匹配,或在 exact=false 时进行不区分大小写的词元匹配
find_usages查找引用给定符号名称的代码(先进行语义搜索,再排除定义本身)
get_code_context直接从 GitHub 获取文件的完整源代码,或文件中特定符号的源代码
reindex触发对一个或所有服务的代码索引(默认增量索引;使用 force 重新生成嵌入)
index_history为 git 提交历史建立索引;自动获取缺少差异内容的提交
search_commits使用自然语言搜索 git 提交历史
get_commit获取特定提交的完整详情,包括更改的文件和差异
list_indexed_services列出已建立索引的服务,包括分块和文件数量、语言以及最近索引时间
index_stats显示 Qdrant 集合统计信息和已配置的服务

find_symbol(exact=false) 会针对符号名称的 camelCase/snake_case 词元全文索引进行匹配,因此无论集合大小如何,order 或 ord 都能在约 2 ms 内找到 placeOrderRequest。中间词元片段(rder)也能匹配,但会回退到客户端扫描,其耗时与集合大小呈线性关系。在此字段出现之前建立索引的集合会一直使用相同的回退方式,直到重新建立索引——由于变更检测会跳过未更改的文件,要填充此字段,需要使用 force 重新建立索引(POST /reindex {"force": true}),这会为每个符号重新生成嵌入。请参阅 docs/retrieval-rrf.md。

MCP 提示词

提示词参数描述
service_overviewservice引导客户端生成服务的架构概览:HTTP 入口点、领域类型和重要的框架约定
system_design_overview(无)引导客户端生成完整的系统设计概览:服务清单、通信拓扑、共享数据存储和横切关注点——包含 Mermaid 图表

HTTP API

除 MCP 工具外,服务器还会公开两个 HTTP 端点,供 CI/CD 或外部调度器触发索引:

端点请求体描述
POST /reindex{"service": "<name>"?, "force": <bool>?, "github_repo": "<owner/repo>"?, "github_ref": "<ref>"?, "root": "<path>"?, "exclude": [<glob>, ...]?}为一个或所有服务重新建立索引——返回 NDJSON
POST /reindex-history{"service": "<name>"?, "force": <bool>?}为 Git 提交历史建立索引——返回 NDJSON

所有请求体字段均为可选项——省略 service 可作用于所有服务,省略 force 则进行增量索引。 两个端点都会流式传输换行符分隔的 JSON(每行一帧),因此你可以从 CI/CD 流水线或任何其他客户端实时获取进度。

**在没有 config.yaml 的情况下注册仓库:**如果 POST /reindex 的请求体包含 github_repo,则会在开始索引前将该仓库定义注册到 service 名称下(并持久化,因此重启后仍然有效,之后的行为与 config.yaml 中定义的服务相同)——此时必须提供 service。github_ref 默认为 main;root/exclude 与 config.yaml 中的同名字段一致。若 config.yaml 中已定义该 service 名称,则始终优先使用该定义。此端点没有身份验证——与 /reindex 的其他部分相同——因此在对外开放之前,请将其置于你自己的网络边界之后。请参阅 examples/github-actions/reindex-on-merge.yml,了解可直接使用的工作流。

帧格式:

// in-flight progress
{"type": "progress", "phase": "discovery|upserting|cleanup", "current": 12, "total": 200, "percentage": 6.0, "service": "my-service"}
// final summary (one per request)
{"type": "done", "result": {"files": 42, "chunks": 318, "skipped": 5}}
// emitted instead of "done" on failure
{"type": "error", "message": "..."}

对于 /reindex,upserting 帧中的 current 表示已处理文件数,并单调递增;已处理文件包括完成索引、因内容未变而跳过,或因获取/解析失败而丢弃的文件,因此该值最终始终会达到 total。文件会并发建立索引,因此帧按批次而非逐个文件发出。

对于 /reindex-history,phase 的值为 discovery|embedding|upserting,done 的结果为 {"new": int, "skipped": int, "diff_updated": int}。

环境变量

变量默认值描述
GITHUB_TOKEN(必填)具有仓库读取权限的 GitHub 令牌
GITHUB_API_URLhttps://api.github.comGitHub API 根地址;GitHub Enterprise Server 使用 https://<host>/api/v3
QDRANT_URLhttp://localhost:6333Qdrant 连接 URL
QDRANT_COLLECTIONcode_symbols代码符号向量的集合名称
QDRANT_COMMITS_COLLECTIONgit_commits提交消息向量的集合名称
EMBEDDINGS_PROVIDERjina可选 jina、jina-api、voyage、openai、ollama — 参见下文的 嵌入提供方
GIT_HISTORY_MAX_COMMITS500每个服务索引的最大提交数
CODE_CONTEXT_CACHE_SIZE128内存中缓存的文件数,供 get_code_context 使用(以 blob SHA 为键);0 表示禁用
CODE_CONTEXT_CACHE_TTL900缓存的文件内容保持有效的秒数
MCP_TRANSPORTstreamable-http可选 streamable-http、sse、stdio
MCP_HOST / MCP_PORT127.0.0.1 / 8090服务绑定地址
MCP_STATELESS_HTTPtrue在不进行会话跟踪的情况下提供 streamable-http(无需粘性会话);false 会恢复按客户端划分的 MCP 会话。仅适用于 streamable-http
CONFIG_PATH./config.yaml服务配置文件的路径

嵌入提供方

可通过 EMBEDDINGS_PROVIDER 选择嵌入后端。默认值为 jina,因此现有部署无需更改即可继续运行。每个提供方都会根据所配置的模型确定自己的向量维度 — 除非要覆盖,否则无需手动设置维度。

变量默认值适用对象描述
JINA_URLhttp://localhost:8087jinaTEI 基础 URL
JINA_MODELjinaai/jina-embeddings-v2-base-codejina仅供参考——实际加载的模型由 TEI 容器的 --model-id 标志决定。编辑 docker-compose.yaml 以更改模型。
JINA_DIMENSIONS768jinaTEI 模型的向量维度
JINA_API_KEY(provider=jina-api 时必填)jina-apiJina AI API 密钥(托管端点位于 api.jina.ai)
JINA_API_MODELjina-embeddings-v2-base-codejina-api托管的 Jina 模型——也支持 jina-code-embeddings-0.5b、jina-code-embeddings-1.5b
JINA_API_DIMENSIONS(原生)jina-api可选的 Matryoshka 覆盖值(code-embeddings 模型支持缩减维度);没有原生默认值的模型必须指定此值
VOYAGE_API_KEY(provider=voyage 时必填)voyageVoyage AI API 密钥
VOYAGE_URLhttps://api.voyageai.com/v1/embeddingsvoyageEmbeddings 端点覆盖值(必须遵循 Voyage 协议)
VOYAGE_MODELvoyage-code-3voyageVoyage 嵌入模型
VOYAGE_DIMENSIONS(原生)voyage可选覆盖值——Voyage code-3 支持 256 / 512 / 1024 / 2048
OPENAI_API_KEY(provider=openai 时必填)openaiOpenAI API 密钥
OPENAI_URLhttps://api.openai.com/v1/embeddingsopenaiEmbeddings 端点覆盖值(必须遵循 OpenAI 协议)
OPENAI_EMBEDDING_MODELtext-embedding-3-largeopenaiOpenAI 嵌入模型
OPENAI_DIMENSIONS(原生)openai可选覆盖值(text-embedding-3-* 模型支持缩减维度)
OLLAMA_URLhttp://localhost:11434ollamaOllama 基础 URL
OLLAMA_MODELnomic-embed-textollamaOllama 嵌入模型
OLLAMA_DIMENSIONS(原生)ollama使用不在内置维度表中的模型时必填
voyage-code-3 在大多数代码检索基准测试中的表现都优于 jinaai/jina-embeddings-v2-base-code,
因此,切换到 Voyage 不仅能提高灵活性,也能提升质量。

**针对现有索引切换提供商:**如果新提供商的向量大小与现有 Qdrant 集合不同,服务会在启动时立即失败,并明确指出有问题的集合。要切换提供商,请通过 Qdrant UI 或 API 删除两个集合(code_symbols 和 git_commits),然后重新建立索引。不会自动迁移。

**仅使用托管服务的设置(无本地 TEI 容器):**在 .env 中设置 EMBEDDINGS_PROVIDER 和相应的 API 密钥,然后在不启用 jina 配置的情况下启动(docker-compose up / make docker-up)。jina-embeddings 容器不会启动。

Qdrant 集合

code_symbols — 每个解析出的符号对应一个点,包含两个命名向量:

  • text-dense — 余弦距离,HNSW(m=16,ef_construct=128),大小由嵌入提供商决定
  • text-sparse — 基于代码标识符子词元的 BM25,内存稀疏索引

search_code 通过一次 Qdrant query_points 调用,使用 FusionQuery(fusion=RRF) 同时查询两者。索引的载荷字段(language、service、symbol_type、chunk_tier、parent_name、file_path)可用作筛选条件。search_code 和 find_symbol 直接提供 chunk_tier("method" 或 "class"),因此查询可限定为仅搜索类或仅搜索方法。完整载荷还包括 signature、docstring、annotations、package、 start_line、end_line、file_hash、indexed_at 以及特定语言的扩展字段(http_method、 http_route、spring_stereotype、lombok_annotations、is_async、uses_memo,等等)。

git_commits — 每个提交对应一个仅含稠密向量的向量(余弦距离,HNSW m=16 / ef_construct=128)。 载荷包括 sha、service、message、author_name、author_email、committed_at、 indexed_at、has_diff、diff_truncated 和 files(包含变更文件的数组,字段有 filename、 status、additions、deletions、patch)。sha、service、author_name 和 has_diff 是索引的载荷字段。

版本管理与发布

版本号只在一个地方维护:pyproject.toml 中的 version。server/main.py 通过 importlib.metadata.version("semcode") 读取该值,并将其报告为 MCP serverInfo.version,因此客户端始终看到其实际运行的软件包版本。

**切勿手动编辑该版本号。**发布由 release-please 自动完成(.github/workflows/release.yml):

  1. 使用 Conventional Commits 将提交合入 main。
  2. release-please 会创建(或更新)一个 chore(main): release X.Y.Z PR,更新 pyproject.toml,并根据这些提交消息生成 CHANGELOG.md。
  3. 合并该 PR 后,会为提交打上 vX.Y.Z 标签并创建 GitHub Release。只有人工合并后才会发布。

目前,发布会生成一个包含源代码和自动生成的变更日志的 GitHub Release。不会发布到 PyPI,也不会推送容器镜像——semcode 仍会在本地通过 Dockerfile 构建。

提交类型和版本升级
提交前缀升级更新日志章节
feat!: / BREAKING CHANGE:major⚠ 重大变更
feat:minor功能
fix:patch错误修复
perf:patch性能改进
deps:patch依赖项
refactor:patch代码重构
docs: test: style: chore: ci: build:patch隐藏

Dependabot 已配置为使用 deps 前缀(.github/dependabot.yml),因此一周的依赖更新仍会生成一个 patch 版本发布,并标明哪些依赖集是一起测试的。

major 版本仅用于对MCP 工具签名或配置架构进行不兼容变更——客户端和部署所依赖的接口。

说明
  • 由于 main 上的提交消息决定了所有事项,压缩合并标题必须符合规范的 Conventional Commits 格式。仓库应启用 “压缩合并时默认使用 PR 标题”。
  • 发布 PR 使用 GITHUB_TOKEN 创建,按设计不会触发其他工作流——CI 不会在发布 PR 本身上重新运行。该 PR 发布的提交已在 main 上通过测试。

项目结构

server/
├── main.py          # MCP server entry point + lifespan
├── config.py        # Settings and service configuration
├── state.py         # Shared store singletons
├── parser/          # Tree-sitter parsers (Go, Java, Python, TypeScript, Rust, C#, C, C++, Ruby, PHP, Kotlin, Scala, Swift, Dart, Bash, SQL, Lua, R, Dockerfile, Compose, Markdown, JSON, HTML, CSS, XML)
├── embeddings/      # Pluggable dense providers (Jina/Voyage/OpenAI/Ollama) + BM25 sparse + code identifier tokenizer
├── indexer/         # GitHub fetcher, code indexing pipeline, git history pipeline
├── store/           # Qdrant vector stores (code_symbols hybrid + git_commits dense)
├── tools/           # MCP tool implementations (search, index, history, admin)
├── prompts/         # MCP prompt templates (service_overview, system_design_overview)
└── routes/          # HTTP routes (reindex, reindex-history)

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。