Senior Code MCP
Senior Code MCP lets an agent ingest a local Python repo, then retrieve code by meaning and by call/import structure, with health diagnostics along the way.
search_similar_code— Semantic search: embed a natural-language or code query and get the top-k matching symbol chunks (path, name, kind, line range, docstring, truncated text, score).search_related_code— Structural search: expand the call/import graph from given symbol names up tohopsaway and return callers, callees, and imports with hop distance.search_context— Two-stage retrieval in one call: vector search for a query, then one-hop graph expansion on the top hits, returningsimilar_chunks+related_symbolstogether.ingest_repo— Ingest a repo end to end (parse → chunk → embed → upsert to Qdrant → build + save graph); appends to the existing collection by default, orreset=Trueto drop and recreate it.store_stats— Diagnostic counts: vectors in Qdrant plus graph node and edge totals.doctor— Read-only prerequisite check (Qdrant reachable, collection exists + vector count, Ollama reachable + embed model pulled, graph file present with counts) returning per-check status and an overallhealthyflag.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Senior Code MCP search for retry implementation and all functions that call it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Senior Code MCP
Give your coding agent a memory of your codebase — so it reuses proven patterns instead of guessing, cuts the tokens you burn pasting whole files into context, and ships higher-quality code.
An MCP server that lets Cursor, Claude Code, or any MCP client search your repos two ways before writing a line of new code:
Semantic similarity — symbol-level chunks embedded with a local model and stored in Qdrant.
Structural relationships — a graph of calls and imports between symbols, expanded via NetworkX.
One search_context call does both: vector search for the concept, then graph expansion on the top hits, in one combined result.
Measured on our own corpus: finds the right symbol in the top-3 75% of the time vs 50% for grep, while handing the agent ~3× less code to read (66% fewer tokens). Retrieval core scores 0.266 NDCG@10 on the official CoIR
cosqabenchmark with a free, fully-local embedder. See Benchmarks.
Why this is different
Most code-search tools give an agent one lens. A plain vector store returns chunks of text that look similar to the query — useful, but blind to structure: it can't tell you that the retry helper it just found is called by 14 services, or that it implements an interface three other modules depend on. A pure code-graph tool gives the opposite lens — relationships without semantic ranking, so you have to already know the symbol name before you can expand from it.
Senior Code MCP runs both lenses on symbol-level chunks produced by a real AST parse:
Senior Code MCP | Generic vector memory (e.g. | Code-graph MCPs ( | |
Semantic vector search | yes | yes | yes |
Call/import graph expansion | yes | no | yes |
Chunk granularity | AST symbols (Python | raw text windows | AST symbols (Tree-sitter, many languages) |
Default deployment | local; code stays on the machine | depends on config | local |
Language coverage | Python | language-agnostic | 10+ languages |
The tradeoff is deliberate. The tools on the right do more; this one does less, in a slice small enough to read, run, and reason about in an evening. What that focus buys is a retrieval step that returns not just "here is similar code" but "here is similar code, and everything that calls it, imports it, or shares its shape" — the context an agent needs to reuse a proven implementation instead of writing a parallel one.
Related MCP server: GraphHub
How it works
repo -> parse (Python stdlib ast) -> symbol chunks
-> embed (Ollama nomic-embed-text, 768d) -> Qdrant
-> call/import edges -> NetworkX graph (graph.json)Ingestion walks a repo, extracts functions/classes/methods with the Python ast module, embeds each symbol's source, upserts into Qdrant, and builds a directed graph of call and import relationships. Multiple repos coexist in one collection, each chunk tagged with its repo name.
Architecture
Full design document: ARCHITECTURE.md. It has diagrams, module reference, runtime flows, data model, evaluation harness and known limitations. The summary follows.
src/senior_code_mcp/
├── __init__.py # Package metadata (__version__)
├── server.py # MCP server: FastMCP, stdio transport, 6 tools
├── cli.py # senior-code-ingest entry point (--reset flag)
├── pipeline.py # Shared ingest: parse → chunk → embed + upsert → graph
├── ingest/ # Code analysis
│ ├── parser.py # stdlib ast walk → Symbol (definitions, imports, calls)
│ └── chunker.py # One Chunk per function / class / method
└── store/ # Persistence
├── vectors.py # Ollama embed client + Qdrant collection, search
└── graph.py # NetworkX DiGraph: call + import edges, BFS expand
eval/
├── retrieval_ab.py # Ablation: dense retrieval vs BM25/grep baseline
├── coir_bench.py # CoIR runner (cosqa, codesearchnet-python)
└── results/ # cosqa.json, retrieval_ab.txt
AGENTS.md # Onboarding runbook for AI coding agents
FINALS.md # Hackathon demo playbook
docker-compose.yml # Qdrant + Ollama services
.cursor/mcp.json # Example MCP client registrationIngest path
ingest_repo (MCP tool) and senior-code-ingest (CLI) call the same function, pipeline.ingest_repo.
parser.parse_reporeads each.pyfile. It skips hidden, virtual-environment and build directories.The parser emits one
Symbolfor each definition, import and call. A call symbol records its enclosing definition.chunker.chunk_repokeeps only the definitions. Each chunk holds the source text, the line range and the docstring.vectors.upsert_chunkssends the chunk text to Ollama in batches of 32. Then it writes the vectors to Qdrant.graph.build_graphmakes the call and import edges.save_graphwrites them tograph.json.
Query path
Tool | Data source | Result |
| Qdrant | Top-k chunks with score. The text is cut to 80 lines or 2,000 characters. |
|
| Nodes within |
| Qdrant, then | Vector hits, then the graph neighbors of their names (hop ≥ 1). |
| Both | Vector count, node count and edge count. |
| Qdrant, Ollama, | One status for each prerequisite. This tool does not write data. |
Data model
Qdrant collection (code_chunks, cosine distance):
One point for each function, class or method.
The point ID is a UUIDv5 of
path:start_line:end_line:name. A second ingest of the same code replaces the points. It does not add copies.The payload holds
repo,path,name,kind,start_line,end_line,textanddocstring.The first embedding response sets the vector size (768 for
nomic-embed-text).
Graph file (graph.json, NetworkX node-link JSON):
Definition nodes use the qualified name as the key, for example
Class.method.File nodes use the key
file:<path>. Module nodes use the keymodule:<name>.A
callsedge goes from the enclosing definition to the callee. The resolver matches the callee by its last name segment and uses the first match.An
importsedge goes from a file node to a module node.
Benchmarks
Proof, not vibes. Two questions matter for a retrieval tool: does it find the right code (quality), and does it cost the agent fewer tokens than the alternative (efficiency). We measure both, plus an external leaderboard number for the embedding core. All reproducible (eval/).
1. Ablation vs grep — the tool's actual job. Same 2 ingested repos (394 symbol chunks, 12 hand-labelled query→symbol tasks), semantic retrieval vs a BM25/grep lexical baseline over the identical corpus:
Metric | Senior Code MCP (semantic) | grep / BM25 baseline |
Hit@1 | 58% | 33% |
Hit@3 | 75% | 50% |
MRR | 0.69 | 0.43 |
Tokens to reach answer | ~1,100 / query | ~3,200 / query |
→ 66% fewer tokens (2.9× less context) |
~1.6× higher top-1 hit-rate and ~3× less code fed into context — the token savings and quality lift the tool exists to deliver. (Token cost is a char/4 proxy; the ratio is the point. Baseline reads whole files a grep hit points at; the tool returns ranked symbol chunks.)
2. CoIR cosqa — official external benchmark. Same schema/metrics as the CoIR + MTEB leaderboards, run on our exact retrieval core (nomic-embed-text, local via Ollama), 500 queries vs a 20,604-doc corpus:
NDCG@10 | Recall@10 | Recall@100 | MAP@10 |
0.266 | 0.47 | 0.81 | 0.20 |
A defensible baseline for a free, offline, no-API embedder (code-specialized cloud models score higher — and none of them ship the graph layer this tool adds on top).
Reproduce:
uv sync --extra eval
uv run --extra eval python eval/retrieval_ab.py # ablation vs grep (needs repos ingested)
uv run --extra eval python eval/coir_bench.py --task cosqa # official CoIR numberMCP tools (6)
Tool | What it does |
| Embeds a natural-language or code query, returns top-k matching symbols (path, lines, docstring, truncated source, score). |
| Given symbol names, expands N hops through the call/import graph and returns connected symbols. |
| One call, two-stage retrieval: vector search for the query, then graph expansion on the top hits' symbol names. Returns one combined result ( |
| Runs the full pipeline on a local repo path (parse, embed, upsert, build graph). |
| Diagnostic: vector count in Qdrant, node/edge counts in the graph. |
| Read-only prerequisite self-diagnosis (qdrant reachable, collection exists + vector count, ollama reachable + embed model present, graph file + node/edge counts). The onboarding agent's first call. |
Typical agent flow: doctor first to confirm the store is healthy, then search_similar_code for a concept, then search_related_code on the hit names — or search_context to get both stages in a single call.
Why organizations adopt it easily
Fully local by default. Ollama embeddings + Qdrant on the machine. Code never leaves the perimeter — no cloud embedding API, no hosted vector DB, no surprise egress. (A cloud embedding API is supported only with explicit written approval, per
AGENTS.md.)Three commands to a working index.
docker run qdrant,ollama pull nomic-embed-text,senior-code-ingest /your/repo. No cluster, no accounts, no billing.Self-onboarding agent.
AGENTS.mdis a runbook an AI coding agent auto-reads on repo open: it callsdoctor, asks the org the three questions that actually need a human (code perimeter, which repos, re-index cadence), respects hard guardrails (never reset a collection, never send code externally without approval, secrets in env), then ingests + registers + verifies on its own.Drops into existing agent stacks. Std MCP over stdio — Cursor, Claude Code, any MCP client. One entry in
mcp.json.No vendor lock-in. Open Python, stdlib
ast, Qdrant, NetworkX. Read every file in an evening.
Quick start (~5 min)
docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant
ollama pull nomic-embed-text
uv sync
senior-code-ingest /path/to/any/python/repoAlternative: docker compose up brings up Qdrant + Ollama together — on macOS, native Ollama is preferred (faster, uses Metal GPU) over the container.
Then register in Cursor (.cursor/mcp.json in this repo is an example, or add to global ~/.cursor/mcp.json):
{
"mcpServers": {
"senior-code-mcp": {
"command": "/absolute/path/to/.venv/bin/senior-code-mcp",
"args": []
}
}
}Restart Cursor, then ask it to "call doctor", "call store_stats", and "search similar code for ".
Config
Setting | Default | Env var |
Qdrant URL |
|
|
Collection |
|
|
Ollama URL |
|
|
Embed model |
|
|
Graph path |
|
|
Honest limitations
Python files only (stdlib
ast; tree-sitter multi-language is the planned upgrade).Fully local: no hosted embeddings, no cloud vector DB.
Single shared collection; multi-tenant separation is future work.
No incremental ingest yet — re-running re-embeds the repo (idempotent via deterministic IDs, but not free).
Each ingest rewrites
graph.jsonfrom the current repo only. Qdrant keeps all repos, but the graph holds only the last repo ingested.Call edges resolve by the last name segment, first match. Two definitions with the same name can get the wrong edge.
Built at the Cursor x Superteam Georgia hackathon (Tbilisi, Jul 22 2026) — built with Cursor, end to end, in one night.
Available Tools
6 toolsdoctorA
Self-diagnose prerequisites before any org-facing setup.
The onboarding agent calls this first to learn what is already healthy and what is missing, so it only asks the org about the things that actually need a human decision. Non-destructive: never writes, never creates a collection, never pulls a model.
Checks:
Qdrant reachable on the configured URL.
Target collection exists and its vector count.
Ollama reachable and the configured embed model is pulled.
Graph file exists with node and edge counts.
Returns:
Per-check status (ok bool + detail) and an overall healthy flag.
Inputs: no named parameters.
ingest_repoA
Ingest a repo: parse, chunk, embed + upsert to Qdrant, build + save graph.
Appends to the existing collection by default so multiple repos coexist;
pass reset=True to drop + recreate the collection first. Every chunk is
tagged with its repo name.
Inputs: path (required), reset.
search_contextA
Two-stage retrieval in one call: semantic search + graph expansion.
Runs vector search for query (top-k), takes the symbol names from those
hits, expands the graph one hop from them, and returns a combined result:
similar_chunks (the vector hits) plus related_symbols (graph neighbors).
Inputs: query (required), hops, top_k.
search_similar_codeA
Semantic search: embed query, return top-k matching code chunks.
Each result carries score + payload (path, name, kind, line range, docstring, text).
Inputs: query (required), top_k. Returns: result
store_statsA
Return store stats: vector count (Qdrant) + node/edge counts (graph).
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
The tools are clearly distinct: search_similar_code handles semantic search, search_related_code handles graph-based structural search, and search_context combines both. ingest_repo, store_stats, and doctor cover ingestion, statistics, and diagnostics respectively, with no overlapping purposes.
Most tools follow a verb_noun pattern (search_context, search_related_code, ingest_repo, store_stats). The 'search_*' prefix is consistently used for search operations. The 'doctor' tool deviates by using a noun instead of a verb, but it is still recognizable and not chaotic.
With 6 tools, the set is well-scoped for a code comprehension server. Each tool serves a distinct and necessary function (ingest, search, stats, diagnostics), and the count is well within the optimal range.
The tool surface covers the full lifecycle for code search and understanding: ingestion with reset capability, multiple search modalities (semantic, structural, combined), statistics, and pre-flight diagnostics. No major gaps are apparent for the stated purpose.
Maintenance
Related MCP Connectors
Shared memory for coding agents. Stop re-explaining your codebase every session.
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Persistent engineering memory designed to follow developers across coding agents.
Give your AI agent a persistent map of your project's structure, dependencies, and bugs.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides semantic code search and retrieval capabilities for AI agents, enabling them to query codebases using natural language with automatic learning, hybrid search, and intelligent chunking of functions and classes.14 npm31ISC
- AlicenseNot gradedqualityCmaintenanceTransforms codebases into a knowledge graph for AI agents, enabling semantic search, impact analysis, and persistent session memory with up to 94% token savings.4 npm15ISC
- AlicenseNot gradedqualityDmaintenanceAdds semantic code search to AI coding agents, enabling natural language queries across entire codebases to retrieve relevant code chunks, saving tokens and providing deep context.41 npm1MIT
- AlicenseNot gradedqualityDmaintenanceProvides AI coding agents with persistent architectural memory of codebases, enabling impact analysis, test generation, and code generation with reduced token usage.MIT