Skip to main content

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.

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

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
Claude Desktop / other MCP clients (JSON config)
{
  "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

Metadata

Release files for semantic-code-mcp 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for semantic-code-mcp 0.4.0
File Size Uploaded Provenance
semantic_code_mcp-0.4.0.tar.gz 129.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for semantic-code-mcp 0.4.0
File Interpreter ABI Platform
semantic_code_mcp-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 167.3 kB

Release files / semantic_code_mcp-0.4.0.tar.gz

Download URL semantic_code_mcp-0.4.0.tar.gz
Size 129.4 kB
Tags Source
SHA-256 checksum
How to use checksums
2d9ff02d953ccea21402f53a11f18a19d6b968942d8fb8612709736631127fb4
BLAKE2b-256 checksum
How to use checksums
f49347ce3389933aae1100a421b46274707f4020129c9c5de6cd8daae0b9b3c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / semantic_code_mcp-0.4.0-py3-none-any.whl

Download URL semantic_code_mcp-0.4.0-py3-none-any.whl
Size 37.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b1f31639584b476615e7f0bdd8c2a64e8954fd9ee4e821e767a6da365853131a
BLAKE2b-256 checksum
How to use checksums
1a5d241caba8b8d80b639175930cab243f88d85ccacfb53fc8e35cb0408fdfb3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for semantic-code-mcp 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page