Flagship project
codebase-mcp
- Problem
- A chat LLM like Claude Desktop can reason about code but cannot see your project, remember what it learned last session, or edit a large file without rewriting all of it.
- Approach
- An open-source MCP server that gives the client tools for local semantic code search, a persistent memory store, and an edit pipeline where a second model applies a sketched edit and every result is formatted, scored and committed to a separate git history.
- Result
- Open source under Apache-2.0 with 50 GitHub stars (Oct 2026). Embeddings and search run on the local machine; only the file being edited is sent to an external API.
- My role
- Sole author (2025). Designed and wrote the MCP server, the FastAPI backend, the search and memory systems, the edit pipeline and the web dashboard.
- Stack
- Python 3.11
- MCP (FastMCP, stdio)
- FastAPI
- httpx
- sentence-transformers
- all-MiniLM-L6-v2
- FAISS (IndexFlatIP)
- SQLite
- Gemini 2.5 Flash
- Black + Ruff
- Prettier
- Git
- Links
01
Architecture
Step 1 of 7: The client calls a tool over stdio
1The client calls a tool over stdio
Claude Desktop starts mcp_server.py, a FastMCP server on the stdio transport with 16 tools (search, memory, read, write, edit, git, session and project tools) plus a few read-only resources. Each tool is a thin proxy: it calls a long-running FastAPI server on localhost:6789 through httpx and turns the JSON reply into text for the model.
2The codebase is chunked and embedded locally
Python files are split with the ast module into a file overview, functions and top-level classes; JavaScript and TypeScript are split by regex into functions, arrow functions, classes and interfaces. Chunks are embedded on the machine with all-MiniLM-L6-v2 (384 dimensions), L2-normalised and stored in a FAISS flat inner-product index (IndexFlatIP), where inner product on unit vectors equals cosine; their metadata sits in SQLite. A SHA-1 per file means a re-index only re-chunks files that changed.
3Search has four modes
Semantic search embeds the query and ranks chunks by cosine similarity. The other three run on the SQLite metadata: fuzzy symbol match, plain text match and exact symbol lookup, so the model can jump straight to a function by name instead of reading whole files.
4Memory carries context across sessions
The model stores memories itself, each with one of eight categories (progress, learning, preference, mistake, solution, architecture, integration, debug) and an importance from 1 to 5. Memories are embedded with the same local model and kept in the same SQLite file. Search filters by category, importance and age, then ranks by cosine. A new session starts from a summary: recent progress, high-importance learnings, preferences and recent mistakes.
5Edits are sketched by Claude and applied by Gemini
For an edit, Claude sends instructions and only the changed lines, with "// ... existing code ..." markers for everything it leaves alone. Gemini 2.5 Flash merges that sketch into the full file. Only the file being edited is sent; a client-side limiter keeps calls within the free tier (15 requests per minute, 1,000 per day).
6Every result is formatted, checked and scored
The write pipeline formats Python with Black and lints it with Ruff, formats JavaScript and TypeScript with Prettier, checks imports against the index, and computes a quality score from 0 to 1. If the edited file has errors or scores below 0.6, the errors go back to Gemini for up to three correction attempts.
7Good changes are committed to a separate history
AI changes are tracked in a .codebase git directory with the project as its work tree, so they never touch the user's own .git. Work happens on session branches, and a change is auto-committed only when its quality score is at least 0.8.
02
Key decisions
A thin MCP proxy in front of a long-running FastAPI server
The MCP process stays small and starts fast, while the embedding model, index and git state load once in the FastAPI server and stay warm between tool calls; the same API also serves a web dashboard. The cost is two processes to start and keep in sync, and a tool call fails with a connection error if the server is not running.
A small local embedding model instead of an embedding API
all-MiniLM-L6-v2 runs on a laptop CPU, costs nothing per query and keeps code on the machine. At 384 dimensions it is weaker on code semantics than larger hosted models, which is why exact and fuzzy symbol search sit next to semantic search.
Sketch-and-apply edits with a second model
Having Claude rewrite a large file in full is slow and burns output tokens. Sending only a sketch and letting a cheap, fast model merge it keeps the main conversation short. The cost is an external call for the edited file and a merge step that can drift, so every merged file is validated and can be sent back for correction.
A shadow git repository for AI changes
Keeping AI commits in .codebase gives per-session branches and a full log of what the assistant changed, without polluting the user's own history. The trade-off is two histories over the same files that the user has to reconcile.
03
Results
- 50 GitHub stars (Oct 2026).
- Open source under Apache-2.0, installable with uv and configured in Claude Desktop with one JSON entry.
- 16 MCP tools on top of a FastAPI server with about 40 REST endpoints and a browser dashboard for search, memory, files and git.
- Indexing, search and memory run fully on the local machine after a one-time model download; only the edit tool calls an external API, with the single file being edited.
04
What I'd do next
- Add an automated test suite: pytest is a dependency, but the repository has no tests yet.
- Rebuild or compact the vector index after re-indexing; vectors for changed files are dropped from SQLite but stay in the FAISS index.
- Replace the regex JavaScript and TypeScript chunker with a real parser, and add more languages.
- Offer a local model for the apply step, so editing can run fully offline as well.