semcode
सिमैंटिक कोड-सर्च (semcode) MCP के बारे में। कोड प्रतीकों और कमिट इतिहास को अनुक्रमित करता है। हाइब्रिड खोज के लिए सघन एम्बेडिंग को स्पार्स BM25 वैक्टर के साथ जोड़ता है जो सिमैंटिक समझ और कीवर्ड सटीकता के बीच संतुलन बनाता है।
दस्तावेज़
semcode
Hybrid semantic search across all your team's GitHub repos — and their commit history — served to any AI agent over MCP.
Quick start · Features · MCP tools · Docs · Blog
Why semcode
Coding agents are good at reading the project you have open. They are bad at answering questions that span
the rest of your organisation: "which service publishes OrderPlaced?", "how do other teams call the
billing API?", "why did someone change the retry logic last month?"
| Without semcode | With semcode | |
|---|---|---|
| Code in other repos | Clone it, or paste it into the chat | One search_code call across every indexed repo |
"Where is PlaceOrderRequest defined?" | grep — if the repo happens to be checked out | Exact or partial symbol-name lookup |
| "Where do we publish order events?" | Guess the right keywords | Natural-language search (dense + BM25, fused with RRF) |
| "Why did this change?" | git log, repo by repo | Semantic search over commit messages, with full diffs |
| Where your code goes | — | Nowhere — self-hosted, with local Jina or Ollama embeddings |
How it works
flowchart LR
GH[GitHub repos] -->|source files| TS[Tree-sitter<br/>symbol parsing]
TS --> DE[Dense embeddings<br/>Jina · Voyage · OpenAI · Ollama]
TS --> BM[BM25 sparse vectors<br/>code-aware tokenizer]
GH -->|commits + diffs| CE[Commit embeddings]
DE --> Q[(Qdrant)]
BM --> Q
CE --> Q
Q -->|hybrid search · RRF| S[semcode<br/>MCP server]
S <-->|MCP| A[Your AI agent]
CI[CI on merge] -->|POST /reindex| S
semcode fetches files from GitHub, splits them into symbols (functions, classes, methods, components) with
Tree-sitter, and stores two vectors per symbol in Qdrant: a dense semantic embedding and a BM25 vector over
code-identifier subwords (getUserById → get, user, by, id). Queries run both and fuse the rankings with
Reciprocal Rank Fusion, so natural language and exact symbol names work. Indexing is incremental — unchanged
files are skipped by Git blob SHA, and deleted files are cleaned up.
→ Deep dive: ingestion · dense vectors · sparse vectors · retrieval with RRF · the blog post
🚀 Quick start
You need: Docker, and a GitHub token with Contents: read on the repos you want indexed.
1. Start semcode, Qdrant and a local embedding model (no API key needed):
git clone https://github.com/GoodbyePlanet/semcode && cd semcode
cp .env.example .env # then set GITHUB_TOKEN in .env
make docker-up-jina
2. Index a repo:
curl -N -X POST http://localhost:8090/reindex \
-H 'Content-Type: application/json' \
-d '{"service": "my-service", "github_repo": "owner/repo"}'
Progress streams back as NDJSON and ends with {"type": "done", ...}. The repo stays registered, so later
reindexes are incremental.
3. Connect your agent:
claude mcp add --transport http semcode http://localhost:8090/mcp
That's it. Prefer a hosted embedding provider (Voyage, OpenAI, Jina API) or Ollama? Set EMBEDDINGS_PROVIDER
in .env and run make docker-up instead. Want a curated list of repos in a config.yaml, or to run without
Docker? See Deployment.
💬 Using it
Ask your agent in plain English:
- "Index
acme/paymentswith semcode." - "Where do we publish order events?"
- "Find everything that uses
PlaceOrderRequest, across all services." - "Search the commit history: who changed the retry logic in payments, and why?"
- Run the
system_design_overviewprompt for a full architecture write-up with Mermaid diagrams.
✨ Features
- Many repos, one index. List services in
config.yaml, or let each repo register itself from CI with the drop-in GitHub Actions workflow. - Hybrid retrieval. Dense embeddings plus BM25 with a camelCase/snake_case-aware tokenizer, fused with RRF.
- Commit history. Commit messages and changed files are searchable; full diffs are one tool call away.
- 25 languages and file formats, framework-aware. Go, Java, Python, TypeScript/JavaScript, Rust, C#, C, C++, Ruby, PHP, Kotlin, Scala, Swift, Dart, Bash, SQL, Lua, R, Dockerfile, Docker Compose, Markdown, JSON, HTML, CSS, XML. Parsers extract Spring stereotypes and HTTP routes, FastAPI/Pydantic, ASP.NET, Rails, Laravel/Symfony, React/SwiftUI/Flutter widgets and more.
- Pluggable embeddings. Jina (local TEI or hosted API), Voyage, OpenAI or Ollama.
- CI-friendly. Streaming NDJSON reindex endpoints for pipelines and schedulers.
- GitHub Enterprise Server support via
GITHUB_API_URL.
🛠 MCP tools
| Tool | What it does |
|---|---|
search_code | Hybrid search, filterable by language, service and symbol type |
find_symbol | Look up a symbol by exact name, or by case-insensitive token match (exact=false) |
find_usages | Find code that references a symbol |
get_code_context | Fetch the full source of a file, or one symbol in it, from GitHub |
search_commits | Natural-language search over commit history |
get_commit | Full details of a commit, including changed files and diffs |
reindex | Index one or all services (incremental by default; force to re-embed) |
index_history | Index git commit history |
list_indexed_services | Indexed services with file/chunk counts, languages and last-indexed time |
index_stats | Qdrant collection statistics and configured services |
Prompts: service_overview(service) walks the agent through an architectural overview of one service —
HTTP entry points, domain types, framework conventions. system_design_overview does the whole system: service
inventory, communication topology, shared data stores and cross-cutting concerns, with Mermaid diagrams.
🔌 Connecting other clients
The server speaks streamable HTTP at http://localhost:8090/mcp.
VS Code
Add to .vscode/mcp.json:
{
"servers": {
"semcode": { "type": "http", "url": "http://localhost:8090/mcp" }
}
}
Or from the command line:
code --add-mcp '{"name":"semcode","type":"http","url":"http://localhost:8090/mcp"}'
Codex CLI
Add to ~/.codex/config.toml:
[mcp_servers.semcode]
url = "http://localhost:8090/mcp"
Other MCP clients (Cursor, Windsurf, …)
Add an entry to the client's MCP config:
{
"mcpServers": {
"semcode": { "transport": "http", "url": "http://localhost:8090/mcp" }
}
}
stdio — the client spawns the server
Needs Qdrant reachable (e.g. docker compose up -d qdrant) and dependencies installed (uv sync).
GITHUB_TOKEN, QDRANT_URL and the embedding variables are still read from .env in the project directory.
claude mcp add semcode --transport stdio --env MCP_TRANSPORT=stdio \
-- uv run --directory /path/to/semcode python -m server.main
{
"mcpServers": {
"semcode": {
"command": "uv",
"args": ["run", "--directory", "/path/to/semcode", "python", "-m", "server.main"],
"env": { "MCP_TRANSPORT": "stdio" }
}
}
}
SSE — legacy transport
Only for clients that don't support streamable HTTP yet. Set MCP_TRANSPORT=sse in .env, start the server as
usual, and point the client at http://localhost:8090/sse:
claude mcp add --transport sse semcode http://localhost:8090/sse
⚖️ How it compares
| semcode | claude-context | Serena | grep / file reads | |
|---|---|---|---|---|
| Scope | Many remote GitHub repos | Local codebase | Local project | Local checkout |
| Search | Hybrid (dense + BM25, RRF) | Hybrid (dense + BM25) | Symbol-level, via language servers | Exact text |
| Commit history | ✅ semantic search + diffs | — | — | git log |
| Deployment | Shared team service | Per developer | Per developer | — |
| Needs an index | Yes (Qdrant) | Yes (Milvus / Zilliz Cloud) | No | No |
When semcode doesn't help: a single small repo you already have open — your agent can read it directly, and editing-oriented tools like Serena are a better fit there. semcode pays off when the answer lives in code you don't have checked out.
📚 Documentation
The docs site covers everything this page leaves out:
- Deployment — Docker services, embedding paths,
config.yaml, transports - Configuration — every environment variable and embedding provider setting
- HTTP API —
/reindex,/reindex-history, NDJSON frame shapes - Qdrant collections — vectors, HNSW settings, payload fields
- Ingestion and retrieval with RRF — how it works inside
- Changelog — release history, generated from commit messages
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for dev setup, tests, adding a language parser, and the Conventional Commits rules that drive releases.