Skip to content

About

An MCP-powered agentic RAG assistant built with FastMCP, Qdrant, BGE-small embeddings, RAG reranking, Gemini generation, evidence verification, and Bright Data web fallback.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

Repository files navigation

MCP-Powered Agentic🤖 RAG

A production-style Agentic🤖 Retrieval-Augmented Generation system exposed through the Model Context Protocol.

This project is an end-to-end RAG assistant that can be connected to MCP-compatible clients such as Cursor. It takes a user question, rewrites it into a better retrieval query, searches a Qdrant vector database using BGE-small embeddings, reranks the retrieved chunks with a cross-encoder, generates a grounded answer with Gemini, verifies the answer against evidence, and selectively falls back to live web search through Bright Data when local evidence is weak or the question needs freshness.

What This Project Demonstrates

  • MCP server development with FastMCP
  • Agentic RAG orchestration across retrieval, reranking, generation, and verification
  • Semantic search using Qdrant and BGE-small embeddings
  • Cross-encoder reranking for higher-quality evidence selection
  • Gemini-powered query rewriting, answer generation, and evidence checking
  • Selective Bright Data web fallback for recent or low-confidence questions
  • Modular Python architecture with testable components
  • Environment-based configuration and local Qdrant indexing

Tech Stack

Layer Technology
Language Python 3.10+
MCP Server FastMCP
Vector Database Qdrant
Embedding Model BAAI/bge-small-en-v1.5
Embedding Library Sentence Transformers
Similarity Search Cosine distance
Reranker cross-encoder/ms-marco-MiniLM-L-6-v2
LLM Google Gemini, default gemini-2.5-flash-lite
Web Fallback Bright Data proxy search
Configuration .env with python-dotenv
Testing Pytest
Local Infrastructure Docker for Qdrant

System Architecture

flowchart TD
    A[User asks a question in an MCP client] --> B[FastMCP server receives tool call]
    B --> C{Tool selected}

    C -->|search_knowledge| D[Rewrite query with Gemini]
    C -->|answer_with_rag| D
    C -->|web_search| W[Bright Data web search]
    C -->|rebuild_knowledge_index| X[Rebuild Qdrant collection]

    D --> E[Embed rewritten query with BGE-small]
    E --> F[Search Qdrant collection]
    F --> G[Return top semantic candidates]
    G --> H[Cross-encoder reranking]
    H --> I[Select strongest evidence chunks]

    I --> J{Need web fallback?}
    J -->|Recent/current query| W
    J -->|Low or missing evidence| W
    J -->|Evidence is enough| K[Generate grounded answer with Gemini]
    W --> L[Convert web results into evidence]
    L --> K

    K --> M[Verify answer against evidence with Gemini]
    M --> N{Fully supported?}
    N -->|No| O[Regenerate with verifier feedback]
    O --> M
    N -->|Yes| P[Return answer, sources, verification, rewritten query]

    X --> Y[Load seed FAQ chunks]
    Y --> Z[Embed documents with BGE-small]
    Z --> AA[Store vectors and metadata in Qdrant]
Loading

End-to-End Flow

  1. MCP client sends a request

    A client such as Cursor calls one of the MCP tools exposed by server.py. The main tools are search_knowledge, answer_with_rag, web_search, and rebuild_knowledge_index.

  2. FastMCP routes the tool call

    server.py stays intentionally thin. It validates basic input types and forwards the real work to AgenticRagService in rag/service.py.

  3. The query is rewritten

    rag/query_rewriter.py uses Gemini to rewrite the user's question into a standalone retrieval query. If conversation context is provided, it is used only to resolve ambiguity.

  4. The rewritten query is embedded

    rag/embeddings.py loads BAAI/bge-small-en-v1.5 through Sentence Transformers and creates a normalized 384-dimensional query embedding.

  5. Qdrant retrieves candidate chunks

    rag/vector_store.py searches the Qdrant collection using cosine similarity. The first retrieval stage is optimized for recall and returns the initial top candidates.

  6. A cross-encoder reranks the evidence

    rag/reranker.py scores each query-document pair with cross-encoder/ms-marco-MiniLM-L-6-v2. This second stage improves precision and keeps the strongest evidence chunks.

  7. The service decides whether web search is needed

    rag/service.py checks for freshness hints such as latest, recent, current, today, 2025, or 2026. It also falls back to web search if no evidence is found or the best rerank score is below the configured relevance threshold.

  8. Bright Data adds fresh external evidence when required

    rag/web_search.py performs a Bright Data-backed Google search and converts useful search results into evidence-like chunks. This keeps web search selective instead of using it for every query.

  9. Gemini generates a grounded answer

    rag/generator.py asks Gemini to answer using only the supplied evidence. The output includes the final answer and the source chunks that support it.

  10. Gemini verifies the answer

    rag/verifier.py checks whether the generated answer is supported by the retrieved evidence. It classifies important claims as supported, partially supported, or unsupported.

  11. Unsupported answers get one repair pass

    If verification fails, the service sends the verifier feedback back into the generator and asks Gemini to revise or remove unsupported claims.

  12. The final response is returned

    The MCP tool returns the answer, source metadata, verification summary, claim-level checks, rewritten query, and evidence count.

Project Structure🤖

.
|-- AGENTS.md                    # Repository instructions for coding agents
|-- README.md                    # Project documentation
|-- server.py                    # FastMCP entry point and public MCP tools
|-- rag_code.py                  # Experimental or notebook-derived RAG code
|-- notebook.ipynb               # Development notebook
|-- requirements.txt             # Runtime and test dependencies
|-- .env.example                 # Safe environment variable template
|-- scripts/
|   `-- rebuild_index.py         # Recreates Qdrant collection and embeds seed data
|-- rag/
|   |-- __init__.py
|   |-- config.py                # Environment-based settings
|   |-- data.py                  # Demo ML FAQ seed corpus
|   |-- embeddings.py            # BGE-small embedding wrapper
|   |-- generator.py             # Gemini grounded answer generation
|   |-- llm.py                   # Gemini client helpers
|   |-- query_rewriter.py        # Query rewriting stage
|   |-- reranker.py              # Cross-encoder reranking stage
|   |-- schemas.py               # Shared evidence data structures
|   |-- service.py               # Main agentic RAG orchestration
|   |-- vector_store.py          # Qdrant collection, ingest, and search logic
|   `-- web_search.py            # Bright Data web fallback
`-- tests/
    |-- test_data.py             # Seed corpus tests
    |-- test_query_rewriter.py   # Query rewriter unit tests
    |-- test_reranker.py         # Reranker unit tests
    `-- test_verifier.py         # Evidence verifier unit tests

Generated local folders such as hf_cache/, qdrant_storage/, __pycache__/, and .pytest_cache/ should stay out of commits.

MCP Tools

Tool Purpose
search_knowledge(query, conversation_context="") Rewrites the query, retrieves Qdrant candidates, reranks them, and returns evidence chunks.
answer_with_rag(query, conversation_context="") Runs the full agentic RAG pipeline: rewrite, retrieve, rerank, optionally web search, generate, verify, and repair.
web_search(query) Runs a Bright Data-backed web search for recent or external information.
rebuild_knowledge_index() Recreates the Qdrant collection and indexes the seed knowledge base.

Setup

Create and activate a virtual environment:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Create a local environment file:

cp .env.example .env

Update .env with your local or cloud configuration:

QDRANT_URL=http://localhost:6333
QDRANT_COLLECTION=ml_faq_collection
GEMINI_API_KEY=your_gemini_api_key
GEMINI_MODEL=gemini-2.5-flash-lite
BRIGHT_DATA_USERNAME=your_bright_data_username
BRIGHT_DATA_PASSWORD=your_bright_data_password

Optional local model cache:

export HF_HOME="$PWD/hf_cache"

Run Locally

Start Qdrant:

docker run --name local-qdrant \
  -p 6333:6333 -p 6334:6334 \
  -v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
  qdrant/qdrant

Build the vector index:

python scripts/rebuild_index.py

Start the MCP server:

python server.py

By default, the MCP endpoint runs at:

http://127.0.0.1:8080/mcp

Cursor MCP Configuration

Create .cursor/mcp.json in your workspace:

{
  "mcpServers": {
    "mcp-powered-agentic-rag": {
      "url": "http://127.0.0.1:8080/mcp"
    }
  }
}

Example prompt in Cursor:

Use answer_with_rag to explain how overfitting can be prevented.

Testing

Run the unit test suite:

pytest -q

Check Python syntax:

python -m compileall -q server.py rag scripts tests

The tests are focused on local behavior and use fakes where possible, so the default test run avoids live Gemini, Bright Data, and Qdrant dependencies.

Configuration Reference

Variable Description Default
QDRANT_URL Qdrant endpoint http://localhost:6333
QDRANT_API_KEY Qdrant Cloud API key, optional for local Qdrant Empty
QDRANT_COLLECTION Vector collection name ml_faq_collection
GEMINI_API_KEY Gemini API key Required for LLM stages
GEMINI_MODEL Gemini model used for rewrite, generation, and verification gemini-2.5-flash-lite
EMBEDDING_MODEL Sentence Transformers embedding model BAAI/bge-small-en-v1.5
RERANKER_MODEL Cross-encoder reranking model cross-encoder/ms-marco-MiniLM-L-6-v2
RAG_INITIAL_TOP_K Number of semantic candidates retrieved from Qdrant 20
RAG_FINAL_TOP_K Number of reranked chunks used as evidence 5
RAG_MIN_RELEVANCE_SCORE Threshold for triggering low-confidence web fallback 0.15
BRIGHT_DATA_HOST Bright Data proxy host brd.superproxy.io
BRIGHT_DATA_PORT Bright Data proxy port 33335
BRIGHT_DATA_USERNAME Bright Data username Required for web search
BRIGHT_DATA_PASSWORD Bright Data password Required for web search
MCP_HOST MCP server host 127.0.0.1
MCP_PORT MCP server port 8080

Why This Is Recruiter-Friendly

This repository shows more than a basic chatbot wrapper. It demonstrates practical backend AI engineering: modular orchestration, retrieval quality improvements, model-based validation, MCP tool exposure, vector database integration, local infrastructure, test coverage, and secure configuration practices.

The most important engineering decision is that the system does not blindly trust the first generated answer. It retrieves evidence, reranks it, generates a grounded response, verifies the claims, and performs a repair pass when the answer is not fully supported.

Security Notes

  • Keep .env out of Git.
  • Never commit Gemini, Qdrant, or Bright Data credentials.
  • Rotate any key exposed in logs, screenshots, commits, or chat.
  • Keep web fallback selective so external search is used only when the local knowledge base is insufficient or freshness is required. RAG system with FastMCP, Qdrant, BGE embeddings, cross-encoder reranking, Gemini verification, and Bright Data web fallback.

About

An MCP-powered agentic RAG assistant built with FastMCP, Qdrant, BGE-small embeddings, RAG reranking, Gemini generation, evidence verification, and Bright Data web fallback.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages