mcpField
S
semhood

semhood

本地服务
github.com/ahmeedgamil搜索与检索121 周前更新

关于 semhood

semhood 是面向开发者和编码 Agent 的 AST 语义代码搜索引擎。它结合混合检索与可选的 LLM 增强,并在代码结果中提供调用图上下文。

主要功能

  1. 01按 AST 索引函数和类
  2. 02语义与 BM25 混合搜索
  3. 03可选的 LLM 摘要和查询增强
  4. 04结果附带调用者与被调用项
  5. 05支持命令行、HTTP 和 MCP
  6. 06增量索引变更文件

适用场景

  1. 01按代码行为而非关键词查找
  2. 02追踪符号的调用者和依赖项
  3. 03为编码 Agent 提供精简代码上下文
  4. 04无需 API 密钥搜索代码库

MCP 相关

其 MCP 服务向 MCP 客户端提供搜索、符号查找、代码块上下文、索引状态和增强工具。它将请求转发给当前工作区项目对应的 semhood 守护进程。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"ahmeedgamil-semhood": {
"command": "uvx",
"args": [
"semhood"
]
}
}
}
启动命令uvx semhood

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypisemhood0.1.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

semhood 徽标

semhood

别再用 grep 搜索。 按意图而非关键词,找到 AI Agent 所需的准确代码。semhood 是一款支持 AST 感知的语义代码搜索引擎,可根据代码的功能检索代码,并提供调用图上下文和可选的大模型增强。

完全离线运行,无需 API 密钥;也可以接入云端嵌入模型——Voyage 专门针对代码的模型,或 OpenAI 强大的通用(自然语言)嵌入模型——以提升检索质量。可选的大模型增强会为每个代码块添加逻辑摘要和开发者查询;提交一次即可共享——每条结果还会附带调用图(它调用了什么,以及什么调用了它)。

许可证:MIT 构建状态 MCP Tree-sitter

为何选择 semhood · 安装 · 快速开始 · MCP 设置 · 架构 · 配置 · 故障排除


   ┌──────────────┐    parse + embed     ┌──────────────┐    LLM enrich    ┌──────────────┐
   │  source tree │ ───────────────────► │ code  vector │ ──────────────► │  description │
   │              │                      │ + BM25 sparse│                  │  + queries   │
   └──────────────┘                      └──────────────┘                  └──────────────┘

                                Search via CLI, HTTP, or MCP.

semhood 按照开发者理解代码库的方式为代码建立索引:每个函数、方法和类都会成为一个代码块,并附带其调用图、文档字符串和签名。你可以按意图搜索(“我们如何重试临时支付失败?”),并获得真正能回答问题的少数几个代码块。

分为两个阶段:结构化处理(始终执行、免费、约需数秒)和增强处理(可选,由大模型或编码 Agent 执行,并从 pending 队列中取出任务)。第 1 阶段完成后即可查询索引;第 2 阶段只是让自然语言匹配更加精准。

该软件包附带一个 MCP 服务,让 Claude Desktop、Cursor、Cline、Continue、Kiro、Zed 及任何其他兼容 MCP 的客户端都能将 semhood 作为工具调用——你的 AI Agent 可在内置的 read_file 和 grep 旁使用 search、find_symbol 和 get_chunk_context。


semhood 有何不同

大多数代码搜索工具会将原始源代码转换为嵌入向量,并寄望自然语言查询能与其匹配。semhood 增加了两项普通向量搜索和 grep 无法实现的功能:

🧠 像开发者一样思考的增强

大模型会读取每个函数和类,并编写两类内容,分别存储为独立的搜索向量:

  • 逻辑摘要——用通俗语言说明代码实际做什么。不是它的名称,也不是它的签名,而是它的行为。
  • 预测的开发者问题——工程师为找到这段代码会提出的真实问题:“如何重试失败的付款?”、“在哪里验证客户邮箱?”

这正是让检索效果出色的关键。当你用问题进行搜索时,实际上是在匹配代码预先标注要回答的问题——因此,即使查询和代码块之间没有任何共同关键词,正确的代码块也能胜出。增强内容只需生成一次,提交到 git,整个团队以及每个 AI Agent 都能免费获得更好的检索效果。→ 可移植的增强内容

为什么增强很重要:有些代码没有可供搜索的词语。 纯语义搜索只有在源代码包含与你的问题相近的语言时才有效。许多重要代码并非如此——名称简短、只有原始数学运算,或包含业务规则。例如这样的函数:

def _calc(p, r, n):
    return p * (1 + r) ** n

如果问*“如何计算复利?”*,纯向量搜索会一无所获——源代码里没有“利息”、“复利”之类的词,也没有任何内容与问题的含义相近。增强功能会读取代码并生成:

{
  "logic_summary": "Computes compound interest — final balance = principal × (1 + rate)^periods.",
  "developer_queries": [
    "how do we calculate compound interest?",
    "where is the future-value / compounding formula?",
    "how is a balance grown over multiple periods?"
  ]
}

现在,你的问题可以匹配到一个含义相同的预先编写的问题,而 _calc 会排在首位——尽管它和你的查询之间没有任何共同词语。晦涩但至关重要的函数,正是纯语义搜索会漏掉、而增强功能能找回的内容。

🕸️ 每条结果都附带调用图

每个代码块都知道自己调用了什么以及谁会调用自己。因此,结果不只是“这是函数”,而是函数及其周边调用关系。一次 get_chunk_context 调用就能同时返回函数体、calls 和 called_by,让你的 AI Agent 在同一响应中获取调用方和被调用方的上下文,无需手动打开文件并追踪引用。


功能

  • 提升检索效果的增强功能——大模型为每个代码块生成通俗易懂的逻辑摘要和预测的开发者问题,并将它们作为独立向量编入索引,让问题式查询即使没有共同关键词,也能命中正确的代码。只需生成一次,提交到 git,即可与团队共享。
  • 包含调用图——每条结果都知道自己调用了什么以及谁会调用自己,让 Agent 获取周边调用关系,而不只是函数本身
  • 通过 Tree-sitter 实现感知 AST 的分块——每个函数、方法和类都是独立可搜索的单元
  • 混合检索——密集向量(code、description、developer_queries)+ BM25 稀疏检索,一次查询全部完成
  • 节省 AI Agent 的令牌——用一次 search 替代数十次 read_file + grep 调用
  • 开箱即用的 MCP 服务——适用于 Claude Desktop、Cursor、Cline、Continue、Kiro、Zed
  • 支持 10 种语言——Python、JavaScript、TypeScript、Java、Go、PHP、C#、Ruby、Rust、C++
  • 免费层即可使用——本地嵌入和结构化处理流程无需任何 API 密钥
  • 增量索引——--changed 只会为 git diff 涉及的内容重新编制索引

安装

# Local-only (free, offline embeddings via sentence-transformers)
pip install "semhood[local]"

# With everything: voyage + openai + anthropic + cohere + chroma
pip install "semhood[all]"

# Pick exactly what you need
pip install "semhood[anthropic,local]"

更倾向于隔离安装 CLI? pipx 可将 semhood 及其依赖与全局环境隔离——推荐用于命令行工具:

pipx install "semhood[local]"

只想试用,不想安装? 使用 uv,直接从 PyPI 运行:

uvx --from "semhood[local]" semhood index .

需要 Python 3.11+。首次编制索引时会下载嵌入模型(默认 all-mpnet-base-v2 约 420 MB)并将其缓存。


60 秒快速入门

无需配置文件,无需 API 密钥,无需设置。semhood 默认使用本地嵌入模型,可离线运行。只需 cd 到任意项目目录并为其建立索引:

# 1. structural index — no LLM, free, no config needed
cd ~/code/your-project
semhood index .

# 2. search — pure retrieval, ~80 ms (a background daemon stays warm)
semhood search "how does the payment retry logic work?"

# 3. (optional) LLM enrichment — needs an Anthropic/OpenAI/OpenRouter/Ollama key
semhood enrich

# 4. (optional) full RAG with answer generation
semhood query "where is auth handled?"

第一条命令会自动启动后台守护进程,该进程只加载一次嵌入模型并保持就绪状态,因此之后的每次搜索(无论来自哪个终端或编辑器)都能即时完成。每个项目都会自动在 ~/.semhood/indexes/ 下获得独立索引,并以仓库根目录为键。全局配置位于 ~/.semhood/config.yaml(首次运行时创建);无需管理项目级配置文件。


CLI 命令

命令功能
semhood index <path>阶段 1:解析 + 嵌入 + 写入。无需大模型。
semhood index <path> --changed增量处理——仅处理 git diff HEAD~1 中的文件。
semhood index <path> --reset从头重建(更换嵌入模型后使用)。
semhood enrich阶段 2:通过大模型处理所有待处理分块。
semhood enrich --force重新处理每个分块。
semhood compact从 .semhood/enrichment.jsonl 中清理孤立记录。
semhood search "query"纯检索。--format json/paths/compact/table。
semhood query "question"完整 RAG:检索 + 答案生成。
semhood status按状态统计分块数量 + 提供方摘要。
semhood projects列出 ~/.semhood/indexes/ 中的所有已建索引项目。
semhood serve在前台运行守护进程(否则会自动启动)。
semhood stop停止后台守护进程。
semhood doctor检查守护进程和配置的运行状况。

所有命令都作用于当前项目(从当前工作目录向上找到最近的 git 根目录)。 使用 --root /path/to/repo 可指定其他项目。这些命令是守护进程的轻量客户端——无需加载模型,也没有 config.yaml 标志。


MCP — 将其接入你的 AI 编辑器

此软件包附带一个 MCP 服务(semhood-mcp),提供八种工具——五种用于搜索,三种用于由 Agent 驱动的增强:

工具用途
search对索引进行语义搜索。
search_many在一次调用中执行多次搜索——结果按查询分组。
find_symbol按函数/方法/类的准确名称查找。
get_chunk_context获取某个符号的完整源代码、调用方和被调用方。
index_status检查索引状态。
list_pending_enrichments获取一批需要大模型增强的代码块。
save_enrichment保存 Agent 撰写的摘要。
enrichment_progress循环哨兵——显示待处理与已完成的数量。

全局注册一次——之后在你打开的每个项目中都能使用,无需为每个项目单独配置。以下是完整配置——将其放入编辑器的用户级 MCP 文件中:

{
  "mcpServers": {
    "semhood": {
      "command": "semhood-mcp"
    }
  }
}
各编辑器的配置文件位置(点击展开)
编辑器配置文件
Claude Desktop(macOS)~/Library/Application Support/Claude/claude_desktop_config.json
Claude Desktop(Windows)%APPDATA%\Claude\claude_desktop_config.json
Cursor~/.cursor/mcp.json(全局)或 .cursor/mcp.json(每个项目)
Windsurf~/.codeium/windsurf/mcp_config.json
Cline(VS Code)Cline 面板 → MCP 服务器 → 配置(编辑 cline_mcp_settings.json)
Continue~/.continue/config.yaml → 在 mcpServers: 块下
Kiro~/.kiro/settings/mcp.json
Claude Codeclaude mcp add semhood semhood-mcp

有些客户端使用的格式略有不同——例如,VS Code 原生 MCP 使用顶层 "servers" 键,而不是 "mcpServers"。如果你的格式不同,请保留 command: "semhood-mcp" 部分,并参照客户端的 MCP 文档设置外层结构。

这就是全部配置——无需指定 config.yaml 路径,也无需逐个项目添加配置。该服务是一个轻量代理:它会将每次调用转发给已预热的守护进程,并附上编辑器当前打开的项目(最近的 git 根目录)。大多数编辑器会将工作区设为服务的工作目录,因此无需额外设置即可运行;如果你的编辑器不是这样,请显式传入根目录:

{ "command": "semhood-mcp", "args": ["--root", "${workspaceFolder}"] }

重启编辑器后,Agent 就能看到 semhood.search、semhood.find_symbol 等工具。守护进程只会为整台机器加载一次模型——因此,无论你打开多少个编辑器和终端,内存中都只有一个模型,每次调用耗时约 80 ms。

教会 Agent 何时使用它(可选)

MCP 服务为 Agent 提供工具;简短的技能则教会它优先使用语义搜索,而不是 grep/read。只需安装一次,即可在你使用的每个 AI 编辑器中以用户级配置启用:

semhood install-skill            # auto-detects installed editors
semhood install-skill -t all     # or force every supported target

支持:Claude Code(技能)、Cursor 和 Windsurf(规则)、Kiro(引导配置)、Codex(AGENTS.md)。它会按照每个编辑器自己的约定写入用户级配置——因此,和这里的其他内容一样,只需设置一次,就适用于每个项目。随时可以重新运行以就地更新。

为什么这会影响令牌用量

如果没有语义搜索,当被问到*“我们在哪里验证电子邮件?”*时,AI Agent 会运行 grep -r email,得到 200 条匹配结果,然后读取几十个文件。使用 semhood 时,它会调用 search("validate email"),以 JSON 格式获取 3 个排序后的代码块(约 500 个令牌),然后只读取所需内容。

实战示例——“OrderService 如何验证订单?”

我为 sample_project/ 建立了索引,然后原样提出了这个问题。Agent 调用了 两个 MCP 工具,就得出了答案——没有用到 read_file,也没有用 grep。

步骤 1 — search 将问题缩小到几个候选项
{
  "query": "how does OrderService validate an order before processing",
  "embedding_dim": 768,
  "results": [
    {
      "score": 0.455,
      "qualified_name": "OrderService::_validate",
      "file": "orders.py", "line_start": 115, "line_end": 124,
      "type": "method", "enrichment_state": "pending"
    },
    {
      "score": 0.397,
      "qualified_name": "OrderService",
      "file": "orders.py", "line_start": 49, "line_end": 124,
      "type": "class",
      "summary": "High-level orchestrator for placing and processing orders. Coordinates payment authorization (PaymentProcessor) and customer notification (NotificationService)."
    },
    {
      "score": 0.363,
      "qualified_name": "OrderService::place_order",
      "file": "orders.py", "line_start": 67, "line_end": 93,
      "summary": "Validate, charge, and confirm an order in one shot."
    }
  ]
}

_validate 方法排名第一。类和 place_order 排名稍低——它们是有用的上下文,但不是答案。

步骤 2 — get_chunk_context 在不打开文件的情况下提取函数体、调用方和被调用方
{
  "found": true,
  "chunk": {
    "qualified_name": "OrderService::_validate",
    "file": "orders.py", "line_start": 115, "line_end": 124,
    "source": "def _validate(self, order: Order) -> None:\n    if order.is_empty():\n        raise ValueError(\"Order has no line items\")\n    if order.total_cents() < self.MIN_ORDER_CENTS:\n        raise ValueError(...)\n    if \"@\" not in order.customer_email:\n        raise ValueError(\"customer_email must be a valid email address\")",
    "calls": ["order.is_empty", "ValueError", "order.total_cents"],
    "called_by": [
      {"function": "place_order", "class_name": "OrderService", "file": "orders.py", "line": 67}
    ]
  }
}

这就是完整答案:三项检查(非空、最低总额、邮箱包含 @),并且只从 place_order 调用一次。总成本:约 1.4 KB 的 JSON、两次 MCP 调用,耗时不到一秒。

与先用 grep 再读取的做法相比——打开 orders.py(3.5 KB),搜索 validate,然后追踪到 place_order 以确认调用关系——MCP 方案使用的 token 大约只有 40%,而且完全跳过了文件 I/O。


两种丰富方式

第 2 阶段(description / developer_queries 向量)需要大模型。你可以自行选择:

选项 A — 直接调用 API

semhood 自行调用 Claude / GPT / OpenRouter / Ollama。

semhood enrich

最适合 CI、批处理任务,或没有 AI 编辑器的用户。在 config.yaml 中设置 llm.provider + llm.<provider>.api_key。

选项 B — 由你的 AI Agent 完成

跳过 API 密钥。你编辑器中的 Agent(Cursor 中的 Claude、Kiro、Cline、Continue 等)通过 MCP 工具遍历待处理的代码块并自行编写摘要。**semhood 不产生大模型费用。**只需说:

“丰富代码库索引”

Agent 会依次执行 list_pending_enrichments → 编写摘要 → save_enrichment,然后重复操作,直到 enrichment_progress 报告待处理项为零。使用你已经付费订阅的模型和服务。


可移植的丰富数据——付费一次、共享使用、模型变更后仍可保留

丰富数据(由大模型编写的摘要和开发者查询)是 semhood 中唯一会消耗 token 的部分。semhood 会将这些文本持久化到仓库中的 .semhood/enrichment.jsonl,并以每个代码块的内容哈希为键——与向量索引分开保存(向量索引位于 ~/.semhood/indexes/,可随时丢弃)。

**将 .semhood/enrichment.jsonl 提交到 git。**这样做可以:

  • 在团队中共享——队友克隆仓库并运行 semhood index 后,丰富数据会从文件中恢复并在本地重新嵌入。对于已完成丰富的代码,他们完全不需要消耗大模型 token。
  • 在更换嵌入模型后继续使用——从本地模型切换到 Voyage/OpenAI,运行 semhood index --reset,丰富数据就会重新嵌入到新的向量空间中,无需重新丰富。(如果没有此功能,更换模型就意味着要为所有内容重新付费。)
  • 在切换分支或回退后继续使用——旧记录会作为内容寻址缓存保留,因此检出较早的修订版时,可以立即复用其丰富数据。

数据采用内容寻址,因此始终安全:如果代码块发生变化,其哈希就不会匹配,该代码块只会重新丰富——过期摘要绝不会关联到已更改的代码。运行 semhood compact 可清理不再被任何代码引用的记录。该文件只包含文本,不含任何机密信息。

.semhood/enrichment.jsonl   ← commit this (portable enrichment, ~text)
~/.semhood/indexes/<id>/    ← never committed (vectors, machine-local)

OpenRouter——一把密钥,调用所有模型

如果你不想分别管理 Anthropic + OpenAI + Google 账号,可以让 semhood 使用 OpenRouter:

llm:
  provider: "openrouter"
  openrouter:
    api_key: "${OPENROUTER_API_KEY}"
    model: "anthropic/claude-sonnet-4.6"   # or openai/gpt-5.5, anthropic/claude-opus-4.7, etc.

使用任意受支持的模型标识。semhood enrich 和 semhood query 命令与之前相同。


架构

每个代码块包含三个命名的稠密向量:code(始终存在)、description(增强后生成)、developer_queries(增强后生成),以及一个 bm25 稀疏向量。增强前,搜索仍可仅使用 code 和 BM25。

阶段 1(semhood index)使用 Tree-sitter 解析文件、构建调用图、计算源代码哈希、将原始源代码嵌入 code 向量,并写入 Qdrant。不调用 LLM。每个代码块的状态初始均为 pending。

阶段 2(semhood enrich)通过 LLM 处理待处理队列,为每个代码块生成一个逻辑摘要和 5–10 个开发者查询,将它们嵌入 description 和 developer_queries 向量,并将文本同步到可移植的 .semhood/enrichment.jsonl 存储中。状态变为 fresh。简单代码块使用免费的模板;测试代码会按模式跳过。


配置

semhood 使用 ~/.semhood/config.yaml 中的单个全局配置(首次运行时会创建一份默认配置)——守护进程会为每个项目加载此配置。你仍可通过 $SEMHOOD_CONFIG 指定显式配置文件。环境变量引用(${VAR})从 ~/.semhood/.env、本地 .env.semhood / .env 或实际环境中解析。索引集中存储在 ~/.semhood/indexes/<id>/ 下,每个项目根目录对应一个索引——无需设置 path。

embeddings:
  provider: "local"            # local | voyage | openai | cohere
  local:
    model: "sentence-transformers/all-mpnet-base-v2"
  # voyage:                    # code-tuned, no local load — needs an API key
  #   api_key: "${VOYAGE_API_KEY}"
  #   model: "voyage-code-2"

llm:
  provider: "anthropic"
  anthropic:
    api_key: "${ANTHROPIC_API_KEY}"
    model: "claude-sonnet-4-6"

vector_db:
  provider: "qdrant"        # path is managed per-project by the daemon

enrichment:
  enabled: true
  version: 1
  llm_concurrency: 4
  skip_patterns: ["**/test_*.py", "**/*_test.go", "**/tests/**"]
  skip_trivial:
    enabled: true
    max_lines: 3
支持的语言

Python JavaScript TypeScript Java Go PHP C# Ruby Rust C++


故障排除

症状原因解决方法
qdrant... already accessed by another instance守护进程持有索引时,有其他程序直接打开了该索引按设计,索引仅由守护进程持有——请使用 CLI/MCP,不要自行打开 ~/.semhood/indexes/*。使用 semhood stop 重启。
搜索 description / developer_queries 没有结果尚未运行阶段 2运行 semhood enrich,或使用 MCP 的 list_pending_enrichments 工作流。
查询时维度不匹配自上次建立索引以来嵌入模型发生了变化删除该项目在 ~/.semhood/indexes/ 下的目录,然后重新运行 semhood index .
首条命令耗时约 15 秒守护进程正在加载模型(整台机器仅加载一次)首次使用时属正常情况;之后每次调用约需 80 ms。运行 semhood doctor 确认模型已就绪。
守护进程无法启动 / 命令卡住配置错误或端口被占用检查 ~/.semhood/daemon.log;若 7711 已被占用,请设置 SEMHOOD_DAEMON_PORT。
Voyage / Anthropic 出现 429 速率限制免费套餐限制较低添加账单信息,或调低 enrichment.llm_concurrency。

状态

版本0.1.0
Python3.11、3.12
许可证MIT
阶段 1(结构分析)稳定
MCP 服务稳定 — 主要发布形式
阶段 2(增强)Beta — 免费 LLM 套餐下易受速率限制影响

调整 enrichment.llm_concurrency,或者在遇到速率限制时使用由 Agent 驱动的增强工作流。


贡献

欢迎提交问题和 PR。

# Run tests
pytest

# Build a release
python -m build

请查看待处理问题,了解可以参与处理的事项。


由 Ahmed Gamil 开发和设计

采用 MIT 许可证 — 详见 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

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

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