mcp-knowledge-server
# MCP Knowledge Server
Production-grade Retrieval-Augmented Generation (RAG) server with centralized knowledge base backed by Qdrant. Exposes identical functionality through **Model Context Protocol (MCP)** and **FastAPI REST API**.
Designed for enterprise scale: clean architecture, SOLID principles, dependency injection, and fully env-configurable providers.
## Architecture
```
Cursor IDE (MCP Client)
↓
MCP Server (stdio / streamable-HTTP)
↓
Application Services
↓
RAG Pipeline → Embedding → Qdrant
↓
PostgreSQL (metadata) + Knowledge Base
```
### Key Components
| Layer | Responsibility |
|-------|----------------|
| `app/api/` | FastAPI REST endpoints |
| `app/mcp/` | MCP tool registration (12 tools) |
| `app/services/` | Use case orchestration |
| `app/rag/` | Retrieval pipeline, prompts, compression |
| `app/domain/` | Entities, ports, exceptions |
| `app/infrastructure/` | LLM, embeddings, Qdrant, persistence |
| `app/ingestion/` | Loaders, chunkers, cleaning |
## Quick Start
### Prerequisites
- Python 3.12+
- [uv](https://docs.astral.sh/uv/) package manager
- Qdrant (local or Docker)
- Ollama (optional, for local LLM)
### Local Development
```bash
# Clone and setup
git clone <repo-url> mcp-knowledge-server
cd mcp-knowledge-server
cp .env.example .env
# Install dependencies
./scripts/setup.sh
# Start Qdrant (Docker)
docker run -p 6333:6333 qdrant/qdrant:v1.12.5
# Start REST API
uv run mcp-knowledge-server-api
# Start MCP server (stdio for Cursor)
uv run mcp-knowledge-server-mcp-stdio
```
### Docker Compose (Full Stack)
```bash
cp .env.example .env
docker compose -f docker/docker-compose.yml up
```
Services:
- **API**: http://localhost:8000
- **MCP HTTP**: http://localhost:8001/mcp
- **Qdrant**: http://localhost:6333
- **PostgreSQL**: localhost:5432
## Configuration
All settings via `.env` — never modify source code to change providers.
### LLM Providers
```env
# Local (macOS)
LLM_PROVIDER=ollama
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=qwen3:8b
# Cloud
LLM_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4.1
```
Supported LLM providers: `openai`, `anthropic`, `gemini`, `groq`, `together`, `openrouter`, `ollama`, `lmstudio`, `llamacpp`, `openai_compatible`
### Embedding Providers
```env
EMBEDDING_PROVIDER=sentence_transformers
EMBEDDING_MODEL=all-MiniLM-L6-v2
```
Supported: `sentence_transformers`, `openai`, `ollama`, `voyage`, `cohere`
### Chunking Strategies
```env
CHUNK_STRATEGY=recursive # recursive | token | markdown | semantic
CHUNK_SIZE=1000
CHUNK_OVERLAP=200
```
## macOS + Ollama Setup
```bash
# Install Ollama
brew install ollama
# Start Ollama
ollama serve
# Pull recommended models
ollama pull qwen3:8b
ollama pull nomic-embed-text
# Configure .env
LLM_PROVIDER=ollama
OLLAMA_MODEL=qwen3:8b
EMBEDDING_PROVIDER=ollama
OLLAMA_EMBEDDING_MODEL=nomic-embed-text
```
Recommended models: qwen3, qwen2.5, llama3.2, mistral, gemma3, deepseek, phi
## Cursor MCP Configuration
Copy `.cursor/mcp.json.example` to your Cursor MCP settings:
```json
{
"mcpServers": {
"knowledge-server": {
"command": "uv",
"args": ["run", "python", "-m", "app.mcp.main"],
"cwd": "/path/to/mcp-knowledge-server",
"env": {
"LLM_PROVIDER": "ollama",
"OLLAMA_BASE_URL": "http://localhost:11434",
"OLLAMA_MODEL": "qwen3:8b"
}
}
}
}
```
### MCP Tools
| Tool | Description |
|------|-------------|
| `search_documents` | Semantic search over knowledge base |
| `rag_answer` | Generate RAG answer with citations |
| `add_document` | Ingest a document file |
| `update_document` | Re-ingest an existing document |
| `delete_document` | Remove document and vectors |
| `list_documents` | List indexed documents |
| `get_document` | Get document metadata |
| `similar_documents` | Find similar chunks |
| `create_collection` | Create a new collection |
| `delete_collection` | Delete a collection |
| `list_collections` | List all collections |
| `health_check` | Server health status |
## REST API
OpenAPI docs: http://localhost:8000/docs
### Examples
```bash
# Health check
curl http://localhost:8000/health
# Upload document
curl -X POST http://localhost:8000/documents/upload \
-F "file=@documents/sample.txt" \
-F "collection=knowledge_base"
# Search
curl -X POST http://localhost:8000/search \
-H "Content-Type: application/json" \
-d '{"query": "What is this about?", "top_k": 5}'
# RAG answer
curl -X POST http://localhost:8000/rag \
-H "Content-Type: application/json" \
-d '{"query": "Summarize the knowledge base"}'
# List collections
curl http://localhost:8000/collections
# Create collection
curl -X POST http://localhost:8000/collections \
-H "Content-Type: application/json" \
-d '{"name": "my_docs", "description": "My documents"}'
```
## Supported Document Formats
PDF, DOCX, TXT, Markdown, HTML, CSV
## Adding New Providers
### LLM Provider
1. If OpenAI-compatible: add config to `OpenAICompatibleLLMProvider.from_settings()` in `app/infrastructure/llm/openai_compatible.py`
2. If custom API: implement `BaseLLMProvider` in `app/infrastructure/llm/`
3. Register in `LLMProviderFactory` in `app/infrastructure/llm/factory.py`
4. Add env vars to `.env.example`
### Document Loader
1. Implement `BaseDocumentLoader` in `app/ingestion/loaders/`
2. Register in `LoaderRegistry` in `app/ingestion/loaders/registry.py`
### Embedding Provider
1. Implement `BaseEmbeddingProvider` in `app/infrastructure/embeddings/`
2. Register in `EmbeddingProviderFactory`
## Development
```bash
# Install with dev dependencies
uv sync --all-extras
# Lint
uv run ruff check app tests
uv run black --check app tests
# Type check
uv run mypy app
# Tests
uv run pytest
# Pre-commit
uv run pre-commit install
uv run pre-commit run --all-files
```
## Project Structure
```
app/
├── api/ # FastAPI REST API
├── mcp/ # MCP server tools
├── services/ # Application use cases
├── rag/ # RAG pipeline stages
├── domain/ # Entities, ports, exceptions
├── infrastructure/# External adapters
├── ingestion/ # Loaders, chunkers, cleaning
├── config/ # Pydantic settings
├── logging/ # Structured logging
└── container.py # Composition root (DI)
tests/
docker/
scripts/
alembic/
```
## Deployment
### Production Checklist
- Set `APP_ENV=production`
- Use PostgreSQL: `DATABASE_URL=postgresql+asyncpg://...`
- Configure Qdrant with API key and HTTPS
- Enable auth: `ENABLE_AUTH=true`, set `API_KEY`
- Use cloud LLM or dedicated Ollama instance
- Run behind reverse proxy (nginx/traefik)
- Set resource limits in Docker Compose
### Environment Variables
See [`.env.example`](.env.example) for the complete list.
## License
MIT
TDQS
Scored across 12 tools
Each tool targets a distinct action on either documents or collections. search_documents and similar_documents are differentiated by input (query text vs. chunk ID), and rag_answer is clearly for answer generation, so there is no ambiguity.
Most tools follow a verb_noun pattern with snake_case (add_document, delete_document, list_collections). However, 'add' and 'create' are used interchangeably for creation, and 'similar_documents' uses an adjective instead of a verb, creating minor inconsistencies.
With 12 tools, the server covers document CRUD, collection management, search/retrieval, and health monitoring. This is well-scoped for a knowledge server and each tool earns its place without redundancy.
The tool surface provides full document lifecycle (add, get, update, delete, list), collection management (create, delete, list), semantic search, similar-document lookup, and RAG. Minor gaps such as missing get_collection or update_collection exist, but core workflows are fully covered.