Skip to main content
Glama
vrppaul
by vrppaul

semantic-code-mcp

MCP server that provides semantic code search for Claude Code. Instead of iterative grep/glob, it indexes your codebase with embeddings and returns ranked results by meaning.

Supports Python, Rust, and Markdown — more languages planned.

How It Works

Claude Code ──(MCP/STDIO)──▶ semantic-code-mcp server
                                    │
                    ┌───────────────┼───────────────┐
                    ▼               ▼               ▼
              AST Chunker      Embedder        LanceDB
             (tree-sitter)  (sentence-trans)  (vectors)
  1. Chunking — tree-sitter parses source files into functions, classes, methods, structs, traits, markdown sections, etc.

  2. Embedding — sentence-transformers encodes each chunk (all-MiniLM-L6-v2, 384d)

  3. Storage — vectors stored in LanceDB (embedded, like SQLite)

  4. Search — hybrid semantic + keyword search with recency boosting

Indexing is incremental (mtime-based) and uses git ls-files for fast file discovery. The embedding model loads lazily on first query.

Related MCP server: codebaxing

Installation

macOS / Windows

PyPI ships CPU-only torch on these platforms, so no extra flags are needed (~1.7GB install).

uvx semantic-code-mcp

Claude Code integration:

claude mcp add --scope user semantic-code -- uvx semantic-code-mcp

Linux

IMPORTANT

Without the--index flag, PyPI installs CUDA-bundled torch (~3.5GB). Unless you need GPU acceleration (you don't — embeddings run on CPU), use the command below to get the CPU-only build (~1.7GB).

uvx --index pytorch-cpu=https://download.pytorch.org/whl/cpu semantic-code-mcp

Claude Code integration:

claude mcp add --scope user semantic-code -- \
  uvx --index pytorch-cpu=https://download.pytorch.org/whl/cpu semantic-code-mcp
{
  "mcpServers": {
    "semantic-code": {
      "command": "uvx",
      "args": ["--index", "pytorch-cpu=https://download.pytorch.org/whl/cpu", "semantic-code-mcp"]
    }
  }
}

On macOS/Windows you can omit the --index and pytorch-cpu args.

Updating

uvx caches the installed version. To get the latest release:

uvx --upgrade semantic-code-mcp

Or pin a specific version in your MCP config:

claude mcp add --scope user semantic-code -- uvx semantic-code-mcp@0.2.0

MCP Tools

search_code

Search code by meaning, not just text matching. Auto-indexes on first search.

Parameter

Type

Default

Description

query

str

required

Natural language description of what you're looking for

project_path

str

required

Absolute path to the project root

limit

int

10

Maximum number of results

Returns ranked results with file_path, line_start, line_end, name, chunk_type, content, and score.

index_codebase

Index a codebase for semantic search. Only processes new and changed files unless force=True.

Parameter

Type

Default

Description

project_path

str

required

Absolute path to the project root

force

bool

False

Re-index all files regardless of changes

index_status

Check indexing status for a project.

Parameter

Type

Default

Description

project_path

str

required

Absolute path to the project root

Returns is_indexed, files_count, and chunks_count.

Configuration

All settings are environment variables with the SEMANTIC_CODE_MCP_ prefix (via pydantic-settings):

Variable

Default

Description

SEMANTIC_CODE_MCP_CACHE_DIR

~/.cache/semantic-code-mcp

Where indexes are stored

SEMANTIC_CODE_MCP_LOCAL_INDEX

false

Store index in .semantic-code/ within each project

SEMANTIC_CODE_MCP_EMBEDDING_MODEL

all-MiniLM-L6-v2

Sentence-transformers model

SEMANTIC_CODE_MCP_DEBUG

false

Enable debug logging

SEMANTIC_CODE_MCP_PROFILE

false

Enable pyinstrument profiling

Pass environment variables via the env field in your MCP config:

{
  "mcpServers": {
    "semantic-code": {
      "command": "uvx",
      "args": ["semantic-code-mcp"],
      "env": {
        "SEMANTIC_CODE_MCP_DEBUG": "true",
        "SEMANTIC_CODE_MCP_LOCAL_INDEX": "true"
      }
    }
  }
}

Or with Claude Code CLI:

claude mcp add --scope user semantic-code \
  -e SEMANTIC_CODE_MCP_DEBUG=true \
  -e SEMANTIC_CODE_MCP_LOCAL_INDEX=true \
  -- uvx semantic-code-mcp

Tech Stack

Component

Choice

Rationale

MCP Framework

FastMCP

Python decorators, STDIO transport

Embeddings

sentence-transformers

Local, no API costs, good quality

Vector Store

LanceDB

Embedded (like SQLite), no server needed

Chunking

tree-sitter

AST-based, respects code structure

Development

uv sync                            # Install dependencies
uv run python -m semantic_code_mcp # Run server
uv run pytest                      # Run tests
uv run ruff check src/             # Lint
uv run ruff format src/            # Format

Pre-commit hooks enforce linting, formatting, type-checking (ty), security scanning (bandit), and Conventional Commits.

Releasing

Versions are derived from git tags automatically (hatch-vcs) — there's no hardcoded version in pyproject.toml.

git tag v0.2.0
git push origin v0.2.0

CI builds the package, publishes to PyPI, and creates a GitHub Release with auto-generated notes.

Adding a New Language

The chunker system is designed to make adding languages straightforward. Each language needs:

  1. A tree-sitter grammar package (e.g. tree-sitter-javascript)

  2. A chunker subclass that walks the AST and extracts meaningful chunks

Steps:

uv add tree-sitter-mylang

Create src/semantic_code_mcp/chunkers/mylang.py:

from enum import StrEnum, auto

import tree_sitter_mylang as tsmylang
from tree_sitter import Language, Node

from semantic_code_mcp.chunkers.base import BaseTreeSitterChunker
from semantic_code_mcp.models import Chunk, ChunkType


class NodeType(StrEnum):
    function_definition = auto()
    # ... other node types


class MyLangChunker(BaseTreeSitterChunker):
    language = Language(tsmylang.language())
    extensions = (".ml",)

    def _extract_chunks(self, root: Node, file_path: str, lines: list[str]) -> list[Chunk]:
        chunks = []
        for node in root.children:
            match node.type:
                case NodeType.function_definition:
                    name = node.child_by_field_name("name").text.decode()
                    chunks.append(self._make_chunk(node, file_path, lines, ChunkType.function, name))
                # ... other node types
        return chunks

Register it in src/semantic_code_mcp/container.py:

from semantic_code_mcp.chunkers.mylang import MyLangChunker

def get_chunkers(self) -> list[BaseTreeSitterChunker]:
    return [PythonChunker(), RustChunker(), MarkdownChunker(), MyLangChunker()]

The CompositeChunker handles dispatch by file extension automatically. Use BaseTreeSitterChunker._make_chunk() for consistent chunk construction. See chunkers/python.py and chunkers/rust.py for complete examples.

Project Structure

  • src/semantic_code_mcp/chunkers/ — language chunkers (base.py, composite.py, python.py, rust.py, markdown.py)

  • src/semantic_code_mcp/services/ — IndexService (scan/chunk/index), SearchService (search + auto-index)

  • src/semantic_code_mcp/indexer.py — embed + store pipeline

  • docs/decisions/ — architecture decision records

  • TODO.md — epics and planning

  • CHANGELOG.md — completed work (Keep a Changelog format)

  • .claude/rules/ — context-specific coding rules for AI agents

License

MIT

Available Tools

3 tools
index_codebaseA

Index a codebase for semantic search.

Scans Python files, extracts functions/classes/methods, generates embeddings, and stores them for fast semantic search.

Use force=True to re-index everything even if files haven't changed. Otherwise, only new and modified files are indexed (incremental).

Args: project_path: Absolute path to the project root directory. force: If True, re-index all files regardless of changes.

Returns: Statistics about the indexing operation.

ParametersJSON Schema
NameRequiredDescriptionDefault
project_pathYes
forceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description discloses key behaviors: scanning Python files, extracting code elements, generating embeddings, and storing for search. It mentions incremental vs full re-indexing and returns statistics. However, it lacks warnings about prerequisites or performance impact.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with a clear header, bullet explanation, and structured Args/Returns sections. Every sentence adds value without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, the description adequately covers purpose, parameters, and behavioral nuances. It could mention that only Python files are supported and any prerequisites, but overall it is complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaning beyond the input schema by explaining project_path as an absolute path and force as a re-index flag. Schema coverage is 0% per context, so description compensates well, though both parameters are described.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool indexes a codebase for semantic search, scanning Python files and extracting functions/classes/methods. This distinguishes it from siblings like 'search_code' and 'index_status'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use force=True vs incremental indexing, but does not explicitly state when not to use the tool or compare with alternatives like search_code. It provides clear context for the force parameter.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

index_statusA

Get the index status for a project.

Returns information about whether the project is indexed, when it was last updated, and how many files and chunks are indexed.

Note: search_code automatically re-indexes stale files before searching, so there is no need to check or act on staleness manually.

Args: project_path: Absolute path to the project root directory.

Returns: Index status including files count and chunks count.

ParametersJSON Schema
NameRequiredDescriptionDefault
project_pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully carries the burden. It clearly states what the tool returns and includes a note about staleness not needing manual action, implying no destructive side effects. It does not mention authentication or rate limits, but those are often implicit for read-only tools. The behavioral description is adequate for the tool's simplicity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very concise: two short sentences in the first paragraph, a one-sentence note, and an Args/Returns block that is minimal. Every element is useful, no redundant phrases. The structure is front-loaded with the purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has only one parameter and an output schema (though not detailed in the description), the description provides sufficient information about what the tool does and returns. The note about staleness adds valuable context. It could be slightly more precise about the return structure, but it is complete enough for typical use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has one parameter (project_path) with no description beyond title and type (0% coverage). The description adds 'Absolute path to the project root directory,' providing essential semantics. This fully compensates for the lack of schema description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets index status for a project, specifying the returned information (indexed status, last updated, files/chunks count). It distinguishes from the sibling search_code by noting that search_code automatically re-indexes stale files, implying this tool is for checking status without acting on staleness. The verb 'Get' and resource 'index status' are specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells when to use (to get index status) and when not to (no need to manually check staleness because search_code handles it). However, it does not provide guidance on when to use this tool versus the sibling index_codebase, which is a minor omission.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_codeA

Search for code semantically similar to the query.

Finds code by meaning, not just text matching. Use this when you want to find code related to a concept without knowing exact variable/function names.

Examples:

  • "authentication logic" - finds login, session handling, token validation

  • "error handling for API calls" - finds try/except blocks, error responses

  • "database connection setup" - finds connection pooling, ORM initialization

Automatically indexes the project if not already indexed, and re-indexes any files that have changed since the last search.

Args: query: Natural language description of what you're looking for. project_path: Absolute path to the project root directory. limit: Maximum number of results to return (default 10).

Returns: List of matching code chunks with file path, line numbers, content, and score.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes
project_pathYes
limitNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses automatic indexing and re-indexing of changed files, which is a key behavioral trait. No annotations are provided, so the description handles the transparency burden well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: purpose, usage, behavioral note, args, and return. While slightly verbose in examples, every sentence adds value and it is easily scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of semantic search with auto-indexing, the description covers purpose, usage context, parameter details, behavior, and return format. It lacks a warning about potential indexing delays but is otherwise complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, but the description explains each parameter in natural language: query as 'Natural language description,' project_path as 'Absolute path,' limit with default and maximum. This adds significant meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs semantic code search, distinguishes from text matching, and provides concrete examples. It differentiates from sibling tools (index_codebase, index_status) which are about indexing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description advises when to use: 'when you want to find code related to a concept without knowing exact variable/function names.' It implicitly contrasts with text search but does not explicitly mention alternatives like grep. However, the guidance is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 3 tool updatesv0.1.0
    • First observedindex_codebase
    • First observedindex_status
    • First observedsearch_code

TDQS

A4.5/5.0
Disambiguation5/5

Each tool has a distinct purpose: indexing, status checking, and searching. There is no overlap or ambiguity between them.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case: index_codebase, index_status, search_code.

Tool Count5/5

Three tools is well-scoped for a semantic code search server: one for building the index, one for checking its status, and one for querying it. Not too few, not too many.

Completeness4/5

The tools cover the core workflow (index, check, search). The search tool automatically re-indexes stale files, reducing the need for manual management. A minor gap is lack of an explicit delete or clear index tool, but it's not essential for basic usage.

Maintenance

ActivityInactive
ResponsivenessUnresponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    A semantic code search MCP server that enables natural language queries against your codebase, supporting features like related file discovery and context expansion, all running locally.
    2
    -
  • A
    license
    A
    quality
    F
    maintenance
    MCP server for semantic code search that indexes your codebase and allows AI editors to search using natural language queries.
    9
    16
    53
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    A local MCP server that enables LLM clients like Claude to perform semantic code search and answer questions about a codebase using tree-sitter parsing and sqlite-vec vector storage.
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vrppaul/semantic-code-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server