A production-ready Retrieval-Augmented Generation (RAG) server that implements the Model Context Protocol (MCP) for seamless integration with AI assistants like Cursor, Claude, and other MCP-compatible clients.
- MCP Protocol: Full implementation of Anthropic's Model Context Protocol (JSON-RPC 2.0)
- RAG Pipeline: Vector-based document retrieval using LlamaIndex + ChromaDB
- Multi-Source Ingestion: Automatic data collection from GitHub and OneDrive
- Dockerized: Complete containerization with persistent storage
- Local Embeddings: Self-contained using sentence-transformers (no API keys needed)
- Document Processing: Supports .md, .pdf, .docx, and .pptx files
┌─────────────┐
│ AI Client │ (Cursor, Claude, etc.)
│ (MCP) │
└──────┬──────┘
│ HTTP/JSON-RPC 2.0
▼
┌─────────────────────────────┐
│ FastAPI Server │
│ - /mcp endpoint │
│ - tools/list, tools/call │
└──────────┬──────────────────┘
│
▼
┌──────────────────────────────┐
│ RAG Pipeline │
│ - LlamaIndex │
│ - ChromaDB (persistent) │
│ - HuggingFace Embeddings │
└──────────────────────────────┘
- Docker & Docker Compose
- GitHub Personal Access Token (for private repo access)
- OneDrive rclone configuration (see below)
git clone <your-repo>
cd rag-mcp-serverCreate a .env file:
# GitHub Configuration
GITHUB_REPO_URL=https://github.com/your-org/your-docs-repo.git
GITHUB_TOKEN=ghp_your_github_personal_access_token
# OneDrive Configuration
ONE_DRIVE_REMOTE_PATH=my-onedrive:Engineering/Technical Docs
RCLONE_CONFIG=<see below># Install rclone (if not already installed)
curl https://rclone.org/install.sh | sudo bash
# Configure OneDrive
rclone config
# Follow prompts:
# - Name: my-onedrive
# - Storage: onedrive
# - Follow OAuth flow# View your rclone config
cat ~/.config/rclone/rclone.conf
# Copy the ENTIRE output and set it as RCLONE_CONFIG in .env
# Example format:
# [my-onedrive]
# type = onedrive
# token = {"access_token":"..."}
# drive_id = ...
# drive_type = businessImportant: The RCLONE_CONFIG should be the entire multi-line config block. In your .env file, you can use:
RCLONE_CONFIG='[my-onedrive]
type = onedrive
token = {"access_token":"eyJ0..."}
drive_id = b!abc123
drive_type = business'# Build the Docker image
docker-compose build
# Start the server
docker-compose up -d
# Check logs
docker-compose logs -f# Run the ingestion script inside the container
docker-compose exec rag-mcp-server python ingest.py
# This will:
# 1. Clone your GitHub repo
# 2. Download files from OneDrive
# 3. Convert documents to text
# 4. Build vector index# Check health
curl http://localhost:8000/health
# Check index stats
curl http://localhost:8000/stats
# Test search (non-MCP endpoint)
curl -X POST "http://localhost:8000/search?query=authentication&top_k=3"Add to your MCP client configuration:
{
"mcpServers": {
"rag-docs": {
"url": "http://localhost:8000/mcp",
"transport": "http"
}
}
}Tool: search_docs
Description: Search internal documentation using vector similarity
Parameters:
query(string, required): The search querytop_k(integer, optional): Number of results (1-20, default: 5)
Example MCP Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_docs",
"arguments": {
"query": "How do I configure authentication?",
"top_k": 5
}
}
}.
├── main.py # FastAPI server + MCP protocol
├── rag_pipeline.py # RAG logic (LlamaIndex + ChromaDB)
├── ingest.py # Data ingestion script
├── requirements.txt # Python dependencies
├── Dockerfile # Container definition
├── docker-compose.yml # Service orchestration
└── README.md # This file
# Generated at runtime:
├── db/ # Persistent vector database
│ └── chroma/ # ChromaDB storage
├── staging/ # Temporary ingestion files
├── repo/ # GitHub clone
├── onedrive/ # OneDrive downloads
└── processed/ # Converted documents
POST /mcp
Handles MCP JSON-RPC 2.0 requests:
initialize: Server capabilitiestools/list: Available toolstools/call: Execute search
GET /
- Server information
GET /health
- Health check + index stats
GET /stats
- Detailed index statistics
POST /search?query=...&top_k=5
- Simple search endpoint (non-MCP, for testing)
# Re-run ingestion to update the index
docker-compose exec rag-mcp-server python ingest.pydocker-compose logs -f rag-mcp-server# Stop the server
docker-compose down
# Remove the persistent volume
docker volume rm rag-db-data
# Restart and re-ingest
docker-compose up -d
docker-compose exec rag-mcp-server python ingest.py# Rebuild after code changes
docker-compose build
docker-compose up -dSolution: Run the ingestion script:
docker-compose exec rag-mcp-server python ingest.pyCause: Invalid or expired GITHUB_TOKEN
Solution:
- Generate a new Personal Access Token at https://github.com/settings/tokens
- Ensure it has
reposcope - Update
.envand restart:docker-compose restart
Cause: Expired rclone OAuth token
Solution:
- Run
rclone config reconnect my-onedriveon your local machine - Copy updated config from
~/.config/rclone/rclone.conf - Update
RCLONE_CONFIGin.env - Restart:
docker-compose restart
Solution:
# Check logs for errors
docker-compose logs rag-mcp-server
# Common fixes:
# 1. Verify .env file exists and has all required variables
# 2. Check port 8000 is not already in use
# 3. Rebuild: docker-compose build --no-cacheEdit rag_pipeline.py:
EMBEDDING_MODEL = "sentence-transformers/all-mpnet-base-v2" # Higher qualityEdit rag_pipeline.py:
CHUNK_SIZE = 1024 # Larger chunks
CHUNK_OVERLAP = 100Edit ingest.py to add custom converters:
elif suffix == ".html":
# Your custom conversion logic
text = convert_html_to_text(file_path)- Never commit
.envfile to version control - Rotate GitHub tokens regularly
- Use private networks in production (not exposed to internet)
- Consider adding authentication middleware to
/mcpendpoint
- First ingestion: ~5-15 minutes (depends on document count)
- Query latency: ~100-500ms (local embeddings)
- Memory usage: ~2-4GB (includes embedding model)
- Storage: ~100MB + (document size × 1.5)
MIT
For issues or questions:
- Check the troubleshooting section above
- Review logs:
docker-compose logs - Open an issue in this repository
Built with: FastAPI • LlamaIndex • ChromaDB • Docker • MCP Protocol