qdrant-mcp
by dutchakdev
README.md
# qdrant-mcp
MCP server that gives AI coding agents persistent, semantic memory via [Qdrant](https://qdrant.tech) vector search.
Built for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) but works with any MCP-compatible client.
```
"How does the price sync work?"
┌─ codebase ──────── sync-prices.ts (function syncFromAPI)
├─ documentation ─── API reference: POST /products/sync
├─ business_rules ── "Manual discounts override synced prices"
└─ decisions ─────── ADR-007: Pull model chosen over webhooks
```
## Key Features
**Workspace-aware search** — detects uncommitted changes via `git status`. Modified files return fresh content from disk, not stale embeddings. New files are discovered even before their first commit.
**4 knowledge collections** — code, documentation, business rules, architectural decisions. Search one or all at once.
**Content-hashed indexing** — only re-embeds chunks that actually changed. Full reindex of a large project takes seconds, not minutes.
**Incremental by default** — git post-commit hook triggers indexing of changed files in the background. Zero manual effort after setup.
## Architecture
```
┌────────────────────────────────────────────────────────┐
│ Claude Code Agent │
│ │ │
│ MCP Protocol │
└────────────────────────┬───────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ qdrant-mcp (this server) │
│ │
│ Tools: │
│ search_codebase search_docs search_business │
│ search_decisions search_all reindex │
│ │
│ Workspace-Aware Layer: │
│ ┌──────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │WorkspaceState│→│FreshContent │→│NewFiles │ │
│ │ git status │ │Resolver │ │Matcher │ │
│ │ dirty/new/del│ │ disk override │ │ path+keyword │ │
│ └──────────────┘ └───────────────┘ └───────────────┘ │
└────────────────────────┬───────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ Qdrant (Docker) │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ codebase │ │documentation │ │ business_rules │ │
│ └──────────┘ └──────────────┘ └────────────────────┘ │
│ ┌──────────────────┐ │
│ │ decisions │ │
│ └──────────────────┘ │
└────────────────────────────────────────────────────────┘
```
## Quick Start
### Prerequisites
- Node.js >= 20
- Docker (for Qdrant)
- OpenAI API key (or [Ollama](https://ollama.ai) for local embeddings)
### Install
```bash
git clone https://github.com/dutchakdev/qdrant-mcp.git
cd qdrant-mcp
npm install
npm run build
```
### Configure
```bash
cp .env.example .env
```
Edit `.env`:
```env
QDRANT_URL=http://localhost:6333
EMBEDDING_PROVIDER=openai
OPENAI_API_KEY=sk-your-key-here
PROJECT_ROOT=/path/to/your/project
```
### Setup (one command)
```bash
npm run setup
```
This will:
1. Start Qdrant via Docker Compose
2. Create all 4 collections with proper indexes
3. Run initial codebase indexing
4. Install git post-commit hook
### Connect to Claude Code
Add to your `.claude/settings.json` or `claude_desktop_config.json`:
```json
{
"mcpServers": {
"project-knowledge": {
"command": "node",
"args": ["/absolute/path/to/qdrant-mcp/dist/index.js"],
"env": {
"PROJECT_ROOT": "/path/to/your/project",
"QDRANT_URL": "http://localhost:6333",
"EMBEDDING_PROVIDER": "openai",
"OPENAI_API_KEY": "sk-..."
}
}
}
}
```
## MCP Tools
| Tool | Description |
|------|-------------|
| `search_codebase` | Semantic code search. Filters by language, project. Workspace-aware. |
| `search_docs` | Documentation search across all indexed sources. |
| `search_business` | Business rules and domain logic. Filter by domain. |
| `search_decisions` | Architectural decisions, ADRs, resolved issues. |
| `search_all` | Hybrid search across all collections at once. |
| `reindex` | Trigger re-indexing (`full` or `changed` mode). |
## How Workspace Awareness Works
The core problem: you edit a file, but Qdrant still has the old embedding. The agent gets stale context.
The solution is a 3-component pipeline that runs on every search:
**WorkspaceState** — calls `git status --porcelain=v2` (cached 2s). Knows which files are modified, new, deleted, or renamed.
**FreshContentResolver** — if a Qdrant result points to a dirty file, reads the fresh version from disk and replaces the stale content. Tries to extract the same symbol (function/class) via regex for precision.
**NewFilesMatcher** — discovers relevant new files that Qdrant doesn't know about. Three-phase matching: path tokens → content keywords → (optional) on-the-fly embedding.
Overhead: ~10-30ms per search. Negligible compared to embedding + vector search latency.
See [RACE-CONDITIONS.md](./RACE-CONDITIONS.md) for the full edge case matrix.
## CLI
```bash
# One-time setup (Qdrant + collections + initial index + git hook)
npm run setup
# Index changed files (default: since last commit)
npm run index
# Full reindex
npm run index:full
# Watch mode (real-time indexing on file save)
npm run watch
# Show collection stats
npm run status
```
## Embedding Providers
### OpenAI (default)
```env
EMBEDDING_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_EMBEDDING_MODEL=text-embedding-3-small # 1536 dim, ~$0.02/1M tokens
```
### Ollama (local, free)
```env
EMBEDDING_PROVIDER=ollama
OLLAMA_URL=http://localhost:11434
OLLAMA_EMBEDDING_MODEL=nomic-embed-text # 768 dim
```
Install the model first: `ollama pull nomic-embed-text`
## Project Structure
```
src/
├── index.ts # MCP server entry point
├── cli.ts # CLI (setup, index, watch, status)
├── config.ts # Environment-based configuration
├── types/
│ └── index.ts # Shared type definitions
├── embeddings/
│ └── provider.ts # OpenAI + Ollama embedding providers
├── qdrant/
│ ├── client.ts # Qdrant client singleton + init
│ └── collections.ts # Collection schemas + setup
├── indexers/
│ └── code-indexer.ts # Code chunking + content-hashed indexing
├── search/
│ └── workspace-aware-search.ts # Main search pipeline
├── workspace/
│ ├── workspace-state.ts # Git status → dirty/new/deleted detection
│ ├── fresh-content-resolver.ts # Stale → fresh content replacement
│ ├── new-files-matcher.ts # New file discovery (path + keyword + embedding)
│ └── index.ts
└── tools/
└── definitions.ts # MCP tool schemas
```
## Customization
### Adding new collections
Edit `src/qdrant/collections.ts` to add a collection, then add a corresponding search tool in `src/tools/definitions.ts` and handler in `src/index.ts`.
### Indexing non-code content
The `documentation` and `business_rules` collections are ready but need custom indexers for your data sources. Create an indexer in `src/indexers/` following the `CodeIndexer` pattern.
### Adjusting chunking
The code indexer uses regex-based chunking by default (functions, classes, exports). For more precise AST-based chunking, replace the regex patterns in `code-indexer.ts` with [tree-sitter](https://tree-sitter.github.io/tree-sitter/) parsing.
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues